From ffe8bbd2ddd39de83ce87cfaf7e04a439991bec8 Mon Sep 17 00:00:00 2001 From: bzzt Date: Wed, 29 May 2019 13:37:00 +0000 Subject: [PATCH 01/62] racingcrashfix #4766 --- components/nifosg/nifloader.cpp | 12 ++++++++++-- components/shader/shadervisitor.cpp | 5 ++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index d6a459b1b..f5f7c3704 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -400,7 +400,10 @@ namespace NifOsg return; } - osg::ref_ptr texture2d (new osg::Texture2D(handleSourceTexture(textureEffect->texture.getPtr(), imageManager))); + osg::ref_ptr image (handleSourceTexture(textureEffect->texture.getPtr(), imageManager)); + osg::ref_ptr texture2d (new osg::Texture2D(image)); + if (image) + texture2d->setTextureSize(image->s(), image->t()); texture2d->setName("envMap"); unsigned int clamp = static_cast(textureEffect->clamp); int wrapT = (clamp) & 0x1; @@ -770,7 +773,10 @@ namespace NifOsg wrapT = inherit->getWrap(osg::Texture2D::WRAP_T); } - osg::ref_ptr texture (new osg::Texture2D(handleSourceTexture(st.getPtr(), imageManager))); + osg::ref_ptr image (handleSourceTexture(st.getPtr(), imageManager)); + osg::ref_ptr texture (new osg::Texture2D(image)); + if (image) + texture->setTextureSize(image->s(), image->t()); texture->setWrap(osg::Texture::WRAP_S, wrapS); texture->setWrap(osg::Texture::WRAP_T, wrapT); textures.push_back(texture); @@ -1337,6 +1343,8 @@ namespace NifOsg const Nif::NiSourceTexture *st = tex.texture.getPtr(); osg::ref_ptr image = handleSourceTexture(st, imageManager); texture2d = new osg::Texture2D(image); + if (image) + texture2d->setTextureSize(image->s(), image->t()); } else texture2d = new osg::Texture2D; diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index 63c676118..e40cc255b 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -163,6 +163,7 @@ namespace Shader if (image) { osg::ref_ptr normalMapTex (new osg::Texture2D(image)); + normalMapTex->setTextureSize(image->s(), image->t()); normalMapTex->setWrap(osg::Texture::WRAP_S, diffuseMap->getWrap(osg::Texture::WRAP_S)); normalMapTex->setWrap(osg::Texture::WRAP_T, diffuseMap->getWrap(osg::Texture::WRAP_T)); normalMapTex->setFilter(osg::Texture::MIN_FILTER, diffuseMap->getFilter(osg::Texture::MIN_FILTER)); @@ -186,7 +187,9 @@ namespace Shader boost::replace_last(specularMapFileName, ".", mSpecularMapPattern + "."); if (mImageManager.getVFS()->exists(specularMapFileName)) { - osg::ref_ptr specularMapTex (new osg::Texture2D(mImageManager.getImage(specularMapFileName))); + osg::ref_ptr image (mImageManager.getImage(specularMapFileName)); + osg::ref_ptr specularMapTex (new osg::Texture2D(image)); + specularMapTex->setTextureSize(image->s(), image->t()); specularMapTex->setWrap(osg::Texture::WRAP_S, diffuseMap->getWrap(osg::Texture::WRAP_S)); specularMapTex->setWrap(osg::Texture::WRAP_T, diffuseMap->getWrap(osg::Texture::WRAP_T)); specularMapTex->setFilter(osg::Texture::MIN_FILTER, diffuseMap->getFilter(osg::Texture::MIN_FILTER)); From ebe5448816532c55b9c19ded462b8e65701bd8bb Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Thu, 16 May 2019 00:15:21 +0300 Subject: [PATCH 02/62] Content selector: drop duplicates of the added file (bug #2395) --- CHANGELOG.md | 1 + components/contentselector/model/contentmodel.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5c6a0885..3658b839a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ------ Bug #1515: Opening console masks dialogue, inventory menu + Bug #2395: Duplicated plugins in the launcher when multiple data directories provide the same plugin Bug #2969: Scripted items can stack Bug #2987: Editor: some chance and AI data fields can overflow Bug #3006: 'else if' operator breaks script compilation diff --git a/components/contentselector/model/contentmodel.cpp b/components/contentselector/model/contentmodel.cpp index 7a4558d57..ef27f938d 100644 --- a/components/contentselector/model/contentmodel.cpp +++ b/components/contentselector/model/contentmodel.cpp @@ -408,6 +408,17 @@ bool ContentSelectorModel::ContentModel::dropMimeData(const QMimeData *data, Qt: void ContentSelectorModel::ContentModel::addFile(EsmFile *file) { + for (int row = 0; row < mFiles.size(); row++) + { + if (mFiles.at(row)->fileName() == file->fileName()) + { + beginRemoveRows(QModelIndex(), row, row); + mFiles.removeAt(row); + endRemoveRows(); + emit dataChanged(index(row, 0), index(mFiles.size(), 0)); + break; + } + } beginInsertRows(QModelIndex(), mFiles.count(), mFiles.count()); mFiles.append(file); endInsertRows(); From e14ada8f364ffa77a9e01997ca83b2ffc9ba6173 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Thu, 16 May 2019 14:06:33 +0300 Subject: [PATCH 03/62] Make file name comparison case-insensitive --- components/contentselector/model/contentmodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/contentselector/model/contentmodel.cpp b/components/contentselector/model/contentmodel.cpp index ef27f938d..d39df8ce6 100644 --- a/components/contentselector/model/contentmodel.cpp +++ b/components/contentselector/model/contentmodel.cpp @@ -410,7 +410,7 @@ void ContentSelectorModel::ContentModel::addFile(EsmFile *file) { for (int row = 0; row < mFiles.size(); row++) { - if (mFiles.at(row)->fileName() == file->fileName()) + if (!mFiles.at(row)->fileName().compare(file->fileName(), Qt::CaseInsensitive)) { beginRemoveRows(QModelIndex(), row, row); mFiles.removeAt(row); From 2fbed21f83bc6c3af9f06b07e30ce306f1589111 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sat, 18 May 2019 14:17:18 +0300 Subject: [PATCH 04/62] Avoid a memory leak --- components/contentselector/model/contentmodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/contentselector/model/contentmodel.cpp b/components/contentselector/model/contentmodel.cpp index d39df8ce6..3e5afc76d 100644 --- a/components/contentselector/model/contentmodel.cpp +++ b/components/contentselector/model/contentmodel.cpp @@ -413,7 +413,7 @@ void ContentSelectorModel::ContentModel::addFile(EsmFile *file) if (!mFiles.at(row)->fileName().compare(file->fileName(), Qt::CaseInsensitive)) { beginRemoveRows(QModelIndex(), row, row); - mFiles.removeAt(row); + delete mFiles.takeAt(row); endRemoveRows(); emit dataChanged(index(row, 0), index(mFiles.size(), 0)); break; From 5cd781b3ebc462bffbb32c10d437985bcc1d57c8 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sat, 18 May 2019 17:21:27 +0300 Subject: [PATCH 05/62] Experimental folder handling rewrite --- apps/launcher/datafilespage.cpp | 9 ++++----- apps/opencs/editor.cpp | 19 +++---------------- apps/opencs/editor.hpp | 2 -- .../contentselector/model/contentmodel.cpp | 9 ++------- 4 files changed, 9 insertions(+), 30 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 055426f30..8554b620b 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -109,15 +109,14 @@ void Launcher::DataFilesPage::populateFileViews(const QString& contentModelName) { QStringList paths = mGameSettings.getDataDirs(); - foreach(const QString &path, paths) - mSelector->addFiles(path); - mDataLocal = mGameSettings.getDataLocal(); if (!mDataLocal.isEmpty()) - mSelector->addFiles(mDataLocal); + paths.insert(0, mDataLocal); + + foreach(const QString &path, paths) + mSelector->addFiles(path); - paths.insert(0, mDataLocal); PathIterator pathIterator(paths); mSelector->setProfileContent(filesInProfile(contentModelName, pathIterator)); diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 7b5c3f7ab..b22f5464d 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -28,8 +28,6 @@ CS::Editor::Editor (int argc, char **argv) mViewManager = new CSVDoc::ViewManager(mDocumentManager); - setupDataFiles (config.first); - NifOsg::Loader::setShowMarkers(true); mDocumentManager.setFileData(mFsStrict, config.first, config.second); @@ -79,15 +77,6 @@ CS::Editor::~Editor () remove(mPid.string().c_str())); // ignore any error } -void CS::Editor::setupDataFiles (const Files::PathContainer& dataDirs) -{ - for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter) - { - QString path = QString::fromUtf8 (iter->string().c_str()); - mFileDialog.addFiles(path); - } -} - std::pair > CS::Editor::readConfig(bool quiet) { boost::program_options::variables_map variables; @@ -160,7 +149,7 @@ std::pair > CS::Editor::readConfi dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end()); //iterate the data directories and add them to the file dialog for loading - for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter) + for (Files::PathContainer::const_reverse_iterator iter = dataDirs.rbegin(); iter != dataDirs.rend(); ++iter) { QString path = QString::fromUtf8 (iter->string().c_str()); mFileDialog.addFiles(path); @@ -199,8 +188,7 @@ void CS::Editor::createAddon() mStartup.hide(); mFileDialog.clearFiles(); - std::pair > config = readConfig(/*quiet*/true); - setupDataFiles (config.first); + readConfig(/*quiet*/true); mFileDialog.showDialog (CSVDoc::ContentAction_New); } @@ -224,8 +212,7 @@ void CS::Editor::loadDocument() mStartup.hide(); mFileDialog.clearFiles(); - std::pair > config = readConfig(/*quiet*/true); - setupDataFiles (config.first); + readConfig(/*quiet*/true); mFileDialog.showDialog (CSVDoc::ContentAction_Edit); } diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index 2c2e88aef..0c3ece905 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -55,8 +55,6 @@ namespace CS CSVTools::Merge mMerge; CSVDoc::ViewManager* mViewManager; - void setupDataFiles (const Files::PathContainer& dataDirs); - std::pair > readConfig(bool quiet=false); ///< \return data paths diff --git a/components/contentselector/model/contentmodel.cpp b/components/contentselector/model/contentmodel.cpp index 3e5afc76d..6ac074b4d 100644 --- a/components/contentselector/model/contentmodel.cpp +++ b/components/contentselector/model/contentmodel.cpp @@ -411,14 +411,9 @@ void ContentSelectorModel::ContentModel::addFile(EsmFile *file) for (int row = 0; row < mFiles.size(); row++) { if (!mFiles.at(row)->fileName().compare(file->fileName(), Qt::CaseInsensitive)) - { - beginRemoveRows(QModelIndex(), row, row); - delete mFiles.takeAt(row); - endRemoveRows(); - emit dataChanged(index(row, 0), index(mFiles.size(), 0)); - break; - } + return; } + beginInsertRows(QModelIndex(), mFiles.count(), mFiles.count()); mFiles.append(file); endInsertRows(); From 0fcb75fb213f33107271fea26f712a6828d1ac9c Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Wed, 22 May 2019 20:55:30 +0300 Subject: [PATCH 06/62] Achieve CHIM and get rid of the loop --- components/contentselector/model/contentmodel.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/components/contentselector/model/contentmodel.cpp b/components/contentselector/model/contentmodel.cpp index 6ac074b4d..390dde223 100644 --- a/components/contentselector/model/contentmodel.cpp +++ b/components/contentselector/model/contentmodel.cpp @@ -408,12 +408,6 @@ bool ContentSelectorModel::ContentModel::dropMimeData(const QMimeData *data, Qt: void ContentSelectorModel::ContentModel::addFile(EsmFile *file) { - for (int row = 0; row < mFiles.size(); row++) - { - if (!mFiles.at(row)->fileName().compare(file->fileName(), Qt::CaseInsensitive)) - return; - } - beginInsertRows(QModelIndex(), mFiles.count(), mFiles.count()); mFiles.append(file); endInsertRows(); @@ -434,7 +428,7 @@ void ContentSelectorModel::ContentModel::addFiles(const QString &path) { QFileInfo info(dir.absoluteFilePath(path2)); - if (item(info.absoluteFilePath()) != 0) + if (item(info.fileName())) continue; try { From 596dbbe70b872ba766aacdbb6536b48e11fa9f90 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Mon, 3 Jun 2019 20:04:40 +0300 Subject: [PATCH 07/62] Make sure fade operations properly end (bug #4639) --- CHANGELOG.md | 1 + apps/openmw/mwgui/screenfader.cpp | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82621d794..cc0c8c6de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Bug #4384: Resist Normal Weapons only checks ammunition for ranged weapons Bug #4411: Reloading a saved game while falling prevents damage in some cases Bug #4540: Rain delay when exiting water + Bug #4639: Black screen after completing first mages guild mission + training Bug #4701: PrisonMarker record is not hardcoded like other markers Bug #4703: Editor: it's possible to preview levelled list records Bug #4705: Editor: unable to open exterior cell views from Instances table diff --git a/apps/openmw/mwgui/screenfader.cpp b/apps/openmw/mwgui/screenfader.cpp index e75e4954e..619852a22 100644 --- a/apps/openmw/mwgui/screenfader.cpp +++ b/apps/openmw/mwgui/screenfader.cpp @@ -38,12 +38,20 @@ namespace MWGui if (!mRunning) return; - if (mRemainingTime <= 0 || mStartAlpha == mTargetAlpha) + if (mStartAlpha == mTargetAlpha) { finish(); return; } + if (mRemainingTime <= 0) + { + // Make sure the target alpha is applied + mFader->notifyAlphaChanged(mTargetAlpha); + finish(); + return; + } + if (mRemainingTime > mTargetTime) { mRemainingTime -= dt; @@ -162,7 +170,7 @@ namespace MWGui if (time < 0.f) return; - if (time == 0.f) + if (time == 0.f && delay == 0.f) { mCurrentAlpha = targetAlpha; applyAlpha(); From 4aca8240e5ed3b3fef006948cdcc51f1d5aa3324 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Thu, 6 Jun 2019 22:09:45 +0200 Subject: [PATCH 08/62] implement ^W and ^U in the console --- apps/openmw/mwgui/console.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 705e28138..cc900350d 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -229,7 +229,27 @@ namespace MWGui MyGUI::KeyCode key, MyGUI::Char _char) { - if( key == MyGUI::KeyCode::Tab) + if(MyGUI::InputManager::getInstance().isControlPressed()) + { + if(key == MyGUI::KeyCode::W) + { + std::string text = mCommandLine->getCaption(); + if(text.empty()) + return; + size_t max = text.size(); + while(max > 0 && (text[max - 1] == ' ' || text[max - 1] == '\t' || text[max - 1] == '>')) + max--; + while(max > 0 && text[max - 1] != ' ' && text[max - 1] != '\t' && text[max - 1] != '>') + max--; + text.resize(max); + mCommandLine->setCaption(text); + } + else if(key == MyGUI::KeyCode::U) + { + mCommandLine->setCaption(""); + } + } + else if(key == MyGUI::KeyCode::Tab) { std::vector matches; listNames(); From 67fb19c2b925b54af18080ecf4c4f7294ceab466 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Fri, 7 Jun 2019 18:41:35 +0200 Subject: [PATCH 09/62] fix deletion when not at end of line and implement ^LEFT and ^RIGHT --- apps/openmw/mwgui/console.cpp | 53 +++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index cc900350d..c3ec52039 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -225,6 +225,11 @@ namespace MWGui resetReference(); } + bool isWhitespace(char c) + { + return c == ' ' || c == '\t'; + } + void Console::keyPress(MyGUI::Widget* _sender, MyGUI::KeyCode key, MyGUI::Char _char) @@ -233,20 +238,52 @@ namespace MWGui { if(key == MyGUI::KeyCode::W) { - std::string text = mCommandLine->getCaption(); - if(text.empty()) + const auto& caption = mCommandLine->getCaption(); + if(caption.empty()) return; - size_t max = text.size(); - while(max > 0 && (text[max - 1] == ' ' || text[max - 1] == '\t' || text[max - 1] == '>')) + size_t max = mCommandLine->getTextCursor(); + while(max > 0 && (isWhitespace(caption[max - 1]) || caption[max - 1] == '>')) max--; - while(max > 0 && text[max - 1] != ' ' && text[max - 1] != '\t' && text[max - 1] != '>') + while(max > 0 && !isWhitespace(caption[max - 1]) && caption[max - 1] != '>') max--; - text.resize(max); - mCommandLine->setCaption(text); + size_t length = mCommandLine->getTextCursor() - max; + if(length > 0) + { + std::string text = caption; + text.erase(max, length); + mCommandLine->setCaption(text); + mCommandLine->setTextCursor(max); + } } else if(key == MyGUI::KeyCode::U) { - mCommandLine->setCaption(""); + if(mCommandLine->getTextCursor() > 0) + { + std::string text = mCommandLine->getCaption(); + text.erase(0, mCommandLine->getTextCursor()); + mCommandLine->setCaption(text); + mCommandLine->setTextCursor(0); + } + } + else if(key == MyGUI::KeyCode::ArrowRight) + { + const auto& caption = mCommandLine->getCaption(); + size_t pos = mCommandLine->getTextCursor(); + while(pos < caption.size() && (isWhitespace(caption[pos]) || caption[pos] == '-')) + pos++; + while(pos < caption.size() && !isWhitespace(caption[pos]) && caption[pos] != '-') + pos++; + mCommandLine->setTextCursor(pos); + } + else if(key == MyGUI::KeyCode::ArrowLeft) + { + const auto& caption = mCommandLine->getCaption(); + size_t pos = mCommandLine->getTextCursor(); + while(pos > 0 && (isWhitespace(caption[pos - 1]) || caption[pos - 1] == '>')) + pos--; + while(pos > 0 && !isWhitespace(caption[pos - 1]) && caption[pos - 1] != '>') + pos--; + mCommandLine->setTextCursor(pos); } } else if(key == MyGUI::KeyCode::Tab) From ef2a7160fa21142fe0f4d6fdac2cafa40a651c08 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sat, 8 Jun 2019 15:06:04 +0300 Subject: [PATCH 10/62] Fix automovement toggling on "joystick used" flag --- apps/openmw/mwinput/inputmanagerimp.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 4b11d9af4..d66cc6577 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -623,11 +623,7 @@ namespace MWInput mPlayer->setAutoMove (false); mPlayer->setForwardBackward((yAxis - 0.5f) * 2 * -1); } - else if(mPlayer->getAutoMove()) - { - triedToMove = true; - mPlayer->setForwardBackward (1); - } + if (triedToMove) mJoystickLastUsed = true; @@ -649,7 +645,8 @@ namespace MWInput mPlayer->setAutoMove (false); mPlayer->setForwardBackward (actionIsActive(A_MoveForward) ? 1 : -1); } - else if(mPlayer->getAutoMove()) + + if (mPlayer->getAutoMove()) { alwaysRunAllowed = true; triedToMove = true; From 295ee11063f27e1faa826dd9117a79cdd051b338 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sat, 8 Jun 2019 17:06:34 +0300 Subject: [PATCH 11/62] Make Player->Cast select the spell instead (bug #5056) --- CHANGELOG.md | 1 + apps/openmw/mwscript/miscextensions.cpp | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7b346414..fb6b9d5ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -99,6 +99,7 @@ Bug #5038: Enchanting success chance calculations are blatantly wrong Bug #5047: # in cell names sets color Bug #5050: Invalid spell effects are not handled gracefully + Bug #5056: Calling Cast function on player doesn't equip the spell but casts it Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index d74893a0f..65c684fc5 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -1096,21 +1096,29 @@ namespace MWScript std::string targetId = ::Misc::StringUtils::lowerCase(runtime.getStringLiteral (runtime[0].mInteger)); runtime.pop(); - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get().find (spellId); + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get().search(spellId); if (!spell) { - runtime.getContext().report("spellcasting failed: can not find spell \""+spellId+"\""); + runtime.getContext().report("spellcasting failed: cannot find spell \""+spellId+"\""); return; } if (spell->mData.mType != ESM::Spell::ST_Spell && spell->mData.mType != ESM::Spell::ST_Power) { - runtime.getContext().report("spellcasting failed: you can cast only spells and powers."); + runtime.getContext().report("spellcasting failed: you can only cast spells and powers."); return; } - // Obviously we can not use casting animation for player here - if (ptr.getClass().isActor() && ptr != MWMechanics::getPlayer()) + if (ptr == MWMechanics::getPlayer()) + { + MWWorld::InventoryStore& store = ptr.getClass().getInventoryStore(ptr); + store.setSelectedEnchantItem(store.end()); + MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, ptr))); + MWBase::Environment::get().getWindowManager()->updateSpellWindow(); + return; + } + + if (ptr.getClass().isActor()) { MWMechanics::AiCast castPackage(targetId, spellId, true); ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(castPackage, ptr); From 7c8360d0f32f14c93fc8343a1c0f01ebedf5fb4c Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sun, 9 Jun 2019 01:58:02 +0300 Subject: [PATCH 12/62] Use NiSwitchNode initial index field --- components/nif/node.hpp | 4 +++- components/nifosg/nifloader.cpp | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/nif/node.hpp b/components/nif/node.hpp index d9afbbed7..cc1871d83 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -238,10 +238,12 @@ struct NiRotatingParticles : Node // A node used as the base to switch between child nodes, such as for LOD levels. struct NiSwitchNode : public NiNode { + unsigned int initialIndex; + void read(NIFStream *nif) { NiNode::read(nif); - nif->getInt(); // unknown + initialIndex = nif->getUInt(); } }; diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index d6a459b1b..9945eefb2 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -629,10 +629,8 @@ namespace NifOsg if (nifNode->recType == Nif::RC_NiSwitchNode) { - // show only first child by default - node->asSwitch()->setSingleChildOn(0); - const Nif::NiSwitchNode* niSwitchNode = static_cast(nifNode); + node->asSwitch()->setSingleChildOn(niSwitchNode->initialIndex); if (niSwitchNode->name == Constants::NightDayLabel && !SceneUtil::hasUserDescription(rootNode, Constants::NightDayLabel)) rootNode->getOrCreateUserDataContainer()->addDescription(Constants::NightDayLabel); else if (niSwitchNode->name == Constants::HerbalismLabel && !SceneUtil::hasUserDescription(rootNode, Constants::HerbalismLabel)) From 56539fee4fa0203f2ede8251d6fc2bd413346096 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sun, 9 Jun 2019 02:08:09 +0300 Subject: [PATCH 13/62] Partially revert "Get rid of redundant setKeyFocusWidget() method" --- apps/openmw/mwbase/windowmanager.hpp | 3 +++ apps/openmw/mwgui/alchemywindow.cpp | 3 +-- apps/openmw/mwgui/birth.cpp | 3 +-- apps/openmw/mwgui/bookwindow.cpp | 6 +++--- apps/openmw/mwgui/class.cpp | 7 +++---- apps/openmw/mwgui/confirmationdialog.cpp | 3 +-- apps/openmw/mwgui/console.cpp | 5 ++--- apps/openmw/mwgui/container.cpp | 6 +++--- apps/openmw/mwgui/countdialog.cpp | 3 +-- apps/openmw/mwgui/dialogue.cpp | 7 +++---- apps/openmw/mwgui/enchantingdialog.cpp | 3 +-- apps/openmw/mwgui/journalwindow.cpp | 6 +++--- apps/openmw/mwgui/keyboardnavigation.cpp | 12 ++++++------ apps/openmw/mwgui/mainmenu.cpp | 7 +++---- apps/openmw/mwgui/mapwindow.cpp | 2 +- apps/openmw/mwgui/race.cpp | 3 +-- apps/openmw/mwgui/savegamedialog.cpp | 12 ++++++------ apps/openmw/mwgui/scrollwindow.cpp | 3 +-- apps/openmw/mwgui/settingswindow.cpp | 3 +-- apps/openmw/mwgui/spellcreationdialog.cpp | 3 +-- apps/openmw/mwgui/spellwindow.cpp | 2 +- apps/openmw/mwgui/textinput.cpp | 7 +++---- apps/openmw/mwgui/tradewindow.cpp | 2 +- apps/openmw/mwgui/waitdialog.cpp | 6 +++--- apps/openmw/mwgui/windowmanagerimp.cpp | 13 ++++++++++--- apps/openmw/mwgui/windowmanagerimp.hpp | 3 +++ 26 files changed, 66 insertions(+), 67 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index bbf7a21c4..e8ae61fe5 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -289,6 +289,9 @@ namespace MWBase virtual const Translation::Storage& getTranslationDataStorage() const = 0; + /// Warning: do not use MyGUI::InputManager::setKeyFocusWidget directly. Instead use this. + virtual void setKeyFocusWidget (MyGUI::Widget* widget) = 0; + virtual void loadUserFonts() = 0; virtual Loading::Listener* getLoadingScreen() = 0; diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index c1bdd023f..ad66735bf 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -169,7 +168,7 @@ namespace MWGui update(); - MyGUI::InputManager::getInstance().setKeyFocusWidget(mNameEdit); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mNameEdit); } void AlchemyWindow::onIngredientSelected(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/birth.cpp b/apps/openmw/mwgui/birth.cpp index 8955606d2..6f6a621ad 100644 --- a/apps/openmw/mwgui/birth.cpp +++ b/apps/openmw/mwgui/birth.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -72,7 +71,7 @@ namespace MWGui WindowModal::onOpen(); updateBirths(); updateSpells(); - MyGUI::InputManager::getInstance().setKeyFocusWidget(mBirthList); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mBirthList); // Show the current birthsign by default const std::string &signId = diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index e4cf254e2..86089051d 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -101,7 +101,7 @@ namespace MWGui setTakeButtonShow(showTakeButton); - MyGUI::InputManager::getInstance().setKeyFocusWidget(mCloseButton); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton); } void BookWindow::setTakeButtonShow(bool show) @@ -161,9 +161,9 @@ namespace MWGui mPrevPageButton->setVisible(prevPageVisible); if (focus == mNextPageButton && !nextPageVisible && prevPageVisible) - MyGUI::InputManager::getInstance().setKeyFocusWidget(mPrevPageButton); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mPrevPageButton); else if (focus == mPrevPageButton && !prevPageVisible && nextPageVisible) - MyGUI::InputManager::getInstance().setKeyFocusWidget(mNextPageButton); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mNextPageButton); if (mPages.empty()) return; diff --git a/apps/openmw/mwgui/class.cpp b/apps/openmw/mwgui/class.cpp index 94c493be7..a92ad934c 100644 --- a/apps/openmw/mwgui/class.cpp +++ b/apps/openmw/mwgui/class.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -136,7 +135,7 @@ namespace MWGui WindowModal::onOpen (); updateClasses(); updateStats(); - MyGUI::InputManager::getInstance().setKeyFocusWidget(mClassList); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mClassList); // Show the current class by default MWWorld::Ptr player = MWMechanics::getPlayer(); @@ -437,7 +436,7 @@ namespace MWGui getWidget(mEditName, "EditName"); // Make sure the edit box has focus - MyGUI::InputManager::getInstance().setKeyFocusWidget(mEditName); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mEditName); MyGUI::Button* descriptionButton; getWidget(descriptionButton, "DescriptionButton"); @@ -903,7 +902,7 @@ namespace MWGui okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sInputMenu1", "")); // Make sure the edit box has focus - MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTextEdit); } DescriptionDialog::~DescriptionDialog() diff --git a/apps/openmw/mwgui/confirmationdialog.cpp b/apps/openmw/mwgui/confirmationdialog.cpp index c5a50c2e6..65b079d85 100644 --- a/apps/openmw/mwgui/confirmationdialog.cpp +++ b/apps/openmw/mwgui/confirmationdialog.cpp @@ -2,7 +2,6 @@ #include #include -#include #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" @@ -34,7 +33,7 @@ namespace MWGui mMessage->setSize(mMessage->getWidth(), mMessage->getTextSize().height + 24); - MyGUI::InputManager::getInstance().setKeyFocusWidget(mOkButton); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mOkButton); center(); } diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 705e28138..1633b92db 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -1,7 +1,6 @@ #include "console.hpp" #include -#include #include #include @@ -153,7 +152,7 @@ namespace MWGui { // Give keyboard focus to the combo box whenever the console is // turned on and place it over other widgets - MyGUI::InputManager::getInstance().setKeyFocusWidget(mCommandLine); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCommandLine); MyGUI::LayerManager::getInstance().upLayerItem(mMainWidget); } @@ -450,7 +449,7 @@ namespace MWGui mPtr = object; } // User clicked on an object. Restore focus to the console command line. - MyGUI::InputManager::getInstance().setKeyFocusWidget(mCommandLine); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCommandLine); } else { diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 5aa5d0143..bfe93f6ed 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -141,7 +141,7 @@ namespace MWGui mItemView->setModel (mSortModel); mItemView->resetScrollBars(); - MyGUI::InputManager::getInstance().setKeyFocusWidget(mCloseButton); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton); setTitle(container.getClass().getName(container)); } @@ -175,7 +175,7 @@ namespace MWGui if(mDragAndDrop != nullptr && mDragAndDrop->mIsOnDragAndDrop) return; - MyGUI::InputManager::getInstance().setKeyFocusWidget(mCloseButton); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton); // transfer everything into the player's inventory ItemModel* playerModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getModel(); @@ -222,7 +222,7 @@ namespace MWGui { if(mDragAndDrop == nullptr || !mDragAndDrop->mIsOnDragAndDrop) { - MyGUI::InputManager::getInstance().setKeyFocusWidget(mCloseButton); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton); onTakeAllButtonClicked(mTakeButton); diff --git a/apps/openmw/mwgui/countdialog.cpp b/apps/openmw/mwgui/countdialog.cpp index 30ef50759..baf3a43ab 100644 --- a/apps/openmw/mwgui/countdialog.cpp +++ b/apps/openmw/mwgui/countdialog.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include @@ -48,7 +47,7 @@ namespace MWGui mMainWidget->getHeight()); // by default, the text edit field has the focus of the keyboard - MyGUI::InputManager::getInstance().setKeyFocusWidget(mItemEdit); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mItemEdit); mSlider->setScrollPosition(maxCount-1); diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 4c9e6b230..6b400c172 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include @@ -381,7 +380,7 @@ namespace MWGui { onTopicActivated(topic); if (mGoodbyeButton->getEnabled()) - MyGUI::InputManager::getInstance().setKeyFocusWidget(mGoodbyeButton); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mGoodbyeButton); } else if (topic == sPersuasion) mPersuasionDialog.setVisible(true); @@ -444,7 +443,7 @@ namespace MWGui return; } - MyGUI::InputManager::getInstance().setKeyFocusWidget(mGoodbyeButton); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mGoodbyeButton); setTitle(mPtr.getClass().getName(mPtr)); @@ -623,7 +622,7 @@ namespace MWGui bool goodbyeWasEnabled = mGoodbyeButton->getEnabled(); mGoodbyeButton->setEnabled(goodbyeEnabled); if (goodbyeEnabled && !goodbyeWasEnabled) - MyGUI::InputManager::getInstance().setKeyFocusWidget(mGoodbyeButton); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mGoodbyeButton); bool topicsEnabled = !MWBase::Environment::get().getDialogueManager()->isInChoice() && !mGoodbye; mTopicsList->setEnabled(topicsEnabled); diff --git a/apps/openmw/mwgui/enchantingdialog.cpp b/apps/openmw/mwgui/enchantingdialog.cpp index 41f82bd2f..d0d2118c6 100644 --- a/apps/openmw/mwgui/enchantingdialog.cpp +++ b/apps/openmw/mwgui/enchantingdialog.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include @@ -68,7 +67,7 @@ namespace MWGui void EnchantingDialog::onOpen() { center(); - MyGUI::InputManager::getInstance().setKeyFocusWidget(mName); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mName); } void EnchantingDialog::setSoulGem(const MWWorld::Ptr &gem) diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 34c0fa8e1..43e7edf1e 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -254,7 +254,7 @@ namespace } updateShowingPages(); - MyGUI::InputManager::getInstance().setKeyFocusWidget(getWidget(CloseBTN)); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(getWidget(CloseBTN)); } void onClose() @@ -377,9 +377,9 @@ namespace prevPageBtn->setVisible(prevPageVisible); if (focus == nextPageBtn && !nextPageVisible && prevPageVisible) - MyGUI::InputManager::getInstance().setKeyFocusWidget(prevPageBtn); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(prevPageBtn); else if (focus == prevPageBtn && !prevPageVisible && nextPageVisible) - MyGUI::InputManager::getInstance().setKeyFocusWidget(nextPageBtn); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(nextPageBtn); setVisible (PageOneNum, relPages > 0); setVisible (PageTwoNum, relPages > 1); diff --git a/apps/openmw/mwgui/keyboardnavigation.cpp b/apps/openmw/mwgui/keyboardnavigation.cpp index 79b9e8457..7355dc1f4 100644 --- a/apps/openmw/mwgui/keyboardnavigation.cpp +++ b/apps/openmw/mwgui/keyboardnavigation.cpp @@ -83,7 +83,7 @@ void KeyboardNavigation::restoreFocus(int mode) { MyGUI::Widget* w = found->second; if (w && w->getVisible() && w->getEnabled()) - MyGUI::InputManager::getInstance().setKeyFocusWidget(found->second); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(found->second); } } @@ -130,7 +130,7 @@ void KeyboardNavigation::onFrame() // workaround incorrect key focus resets (fix in MyGUI TBD) if (!shouldAcceptKeyFocus(focus) && shouldAcceptKeyFocus(mCurrentFocus) && (!mModalWindow || isRootParent(mCurrentFocus, mModalWindow))) { - MyGUI::InputManager::getInstance().setKeyFocusWidget(mCurrentFocus); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCurrentFocus); focus = mCurrentFocus; } @@ -154,12 +154,12 @@ void KeyboardNavigation::setDefaultFocus(MyGUI::Widget *window, MyGUI::Widget *d MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget(); if (!focus || !shouldAcceptKeyFocus(focus)) { - MyGUI::InputManager::getInstance().setKeyFocusWidget(defaultFocus); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(defaultFocus); } else { if (!isRootParent(focus, window)) - MyGUI::InputManager::getInstance().setKeyFocusWidget(defaultFocus); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(defaultFocus); } } @@ -276,7 +276,7 @@ bool KeyboardNavigation::switchFocus(int direction, bool wrap) else if (direction == D_Up && (vertdiff >= 0 || !isVertical)) return false; - MyGUI::InputManager::getInstance().setKeyFocusWidget(keyFocusList[index]); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(keyFocusList[index]); return true; } @@ -291,7 +291,7 @@ bool KeyboardNavigation::selectFirstWidget() if (!keyFocusList.empty()) { - MyGUI::InputManager::getInstance().setKeyFocusWidget(keyFocusList[0]); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(keyFocusList[0]); return true; } return false; diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index 782162d32..4778ee7b0 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include @@ -68,12 +67,12 @@ namespace MWGui if (isMainMenu) { if (mButtons["loadgame"]->getVisible()) - MyGUI::InputManager::getInstance().setKeyFocusWidget(mButtons["loadgame"]); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mButtons["loadgame"]); else - MyGUI::InputManager::getInstance().setKeyFocusWidget(mButtons["newgame"]); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mButtons["newgame"]); } else - MyGUI::InputManager::getInstance().setKeyFocusWidget(mButtons["return"]); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mButtons["return"]); } Layout::setVisible (visible); diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 7d622ab54..02d2be577 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -1123,7 +1123,7 @@ namespace MWGui { WindowModal::onOpen(); center(); - MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTextEdit); } void EditNoteDialog::onCancelButtonClicked(MyGUI::Widget *sender) diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index 9d3e1e0a9..cf69ecca3 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include @@ -166,7 +165,7 @@ namespace MWGui mHeadRotate->setScrollPosition(initialPos); onHeadRotate(mHeadRotate, initialPos); - MyGUI::InputManager::getInstance().setKeyFocusWidget(mRaceList); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mRaceList); } void RaceDialog::setRaceId(const std::string &raceId) diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 903fdf69d..e9fb2a964 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -94,7 +94,7 @@ namespace MWGui MWBase::Environment::get().getStateManager()->deleteGame (mCurrentCharacter, mCurrentSlot); mSaveList->removeItemAt(mSaveList->getIndexSelected()); onSlotSelected(mSaveList, mSaveList->getIndexSelected()); - MyGUI::InputManager::getInstance().setKeyFocusWidget(mSaveList); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mSaveList); if (mSaveList->getItemCount() == 0) { @@ -114,7 +114,7 @@ namespace MWGui void SaveGameDialog::onDeleteSlotCancel() { - MyGUI::InputManager::getInstance().setKeyFocusWidget(mSaveList); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mSaveList); } void SaveGameDialog::onSaveNameChanged(MyGUI::EditBox *sender) @@ -138,9 +138,9 @@ namespace MWGui mSaveNameEdit->setCaption (""); if (mSaving) - MyGUI::InputManager::getInstance().setKeyFocusWidget(mSaveNameEdit); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mSaveNameEdit); else - MyGUI::InputManager::getInstance().setKeyFocusWidget(mSaveList); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mSaveList); center(); @@ -244,7 +244,7 @@ namespace MWGui void SaveGameDialog::onConfirmationCancel() { - MyGUI::InputManager::getInstance().setKeyFocusWidget(mSaveList); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mSaveList); } void SaveGameDialog::accept(bool reallySure) @@ -331,7 +331,7 @@ namespace MWGui void SaveGameDialog::onCharacterAccept(MyGUI::ComboBox* sender, size_t pos) { // Give key focus to save list so we can confirm the selection with Enter - MyGUI::InputManager::getInstance().setKeyFocusWidget(mSaveList); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mSaveList); } void SaveGameDialog::fillSaveList() diff --git a/apps/openmw/mwgui/scrollwindow.cpp b/apps/openmw/mwgui/scrollwindow.cpp index adbbaba15..f2c967da4 100644 --- a/apps/openmw/mwgui/scrollwindow.cpp +++ b/apps/openmw/mwgui/scrollwindow.cpp @@ -1,7 +1,6 @@ #include "scrollwindow.hpp" #include -#include #include #include @@ -67,7 +66,7 @@ namespace MWGui setTakeButtonShow(showTakeButton); - MyGUI::InputManager::getInstance().setKeyFocusWidget(mCloseButton); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton); } void ScrollWindow::onKeyButtonPressed(MyGUI::Widget *sender, MyGUI::KeyCode key, MyGUI::Char character) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 1cdc67f6a..dc89e6134 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include @@ -616,7 +615,7 @@ namespace MWGui highlightCurrentResolution(); updateControlsBox(); resetScrollbars(); - MyGUI::InputManager::getInstance().setKeyFocusWidget(mOkButton); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mOkButton); } void SettingsWindow::onWindowResize(MyGUI::Window *_sender) diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index 03e6c77f8..23f24e321 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #include @@ -432,7 +431,7 @@ namespace MWGui void SpellCreationDialog::onOpen() { center(); - MyGUI::InputManager::getInstance().setKeyFocusWidget(mNameEdit); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mNameEdit); } void SpellCreationDialog::onReferenceUnavailable () diff --git a/apps/openmw/mwgui/spellwindow.cpp b/apps/openmw/mwgui/spellwindow.cpp index 3f39bd11d..d0be05dfb 100644 --- a/apps/openmw/mwgui/spellwindow.cpp +++ b/apps/openmw/mwgui/spellwindow.cpp @@ -83,7 +83,7 @@ namespace MWGui // Reset the filter focus when opening the window MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget(); if (focus == mFilterEdit) - MyGUI::InputManager::getInstance().resetKeyFocusWidget(); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(nullptr); updateSpells(); } diff --git a/apps/openmw/mwgui/textinput.cpp b/apps/openmw/mwgui/textinput.cpp index 4cc7a576b..54f2d3be9 100644 --- a/apps/openmw/mwgui/textinput.cpp +++ b/apps/openmw/mwgui/textinput.cpp @@ -5,7 +5,6 @@ #include #include -#include namespace MWGui { @@ -24,7 +23,7 @@ namespace MWGui okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TextInputDialog::onOkClicked); // Make sure the edit box has focus - MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTextEdit); } void TextInputDialog::setNextButtonShow(bool shown) @@ -47,7 +46,7 @@ namespace MWGui { WindowModal::onOpen(); // Make sure the edit box has focus - MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTextEdit); } // widget controls @@ -57,7 +56,7 @@ namespace MWGui if (mTextEdit->getCaption() == "") { MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage37}"); - MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget (mTextEdit); } else eventDone(this); diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 83096140e..0c9b31b65 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -136,7 +136,7 @@ namespace MWGui onFilterChanged(mFilterAll); - MyGUI::InputManager::getInstance().setKeyFocusWidget(mTotalBalance); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTotalBalance); } void TradeWindow::onFrame(float dt) diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index eb36e3cb2..d18eaebdd 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -93,9 +93,9 @@ namespace MWGui } if (mUntilHealedButton->getVisible()) - MyGUI::InputManager::getInstance().setKeyFocusWidget(mUntilHealedButton); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mUntilHealedButton); else - MyGUI::InputManager::getInstance().setKeyFocusWidget(mWaitButton); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mWaitButton); } bool WaitDialog::exit() @@ -222,7 +222,7 @@ namespace MWGui { mHourText->setCaptionWithReplacing (MyGUI::utility::toString(position+1) + " #{sRestMenu2}"); mManualHours = position+1; - MyGUI::InputManager::getInstance().setKeyFocusWidget(mWaitButton); + MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mWaitButton); } void WaitDialog::onKeyButtonPressed(MyGUI::Widget *sender, MyGUI::KeyCode key, MyGUI::Char character) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index ffcf1323d..4a17dea7b 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -697,7 +697,7 @@ namespace MWGui setCursorVisible(!gameMode); if (gameMode) - MyGUI::InputManager::getInstance().resetKeyFocusWidget(); + setKeyFocusWidget (nullptr); // Icons of forced hidden windows are displayed setMinimapVisibility((mAllowed & GW_Map) && (!mMap->pinned() || (mForceHidden & GW_Map))); @@ -1675,6 +1675,13 @@ namespace MWGui } } + // Remove this wrapper once onKeyFocusChanged call is rendered unnecessary + void WindowManager::setKeyFocusWidget(MyGUI::Widget *widget) + { + MyGUI::InputManager::getInstance().setKeyFocusWidget(widget); + onKeyFocusChanged(widget); + } + void WindowManager::onKeyFocusChanged(MyGUI::Widget *widget) { if (widget && widget->castType(false)) @@ -1868,7 +1875,7 @@ namespace MWGui sizeVideo(screenSize.width, screenSize.height); MyGUI::Widget* oldKeyFocus = MyGUI::InputManager::getInstance().getKeyFocusWidget(); - MyGUI::InputManager::getInstance().setKeyFocusWidget(mVideoWidget); + setKeyFocusWidget(mVideoWidget); mVideoBackground->setVisible(true); @@ -1906,7 +1913,7 @@ namespace MWGui MWBase::Environment::get().getSoundManager()->resumeSounds(); - MyGUI::InputManager::getInstance().setKeyFocusWidget(oldKeyFocus); + setKeyFocusWidget(oldKeyFocus); setCursorVisible(cursorWasVisible); diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 91c61a1e9..e7fc8109d 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -147,6 +147,9 @@ namespace MWGui /// (and will continually update the window while doing so) virtual void playVideo(const std::string& name, bool allowSkipping); + /// Warning: do not use MyGUI::InputManager::setKeyFocusWidget directly. Instead use this. + virtual void setKeyFocusWidget (MyGUI::Widget* widget); + virtual void setNewGame(bool newgame); virtual void pushGuiMode(GuiMode mode, const MWWorld::Ptr& arg); From 6622e36226cd9fe349fcf696fd1f77a909bf52d0 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sun, 9 Jun 2019 11:47:43 +0300 Subject: [PATCH 14/62] Only merge pure osg::Groups in the optimizer --- components/sceneutil/optimizer.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/components/sceneutil/optimizer.cpp b/components/sceneutil/optimizer.cpp index 7c568ff9d..e8ebed868 100644 --- a/components/sceneutil/optimizer.cpp +++ b/components/sceneutil/optimizer.cpp @@ -1802,12 +1802,11 @@ bool Optimizer::MergeGeometryVisitor::mergePrimitive(osg::DrawElementsUInt& lhs, bool Optimizer::MergeGroupsVisitor::isOperationPermissible(osg::Group& node) { - return !node.asSwitch() && - !node.asTransform() && - !node.getCullCallback() && + return !node.getCullCallback() && !node.getEventCallback() && !node.getUpdateCallback() && - isOperationPermissibleForObject(&node); + isOperationPermissibleForObject(&node) && + typeid(node)==typeid(osg::Group); } void Optimizer::MergeGroupsVisitor::apply(osg::LOD &lod) From 347b1e58a1c318443420ccfdc0e983e169c2374f Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Mon, 10 Jun 2019 08:35:41 +0400 Subject: [PATCH 15/62] Add a changelog entry about cell transitions --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7b346414..b25612508 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -134,6 +134,7 @@ Feature #5051: Provide a separate textures for scrollbars Task #4686: Upgrade media decoder to a more current FFmpeg API Task #4695: Optimize Distant Terrain memory consumption + Task #4789: Optimize cell transitions Task #4721: Add NMake support to the Windows prebuild script 0.45.0 From 19b0b056e500d5291749f7dcf0646d3c6efc5ea2 Mon Sep 17 00:00:00 2001 From: Alexander Perepechko Date: Thu, 13 Jun 2019 21:42:25 +0000 Subject: [PATCH 16/62] Remove spell FX and VFX after playing the death animation (bug #5060) --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/actors.cpp | 10 +++++----- apps/openmw/mwmechanics/character.cpp | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ab11f95a..a4881cf43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -102,6 +102,7 @@ Bug #5047: # in cell names sets color Bug #5050: Invalid spell effects are not handled gracefully Bug #5056: Calling Cast function on player doesn't equip the spell but casts it + Bug #5060: Magic effect visuals stop when death animation begins instead of when it ends Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 0317e7dde..5cca894e6 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -551,7 +551,7 @@ namespace MWMechanics void Actors::adjustMagicEffects (const MWWorld::Ptr& creature) { CreatureStats& creatureStats = creature.getClass().getCreatureStats (creature); - if (creatureStats.isDead()) + if (creatureStats.isDeathAnimationFinished()) return; MagicEffects now = creatureStats.getSpells().getMagicEffects(); @@ -1665,10 +1665,6 @@ namespace MWMechanics stats.getActiveSpells().visitEffectSources(soulTrap); } - // Reset magic effects and recalculate derived effects - // One case where we need this is to make sure bound items are removed upon death - stats.modifyMagicEffects(MWMechanics::MagicEffects()); - stats.getActiveSpells().clear(); calculateCreatureStatModifiers(iter->first, 0); if (cls.isEssential(iter->first)) @@ -1680,6 +1676,10 @@ namespace MWMechanics ++mDeathCount[Misc::StringUtils::lowerCase(iter->first.getCellRef().getRefId())]; + // Reset magic effects and recalculate derived effects + // One case where we need this is to make sure bound items are removed upon death + stats.modifyMagicEffects(MWMechanics::MagicEffects()); + stats.getActiveSpells().clear(); // Make sure spell effects are removed purgeSpellEffects(stats.getActorId()); diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index c3eadff59..65013eee9 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -2648,7 +2648,7 @@ void CharacterController::updateContinuousVfx() for (std::vector::iterator it = effects.begin(); it != effects.end(); ++it) { - if (mPtr.getClass().getCreatureStats(mPtr).isDead() + if (mPtr.getClass().getCreatureStats(mPtr).isDeathAnimationFinished() || mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(MWMechanics::EffectKey(*it)).getMagnitude() <= 0) mAnimation->removeEffect(*it); } From 698c90b3ee01bb4e8be7f8ac72ce2029bb681dae Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 16 Jun 2019 14:41:34 +0200 Subject: [PATCH 17/62] fix builds against MyGUI master --- components/esm/custommarkerstate.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esm/custommarkerstate.hpp b/components/esm/custommarkerstate.hpp index fc9286bfe..2be43c53b 100644 --- a/components/esm/custommarkerstate.hpp +++ b/components/esm/custommarkerstate.hpp @@ -16,7 +16,7 @@ struct CustomMarker std::string mNote; - bool operator == (const CustomMarker& other) + bool operator == (const CustomMarker& other) const { return mNote == other.mNote && mCell == other.mCell && mWorldX == other.mWorldX && mWorldY == other.mWorldY; } From 3aa65273c538f8eb146586bff3c1cf4c0bfdbc80 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Tue, 18 Jun 2019 14:47:10 +0300 Subject: [PATCH 18/62] Signedness fixes --- apps/openmw/mwworld/esmstore.cpp | 4 ++-- components/esm/loadclot.hpp | 2 +- components/esm/loadweap.hpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 56b46d856..833353174 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -169,8 +169,8 @@ void ESMStore::validate() if (!fact) { Log(Debug::Verbose) << "NPC '" << npc.mId << "' (" << npc.mName << ") has nonexistent faction '" << npc.mFaction << "', ignoring it."; - npc.mFaction = ""; - npc.mNpdt.mRank = -1; + npc.mFaction.clear(); + npc.mNpdt.mRank = 0; changed = true; } } diff --git a/components/esm/loadclot.hpp b/components/esm/loadclot.hpp index a9ea3e70a..4db791c0c 100644 --- a/components/esm/loadclot.hpp +++ b/components/esm/loadclot.hpp @@ -40,7 +40,7 @@ struct Clothing int mType; float mWeight; unsigned short mValue; - short mEnchant; + unsigned short mEnchant; }; CTDTstruct mData; diff --git a/components/esm/loadweap.hpp b/components/esm/loadweap.hpp index 8b48b71b7..dfe2b695a 100644 --- a/components/esm/loadweap.hpp +++ b/components/esm/loadweap.hpp @@ -59,7 +59,7 @@ struct Weapon short mType; unsigned short mHealth; float mSpeed, mReach; - short mEnchant; // Enchantment points. The real value is mEnchant/10.f + unsigned short mEnchant; // Enchantment points. The real value is mEnchant/10.f unsigned char mChop[2], mSlash[2], mThrust[2]; // Min and max int mFlags; }; // 32 bytes From f984f61055c0fbe77250a1759d3af5c4068c70d7 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Thu, 20 Jun 2019 14:18:12 +0300 Subject: [PATCH 19/62] Ignore any fourth AITravel argument for now --- components/compiler/extensions0.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index e66f051d7..5b60f9d6d 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -33,7 +33,7 @@ namespace Compiler { extensions.registerInstruction ("aiactivate", "c/l", opcodeAIActivate, opcodeAIActivateExplicit); - extensions.registerInstruction ("aitravel", "fff/lx", opcodeAiTravel, + extensions.registerInstruction ("aitravel", "fff/zx", opcodeAiTravel, opcodeAiTravelExplicit); extensions.registerInstruction ("aiescort", "cffff/l", opcodeAiEscort, opcodeAiEscortExplicit); From df89c6b6ce6399c408ccf5538944bee5c34a6338 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Thu, 20 Jun 2019 20:45:52 +0300 Subject: [PATCH 20/62] Make unarmed creature attacks affect shield condition again (bug #5069) --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/combat.cpp | 15 ++++++--------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4881cf43..f1e2614e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -103,6 +103,7 @@ Bug #5050: Invalid spell effects are not handled gracefully Bug #5056: Calling Cast function on player doesn't equip the spell but casts it Bug #5060: Magic effect visuals stop when death animation begins instead of when it ends + Bug #5069: Blocking creatures' attacks doesn't degrade shields Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index da62f6c08..68c94b9ee 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -115,16 +115,13 @@ namespace MWMechanics if (Misc::Rng::roll0to99() < x) { - if (!(weapon.isEmpty() && !attacker.getClass().isNpc())) // Unarmed creature attacks don't affect armor condition - { - // Reduce shield durability by incoming damage - int shieldhealth = shield->getClass().getItemHealth(*shield); + // Reduce shield durability by incoming damage + int shieldhealth = shield->getClass().getItemHealth(*shield); - shieldhealth -= std::min(shieldhealth, int(damage)); - shield->getCellRef().setCharge(shieldhealth); - if (shieldhealth == 0) - inv.unequipItem(*shield, blocker); - } + shieldhealth -= std::min(shieldhealth, int(damage)); + shield->getCellRef().setCharge(shieldhealth); + if (shieldhealth == 0) + inv.unequipItem(*shield, blocker); // Reduce blocker fatigue const float fFatigueBlockBase = gmst.find("fFatigueBlockBase")->mValue.getFloat(); const float fFatigueBlockMult = gmst.find("fFatigueBlockMult")->mValue.getFloat(); From d9439389e6005e439480a7088a96a5131042ec7b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 21 Jun 2019 21:37:38 +0200 Subject: [PATCH 21/62] fix #4665 --- files/mygui/openmw_list.skin.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/files/mygui/openmw_list.skin.xml b/files/mygui/openmw_list.skin.xml index ccaeb0319..db2c722d7 100644 --- a/files/mygui/openmw_list.skin.xml +++ b/files/mygui/openmw_list.skin.xml @@ -19,6 +19,11 @@ + + + + + @@ -27,11 +32,6 @@ - - - - - @@ -61,6 +61,11 @@ + + + + + @@ -69,11 +74,6 @@ - - - - - From e06178bf0f3cdbbfb55a46f10b0522cf19aa1920 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sat, 15 Jun 2019 14:30:42 +0300 Subject: [PATCH 22/62] Make sure shadow shapes aren't visible (bug #5063) --- CHANGELOG.md | 1 + components/nifosg/nifloader.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1e2614e6..4770d0a24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -103,6 +103,7 @@ Bug #5050: Invalid spell effects are not handled gracefully Bug #5056: Calling Cast function on player doesn't equip the spell but casts it Bug #5060: Magic effect visuals stop when death animation begins instead of when it ends + Bug #5063: Shape named "Tri Shadow" in creature mesh is visible if it isn't hidden Bug #5069: Blocking creatures' attacks doesn't degrade shields Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 9945eefb2..7105147e6 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -585,8 +585,11 @@ namespace NifOsg { const Nif::NiTriShape* triShape = static_cast(nifNode); const std::string nodeName = Misc::StringUtils::lowerCase(triShape->name); - static const std::string pattern = "tri editormarker"; - if (!hasMarkers || nodeName.compare(0, pattern.size(), pattern) != 0) + static const std::string markerName = "tri editormarker"; + static const std::string shadowName = "shadow"; + static const std::string shadowName2 = "tri shadow"; + const bool isMarker = hasMarkers && !nodeName.compare(0, markerName.size(), markerName); + if (!isMarker && nodeName.compare(0, shadowName.size(), shadowName) && nodeName.compare(0, shadowName2.size(), shadowName2)) { if (triShape->skin.empty()) handleTriShape(triShape, node, composite, boundTextures, animflags); From 49c691d00a06c20cf81854ee30683369334e424f Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Thu, 30 May 2019 07:10:46 +0300 Subject: [PATCH 23/62] Make settings manager locale-independent again --- components/settings/settings.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/components/settings/settings.cpp b/components/settings/settings.cpp index 59e75dc76..b3701f764 100644 --- a/components/settings/settings.cpp +++ b/components/settings/settings.cpp @@ -7,6 +7,7 @@ #include #include +#include namespace Settings { @@ -354,12 +355,14 @@ float Manager::getFloat (const std::string& setting, const std::string& category const std::string value = getString(setting, category); try { - return std::stof(value); + // We have to rely on Boost because std::stof from C++11 + // uses the current locale for separators which we don't want and often silently ignores parsing errors. + return boost::lexical_cast(value); } - catch(const std::exception& e) + catch (boost::bad_lexical_cast&) { Log(Debug::Warning) << "Cannot parse setting '" << setting << "' (invalid setting value: " << value << ")."; - return 0; + return 0.f; } } @@ -401,12 +404,16 @@ void Manager::setString(const std::string &setting, const std::string &category, void Manager::setInt (const std::string& setting, const std::string& category, const int value) { - setString(setting, category, std::to_string(value)); + std::ostringstream stream; + stream << value; + setString(setting, category, stream.str()); } void Manager::setFloat (const std::string &setting, const std::string &category, const float value) { - setString(setting, category, std::to_string(value)); + std::ostringstream stream; + stream << value; + setString(setting, category, stream.str()); } void Manager::setBool(const std::string &setting, const std::string &category, const bool value) From b87b29eeb00ec5e4a6fdbae67a51e65f3256d855 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Thu, 30 May 2019 07:11:13 +0300 Subject: [PATCH 24/62] Make framerate limit configurable in the launcher --- apps/launcher/graphicspage.cpp | 28 ++++++++++++++++++++++++++++ apps/launcher/graphicspage.hpp | 1 + files/ui/graphicspage.ui | 29 +++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 56cd08680..f9d8e1e1d 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -44,6 +44,7 @@ Launcher::GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, Settings: connect(fullScreenCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotFullScreenChanged(int))); connect(standardRadioButton, SIGNAL(toggled(bool)), this, SLOT(slotStandardToggled(bool))); connect(screenComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(screenChanged(int))); + connect(framerateLimitCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotFramerateLimitToggled(bool))); } @@ -121,6 +122,17 @@ bool Launcher::GraphicsPage::loadSettings() customHeightSpinBox->setValue(height); } + float fpsLimit = mEngineSettings.getFloat("framerate limit", "Video"); + if (fpsLimit != 0) + { + framerateLimitCheckBox->setCheckState(Qt::Checked); + framerateLimitSpinBox->setValue(fpsLimit); + } + else + { + framerateLimitSpinBox->setEnabled(false); + } + return true; } @@ -166,6 +178,17 @@ void Launcher::GraphicsPage::saveSettings() int cScreen = screenComboBox->currentIndex(); if (cScreen != mEngineSettings.getInt("screen", "Video")) mEngineSettings.setInt("screen", "Video", cScreen); + + if (framerateLimitCheckBox->checkState()) + { + float cFpsLimit = framerateLimitSpinBox->value(); + if (cFpsLimit != mEngineSettings.getFloat("framerate limit", "Video")) + mEngineSettings.setFloat("framerate limit", "Video", cFpsLimit); + } + else if (mEngineSettings.getFloat("framerate limit", "Video") != 0) + { + mEngineSettings.setFloat("framerate limit", "Video", 0); + } } QStringList Launcher::GraphicsPage::getAvailableResolutions(int screen) @@ -266,3 +289,8 @@ void Launcher::GraphicsPage::slotStandardToggled(bool checked) customHeightSpinBox->setEnabled(true); } } + +void Launcher::GraphicsPage::slotFramerateLimitToggled(bool checked) +{ + framerateLimitSpinBox->setEnabled(checked); +} diff --git a/apps/launcher/graphicspage.hpp b/apps/launcher/graphicspage.hpp index 9d943d5e2..05915e680 100644 --- a/apps/launcher/graphicspage.hpp +++ b/apps/launcher/graphicspage.hpp @@ -31,6 +31,7 @@ namespace Launcher private slots: void slotFullScreenChanged(int state); void slotStandardToggled(bool checked); + void slotFramerateLimitToggled(bool checked); private: Files::ConfigurationManager &mCfgMgr; diff --git a/files/ui/graphicspage.ui b/files/ui/graphicspage.ui index 0afda6ac7..1f91fb19d 100644 --- a/files/ui/graphicspage.ui +++ b/files/ui/graphicspage.ui @@ -62,6 +62,13 @@ + + + + Framerate limit + + + @@ -143,6 +150,28 @@ + + + + FPS + + + 1 + + + 1 + + + 999 + + + 15 + + + 300 + + + From 9502e9f3f7a049ceb1aa879d6138fb47588909ca Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Thu, 30 May 2019 08:48:39 +0300 Subject: [PATCH 25/62] Disable FPS limit spinbox by default and set the maximum to 1000 Make window border and framerate limit labels consistent with other labels --- apps/launcher/graphicspage.cpp | 4 ---- files/ui/graphicspage.ui | 9 ++++++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index f9d8e1e1d..c991e79f4 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -128,10 +128,6 @@ bool Launcher::GraphicsPage::loadSettings() framerateLimitCheckBox->setCheckState(Qt::Checked); framerateLimitSpinBox->setValue(fpsLimit); } - else - { - framerateLimitSpinBox->setEnabled(false); - } return true; } diff --git a/files/ui/graphicspage.ui b/files/ui/graphicspage.ui index 1f91fb19d..eba913b91 100644 --- a/files/ui/graphicspage.ui +++ b/files/ui/graphicspage.ui @@ -34,7 +34,7 @@ - Window border + Window Border @@ -65,7 +65,7 @@ - Framerate limit + Framerate Limit: @@ -152,6 +152,9 @@ + + false + FPS @@ -162,7 +165,7 @@ 1 - 999 + 1000 15 From dfb852cbb01266b7d22beb3563a4487bf98d3271 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Mon, 3 Jun 2019 12:15:01 +0300 Subject: [PATCH 26/62] Improve Boost apologia --- components/fallback/fallback.cpp | 4 ++-- components/settings/settings.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/fallback/fallback.cpp b/components/fallback/fallback.cpp index e2060935e..d5c6c4e97 100644 --- a/components/fallback/fallback.cpp +++ b/components/fallback/fallback.cpp @@ -30,8 +30,8 @@ namespace Fallback { try { - // We have to rely on Boost because std::stof from C++11 - // uses the current locale for separators which we don't want and often silently ignores parsing errors. + // We have to rely on Boost because std::stof from C++11 uses the current locale + // for separators (which is undesired) and it often silently ignores parsing errors. return boost::lexical_cast(fallback); } catch (boost::bad_lexical_cast&) diff --git a/components/settings/settings.cpp b/components/settings/settings.cpp index b3701f764..42f65fc55 100644 --- a/components/settings/settings.cpp +++ b/components/settings/settings.cpp @@ -355,8 +355,8 @@ float Manager::getFloat (const std::string& setting, const std::string& category const std::string value = getString(setting, category); try { - // We have to rely on Boost because std::stof from C++11 - // uses the current locale for separators which we don't want and often silently ignores parsing errors. + // We have to rely on Boost because std::stof from C++11 uses the current locale + // for separators (which is undesired) and it often silently ignores parsing errors. return boost::lexical_cast(value); } catch (boost::bad_lexical_cast&) From 3cbe4ab85dbed561cd24e86bab767fda6b07c67f Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sat, 22 Jun 2019 23:05:20 +0300 Subject: [PATCH 27/62] Fix idlestorm blend mask (bugs #4240, #5071) --- apps/openmw/mwmechanics/character.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 65013eee9..03382a888 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1135,8 +1135,8 @@ void CharacterController::updateIdleStormState(bool inwater) { if (!mAnimation->isPlaying("idlestorm")) { - mAnimation->play("idlestorm", Priority_Storm, MWRender::Animation::BlendMask_RightArm, true, - 1.0f, "start", "stop", 0.0f, ~0ul); + int mask = MWRender::Animation::BlendMask_Torso | MWRender::Animation::BlendMask_RightArm; + mAnimation->play("idlestorm", Priority_Storm, mask, true, 1.0f, "start", "stop", 0.0f, ~0ul); } else { From 453068cc7d5f73cbae5f3087dbfa4b28aeea684d Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Thu, 27 Jun 2019 19:50:54 +0300 Subject: [PATCH 28/62] Disallow actors to start combat with themselves (bug #3550) Allow creatures to play initial attack dialogue Don't add combat package to dead actors --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/aicombat.cpp | 3 +++ .../mwmechanics/mechanicsmanagerimp.cpp | 21 +++++++++++++------ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4770d0a24..c9002fcb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Bug #3006: 'else if' operator breaks script compilation Bug #3109: SetPos/Position handles actors differently Bug #3282: Unintended behaviour when assigning F3 and Windows keys + Bug #3550: Companion from mod attacks the air after combat has ended Bug #3623: Display scaling breaks mouse recognition Bug #3725: Using script function in a non-conditional expression breaks script compilation Bug #3733: Normal maps are inverted on mirrored UVs diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 32b3f9f2b..78e65ce15 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -116,6 +116,9 @@ namespace MWMechanics || target.getClass().getCreatureStats(target).isDead()) return true; + if (actor == target) // This should never happen. + return true; + if (!storage.isFleeing()) { if (storage.mCurrentAction.get()) // need to wait to init action with its attack range diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 234c39aaa..23f5ea01d 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1647,18 +1647,28 @@ namespace MWMechanics void MechanicsManager::startCombat(const MWWorld::Ptr &ptr, const MWWorld::Ptr &target) { - MWMechanics::AiSequence& aiSequence = ptr.getClass().getCreatureStats(ptr).getAiSequence(); + CreatureStats& stats = ptr.getClass().getCreatureStats(ptr); - if (aiSequence.isInCombat(target)) + // Don't add duplicate packages nor add packages to dead actors. + if (stats.isDead() || stats.getAiSequence().isInCombat(target)) return; - aiSequence.stack(MWMechanics::AiCombat(target), ptr); + // The target is somehow the same as the actor. Early-out. + if (ptr == target) + { + // We don't care about dialogue filters since the target is invalid. + // We still want to play the combat taunt. + MWBase::Environment::get().getDialogueManager()->say(ptr, "attack"); + return; + } + + stats.getAiSequence().stack(MWMechanics::AiCombat(target), ptr); if (target == getPlayer()) { // if guard starts combat with player, guards pursuing player should do the same if (ptr.getClass().isClass(ptr, "Guard")) { - ptr.getClass().getCreatureStats(ptr).setHitAttemptActorId(target.getClass().getCreatureStats(target).getActorId()); // Stops guard from ending combat if player is unreachable + stats.setHitAttemptActorId(target.getClass().getCreatureStats(target).getActorId()); // Stops guard from ending combat if player is unreachable for (Actors::PtrActorMap::const_iterator iter = mActors.begin(); iter != mActors.end(); ++iter) { if (iter->first.getClass().isClass(iter->first, "Guard")) @@ -1676,8 +1686,7 @@ namespace MWMechanics } // Must be done after the target is set up, so that CreatureTargetted dialogue filter works properly - if (ptr.getClass().isNpc() && !ptr.getClass().getCreatureStats(ptr).isDead()) - MWBase::Environment::get().getDialogueManager()->say(ptr, "attack"); + MWBase::Environment::get().getDialogueManager()->say(ptr, "attack"); } void MechanicsManager::getObjectsInRange(const osg::Vec3f &position, float radius, std::vector &objects) From cbb22f0f63deac9f263cd3aebaadf34f0b244281 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Fri, 28 Jun 2019 15:52:37 +0300 Subject: [PATCH 29/62] Correct cast style behavior when there's no object (bug #5075) --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/enchanting.cpp | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4770d0a24..f55284fab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -105,6 +105,7 @@ Bug #5060: Magic effect visuals stop when death animation begins instead of when it ends Bug #5063: Shape named "Tri Shadow" in creature mesh is visible if it isn't hidden Bug #5069: Blocking creatures' attacks doesn't degrade shields + Bug #5075: Enchanting cast style can be changed if there's no object Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls diff --git a/apps/openmw/mwmechanics/enchanting.cpp b/apps/openmw/mwmechanics/enchanting.cpp index 0e7fa5ec0..20ba99825 100644 --- a/apps/openmw/mwmechanics/enchanting.cpp +++ b/apps/openmw/mwmechanics/enchanting.cpp @@ -102,10 +102,7 @@ namespace MWMechanics void Enchanting::nextCastStyle() { if (itemEmpty()) - { - mCastStyle = ESM::Enchantment::WhenUsed; return; - } const bool powerfulSoul = getGemCharge() >= \ MWBase::Environment::get().getWorld()->getStore().get().find ("iSoulAmountForConstantEffect")->mValue.getInteger(); @@ -267,6 +264,8 @@ namespace MWMechanics void Enchanting::setEnchanter(const MWWorld::Ptr& enchanter) { mEnchanter = enchanter; + // Reset cast style + mCastStyle = ESM::Enchantment::CastOnce; } int Enchanting::getEnchantChance() const From b8afe142069c05657031f139e10ee213aec4a38d Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Fri, 28 Jun 2019 16:03:18 +0300 Subject: [PATCH 30/62] Disallow paralyzed actors to greet the player (bug #5074) --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/aiwander.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0263daff..989a49acc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -106,6 +106,7 @@ Bug #5060: Magic effect visuals stop when death animation begins instead of when it ends Bug #5063: Shape named "Tri Shadow" in creature mesh is visible if it isn't hidden Bug #5069: Blocking creatures' attacks doesn't degrade shields + Bug #5074: Paralyzed actors greet the player Bug #5075: Enchanting cast style can be changed if there's no object Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index dc225ac23..d00bbeb5f 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -527,7 +527,8 @@ namespace MWMechanics if (greetingState == AiWanderStorage::Greet_None) { if ((playerPos - actorPos).length2() <= helloDistance*helloDistance && - !player.getClass().getCreatureStats(player).isDead() && MWBase::Environment::get().getWorld()->getLOS(player, actor) + !player.getClass().getCreatureStats(player).isDead() && !actor.getClass().getCreatureStats(actor).isParalyzed() + && MWBase::Environment::get().getWorld()->getLOS(player, actor) && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, actor)) greetingTimer++; From 19dc01232c0585231891c303964f3690e211a7de Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sun, 30 Jun 2019 16:03:24 +0300 Subject: [PATCH 31/62] Fix CenterOnCell target rotation --- apps/openmw/mwworld/worldimp.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 6020572bc..3426e9115 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2808,6 +2808,7 @@ namespace MWWorld /// \note Using _any_ door pointed to the interior, /// not the one pointed to current door. pos = destDoor.mRef.getDoorDest(); + pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; return true; } } @@ -2818,6 +2819,7 @@ namespace MWWorld if (!statics.empty()) { pos = statics.begin()->mRef.getPosition(); + pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; return true; } From 9dfee1dfe20918e56bfed34311556c4d889e1a6d Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sun, 30 Jun 2019 16:13:11 +0300 Subject: [PATCH 32/62] Fix invisibility/chameleon alpha (thanks Hrnchamd) --- apps/openmw/mwmechanics/character.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 03382a888..7966526f2 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -2675,14 +2675,14 @@ void CharacterController::setVisibility(float visibility) if (mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Invisibility).getModifier()) // Ignore base magnitude (see bug #3555). { if (mPtr == getPlayer()) - alpha = 0.4f; + alpha = 0.25f; else - alpha = 0.f; + alpha = 0.05f; } float chameleon = mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Chameleon).getMagnitude(); if (chameleon) { - alpha *= std::max(0.2f, (100.f - chameleon)/100.f); + alpha *= std::min(0.75f, std::max(0.25f, (100.f - chameleon)/100.f)); } visibility = std::min(visibility, alpha); From 8a6a8086da370021d1812cfc956cd082c8a41757 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 1 Jul 2019 00:07:44 +0100 Subject: [PATCH 33/62] Make in-memory buffers seekable to fix fog of war --- components/files/memorystream.hpp | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/components/files/memorystream.hpp b/components/files/memorystream.hpp index 9a3510044..b4c7b7675 100644 --- a/components/files/memorystream.hpp +++ b/components/files/memorystream.hpp @@ -9,11 +9,31 @@ namespace Files struct MemBuf : std::streambuf { MemBuf(char const* buffer, size_t size) - { // a streambuf isn't specific to istreams, so we need a non-const pointer :/ - char* nonconstBuffer = (const_cast(buffer)); - this->setg(nonconstBuffer, nonconstBuffer, nonconstBuffer + size); + : bufferStart(const_cast(buffer)) + , bufferEnd(bufferStart + size) + { + this->setg(bufferStart, bufferStart, bufferEnd); + } + + pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) override + { + if (dir == std::ios_base::cur) + gbump(off); + else + setg(bufferStart, (dir == std::ios_base::beg ? bufferStart : bufferEnd) + off, bufferEnd); + + return gptr() - bufferStart; } + + pos_type seekpos(pos_type pos, std::ios_base::openmode which) override + { + return seekoff(pos, std::ios_base::beg, which); + } + + protected: + char* bufferStart; + char* bufferEnd; }; /// @brief A variant of std::istream that reads from a constant in-memory buffer. From 49f2615d2b63d326fcb4fc0382eeb60c0689c9c0 Mon Sep 17 00:00:00 2001 From: Justin Ivany <1406666+jrivany@users.noreply.github.com> Date: Mon, 1 Jul 2019 17:32:20 -0300 Subject: [PATCH 34/62] Fix scrolling with controller on gui --- apps/openmw/mwinput/inputmanagerimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index d66cc6577..6a6ac20a8 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -560,7 +560,7 @@ namespace MWInput // game mode does not move the position of the GUI cursor float xmove = xAxis * dt * 1500.0f * mInvUiScalingFactor; float ymove = yAxis * dt * 1500.0f * mInvUiScalingFactor; - if (xmove != 0|| ymove != 0) + if (xmove != 0|| ymove != 0 || zAxis != 0) { mGuiCursorX += xmove; mGuiCursorY += ymove; From af1e5e01b43c6e5ff2728ef74f8afa08ff8ac53e Mon Sep 17 00:00:00 2001 From: Nat Meo Date: Mon, 1 Jul 2019 23:26:05 +0000 Subject: [PATCH 35/62] Issue #5005: Instance window via Scene window --- CHANGELOG.md | 1 + apps/opencs/model/prefs/state.cpp | 4 +++ apps/opencs/view/doc/view.cpp | 28 +++++++++++++++++++ apps/opencs/view/doc/view.hpp | 4 +++ apps/opencs/view/render/editmode.cpp | 2 ++ apps/opencs/view/render/editmode.hpp | 3 ++ apps/opencs/view/render/instancemode.cpp | 14 ++++++++++ apps/opencs/view/render/instancemode.hpp | 6 ++++ apps/opencs/view/render/pathgridmode.cpp | 4 +++ apps/opencs/view/render/pathgridmode.hpp | 2 ++ .../opencs/view/render/terraintexturemode.cpp | 4 +++ .../opencs/view/render/terraintexturemode.hpp | 2 ++ apps/opencs/view/render/worldspacewidget.cpp | 10 +++++++ apps/opencs/view/render/worldspacewidget.hpp | 5 ++++ apps/opencs/view/world/scenesubview.cpp | 6 ++++ apps/opencs/view/world/scenesubview.hpp | 4 +++ apps/opencs/view/world/table.cpp | 7 ++++- apps/opencs/view/world/tablesubview.cpp | 5 ++++ apps/opencs/view/world/tablesubview.hpp | 4 +++ 19 files changed, 114 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 989a49acc..795473128 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -135,6 +135,7 @@ Feature #4968: Scalable UI widget skins Feature #4994: Persistent pinnable windows hiding Feature #5000: Compressed BSA format support + Feature #5005: Editor: Instance window via Scene window Feature #5010: Native graphics herbalism support Feature #5031: Make GetWeaponType function return different values for tools Feature #5033: Magic armor mitigation for creatures diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index 9bc0e0877..a206fad6f 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -247,6 +247,9 @@ void CSMPrefs::State::declare() addValues (landeditOutsideVisibleCell); declareInt ("texturebrush-maximumsize", "Maximum texture brush size", 50). setMin (1); + declareBool ("open-list-view", "Open displays list view", false). + setTooltip ("When opening a reference from the scene view, it will open the" + " instance list view instead of the individual instance record view."); declareCategory ("Key Bindings"); @@ -331,6 +334,7 @@ void CSMPrefs::State::declare() declareShortcut ("scene-navi-primary", "Camera Rotation From Mouse Movement", QKeySequence(Qt::LeftButton)); declareShortcut ("scene-navi-secondary", "Camera Translation From Mouse Movement", QKeySequence(Qt::ControlModifier | (int)Qt::LeftButton)); + declareShortcut ("scene-open-primary", "Primary Open", QKeySequence(Qt::ShiftModifier | (int)Qt::LeftButton)); declareShortcut ("scene-edit-primary", "Primary Edit", QKeySequence(Qt::RightButton)); declareShortcut ("scene-edit-secondary", "Secondary Edit", QKeySequence(Qt::ControlModifier | (int)Qt::RightButton)); diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 42dbe51ac..343495518 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -22,6 +22,7 @@ #include "../../model/world/idtable.hpp" #include "../world/subviews.hpp" +#include "../world/scenesubview.hpp" #include "../world/tablesubview.hpp" #include "../tools/subviews.hpp" @@ -626,6 +627,20 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin connect (view, SIGNAL (updateSubViewIndices (SubView *)), this, SLOT (updateSubViewIndices (SubView *))); + CSVWorld::TableSubView* tableView = dynamic_cast(view); + if (tableView) + { + connect (this, SIGNAL (requestFocus (const std::string&)), + tableView, SLOT (requestFocus (const std::string&))); + } + + CSVWorld::SceneSubView* sceneView = dynamic_cast(view); + if (sceneView) + { + connect(sceneView, SIGNAL(requestFocus(const std::string&)), + this, SLOT(onRequestFocus(const std::string&))); + } + view->show(); if (!hint.empty()) @@ -1065,3 +1080,16 @@ void CSVDoc::View::createScrollArea() mScroll->setWidget(&mSubViewWindow); setCentralWidget(mScroll); } + +void CSVDoc::View::onRequestFocus (const std::string& id) +{ + if(CSMPrefs::get()["3D Scene Editing"]["open-list-view"].isTrue()) + { + addReferencesSubView(); + emit requestFocus(id); + } + else + { + addSubView(CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Reference, id)); + } +} diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index c4046a7a1..52057ab37 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -140,6 +140,8 @@ namespace CSVDoc void mergeDocument (CSMDoc::Document *document); + void requestFocus (const std::string& id); + public slots: void addSubView (const CSMWorld::UniversalId& id, const std::string& hint = ""); @@ -262,6 +264,8 @@ namespace CSVDoc void moveScrollBarToEnd(int min, int max); void merge(); + + void onRequestFocus (const std::string& id); }; } diff --git a/apps/opencs/view/render/editmode.cpp b/apps/opencs/view/render/editmode.cpp index 5f0852c90..03451bc1b 100644 --- a/apps/opencs/view/render/editmode.cpp +++ b/apps/opencs/view/render/editmode.cpp @@ -29,6 +29,8 @@ void CSVRender::EditMode::setEditLock (bool locked) } +void CSVRender::EditMode::primaryOpenPressed (const WorldspaceHitResult& hit) {} + void CSVRender::EditMode::primaryEditPressed (const WorldspaceHitResult& hit) {} void CSVRender::EditMode::secondaryEditPressed (const WorldspaceHitResult& hit) {} diff --git a/apps/opencs/view/render/editmode.hpp b/apps/opencs/view/render/editmode.hpp index f9b7027f9..9f3b28957 100644 --- a/apps/opencs/view/render/editmode.hpp +++ b/apps/opencs/view/render/editmode.hpp @@ -39,6 +39,9 @@ namespace CSVRender /// Default-implementation: Ignored. virtual void setEditLock (bool locked); + /// Default-implementation: Ignored. + virtual void primaryOpenPressed (const WorldspaceHitResult& hit); + /// Default-implementation: Ignored. virtual void primaryEditPressed (const WorldspaceHitResult& hit); diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp index 1cf8a5698..0cf58038d 100644 --- a/apps/opencs/view/render/instancemode.cpp +++ b/apps/opencs/view/render/instancemode.cpp @@ -94,6 +94,8 @@ CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, QWidg parent), mSubMode (0), mSubModeId ("move"), mSelectionMode (0), mDragMode (DragMode_None), mDragAxis (-1), mLocked (false), mUnitScaleDist(1) { + connect(this, SIGNAL(requestFocus(const std::string&)), + worldspaceWidget, SIGNAL(requestFocus(const std::string&))); } void CSVRender::InstanceMode::activate (CSVWidget::SceneToolbar *toolbar) @@ -174,6 +176,18 @@ void CSVRender::InstanceMode::primaryEditPressed (const WorldspaceHitResult& hit primarySelectPressed (hit); } +void CSVRender::InstanceMode::primaryOpenPressed (const WorldspaceHitResult& hit) +{ + if(hit.tag) + { + if (CSVRender::ObjectTag *objectTag = dynamic_cast (hit.tag.get())) + { + const std::string refId = objectTag->mObject->getReferenceId(); + emit requestFocus(refId); + } + } +} + void CSVRender::InstanceMode::secondaryEditPressed (const WorldspaceHitResult& hit) { if (CSMPrefs::get()["3D Scene Input"]["context-select"].isTrue()) diff --git a/apps/opencs/view/render/instancemode.hpp b/apps/opencs/view/render/instancemode.hpp index 933cae529..6ddaa254f 100644 --- a/apps/opencs/view/render/instancemode.hpp +++ b/apps/opencs/view/render/instancemode.hpp @@ -55,6 +55,8 @@ namespace CSVRender virtual void setEditLock (bool locked); + virtual void primaryOpenPressed (const WorldspaceHitResult& hit); + virtual void primaryEditPressed (const WorldspaceHitResult& hit); virtual void secondaryEditPressed (const WorldspaceHitResult& hit); @@ -83,6 +85,10 @@ namespace CSVRender virtual int getSubMode() const; + signals: + + void requestFocus (const std::string& id); + private slots: void subModeChanged (const std::string& id); diff --git a/apps/opencs/view/render/pathgridmode.cpp b/apps/opencs/view/render/pathgridmode.cpp index a9cce0200..8863ad235 100644 --- a/apps/opencs/view/render/pathgridmode.cpp +++ b/apps/opencs/view/render/pathgridmode.cpp @@ -63,6 +63,10 @@ namespace CSVRender } } + void PathgridMode::primaryOpenPressed(const WorldspaceHitResult& hitResult) + { + } + void PathgridMode::primaryEditPressed(const WorldspaceHitResult& hitResult) { if (CSMPrefs::get()["3D Scene Input"]["context-select"].isTrue() && diff --git a/apps/opencs/view/render/pathgridmode.hpp b/apps/opencs/view/render/pathgridmode.hpp index e34208f8c..a012a67e4 100644 --- a/apps/opencs/view/render/pathgridmode.hpp +++ b/apps/opencs/view/render/pathgridmode.hpp @@ -21,6 +21,8 @@ namespace CSVRender virtual void deactivate(CSVWidget::SceneToolbar* toolbar); + virtual void primaryOpenPressed(const WorldspaceHitResult& hit); + virtual void primaryEditPressed(const WorldspaceHitResult& hit); virtual void secondaryEditPressed(const WorldspaceHitResult& hit); diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 274e64742..4205188e4 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -77,6 +77,10 @@ void CSVRender::TerrainTextureMode::deactivate(CSVWidget::SceneToolbar* toolbar) EditMode::deactivate(toolbar); } +void CSVRender::TerrainTextureMode::primaryOpenPressed(const WorldspaceHitResult& hit) // Apply changes here +{ +} + void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult& hit) // Apply changes here { CSMDoc::Document& document = getWorldspaceWidget().getDocument(); diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 5184f0f73..10ea842c9 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -35,6 +35,8 @@ namespace CSVRender /// \brief Editmode for terrain texture grid TerrainTextureMode(WorldspaceWidget*, QWidget* parent = nullptr); + void primaryOpenPressed (const WorldspaceHitResult& hit); + /// \brief Create single command for one-click texture editing void primaryEditPressed (const WorldspaceHitResult& hit); diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 7e405266e..1eca61e73 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -101,6 +101,9 @@ CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidg // Shortcuts CSMPrefs::Shortcut* primaryEditShortcut = new CSMPrefs::Shortcut("scene-edit-primary", "scene-speed-modifier", CSMPrefs::Shortcut::SM_Detach, this); + CSMPrefs::Shortcut* primaryOpenShortcut = new CSMPrefs::Shortcut("scene-open-primary", this); + + connect(primaryOpenShortcut, SIGNAL(activated(bool)), this, SLOT(primaryOpen(bool))); connect(primaryEditShortcut, SIGNAL(activated(bool)), this, SLOT(primaryEdit(bool))); connect(primaryEditShortcut, SIGNAL(secondary(bool)), this, SLOT(speedMode(bool))); @@ -696,6 +699,8 @@ void CSVRender::WorldspaceWidget::handleInteractionPress (const WorldspaceHitRes editMode.primarySelectPressed (hit); else if (type == InteractionType_SecondarySelect) editMode.secondarySelectPressed (hit); + else if (type == InteractionType_PrimaryOpen) + editMode.primaryOpenPressed (hit); } CSVRender::EditMode *CSVRender::WorldspaceWidget::getEditMode() @@ -703,6 +708,11 @@ CSVRender::EditMode *CSVRender::WorldspaceWidget::getEditMode() return dynamic_cast (mEditMode->getCurrent()); } +void CSVRender::WorldspaceWidget::primaryOpen(bool activate) +{ + handleInteraction(InteractionType_PrimaryOpen, activate); +} + void CSVRender::WorldspaceWidget::primaryEdit(bool activate) { handleInteraction(InteractionType_PrimaryEdit, activate); diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 9160ca47e..06c182b0c 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -91,6 +91,7 @@ namespace CSVRender InteractionType_PrimarySelect, InteractionType_SecondaryEdit, InteractionType_SecondarySelect, + InteractionType_PrimaryOpen, InteractionType_None }; @@ -263,6 +264,8 @@ namespace CSVRender void showToolTip(); + void primaryOpen(bool activate); + void primaryEdit(bool activate); void secondaryEdit(bool activate); @@ -283,6 +286,8 @@ namespace CSVRender void dataDropped(const std::vector& data); + void requestFocus (const std::string& id); + friend class MouseState; }; } diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index 4b129d32a..44542c529 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -83,6 +83,9 @@ void CSVWorld::SceneSubView::makeConnections (CSVRender::UnpagedWorldspaceWidget connect(widget, SIGNAL(cellChanged(const CSMWorld::UniversalId&)), this, SLOT(cellSelectionChanged(const CSMWorld::UniversalId&))); + + connect(widget, SIGNAL(requestFocus (const std::string&)), + this, SIGNAL(requestFocus (const std::string&))); } void CSVWorld::SceneSubView::makeConnections (CSVRender::PagedWorldspaceWidget* widget) @@ -94,6 +97,9 @@ void CSVWorld::SceneSubView::makeConnections (CSVRender::PagedWorldspaceWidget* connect (widget, SIGNAL (cellSelectionChanged (const CSMWorld::CellSelection&)), this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&))); + + connect(widget, SIGNAL(requestFocus (const std::string&)), + this, SIGNAL(requestFocus (const std::string&))); } CSVWidget::SceneToolbar* CSVWorld::SceneSubView::makeToolbar (CSVRender::WorldspaceWidget* widget, widgetType type) diff --git a/apps/opencs/view/world/scenesubview.hpp b/apps/opencs/view/world/scenesubview.hpp index 0f18e8c30..85f7d0925 100644 --- a/apps/opencs/view/world/scenesubview.hpp +++ b/apps/opencs/view/world/scenesubview.hpp @@ -82,6 +82,10 @@ namespace CSVWorld void cellSelectionChanged (const CSMWorld::UniversalId& id); void handleDrop(const std::vector& data); + + signals: + + void requestFocus (const std::string& id); }; } diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index eb7b8e334..11c2be5fc 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -737,7 +737,12 @@ void CSVWorld::Table::requestFocus (const std::string& id) QModelIndex index = mProxyModel->getModelIndex (id, 0); if (index.isValid()) - scrollTo (index, QAbstractItemView::PositionAtTop); + { + // This will scroll to the row. + selectRow (index.row()); + // This will actually select it. + selectionModel()->select (index, QItemSelectionModel::Select | QItemSelectionModel::Rows); + } } void CSVWorld::Table::recordFilterChanged (std::shared_ptr filter) diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index 12e29995d..b0bae7fdf 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -165,3 +165,8 @@ bool CSVWorld::TableSubView::eventFilter (QObject* object, QEvent* event) } return false; } + +void CSVWorld::TableSubView::requestFocus (const std::string& id) +{ + mTable->requestFocus(id); +} diff --git a/apps/opencs/view/world/tablesubview.hpp b/apps/opencs/view/world/tablesubview.hpp index 7d143d927..1adf862d5 100644 --- a/apps/opencs/view/world/tablesubview.hpp +++ b/apps/opencs/view/world/tablesubview.hpp @@ -60,6 +60,10 @@ namespace CSVWorld void cloneRequest (const CSMWorld::UniversalId& toClone); void createFilterRequest(std::vector< CSMWorld::UniversalId >& types, Qt::DropAction action); + + public slots: + + void requestFocus (const std::string& id); }; } From 643f259cbfd01d0daa3fbe21cb2acc24d2ef302e Mon Sep 17 00:00:00 2001 From: Justin Ivany Date: Tue, 2 Jul 2019 11:19:10 +0000 Subject: [PATCH 36/62] Adding option for cursor speed when using gamepad --- apps/openmw/mwinput/inputmanagerimp.cpp | 5 +++-- apps/openmw/mwinput/inputmanagerimp.hpp | 1 + docs/source/reference/modding/settings/input.rst | 13 +++++++++++++ files/settings-default.cfg | 3 +++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 6a6ac20a8..581a96e7b 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -77,6 +77,7 @@ namespace MWInput , mSneaking(false) , mAttemptJump(false) , mInvUiScalingFactor(1.f) + , mGamepadCursorSpeed(Settings::Manager::getFloat("gamepad cursor speed", "Input")) , mFakeDeviceID(1) { mInputManager = new SDLUtil::InputWrapper(window, viewer, grab); @@ -558,8 +559,8 @@ namespace MWInput // We keep track of our own mouse position, so that moving the mouse while in // game mode does not move the position of the GUI cursor - float xmove = xAxis * dt * 1500.0f * mInvUiScalingFactor; - float ymove = yAxis * dt * 1500.0f * mInvUiScalingFactor; + float xmove = xAxis * dt * 1500.0f * mInvUiScalingFactor * mGamepadCursorSpeed; + float ymove = yAxis * dt * 1500.0f * mInvUiScalingFactor * mGamepadCursorSpeed; if (xmove != 0|| ymove != 0 || zAxis != 0) { mGuiCursorX += xmove; diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 8b3253dcd..caf57681d 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -209,6 +209,7 @@ namespace MWInput std::map mControlSwitch; float mInvUiScalingFactor; + float mGamepadCursorSpeed; private: void convertMousePosForMyGUI(int& x, int& y); diff --git a/docs/source/reference/modding/settings/input.rst b/docs/source/reference/modding/settings/input.rst index 51c72e15d..d481321c2 100644 --- a/docs/source/reference/modding/settings/input.rst +++ b/docs/source/reference/modding/settings/input.rst @@ -133,3 +133,16 @@ which are always sent if a controller is present and detected. Disabling this setting can be useful for working around controller-related issues or for setting up split-screen gameplay configurations. This setting can be toggled in game with the Enable Joystick button in the Controls panel of the Options menu. + +gamepad cursor speed +-------------------- + +:Type: float +:Range: >0 +:Default: 1.0 + +This setting controls the speed of the cursor within GUI mode when using the joystick. +This setting has no effect on the camera rotation speed, which is controlled by the +camera sensitivity setting. + +This setting can only be configured by editing the settings configuration file. diff --git a/files/settings-default.cfg b/files/settings-default.cfg index d3776e92f..d16e8c92c 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -364,6 +364,9 @@ invert y axis = false # Enable controller support. enable controller = true +# Emulated gamepad cursor sensitivity. +gamepad cursor speed = 1.0 + [Saves] # Name of last character played, and default for loading save files. From 8a463b30d63ec94225de381bdbb4de941df16bb3 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Tue, 2 Jul 2019 14:52:50 +0300 Subject: [PATCH 37/62] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 795473128..e6c55a525 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -108,6 +108,7 @@ Bug #5069: Blocking creatures' attacks doesn't degrade shields Bug #5074: Paralyzed actors greet the player Bug #5075: Enchanting cast style can be changed if there's no object + Bug #5082: Scrolling with controller in GUI mode is broken Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls @@ -141,6 +142,7 @@ Feature #5033: Magic armor mitigation for creatures Feature #5034: Make enchanting window stay open after a failed attempt Feature #5036: Allow scripted faction leaving + Feature #5046: Gamepad thumbstick cursor speed Feature #5051: Provide a separate textures for scrollbars Task #4686: Upgrade media decoder to a more current FFmpeg API Task #4695: Optimize Distant Terrain memory consumption From bcc5142b32ad7f4e7fb2c1f036011a1063be4e96 Mon Sep 17 00:00:00 2001 From: Nat Meo Date: Tue, 2 Jul 2019 16:07:38 +0000 Subject: [PATCH 38/62] Issue #4202: Open .omwaddon files without needing to open openmw-cs first. --- CHANGELOG.md | 1 + apps/opencs/editor.cpp | 72 ++++++++++++++++++++++++++++---- apps/opencs/editor.hpp | 5 ++- components/files/linuxpath.cpp | 21 +++++++++- components/files/windowspath.cpp | 18 +++++++- 5 files changed, 106 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6c55a525..3ba7febd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Bug #3765: DisableTeleporting makes Mark/Recall/Intervention effects undetectable Bug #3778: [Mod] Improved Thrown Weapon Projectiles - weapons have wrong transformation during throw animation Bug #3812: Wrong multiline tooltips width when word-wrapping is enabled + Bug #4202: Open .omwaddon files without needing toopen openmw-cs first Bug #4240: Ash storm origin coordinates and hand shielding animation behavior are incorrect Bug #4329: Removed birthsign abilities are restored after reloading the save Bug #4341: Error message about missing GDB is too vague diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index b22f5464d..0ce031548 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -27,6 +27,11 @@ CS::Editor::Editor (int argc, char **argv) std::pair > config = readConfig(); mViewManager = new CSVDoc::ViewManager(mDocumentManager); + if (argc > 1) + { + mFileToLoad = argv[1]; + mDataDirs = config.first; + } NifOsg::Loader::setShowMarkers(true); @@ -103,9 +108,9 @@ std::pair > CS::Editor::readConfi Fallback::Map::init(variables["fallback"].as().mMap); - const std::string encoding = variables["encoding"].as().toStdString(); - mDocumentManager.setEncoding (ToUTF8::calculateEncoding (encoding)); - mFileDialog.setEncoding (QString::fromUtf8(encoding.c_str())); + mEncodingName = variables["encoding"].as().toStdString(); + mDocumentManager.setEncoding(ToUTF8::calculateEncoding(mEncodingName)); + mFileDialog.setEncoding (QString::fromUtf8(mEncodingName.c_str())); mDocumentManager.setResourceDir (mResources = variables["resources"].as().toStdString()); @@ -217,12 +222,19 @@ void CS::Editor::loadDocument() mFileDialog.showDialog (CSVDoc::ContentAction_Edit); } -void CS::Editor::openFiles (const boost::filesystem::path &savePath) +void CS::Editor::openFiles (const boost::filesystem::path &savePath, const std::vector &discoveredFiles) { std::vector files; - foreach (const QString &path, mFileDialog.selectedFilePaths()) - files.push_back(path.toUtf8().constData()); + if(discoveredFiles.empty()) + { + foreach(const QString &path, mFileDialog.selectedFilePaths()) + files.push_back(path.toUtf8().constData()); + } + else + { + files = discoveredFiles; + } mDocumentManager.addDocument (files, savePath, false); @@ -348,9 +360,53 @@ int CS::Editor::run() Misc::Rng::init(); - mStartup.show(); + QApplication::setQuitOnLastWindowClosed(true); + + if (mFileToLoad.empty()) + { + mStartup.show(); + } + else + { + ESM::ESMReader fileReader; + ToUTF8::Utf8Encoder encoder = ToUTF8::calculateEncoding(mEncodingName); + fileReader.setEncoder(&encoder); + fileReader.open(mFileToLoad.string()); - QApplication::setQuitOnLastWindowClosed (true); + std::vector discoveredFiles; + + for (std::vector::const_iterator itemIter = fileReader.getGameFiles().begin(); + itemIter != fileReader.getGameFiles().end(); ++itemIter) + { + for (Files::PathContainer::const_iterator pathIter = mDataDirs.begin(); + pathIter != mDataDirs.end(); ++pathIter) + { + const boost::filesystem::path masterPath = *pathIter / itemIter->name; + if (boost::filesystem::exists(masterPath)) + { + discoveredFiles.push_back(masterPath); + break; + } + } + } + discoveredFiles.push_back(mFileToLoad); + + QString extension = QString::fromStdString(mFileToLoad.extension().string()).toLower(); + if (extension == ".esm") + { + mFileToLoad.replace_extension(".omwgame"); + mDocumentManager.addDocument(discoveredFiles, mFileToLoad, false); + } + else if (extension == ".esp") + { + mFileToLoad.replace_extension(".omwaddon"); + mDocumentManager.addDocument(discoveredFiles, mFileToLoad, false); + } + else + { + openFiles(mFileToLoad, discoveredFiles); + } + } return QApplication::exec(); } diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index 0c3ece905..1c9342761 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -54,6 +54,9 @@ namespace CS bool mFsStrict; CSVTools::Merge mMerge; CSVDoc::ViewManager* mViewManager; + boost::filesystem::path mFileToLoad; + Files::PathContainer mDataDirs; + std::string mEncodingName; std::pair > readConfig(bool quiet=false); ///< \return data paths @@ -81,7 +84,7 @@ namespace CS void cancelFileDialog(); void loadDocument(); - void openFiles (const boost::filesystem::path &path); + void openFiles (const boost::filesystem::path &path, const std::vector &discoveredFiles = std::vector()); void createNewFile (const boost::filesystem::path& path); void createNewGame (const boost::filesystem::path& file); diff --git a/components/files/linuxpath.cpp b/components/files/linuxpath.cpp index 3743eef4c..f2ecb7c13 100644 --- a/components/files/linuxpath.cpp +++ b/components/files/linuxpath.cpp @@ -4,8 +4,10 @@ #include #include +#include #include +#include #include @@ -50,6 +52,9 @@ namespace Files LinuxPath::LinuxPath(const std::string& application_name) : mName(application_name) { + boost::filesystem::path localPath = getLocalPath(); + if (chdir(localPath.string().c_str()) != 0) + Log(Debug::Warning) << "Error " << errno << " when changing current directory"; } boost::filesystem::path LinuxPath::getUserConfigPath() const @@ -75,7 +80,21 @@ boost::filesystem::path LinuxPath::getGlobalConfigPath() const boost::filesystem::path LinuxPath::getLocalPath() const { - return boost::filesystem::path("./"); + boost::filesystem::path localPath("./"); + char binPath[PATH_MAX]; + memset(binPath, 0, sizeof(binPath)); + const char *statusPaths[] = {"/proc/self/exe", "/proc/self/file", "/proc/curproc/exe", "/proc/curproc/file"}; + + for(const char *path : statusPaths) + { + if (readlink(path, binPath, sizeof(binPath)) != -1) + { + localPath = boost::filesystem::path(binPath).parent_path(); + break; + } + } + + return localPath; } boost::filesystem::path LinuxPath::getGlobalDataPath() const diff --git a/components/files/windowspath.cpp b/components/files/windowspath.cpp index 2354e6f31..516f26021 100644 --- a/components/files/windowspath.cpp +++ b/components/files/windowspath.cpp @@ -11,6 +11,8 @@ #include namespace bconv = boost::locale::conv; +#include + /** * FIXME: Someone with Windows system should check this and correct if necessary * FIXME: MAX_PATH is irrelevant for extended-length paths, i.e. \\?\... @@ -33,6 +35,10 @@ WindowsPath::WindowsPath(const std::string& application_name) See boost::filesystem and boost::locale reference for details. */ boost::filesystem::path::imbue(boost::locale::generator().generate("")); + + boost::filesystem::path localPath = getLocalPath(); + if (!SetCurrentDirectoryA(localPath.string().c_str())) + Log(Debug::Warning) << "Error " << GetLastError() << " when changing current directory"; } boost::filesystem::path WindowsPath::getUserConfigPath() const @@ -73,7 +79,17 @@ boost::filesystem::path WindowsPath::getGlobalConfigPath() const boost::filesystem::path WindowsPath::getLocalPath() const { - return boost::filesystem::path("./"); + boost::filesystem::path localPath("./"); + WCHAR path[MAX_PATH + 1]; + memset(path, 0, sizeof(path)); + + if (GetModuleFileNameW(nullptr, path, MAX_PATH + 1) > 0) + { + localPath = boost::filesystem::path(bconv::utf_to_utf(path)).parent_path(); + } + + // lookup exe path + return localPath; } boost::filesystem::path WindowsPath::getGlobalDataPath() const From cb4664b31bacccf78c1c8e24a2d7cbeb299e3887 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 3 Jul 2019 22:38:07 +0200 Subject: [PATCH 39/62] Remove arrow key behaviour as it's in MyGUI now --- apps/openmw/mwgui/console.cpp | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 9c7d1d594..df4bdec5b 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -1,6 +1,7 @@ #include "console.hpp" #include +#include #include #include @@ -264,26 +265,6 @@ namespace MWGui mCommandLine->setTextCursor(0); } } - else if(key == MyGUI::KeyCode::ArrowRight) - { - const auto& caption = mCommandLine->getCaption(); - size_t pos = mCommandLine->getTextCursor(); - while(pos < caption.size() && (isWhitespace(caption[pos]) || caption[pos] == '-')) - pos++; - while(pos < caption.size() && !isWhitespace(caption[pos]) && caption[pos] != '-') - pos++; - mCommandLine->setTextCursor(pos); - } - else if(key == MyGUI::KeyCode::ArrowLeft) - { - const auto& caption = mCommandLine->getCaption(); - size_t pos = mCommandLine->getTextCursor(); - while(pos > 0 && (isWhitespace(caption[pos - 1]) || caption[pos - 1] == '>')) - pos--; - while(pos > 0 && !isWhitespace(caption[pos - 1]) && caption[pos - 1] != '>') - pos--; - mCommandLine->setTextCursor(pos); - } } else if(key == MyGUI::KeyCode::Tab) { From e4e513c5dc9983fde85192cd39b8daeea44f00a5 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Thu, 4 Jul 2019 13:36:27 +0300 Subject: [PATCH 40/62] Fix CI builds Apparently the only tab characters are in this file. --- components/files/linuxpath.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/files/linuxpath.cpp b/components/files/linuxpath.cpp index f2ecb7c13..cceca9732 100644 --- a/components/files/linuxpath.cpp +++ b/components/files/linuxpath.cpp @@ -88,12 +88,12 @@ boost::filesystem::path LinuxPath::getLocalPath() const for(const char *path : statusPaths) { if (readlink(path, binPath, sizeof(binPath)) != -1) - { - localPath = boost::filesystem::path(binPath).parent_path(); - break; + { + localPath = boost::filesystem::path(binPath).parent_path(); + break; } } - + return localPath; } From e4c596adf86930f0651c5a315a12c1da737714fe Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Thu, 4 Jul 2019 14:12:36 +0300 Subject: [PATCH 41/62] =?UTF-8?q?Fix=20CI=20builds=20(attempt=20=E2=84=962?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gosh darn dem tabs --- components/files/linuxpath.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/files/linuxpath.cpp b/components/files/linuxpath.cpp index cceca9732..3acfd825f 100644 --- a/components/files/linuxpath.cpp +++ b/components/files/linuxpath.cpp @@ -89,8 +89,8 @@ boost::filesystem::path LinuxPath::getLocalPath() const { if (readlink(path, binPath, sizeof(binPath)) != -1) { - localPath = boost::filesystem::path(binPath).parent_path(); - break; + localPath = boost::filesystem::path(binPath).parent_path(); + break; } } From c8c06ceee988318b7a505c44c6d2eb2d09d46d39 Mon Sep 17 00:00:00 2001 From: jeremy Date: Thu, 4 Jul 2019 22:48:33 +0200 Subject: [PATCH 42/62] Fixed SoundManager::stopSound when output is not initialized (bug #4600 probably) --- apps/openmw/mwsound/soundmanagerimp.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 77f25f326..aa1686f7c 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -747,6 +747,9 @@ namespace MWSound void SoundManager::stopSound(const std::string& soundId) { + if(!mOutput->isInitialized()) + return; + Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); if (!sfx) return; @@ -755,6 +758,9 @@ namespace MWSound void SoundManager::stopSound3D(const MWWorld::ConstPtr &ptr, const std::string& soundId) { + if(!mOutput->isInitialized()) + return; + Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); if (!sfx) return; From 962462c1c5bfb07cda13b18a6d6a40ba48427da4 Mon Sep 17 00:00:00 2001 From: jeremy Date: Thu, 4 Jul 2019 22:54:39 +0200 Subject: [PATCH 43/62] Removed unnecessary calls to stopSound3D playSound3D (the one taking a ptr) already stops the sound if it's playing. --- apps/openmw/mwmechanics/character.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 7966526f2..00b3c0c67 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -983,7 +983,6 @@ void CharacterController::handleTextKey(const std::string &groupname, const std: if(evt.compare(0, 7, "sound: ") == 0) { MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); - sndMgr->stopSound3D(mPtr, evt.substr(7)); sndMgr->playSound3D(mPtr, evt.substr(7), 1.0f, 1.0f); return; } @@ -1024,7 +1023,6 @@ void CharacterController::handleTextKey(const std::string &groupname, const std: } else { - sndMgr->stopSound3D(mPtr, sound); sndMgr->playSound3D(mPtr, sound, volume, pitch); } } From 940625b1381156912c9e6f590895f8f4e69a9b17 Mon Sep 17 00:00:00 2001 From: jeremy Date: Fri, 5 Jul 2019 08:46:46 +0200 Subject: [PATCH 44/62] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ba7febd1..1ee3d46d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ Bug #4384: Resist Normal Weapons only checks ammunition for ranged weapons Bug #4411: Reloading a saved game while falling prevents damage in some cases Bug #4540: Rain delay when exiting water + Bug #4600: Crash when no sound output is available or --no-sound is used. Bug #4639: Black screen after completing first mages guild mission + training Bug #4701: PrisonMarker record is not hardcoded like other markers Bug #4703: Editor: it's possible to preview levelled list records From c0f66ac70c4c45e1b0ba7c36877df534544e6ec2 Mon Sep 17 00:00:00 2001 From: Axel Vestin Date: Sat, 6 Jul 2019 00:13:30 +0200 Subject: [PATCH 45/62] Fixes Albemic typo in OpenMW-CS --- apps/opencs/model/world/columns.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 249b43252..5dda78919 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -422,7 +422,7 @@ namespace static const char *sApparatusTypes[] = { - "Mortar & Pestle", "Albemic", "Calcinator", "Retort", 0 + "Mortar & Pestle", "Alembic", "Calcinator", "Retort", 0 }; static const char *sArmorTypes[] = From ca7ac30f6d348adfb0e7e9fdfbaced00717b11c0 Mon Sep 17 00:00:00 2001 From: fredzio Date: Sun, 7 Jul 2019 01:02:38 +0200 Subject: [PATCH 46/62] Use the POSIX pathconf(2) to determine the maximum path length. It fixes build on BSD platforms where PATH_MAX is defined in vs on Linux. --- components/files/linuxpath.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/components/files/linuxpath.cpp b/components/files/linuxpath.cpp index 3acfd825f..5f34539d5 100644 --- a/components/files/linuxpath.cpp +++ b/components/files/linuxpath.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include @@ -81,13 +80,12 @@ boost::filesystem::path LinuxPath::getGlobalConfigPath() const boost::filesystem::path LinuxPath::getLocalPath() const { boost::filesystem::path localPath("./"); - char binPath[PATH_MAX]; - memset(binPath, 0, sizeof(binPath)); + std::string binPath(pathconf(".", _PC_PATH_MAX), '\0'); const char *statusPaths[] = {"/proc/self/exe", "/proc/self/file", "/proc/curproc/exe", "/proc/curproc/file"}; for(const char *path : statusPaths) { - if (readlink(path, binPath, sizeof(binPath)) != -1) + if (readlink(path, &binPath[0], binPath.size()) != -1) { localPath = boost::filesystem::path(binPath).parent_path(); break; From 44a01303ed87f36a74bb5fb22c4a8bfab33976b4 Mon Sep 17 00:00:00 2001 From: 8-j <49505326+8-j@users.noreply.github.com> Date: Mon, 8 Jul 2019 23:27:11 +0200 Subject: [PATCH 47/62] Extended.rst: Fix inexistent animation key: `open` -> `start` --- docs/source/reference/modding/extended.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/reference/modding/extended.rst b/docs/source/reference/modding/extended.rst index d7c199b57..9d71f384d 100644 --- a/docs/source/reference/modding/extended.rst +++ b/docs/source/reference/modding/extended.rst @@ -53,7 +53,7 @@ It is also possible to attach opening/closing sounds to container's animations: :: - 1.0: ContainerClose: open + 1.0: ContainerClose: start 1.01: Sound: AC_dw_drawer_close 2.0: ContainerClose: stop From 366906ac51797110d7d5ff79ddfa2886a0be4973 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Fri, 12 Jul 2019 12:31:10 +0300 Subject: [PATCH 48/62] Fix paralyzed actors' death animations --- apps/openmw/mwmechanics/actors.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 5cca894e6..656694b25 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1580,7 +1580,8 @@ namespace MWMechanics else if (!isPlayer) iter->first.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Actor); - if (iter->first.getClass().getCreatureStats(iter->first).isParalyzed()) + const bool isDead = iter->first.getClass().getCreatureStats(iter->first).isDead(); + if (!isDead && iter->first.getClass().getCreatureStats(iter->first).isParalyzed()) ctrl->skipAnim(); // Handle player last, in case a cell transition occurs by casting a teleportation spell From fb9b4a79c12b87197e32f13652da4bcadf1ffc51 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 14 Jul 2019 20:52:36 +0200 Subject: [PATCH 49/62] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ba7febd1..69311c748 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -145,6 +145,7 @@ Feature #5036: Allow scripted faction leaving Feature #5046: Gamepad thumbstick cursor speed Feature #5051: Provide a separate textures for scrollbars + Feature #5094: Unix like console hotkeys Task #4686: Upgrade media decoder to a more current FFmpeg API Task #4695: Optimize Distant Terrain memory consumption Task #4789: Optimize cell transitions From 65ee420ab93422e0b3ee4ce87279cf51b770cce9 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sun, 14 Jul 2019 23:42:42 +0300 Subject: [PATCH 50/62] Only play on-strike failure sound on the player (bug #5092) --- apps/openmw/mwmechanics/spellcasting.cpp | 27 +++++++++++++----------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 2de6f75fa..2c178a40e 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -838,21 +838,24 @@ namespace MWMechanics if (item.getCellRef().getEnchantmentCharge() < castCost) { if (mCaster == getPlayer()) + { MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicInsufficientCharge}"); - // Failure sound - int school = 0; - if (!enchantment->mEffects.mList.empty()) - { - short effectId = enchantment->mEffects.mList.front().mEffectID; - const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get().find(effectId); - school = magicEffect->mData.mSchool; + // Failure sound + int school = 0; + if (!enchantment->mEffects.mList.empty()) + { + short effectId = enchantment->mEffects.mList.front().mEffectID; + const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get().find(effectId); + school = magicEffect->mData.mSchool; + } + + static const std::string schools[] = { + "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" + }; + MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); + sndMgr->playSound3D(mCaster, "Spell Failure " + schools[school], 1.0f, 1.0f); } - static const std::string schools[] = { - "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" - }; - MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); - sndMgr->playSound3D(mCaster, "Spell Failure " + schools[school], 1.0f, 1.0f); return false; } // Reduce charge From 29ebfe709ebc459234107e5dda8401faaf46a4c9 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sun, 14 Jul 2019 23:56:38 +0300 Subject: [PATCH 51/62] Play 'Hand To Hand Hit' only for fatigue damage (bug #5093) --- apps/openmw/mwmechanics/combat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index 68c94b9ee..b39d769b2 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -441,7 +441,7 @@ namespace MWMechanics if(sound) sndMgr->playSound3D(victim, sound->mId, 1.0f, 1.0f); } - else + else if (!healthdmg) sndMgr->playSound3D(victim, "Hand To Hand Hit", 1.0f, 1.0f); } From 6cad48b1ad72ecafb0fe82a53e097049fa10efb0 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sun, 14 Jul 2019 23:57:52 +0300 Subject: [PATCH 52/62] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ba7febd1..dc5b0e4de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -110,6 +110,8 @@ Bug #5074: Paralyzed actors greet the player Bug #5075: Enchanting cast style can be changed if there's no object Bug #5082: Scrolling with controller in GUI mode is broken + Bug #5092: NPCs with enchanted weapons play sound when out of charges + Bug #5093: Hand to hand sound plays on knocked out enemies Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls From d996b565a55668d0c575109e0eec0fabe4afc27f Mon Sep 17 00:00:00 2001 From: Artem Nykolenko Date: Wed, 17 Jul 2019 00:44:36 -0400 Subject: [PATCH 53/62] Improve character window resizing (bug #4276) --- AUTHORS.md | 1 + CHANGELOG.md | 1 + apps/openmw/mwgui/statswindow.cpp | 39 ++++++++++++++++++++++++-- apps/openmw/mwgui/statswindow.hpp | 1 + files/mygui/openmw_stats_window.layout | 5 ++-- 5 files changed, 42 insertions(+), 5 deletions(-) diff --git a/AUTHORS.md b/AUTHORS.md index f6a62c4ce..5b848fab4 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -29,6 +29,7 @@ Programmers Ardekantur Armin Preiml Artem Kotsynyak (greye) + Artem Nykolenko (anikm21) artemutin Arthur Moore (EmperorArthur) Assumeru diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ee3d46d7..e39da05a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Bug #3812: Wrong multiline tooltips width when word-wrapping is enabled Bug #4202: Open .omwaddon files without needing toopen openmw-cs first Bug #4240: Ash storm origin coordinates and hand shielding animation behavior are incorrect + Bug #4276: Resizing character window differs from vanilla Bug #4329: Removed birthsign abilities are restored after reloading the save Bug #4341: Error message about missing GDB is too vague Bug #4383: Bow model obscures crosshair when arrow is drawn diff --git a/apps/openmw/mwgui/statswindow.cpp b/apps/openmw/mwgui/statswindow.cpp index 91d414af3..8998e3a80 100644 --- a/apps/openmw/mwgui/statswindow.cpp +++ b/apps/openmw/mwgui/statswindow.cpp @@ -40,8 +40,8 @@ namespace MWGui , mBounty(0) , mSkillWidgets() , mChanged(true) + , mMinFullWidth(mMainWidget->getSize().width) { - setCoord(0,0,498, 342); const char *names[][2] = { @@ -88,8 +88,41 @@ namespace MWGui void StatsWindow::onWindowResize(MyGUI::Window* window) { - mLeftPane->setCoord( MyGUI::IntCoord(0, 0, static_cast(0.44*window->getSize().width), window->getSize().height) ); - mRightPane->setCoord( MyGUI::IntCoord(static_cast(0.44*window->getSize().width), 0, static_cast(0.56*window->getSize().width), window->getSize().height) ); + int windowWidth = window->getSize().width; + int windowHeight = window->getSize().height; + + //initial values defined in openmw_stats_window.layout, if custom options are not present in .layout, a default is loaded + float leftPaneRatio = 0.44; + if (mLeftPane->isUserString("LeftPaneRatio")) + leftPaneRatio = MyGUI::utility::parseFloat(mLeftPane->getUserString("LeftPaneRatio")); + + int leftOffsetWidth = 24; + if (mLeftPane->isUserString("LeftOffsetWidth")) + leftOffsetWidth = MyGUI::utility::parseInt(mLeftPane->getUserString("LeftOffsetWidth")); + + float rightPaneRatio = 1.f - leftPaneRatio; + int minLeftWidth = static_cast(mMinFullWidth * leftPaneRatio); + int minLeftOffsetWidth = minLeftWidth + leftOffsetWidth; + + //if there's no space for right pane + mRightPane->setVisible(windowWidth >= minLeftOffsetWidth); + if (!mRightPane->getVisible()) + { + mLeftPane->setCoord(MyGUI::IntCoord(0, 0, windowWidth - leftOffsetWidth, windowHeight)); + } + //if there's some space for right pane + else if (windowWidth < mMinFullWidth) + { + mLeftPane->setCoord(MyGUI::IntCoord(0, 0, minLeftWidth, windowHeight)); + mRightPane->setCoord(MyGUI::IntCoord(minLeftWidth, 0, windowWidth - minLeftWidth, windowHeight)); + } + //if there's enough space for both panes + else + { + mLeftPane->setCoord(MyGUI::IntCoord(0, 0, static_cast(leftPaneRatio*windowWidth), windowHeight)); + mRightPane->setCoord(MyGUI::IntCoord(static_cast(leftPaneRatio*windowWidth), 0, static_cast(rightPaneRatio*windowWidth), windowHeight)); + } + // Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden mSkillView->setVisibleVScroll(false); mSkillView->setCanvasSize (mSkillView->getWidth(), mSkillView->getCanvasSize().height); diff --git a/apps/openmw/mwgui/statswindow.hpp b/apps/openmw/mwgui/statswindow.hpp index 8dab2f3d9..7d1be6a15 100644 --- a/apps/openmw/mwgui/statswindow.hpp +++ b/apps/openmw/mwgui/statswindow.hpp @@ -69,6 +69,7 @@ namespace MWGui std::set mExpelled; bool mChanged; + const int mMinFullWidth; protected: virtual void onPinToggled(); diff --git a/files/mygui/openmw_stats_window.layout b/files/mygui/openmw_stats_window.layout index f26f1d598..77de3ac75 100644 --- a/files/mygui/openmw_stats_window.layout +++ b/files/mygui/openmw_stats_window.layout @@ -2,9 +2,10 @@ - - + + + From facbb2e0db9f6de8e9713813bf57a2b6b21e8f6e Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sat, 20 Jul 2019 00:12:05 +0300 Subject: [PATCH 54/62] [Regression] Make sure unloaded objects can be opened --- apps/openmw/mwmechanics/objects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/objects.cpp b/apps/openmw/mwmechanics/objects.cpp index d4a393c72..9e05509f1 100644 --- a/apps/openmw/mwmechanics/objects.cpp +++ b/apps/openmw/mwmechanics/objects.cpp @@ -106,7 +106,7 @@ bool Objects::onOpen(const MWWorld::Ptr& ptr) PtrControllerMap::iterator iter = mObjects.find(ptr); if(iter != mObjects.end()) return iter->second->onOpen(); - return false; + return true; } void Objects::onClose(const MWWorld::Ptr& ptr) From d4ec446141f00383a6ca3a22a692c81c5436511a Mon Sep 17 00:00:00 2001 From: wang ryu <3357032-bzzt@users.noreply.gitlab.com> Date: Thu, 10 Jan 2019 15:20:21 +0000 Subject: [PATCH 55/62] default framelimit --- docs/source/reference/modding/settings/video.rst | 4 +--- files/settings-default.cfg | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/source/reference/modding/settings/video.rst b/docs/source/reference/modding/settings/video.rst index a8a95739e..040b9948f 100644 --- a/docs/source/reference/modding/settings/video.rst +++ b/docs/source/reference/modding/settings/video.rst @@ -140,7 +140,7 @@ framerate limit :Type: floating point :Range: >= 0.0 -:Default: 0.0 +:Default: 300 This setting determines the maximum frame rate in frames per second. If this setting is 0.0, the frame rate is unlimited. @@ -159,8 +159,6 @@ in the sense that enabling vertical sync limits the frame rate to the refresh ra Choosing to limit the frame rate using this setting instead of vsync may reduce input lag due to the game not having to wait for the vertical blanking interval. -This setting can only be configured by editing the settings configuration file. - contrast -------- diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 71a93d1a2..562fb13f7 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -417,7 +417,7 @@ antialiasing = 0 vsync = false # Maximum frames per second. 0.0 is unlimited, or >0.0 to limit. -framerate limit = 0.0 +framerate limit = 300 # Game video contrast. (>0.0). No effect in Linux. contrast = 1.0 From 28e54c25ee3267c4f82713bce9bbf08e027399c6 Mon Sep 17 00:00:00 2001 From: Grigory Date: Sun, 28 Jul 2019 21:04:37 +0300 Subject: [PATCH 56/62] Add -DMYGUI_DONT_REPLACE_NULLPTR --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 98d8ace47..292d1dc06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -215,6 +215,9 @@ endif() # Required for building the FFmpeg headers add_definitions(-D__STDC_CONSTANT_MACROS) +# Reqiuired for unity build +add_definitions(-DMYGUI_DONT_REPLACE_NULLPTR) + # TinyXML option(USE_SYSTEM_TINYXML "Use system TinyXML library instead of internal." OFF) if (USE_SYSTEM_TINYXML) From dcbe76d888dd71ae0ddcab168e0b1544af65ab67 Mon Sep 17 00:00:00 2001 From: capostrophic Date: Wed, 31 Jul 2019 17:34:32 +0300 Subject: [PATCH 57/62] [Regression] Avoid confusing inventory doll with player --- apps/openmw/mwclass/npc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index f22ac06b9..aa326412f 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -1180,7 +1180,7 @@ namespace MWClass MWBase::Environment::get().getWorld()->getStore().get().find(ref->mBase->mRace); // Race weight should not affect 1st-person meshes, otherwise it will change hand proportions and can break aiming. - if (ptr == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->isFirstPerson()) + if (ptr == MWMechanics::getPlayer() && ptr.isInCell() && MWBase::Environment::get().getWorld()->isFirstPerson()) { if (ref->mBase->isMale()) scale *= race->mData.mHeight.mMale; From 5341ca4e22ed03ae8d8f1f42887597679471b393 Mon Sep 17 00:00:00 2001 From: capostrophic Date: Thu, 1 Aug 2019 11:40:53 +0300 Subject: [PATCH 58/62] [Regression] Avoid locale-related conversion issues in editor --- apps/opencs/model/prefs/state.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index a206fad6f..bfe907c19 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -3,6 +3,7 @@ #include #include +#include #include "intsetting.hpp" #include "doublesetting.hpp" @@ -415,7 +416,9 @@ CSMPrefs::DoubleSetting& CSMPrefs::State::declareDouble (const std::string& key, if (mCurrentCategory==mCategories.end()) throw std::logic_error ("no category for setting"); - setDefault(key, std::to_string(default_)); + std::ostringstream stream; + stream << default_; + setDefault(key, stream.str()); default_ = mSettings.getFloat (key, mCurrentCategory->second.getKey()); From 610e87cb24f57aaf4083df6e71f4f83be990fbc2 Mon Sep 17 00:00:00 2001 From: Artem Nykolenko Date: Thu, 1 Aug 2019 10:02:35 +0000 Subject: [PATCH 59/62] Fix Non-swimming enemies entering water if player is water walking (bug #5099) --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/aicombataction.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c481994ea..d7ce62540 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -114,6 +114,7 @@ Bug #5082: Scrolling with controller in GUI mode is broken Bug #5092: NPCs with enchanted weapons play sound when out of charges Bug #5093: Hand to hand sound plays on knocked out enemies + Bug #5099: Non-swimming enemies will enter water if player is water walking Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls diff --git a/apps/openmw/mwmechanics/aicombataction.cpp b/apps/openmw/mwmechanics/aicombataction.cpp index 96ff0c308..167e13128 100644 --- a/apps/openmw/mwmechanics/aicombataction.cpp +++ b/apps/openmw/mwmechanics/aicombataction.cpp @@ -422,6 +422,11 @@ namespace MWMechanics return true; } + if (actor.getClass().isPureLandCreature(actor) && MWBase::Environment::get().getWorld()->isWalkingOnWater(enemy)) + { + return false; + } + if (actor.getClass().isPureFlyingCreature(actor) || actor.getClass().isPureLandCreature(actor)) { if (MWBase::Environment::get().getWorld()->isSwimming(enemy)) From 4ad04a28f925e5c28aa9e052847a0aa555627c7e Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 1 Aug 2019 15:10:46 +0200 Subject: [PATCH 60/62] Reset path after AiTravel is fast forwarded Otherwise actor will keep going to the first path point that may be unreachable. --- apps/openmw/mwmechanics/aitravel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwmechanics/aitravel.cpp b/apps/openmw/mwmechanics/aitravel.cpp index 018756aea..d97edfe2a 100644 --- a/apps/openmw/mwmechanics/aitravel.cpp +++ b/apps/openmw/mwmechanics/aitravel.cpp @@ -88,6 +88,7 @@ namespace MWMechanics // that is the user's responsibility MWBase::Environment::get().getWorld()->moveObject(actor, mX, mY, mZ); actor.getClass().adjustPosition(actor, false); + reset(); } void AiTravel::writeState(ESM::AiSequence::AiSequence &sequence) const From 168e5050bba7e5aaa456390e9ba83a48b563fdf1 Mon Sep 17 00:00:00 2001 From: capostrophic Date: Mon, 29 Jul 2019 15:50:19 +0300 Subject: [PATCH 61/62] Ignore an extra number argument in ModRegion (bug #5110) --- CHANGELOG.md | 1 + components/compiler/extensions0.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7ce62540..213ba55d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -115,6 +115,7 @@ Bug #5092: NPCs with enchanted weapons play sound when out of charges Bug #5093: Hand to hand sound plays on knocked out enemies Bug #5099: Non-swimming enemies will enter water if player is water walking + Bug #5110: ModRegion with a redundant numerical argument breaks script execution Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index 5b60f9d6d..7ccfb9285 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -340,7 +340,7 @@ namespace Compiler extensions.registerFunction ("getmasserphase", 'l', "", opcodeGetMasserPhase); extensions.registerFunction ("getsecundaphase", 'l', "", opcodeGetSecundaPhase); extensions.registerFunction ("getcurrentweather", 'l', "", opcodeGetCurrentWeather); - extensions.registerInstruction ("modregion", "S/llllllllll", opcodeModRegion); + extensions.registerInstruction ("modregion", "S/llllllllllX", opcodeModRegion); } } From ff133bd740a85fc2cfa84aa466a5a5a1ce01bfa2 Mon Sep 17 00:00:00 2001 From: capostrophic Date: Wed, 31 Jul 2019 00:07:03 +0300 Subject: [PATCH 62/62] Don't clamp final actor fight rating to 0 (bug #5105) Fix werewolf aggro distance --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 213ba55d3..29e310b58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -115,6 +115,7 @@ Bug #5092: NPCs with enchanted weapons play sound when out of charges Bug #5093: Hand to hand sound plays on knocked out enemies Bug #5099: Non-swimming enemies will enter water if player is water walking + Bug #5105: NPCs start combat with werewolves from any distance Bug #5110: ModRegion with a redundant numerical argument breaks script execution Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 23f5ea01d..fd7ab63fe 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1785,8 +1785,8 @@ namespace MWMechanics if (ptr.getClass().isNpc()) disposition = getDerivedDisposition(ptr, true); - int fight = std::max(0, ptr.getClass().getCreatureStats(ptr).getAiSetting(CreatureStats::AI_Fight).getModified() - + static_cast(getFightDistanceBias(ptr, target) + getFightDispositionBias(static_cast(disposition)))); + int fight = ptr.getClass().getCreatureStats(ptr).getAiSetting(CreatureStats::AI_Fight).getModified() + + static_cast(getFightDistanceBias(ptr, target) + getFightDispositionBias(static_cast(disposition))); if (ptr.getClass().isNpc() && target.getClass().isNpc()) {