From 39b73405800bd3409184a894a0d899ba28904c41 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 Sep 2015 15:32:18 +0200 Subject: [PATCH 01/84] added mouse button settings for 3D scene (not in use yet) --- apps/opencs/model/settings/usersettings.cpp | 35 +++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 24680ada3..3daf7f9ec 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -371,6 +371,41 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() "list go to the first/last item"); } + declareSection ("scene-input", "3D Scene Input"); + { + QString left ("Left Mouse-Button"); + QString cLeft ("Ctrl-Left Mouse-Button"); + QString right ("Right Mouse-Button"); + QString cRight ("Ctrl-Right Mouse-Button"); + QString middle ("Middle Mouse-Button"); + QString cMiddle ("Ctrl-Middle Mouse-Button"); + + QStringList values; + values << left << cLeft << right << cRight << middle << cMiddle; + + Setting *primaryNavigation = createSetting (Type_ComboBox, "p-navi", "Primary Camera Navigation Button"); + primaryNavigation->setDeclaredValues (values); + primaryNavigation->setDefaultValue (left); + + Setting *secondaryNavigation = createSetting (Type_ComboBox, "s-navi", "Secondary Camera Navigation Button"); + secondaryNavigation->setDeclaredValues (values); + secondaryNavigation->setDefaultValue (cLeft); + + Setting *primaryEditing = createSetting (Type_ComboBox, "p-edit", "Primary Editing Button"); + primaryEditing->setDeclaredValues (values); + primaryEditing->setDefaultValue (right); + + Setting *secondaryEditing = createSetting (Type_ComboBox, "s-edit", "Secondary Editing Button"); + secondaryEditing->setDeclaredValues (values); + secondaryEditing->setDefaultValue (cRight); + + values << "Context Sensitive"; + + Setting *selection = createSetting (Type_ComboBox, "select", "Selection Button"); + selection->setDeclaredValues (values); + selection->setDefaultValue (middle); + } + { /****************************************************************** * There are three types of values: From b2cb5f037447e6baa8ad6bbdeb076c388d89595a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 24 Sep 2015 15:51:16 +0200 Subject: [PATCH 02/84] pass on user settings updates to potentially interested parties within a scene subview --- apps/opencs/view/render/editmode.cpp | 5 +++++ apps/opencs/view/render/editmode.hpp | 3 +++ apps/opencs/view/render/worldspacewidget.cpp | 5 +++++ apps/opencs/view/render/worldspacewidget.hpp | 2 ++ apps/opencs/view/widget/scenetoolmode.cpp | 5 +++++ apps/opencs/view/widget/scenetoolmode.hpp | 3 +++ apps/opencs/view/world/scenesubview.cpp | 15 ++++++++++++--- apps/opencs/view/world/scenesubview.hpp | 4 ++++ 8 files changed, 39 insertions(+), 3 deletions(-) diff --git a/apps/opencs/view/render/editmode.cpp b/apps/opencs/view/render/editmode.cpp index 8a99ba049..bf96fea3a 100644 --- a/apps/opencs/view/render/editmode.cpp +++ b/apps/opencs/view/render/editmode.cpp @@ -16,3 +16,8 @@ void CSVRender::EditMode::activate (CSVWidget::SceneToolbar *toolbar) { mWorldspaceWidget->setInteractionMask (mMask); } + +void CSVRender::EditMode::updateUserSetting (const QString& name, const QStringList& value) +{ + +} diff --git a/apps/opencs/view/render/editmode.hpp b/apps/opencs/view/render/editmode.hpp index c3192f8ea..381a6abcb 100644 --- a/apps/opencs/view/render/editmode.hpp +++ b/apps/opencs/view/render/editmode.hpp @@ -22,6 +22,9 @@ namespace CSVRender unsigned int getInteractionMask() const; virtual void activate (CSVWidget::SceneToolbar *toolbar); + + /// Default-implementation: Do nothing. + virtual void updateUserSetting (const QString& name, const QStringList& value); }; } diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index a1f0f6bf2..2eb84d0a2 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -254,6 +254,11 @@ unsigned int CSVRender::WorldspaceWidget::getInteractionMask() const return mInteractionMask & getVisibilityMask(); } +void CSVRender::WorldspaceWidget::updateUserSetting (const QString& name, const QStringList& value) +{ + +} + void CSVRender::WorldspaceWidget::addVisibilitySelectorButtons ( CSVWidget::SceneToolToggle2 *tool) { diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index fe4555820..c3796af34 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -93,6 +93,8 @@ namespace CSVRender /// marked for interaction. unsigned int getInteractionMask() const; + virtual void updateUserSetting (const QString& name, const QStringList& value); + protected: virtual void addVisibilitySelectorButtons (CSVWidget::SceneToolToggle2 *tool); diff --git a/apps/opencs/view/widget/scenetoolmode.cpp b/apps/opencs/view/widget/scenetoolmode.cpp index 9f963873c..a93bb0556 100644 --- a/apps/opencs/view/widget/scenetoolmode.cpp +++ b/apps/opencs/view/widget/scenetoolmode.cpp @@ -71,6 +71,11 @@ void CSVWidget::SceneToolMode::addButton (ModeButton *button, const std::string& } } +CSVWidget::ModeButton *CSVWidget::SceneToolMode::getCurrent() +{ + return mCurrent; +} + void CSVWidget::SceneToolMode::selected() { std::map::const_iterator iter = diff --git a/apps/opencs/view/widget/scenetoolmode.hpp b/apps/opencs/view/widget/scenetoolmode.hpp index e6f462cf8..6828a2269 100644 --- a/apps/opencs/view/widget/scenetoolmode.hpp +++ b/apps/opencs/view/widget/scenetoolmode.hpp @@ -41,6 +41,9 @@ namespace CSVWidget /// The ownership of \a button is transferred to *this. void addButton (ModeButton *button, const std::string& id); + /// Will return a 0-pointer only if the mode does not have any buttons yet. + ModeButton *getCurrent(); + signals: void modeChanged (const std::string& id); diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index c2f3442f8..f0b18dd86 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -15,6 +15,7 @@ #include "../render/pagedworldspacewidget.hpp" #include "../render/unpagedworldspacewidget.hpp" +#include "../render/editmode.hpp" #include "../widget/scenetoolbar.hpp" #include "../widget/scenetoolmode.hpp" @@ -26,7 +27,8 @@ #include "creator.hpp" CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) -: SubView (id), mScene(NULL), mLayout(new QHBoxLayout), mDocument(document), mToolbar(NULL) +: SubView (id), mScene(NULL), mLayout(new QHBoxLayout), mDocument(document), mToolbar(NULL), + mEditMode (0) { QVBoxLayout *layout = new QVBoxLayout; @@ -121,8 +123,8 @@ CSVWidget::SceneToolbar* CSVWorld::SceneSubView::makeToolbar (CSVRender::Worldsp CSVWidget::SceneToolRun *runTool = widget->makeRunTool (toolbar); toolbar->addTool (runTool); - CSVWidget::SceneToolMode *editModeTool = widget->makeEditModeSelector (toolbar); - toolbar->addTool (editModeTool); + mEditMode = widget->makeEditModeSelector (toolbar); + toolbar->addTool (mEditMode); return toolbar; } @@ -147,6 +149,13 @@ std::string CSVWorld::SceneSubView::getTitle() const return mTitle; } +void CSVWorld::SceneSubView::updateUserSetting (const QString& name, const QStringList& value) +{ + mScene->updateUserSetting (name, value); + dynamic_cast (*mEditMode->getCurrent()).updateUserSetting (name, value); + CSVDoc::SubView::updateUserSetting (name, value); +} + void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::UniversalId& id) { setUniversalId(id); diff --git a/apps/opencs/view/world/scenesubview.hpp b/apps/opencs/view/world/scenesubview.hpp index a34d71901..29aca5ab6 100644 --- a/apps/opencs/view/world/scenesubview.hpp +++ b/apps/opencs/view/world/scenesubview.hpp @@ -27,6 +27,7 @@ namespace CSVRender namespace CSVWidget { class SceneToolbar; + class SceneToolMode; } namespace CSVWorld @@ -45,6 +46,7 @@ namespace CSVWorld CSMDoc::Document& mDocument; CSVWidget::SceneToolbar* mToolbar; std::string mTitle; + CSVWidget::SceneToolMode *mEditMode; public: @@ -58,6 +60,8 @@ namespace CSVWorld virtual std::string getTitle() const; + virtual void updateUserSetting (const QString& name, const QStringList& value); + private: void makeConnections(CSVRender::PagedWorldspaceWidget* widget); From caa119f13c7599736b7e7466371d09c92cd696db Mon Sep 17 00:00:00 2001 From: "Alexander \"Ace\" Olofsson" Date: Thu, 24 Sep 2015 15:55:38 +0200 Subject: [PATCH 03/84] Fix instantiation on non-Visual Studio --- apps/openmw/mwworld/store.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index b647a6c88..7a471eaa4 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -1029,7 +1029,8 @@ namespace MWWorld // Script //========================================================================= - inline void Store::load(ESM::ESMReader &esm, const std::string &id) { + template <> + void Store::load(ESM::ESMReader &esm, const std::string &id) { ESM::Script scpt; scpt.load(esm); Misc::StringUtils::toLower(scpt.mId); @@ -1045,7 +1046,8 @@ namespace MWWorld // StartScript //========================================================================= - inline void Store::load(ESM::ESMReader &esm, const std::string &id) + template <> + void Store::load(ESM::ESMReader &esm, const std::string &id) { ESM::StartScript s; s.load(esm); From 3ada08af90dab4440247ba4b3190b669e6b42b73 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 24 Sep 2015 16:07:17 +0200 Subject: [PATCH 04/84] store lock state and pass it on to edit mode --- apps/opencs/view/render/editmode.cpp | 5 +++++ apps/opencs/view/render/editmode.hpp | 3 +++ apps/opencs/view/world/scenesubview.cpp | 13 +++++++++++-- apps/opencs/view/world/scenesubview.hpp | 3 +++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/render/editmode.cpp b/apps/opencs/view/render/editmode.cpp index bf96fea3a..c3aad3f7a 100644 --- a/apps/opencs/view/render/editmode.cpp +++ b/apps/opencs/view/render/editmode.cpp @@ -21,3 +21,8 @@ void CSVRender::EditMode::updateUserSetting (const QString& name, const QStringL { } + +void CSVRender::EditMode::setEditLock (bool locked) +{ + +} diff --git a/apps/opencs/view/render/editmode.hpp b/apps/opencs/view/render/editmode.hpp index 381a6abcb..1212cd285 100644 --- a/apps/opencs/view/render/editmode.hpp +++ b/apps/opencs/view/render/editmode.hpp @@ -25,6 +25,9 @@ namespace CSVRender /// Default-implementation: Do nothing. virtual void updateUserSetting (const QString& name, const QStringList& value); + + /// Default-implementation: Ignored. + virtual void setEditLock (bool locked); }; } diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index f0b18dd86..967909969 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -28,7 +28,7 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) : SubView (id), mScene(NULL), mLayout(new QHBoxLayout), mDocument(document), mToolbar(NULL), - mEditMode (0) + mEditMode (0), mLocked (false) { QVBoxLayout *layout = new QVBoxLayout; @@ -131,7 +131,8 @@ CSVWidget::SceneToolbar* CSVWorld::SceneSubView::makeToolbar (CSVRender::Worldsp void CSVWorld::SceneSubView::setEditLock (bool locked) { - + mLocked = locked; + dynamic_cast (*mEditMode->getCurrent()).setEditLock (locked); } void CSVWorld::SceneSubView::setStatusBar (bool show) @@ -258,4 +259,12 @@ void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceW mScene->selectDefaultNavigationMode(); setFocusProxy (mScene); + + connect (mEditMode, SIGNAL (modeChanged (const std::string&)), + this, SLOT (editModeChanged (const std::string&))); +} + +void CSVWorld::SceneSubView::editModeChanged (const std::string& id) +{ + dynamic_cast (*mEditMode->getCurrent()).setEditLock (mLocked); } diff --git a/apps/opencs/view/world/scenesubview.hpp b/apps/opencs/view/world/scenesubview.hpp index 29aca5ab6..f59fee37f 100644 --- a/apps/opencs/view/world/scenesubview.hpp +++ b/apps/opencs/view/world/scenesubview.hpp @@ -47,6 +47,7 @@ namespace CSVWorld CSVWidget::SceneToolbar* mToolbar; std::string mTitle; CSVWidget::SceneToolMode *mEditMode; + bool mLocked; public: @@ -85,6 +86,8 @@ namespace CSVWorld void cellSelectionChanged (const CSMWorld::UniversalId& id); void handleDrop(const std::vector& data); + + void editModeChanged (const std::string& id); }; } From d597bef2cda32eea1c12d623d0956d6e18b05976 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 Sep 2015 10:58:20 +0200 Subject: [PATCH 05/84] refined selection related user settings --- apps/opencs/model/settings/usersettings.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 3daf7f9ec..5cc60c318 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -399,11 +399,12 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() secondaryEditing->setDeclaredValues (values); secondaryEditing->setDefaultValue (cRight); - values << "Context Sensitive"; - Setting *selection = createSetting (Type_ComboBox, "select", "Selection Button"); selection->setDeclaredValues (values); selection->setDefaultValue (middle); + + Setting *contextSensitive = createSetting (Type_CheckBox, "context-select", "Context Sensitive Selection"); + contextSensitive->setDefaultValue ("false"); } { From 5c34a0205804dd718cc4d6efe26ee3be51b37101 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 Sep 2015 13:11:40 +0200 Subject: [PATCH 06/84] store mouse bindings in WorldspaceWidget --- apps/opencs/view/render/worldspacewidget.cpp | 57 +++++++++++++++++++- apps/opencs/view/render/worldspacewidget.hpp | 6 +++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 2eb84d0a2..5d866fc6c 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -18,6 +18,8 @@ #include "../../model/world/universalid.hpp" #include "../../model/world/idtable.hpp" +#include "../../model/settings/usersettings.hpp" + #include "../widget/scenetoolmode.hpp" #include "../widget/scenetooltoggle2.hpp" #include "../widget/scenetoolrun.hpp" @@ -26,6 +28,17 @@ #include "elements.hpp" #include "editmode.hpp" +namespace +{ + static const char * const sMappingSettings[] = + { + "p-navi", "s-navi", + "p-edit", "s-edit", + "select", + 0 + }; +} + CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent) : SceneWidget (document.getData().getResourceSystem(), parent), mSceneElements(0), mRun(0), mDocument(document), mInteractionMask (0) @@ -59,6 +72,13 @@ CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidg this, SLOT (debugProfileDataChanged (const QModelIndex&, const QModelIndex&))); connect (debugProfiles, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)), this, SLOT (debugProfileAboutToBeRemoved (const QModelIndex&, int, int))); + + for (int i=0; sMappingSettings[i]; ++i) + { + QString key ("scene-input/"); + key += sMappingSettings[i]; + storeMappingSetting (key, CSMSettings::UserSettings::instance().settingValue (key)); + } } CSVRender::WorldspaceWidget::~WorldspaceWidget () @@ -256,7 +276,8 @@ unsigned int CSVRender::WorldspaceWidget::getInteractionMask() const void CSVRender::WorldspaceWidget::updateUserSetting (const QString& name, const QStringList& value) { - + if (!value.isEmpty() && storeMappingSetting (name, value.first())) + return; } void CSVRender::WorldspaceWidget::addVisibilitySelectorButtons ( @@ -293,6 +314,40 @@ void CSVRender::WorldspaceWidget::dragMoveEvent(QDragMoveEvent *event) event->accept(); } + +bool CSVRender::WorldspaceWidget::storeMappingSetting (const QString& key, const QString& value) +{ + const QString prefix = "scene-input/"; + + if (key.startsWith (prefix)) + { + QString key2 (key.mid (prefix.length())); + + for (int i=0; sMappingSettings[i]; ++i) + if (key2==sMappingSettings[i]) + { + std::cout<<"button :"< (event->mimeData()); diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index c3796af34..23f672fbd 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -1,6 +1,8 @@ #ifndef OPENCS_VIEW_WORLDSPACEWIDGET_H #define OPENCS_VIEW_WORLDSPACEWIDGET_H +#include + #include #include "scenewidget.hpp" @@ -31,6 +33,7 @@ namespace CSVRender CSVWidget::SceneToolRun *mRun; CSMDoc::Document& mDocument; unsigned int mInteractionMask; + std::map, std::string> mButtonMapping; public: @@ -120,6 +123,9 @@ namespace CSVRender void dragMoveEvent(QDragMoveEvent *event); + /// \return Is \a key a button mapping setting? (ignored otherwise) + bool storeMappingSetting (const QString& key, const QString& value); + virtual std::string getStartupInstruction() = 0; private slots: From d46eeb04cd49d3543e3800707789fde4bdf8cadf Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 25 Sep 2015 14:16:41 +0200 Subject: [PATCH 07/84] removed a left-over debugging statement --- apps/opencs/view/render/worldspacewidget.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 5d866fc6c..834762a67 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -326,7 +326,6 @@ bool CSVRender::WorldspaceWidget::storeMappingSetting (const QString& key, const for (int i=0; sMappingSettings[i]; ++i) if (key2==sMappingSettings[i]) { - std::cout<<"button :"< Date: Fri, 25 Sep 2015 14:18:08 +0200 Subject: [PATCH 08/84] scripts: recognize '+' also as a unary operator it fixes the armor sorter in "Blades safe house.esp" --- components/compiler/exprparser.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index b588b6196..53b24eab6 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -650,8 +650,13 @@ namespace Compiler mOperators.push_back ('m'); mTokenLoc = loc; return true; + } else if (code ==Scanner::S_plus && mNextOperand) { + // Also unary, but +, just ignore it + mTokenLoc = loc; + return true; } + if (code==Scanner::S_open) { if (mNextOperand) From 2fff6b06cc604b436fe075232b2e11c5242385b0 Mon Sep 17 00:00:00 2001 From: Emmanuel Anne Date: Thu, 24 Sep 2015 16:42:10 +0200 Subject: [PATCH 09/84] removed items by mods do not break cell loading like fortify intelligence potions removed by sris_alchemy which break the loading of the firewatch mages guild --- apps/openmw/mwworld/containerstore.cpp | 59 ++++++++++++++------------ 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 8c6f7d259..5a26f09f5 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -411,41 +411,48 @@ void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std:: void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, int count, bool topLevel, const std::string& levItem) { - ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id, count); + try { + ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id, count); - if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name()) - { - const ESM::ItemLevList* levItem = ref.getPtr().get()->mBase; - - if (topLevel && std::abs(count) > 1 && levItem->mFlags & ESM::ItemLevList::Each) + if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name()) { - for (int i=0; i 0 ? 1 : -1, true, levItem->mId); - return; + const ESM::ItemLevList* levItem = ref.getPtr().get()->mBase; + + if (topLevel && std::abs(count) > 1 && levItem->mFlags & ESM::ItemLevList::Each) + { + for (int i=0; i 0 ? 1 : -1, true, levItem->mId); + return; + } + else + { + std::string id = MWMechanics::getLevelledItem(ref.getPtr().get()->mBase, false); + if (id.empty()) + return; + addInitialItem(id, owner, count, false, levItem->mId); + } } else { - std::string id = MWMechanics::getLevelledItem(ref.getPtr().get()->mBase, false); - if (id.empty()) - return; - addInitialItem(id, owner, count, false, levItem->mId); + // A negative count indicates restocking items + // For a restocking levelled item, remember what we spawned so we can delete it later when the merchant restocks + if (!levItem.empty() && count < 0) + { + if (mLevelledItemMap.find(id) == mLevelledItemMap.end()) + mLevelledItemMap[id] = 0; + mLevelledItemMap[id] += std::abs(count); + } + count = std::abs(count); + + ref.getPtr().getCellRef().setOwner(owner); + addImp (ref.getPtr(), count); } } - else + catch (const std::exception& e) { - // A negative count indicates restocking items - // For a restocking levelled item, remember what we spawned so we can delete it later when the merchant restocks - if (!levItem.empty() && count < 0) - { - if (mLevelledItemMap.find(id) == mLevelledItemMap.end()) - mLevelledItemMap[id] = 0; - mLevelledItemMap[id] += std::abs(count); - } - count = std::abs(count); - - ref.getPtr().getCellRef().setOwner(owner); - addImp (ref.getPtr(), count); + std::cerr << "Error in MWWorld::ContainerStore::addInitialItem: " << e.what() << std::endl; } + } void MWWorld::ContainerStore::restock (const ESM::InventoryList& items, const MWWorld::Ptr& ptr, const std::string& owner) From 169d76b49b7b304b44170a6a042b627dd2c29e1f Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 Sep 2015 01:20:20 +0200 Subject: [PATCH 10/84] Fix scrollbar step in count dialog --- files/mygui/openmw_count_window.layout | 2 ++ 1 file changed, 2 insertions(+) diff --git a/files/mygui/openmw_count_window.layout b/files/mygui/openmw_count_window.layout index e9a1cb2c8..27b62ebf0 100644 --- a/files/mygui/openmw_count_window.layout +++ b/files/mygui/openmw_count_window.layout @@ -13,6 +13,8 @@ + + From 8e69c80bf60456687491e975c92ab39eaf314cfd Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 Sep 2015 01:21:33 +0200 Subject: [PATCH 11/84] Add framenumber checks in various cull callbacks, so we don't update more than once per frame when multiple cameras are used --- components/nifosg/nifloader.cpp | 13 ++++++++++++- components/sceneutil/riggeometry.cpp | 11 +++++++---- components/sceneutil/riggeometry.hpp | 2 +- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 54a02c950..75a427c5a 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -113,6 +113,7 @@ namespace // NodeCallback used to have a transform always oriented towards the camera. Can have translation and scale // set just like a regular MatrixTransform, but the rotation set will be overridden in order to face the camera. + // Must be set as a cull callback. class BillboardCallback : public osg::NodeCallback { public: @@ -160,24 +161,34 @@ namespace struct UpdateMorphGeometry : public osg::Drawable::CullCallback { UpdateMorphGeometry() + : mLastFrameNumber(0) { } UpdateMorphGeometry(const UpdateMorphGeometry& copy, const osg::CopyOp& copyop) : osg::Drawable::CullCallback(copy, copyop) + , mLastFrameNumber(0) { } META_Object(NifOsg, UpdateMorphGeometry) - virtual bool cull(osg::NodeVisitor *, osg::Drawable * drw, osg::State *) const + virtual bool cull(osg::NodeVisitor* nv, osg::Drawable * drw, osg::State *) const { osgAnimation::MorphGeometry* geom = static_cast(drw); if (!geom) return false; + + if (mLastFrameNumber == nv->getFrameStamp()->getFrameNumber()) + return false; + mLastFrameNumber = nv->getFrameStamp()->getFrameNumber(); + geom->transformSoftwareMethod(); return false; } + + private: + mutable unsigned int mLastFrameNumber; }; // Callback to return a static bounding box for a MorphGeometry. The idea is to not recalculate the bounding box diff --git a/components/sceneutil/riggeometry.cpp b/components/sceneutil/riggeometry.cpp index 2a67c6ce6..8eb08f546 100644 --- a/components/sceneutil/riggeometry.cpp +++ b/components/sceneutil/riggeometry.cpp @@ -60,7 +60,7 @@ public: RigGeometry::RigGeometry() : mSkeleton(NULL) - , mFirstFrame(true) + , mLastFrameNumber(0) , mBoundsFirstFrame(true) { setCullCallback(new UpdateRigGeometry); @@ -72,7 +72,7 @@ RigGeometry::RigGeometry(const RigGeometry ©, const osg::CopyOp ©op) : osg::Geometry(copy, copyop) , mSkeleton(NULL) , mInfluenceMap(copy.mInfluenceMap) - , mFirstFrame(copy.mFirstFrame) + , mLastFrameNumber(0) , mBoundsFirstFrame(copy.mBoundsFirstFrame) { setSourceGeometry(copy.mSourceGeometry); @@ -206,9 +206,12 @@ void RigGeometry::update(osg::NodeVisitor* nv) return; } - if (!mSkeleton->getActive() && !mFirstFrame) + if (!mSkeleton->getActive() && mLastFrameNumber != 0) return; - mFirstFrame = false; + + if (mLastFrameNumber == nv->getFrameStamp()->getFrameNumber()) + return; + mLastFrameNumber = nv->getFrameStamp()->getFrameNumber(); mSkeleton->updateBoneMatrices(nv); diff --git a/components/sceneutil/riggeometry.hpp b/components/sceneutil/riggeometry.hpp index bd7c586c4..e51fc0cf6 100644 --- a/components/sceneutil/riggeometry.hpp +++ b/components/sceneutil/riggeometry.hpp @@ -64,7 +64,7 @@ namespace SceneUtil BoneSphereMap mBoneSphereMap; - bool mFirstFrame; + unsigned int mLastFrameNumber; bool mBoundsFirstFrame; bool initFromParentSkeleton(osg::NodeVisitor* nv); From b9c6a6862a328cc044793a5c8547ca9e67ec9406 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 Sep 2015 01:49:58 +0200 Subject: [PATCH 12/84] Don't reset god mode, scripts enabled and sky enabled flags when loading a save game These flags aren't stored in the save file, so it makes no sense to reset them to their default each time a save game is loaded. Instead, reset on "new game". --- apps/openmw/mwworld/worldimp.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 3ff7a750a..585786136 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -204,6 +204,10 @@ namespace MWWorld mLevitationEnabled = true; mTeleportEnabled = true; + mGodMode = false; + mScriptsEnabled = true; + mSky = true; + // Rebuild player setupPlayer(); @@ -297,9 +301,6 @@ namespace MWWorld mDoorStates.clear(); - mGodMode = false; - mScriptsEnabled = true; - mSky = true; mTeleportEnabled = true; mLevitationEnabled = true; From 387624e1580d4345dcbd3a3ae3a695de94bdd377 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 Sep 2015 01:55:12 +0200 Subject: [PATCH 13/84] Add a threshold to AiFollow distance Idle animations can move the actor around slightly, which sometimes causes AiFollow to constantly toggle between "arrived" and "following" state even when the player isn't moving. Could be observed by summoning a bonelord. --- apps/openmw/mwmechanics/aifollow.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index cd67c6058..d9356da93 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -20,8 +20,9 @@ namespace MWMechanics struct AiFollowStorage : AiTemporaryBase { float mTimer; + bool mMoving; - AiFollowStorage() : mTimer(0.f) {} + AiFollowStorage() : mTimer(0.f), mMoving(false) {} }; int AiFollow::mFollowIndexCounter = 0; @@ -64,10 +65,11 @@ bool AiFollow::execute (const MWWorld::Ptr& actor, CharacterController& characte actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing); + AiFollowStorage& storage = state.get(); + // AiFollow requires the target to be in range and within sight for the initial activation if (!mActive) { - AiFollowStorage& storage = state.get(); storage.mTimer -= duration; if (storage.mTimer < 0) @@ -126,7 +128,15 @@ bool AiFollow::execute (const MWWorld::Ptr& actor, CharacterController& characte //Set the target destination from the actor ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; - if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < followDistance) //Stop when you get close + float dist = distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]); + const float threshold = 10; + + if (storage.mMoving) //Stop when you get close + storage.mMoving = (dist > followDistance); + else + storage.mMoving = (dist > followDistance + threshold); + + if(!storage.mMoving) { actor.getClass().getMovementSettings(actor).mPosition[1] = 0; @@ -141,9 +151,9 @@ bool AiFollow::execute (const MWWorld::Ptr& actor, CharacterController& characte } //Check if you're far away - if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) > 450) + if(dist > 450) actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, true); //Make NPC run - else if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 325) //Have a bit of a dead zone, otherwise npc will constantly flip between running and not when right on the edge of the running threshhold + else if(dist < 325) //Have a bit of a dead zone, otherwise npc will constantly flip between running and not when right on the edge of the running threshhold actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, false); //make NPC walk return false; From 899e35591c24c5cd90d88f680c8a5011b32ab79c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 26 Sep 2015 02:08:23 +0200 Subject: [PATCH 14/84] Escape MyGUI markup codes in console output --- apps/openmw/mwgui/console.cpp | 10 +++++----- apps/openmw/mwgui/console.hpp | 5 ++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index 083dd32b0..761f7d164 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -170,25 +170,25 @@ namespace MWGui mCommandLine->setFontName(fntName); } - void Console::print(const std::string &msg) + void Console::print(const std::string &msg, const std::string& color) { - mHistory->addText(msg); + mHistory->addText(color + MyGUI::TextIterator::toTagsString(msg)); } void Console::printOK(const std::string &msg) { - print("#FF00FF" + msg + "\n"); + print(msg + "\n", "#FF00FF"); } void Console::printError(const std::string &msg) { - print("#FF2222" + msg + "\n"); + print(msg + "\n", "#FF2222"); } void Console::execute (const std::string& command) { // Log the command - print("#FFFFFF> " + command + "\n"); + print("> " + command + "\n"); Compiler::Locals locals; Compiler::Output output (locals); diff --git a/apps/openmw/mwgui/console.hpp b/apps/openmw/mwgui/console.hpp index 09a05be48..98e46a559 100644 --- a/apps/openmw/mwgui/console.hpp +++ b/apps/openmw/mwgui/console.hpp @@ -48,9 +48,8 @@ namespace MWGui void onResChange(int width, int height); - // Print a message to the console. Messages may contain color - // code, eg. "#FFFFFF this is white". - void print(const std::string &msg); + // Print a message to the console, in specified color. + void print(const std::string &msg, const std::string& color = "#FFFFFF"); // These are pre-colored versions that you should use. From ae54f34f25ce08a2abc5ee9a162292940d256c84 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 26 Sep 2015 11:30:35 +0200 Subject: [PATCH 15/84] removed a redundant else and made unary + work also in the console --- components/compiler/exprparser.cpp | 6 ++++-- components/compiler/lineparser.cpp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index 53b24eab6..c0375b436 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -650,13 +650,15 @@ namespace Compiler mOperators.push_back ('m'); mTokenLoc = loc; return true; - } else if (code ==Scanner::S_plus && mNextOperand) { + } + + if (code ==Scanner::S_plus && mNextOperand) + { // Also unary, but +, just ignore it mTokenLoc = loc; return true; } - if (code==Scanner::S_open) { if (mNextOperand) diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 032af7d65..c1622c3e0 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -555,7 +555,7 @@ namespace Compiler } if (mAllowExpression && mState==BeginState && - (code==Scanner::S_open || code==Scanner::S_minus)) + (code==Scanner::S_open || code==Scanner::S_minus || code==Scanner::S_plus)) { scanner.putbackSpecial (code, loc); parseExpression (scanner, loc); From 435e52306a0b1a7ef4cf7059bbc388b3262d2631 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 26 Sep 2015 11:34:46 +0200 Subject: [PATCH 16/84] adjusted a workaround for names starting with digits that interfered with some numerical expressions written without spaces --- components/compiler/scanner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index f25e69e39..3c5bb7747 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -175,7 +175,7 @@ namespace Compiler { value += c; } - else if (isStringCharacter (c)) + else if (c!='-' && isStringCharacter (c)) { error = true; value += c; From 748b13b45b5b08ac0184dd3cb8acd4ef30f5302a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 26 Sep 2015 12:05:44 +0200 Subject: [PATCH 17/84] renamed ObjectHolder into ObjectTag --- apps/opencs/view/render/object.cpp | 2 +- apps/opencs/view/render/object.hpp | 4 ++-- apps/opencs/view/render/worldspacewidget.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/opencs/view/render/object.cpp b/apps/opencs/view/render/object.cpp index f05e311f9..c7485c891 100644 --- a/apps/opencs/view/render/object.cpp +++ b/apps/opencs/view/render/object.cpp @@ -124,7 +124,7 @@ CSVRender::Object::Object (CSMWorld::Data& data, osg::Group* parentNode, mOutline = new osgFX::Scribe; mOutline->addChild(mBaseNode); - mBaseNode->setUserData(new ObjectHolder(this)); + mBaseNode->setUserData(new ObjectTag(this)); parentNode->addChild(mBaseNode); diff --git a/apps/opencs/view/render/object.hpp b/apps/opencs/view/render/object.hpp index 9b3749069..1a1295b53 100644 --- a/apps/opencs/view/render/object.hpp +++ b/apps/opencs/view/render/object.hpp @@ -39,10 +39,10 @@ namespace CSVRender class Object; // An object to attach as user data to the osg::Node, allows us to get an Object back from a Node when we are doing a ray query - class ObjectHolder : public osg::Referenced + class ObjectTag : public osg::Referenced { public: - ObjectHolder(Object* obj) + ObjectTag (Object* obj) : mObject(obj) { } diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 834762a67..378b5bea9 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -463,7 +463,7 @@ void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event) for (std::vector::iterator it = intersection.nodePath.begin(); it != intersection.nodePath.end(); ++it) { osg::Node* node = *it; - if (CSVRender::ObjectHolder* holder = dynamic_cast(node->getUserData())) + if (CSVRender::ObjectTag* holder = dynamic_cast(node->getUserData())) { // hit an Object, toggle its selection state CSVRender::Object* obj = holder->mObject; From 71247a018652cf5ac4894e1f242daccd971e41bb Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 26 Sep 2015 12:18:18 +0200 Subject: [PATCH 18/84] inserted TagBase between ObjectTag and osg::Referenced --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/render/object.cpp | 5 +++++ apps/opencs/view/render/object.hpp | 17 ++++++++--------- apps/opencs/view/render/tagbase.cpp | 9 +++++++++ apps/opencs/view/render/tagbase.hpp | 22 ++++++++++++++++++++++ 5 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 apps/opencs/view/render/tagbase.cpp create mode 100644 apps/opencs/view/render/tagbase.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index f9a73a09f..cfa938473 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -90,7 +90,7 @@ opencs_units (view/render opencs_units_noqt (view/render lighting lightingday lightingnight - lightingbright object cell terrainstorage + lightingbright object cell terrainstorage tagbase ) opencs_hdrs_noqt (view/render diff --git a/apps/opencs/view/render/object.cpp b/apps/opencs/view/render/object.cpp index c7485c891..ac96cb283 100644 --- a/apps/opencs/view/render/object.cpp +++ b/apps/opencs/view/render/object.cpp @@ -38,6 +38,11 @@ namespace } +CSVRender::ObjectTag::ObjectTag (Object* object) +: TagBase (Element_Reference), mObject (object) +{} + + void CSVRender::Object::clear() { } diff --git a/apps/opencs/view/render/object.hpp b/apps/opencs/view/render/object.hpp index 1a1295b53..0858a2edb 100644 --- a/apps/opencs/view/render/object.hpp +++ b/apps/opencs/view/render/object.hpp @@ -8,8 +8,9 @@ #include #include -class QModelIndex; +#include "tagbase.hpp" +class QModelIndex; namespace osg { @@ -35,21 +36,19 @@ namespace CSMWorld namespace CSVRender { - class Object; // An object to attach as user data to the osg::Node, allows us to get an Object back from a Node when we are doing a ray query - class ObjectTag : public osg::Referenced + class ObjectTag : public TagBase { - public: - ObjectTag (Object* obj) - : mObject(obj) - { - } + public: + + ObjectTag (Object* object); - Object* mObject; + Object* mObject; }; + class Object { const CSMWorld::Data& mData; diff --git a/apps/opencs/view/render/tagbase.cpp b/apps/opencs/view/render/tagbase.cpp new file mode 100644 index 000000000..af9a37624 --- /dev/null +++ b/apps/opencs/view/render/tagbase.cpp @@ -0,0 +1,9 @@ + +#include "tagbase.hpp" + +CSVRender::TagBase::TagBase (Elements element) : mElement (element) {} + +CSVRender::Elements CSVRender::TagBase::getElement() const +{ + return mElement; +} diff --git a/apps/opencs/view/render/tagbase.hpp b/apps/opencs/view/render/tagbase.hpp new file mode 100644 index 000000000..874b856c6 --- /dev/null +++ b/apps/opencs/view/render/tagbase.hpp @@ -0,0 +1,22 @@ +#ifndef OPENCS_VIEW_TAGBASE_H +#define OPENCS_VIEW_TAGBASE_H + +#include + +#include "elements.hpp" + +namespace CSVRender +{ + class TagBase : public osg::Referenced + { + Elements mElement; + + public: + + TagBase (Elements element); + + Elements getElement() const; + }; +} + +#endif From 72bb33c2c479ef82eebe5c07450c0f4388848891 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 26 Sep 2015 12:24:41 +0200 Subject: [PATCH 19/84] filter mouse interaction by interaction mask --- apps/opencs/view/render/worldspacewidget.cpp | 21 ++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 378b5bea9..246f6a4bf 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -463,18 +463,27 @@ void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event) for (std::vector::iterator it = intersection.nodePath.begin(); it != intersection.nodePath.end(); ++it) { osg::Node* node = *it; - if (CSVRender::ObjectTag* holder = dynamic_cast(node->getUserData())) + if (CSVRender::TagBase* tag = dynamic_cast(node->getUserData())) { - // hit an Object, toggle its selection state - CSVRender::Object* obj = holder->mObject; - obj->setSelected(!obj->getSelected()); + if (!(tag->getElement() && mInteractionMask)) + break; // not interested -> continue looking + + // hit something marked with a tag + if (CSVRender::ObjectTag *objectTag = dynamic_cast (tag)) + { + // hit an Object, toggle its selection state + CSVRender::Object* object = objectTag->mObject; + object->setSelected (!object->getSelected()); + } + return; } } +// ignoring terrain for now // must be terrain, report coordinates - std::cout << "Terrain hit at " << intersection.getWorldIntersectPoint().x() << " " << intersection.getWorldIntersectPoint().y() << std::endl; - return; +// std::cout << "Terrain hit at " << intersection.getWorldIntersectPoint().x() << " " << intersection.getWorldIntersectPoint().y() << std::endl; +// return; } } From 3844c94975d18f7b98a3cd19f7e57ec310df636c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 26 Sep 2015 17:39:55 +0200 Subject: [PATCH 20/84] bit masking fix --- apps/opencs/view/render/worldspacewidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 246f6a4bf..42f81eea4 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -465,7 +465,7 @@ void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event) osg::Node* node = *it; if (CSVRender::TagBase* tag = dynamic_cast(node->getUserData())) { - if (!(tag->getElement() && mInteractionMask)) + if (!(tag->getElement() & mInteractionMask)) break; // not interested -> continue looking // hit something marked with a tag From 501ae6372d60a6d6932f5ed72719da6196fcc665 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 26 Sep 2015 17:51:41 +0200 Subject: [PATCH 21/84] factored out mouse picking into a separate function --- apps/opencs/view/render/worldspacewidget.cpp | 97 +++++++++++--------- apps/opencs/view/render/worldspacewidget.hpp | 4 + 2 files changed, 57 insertions(+), 44 deletions(-) diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 42f81eea4..15978e0e1 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -347,6 +347,53 @@ bool CSVRender::WorldspaceWidget::storeMappingSetting (const QString& key, const return false; } +osg::ref_ptr CSVRender::WorldspaceWidget::mousePick (QMouseEvent *event) +{ + // (0,0) is considered the lower left corner of an OpenGL window + int x = event->x(); + int y = height() - event->y(); + + osg::ref_ptr intersector (new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, x, y)); + + intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::NO_LIMIT); + osgUtil::IntersectionVisitor visitor(intersector); + + visitor.setTraversalMask(getInteractionMask() << 1); + + mView->getCamera()->accept(visitor); + + for (osgUtil::LineSegmentIntersector::Intersections::iterator it = intersector->getIntersections().begin(); + it != intersector->getIntersections().end(); ++it) + { + osgUtil::LineSegmentIntersector::Intersection intersection = *it; + + // reject back-facing polygons + osg::Vec3f normal = intersection.getWorldIntersectNormal(); + normal = osg::Matrix::transform3x3(normal, mView->getCamera()->getViewMatrix()); + if (normal.z() < 0) + continue; + + for (std::vector::iterator it = intersection.nodePath.begin(); it != intersection.nodePath.end(); ++it) + { + osg::Node* node = *it; + if (osg::ref_ptr tag = dynamic_cast(node->getUserData())) + { + if (!(tag->getElement() & mInteractionMask)) + break; // not interested -> continue looking + + return tag; + } + } + +// ignoring terrain for now + // must be terrain, report coordinates +// std::cout << "Terrain hit at " << intersection.getWorldIntersectPoint().x() << " " << intersection.getWorldIntersectPoint().y() << std::endl; +// return; + } + + return osg::ref_ptr(); +} + void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event) { const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); @@ -436,54 +483,16 @@ void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event) if (event->button() != Qt::RightButton) return; - // (0,0) is considered the lower left corner of an OpenGL window - int x = event->x(); - int y = height() - event->y(); - - osg::ref_ptr intersector (new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, x, y)); - - intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::NO_LIMIT); - osgUtil::IntersectionVisitor visitor(intersector); - - visitor.setTraversalMask(getInteractionMask() << 1); - - mView->getCamera()->accept(visitor); + osg::ref_ptr tag = mousePick (event); - for (osgUtil::LineSegmentIntersector::Intersections::iterator it = intersector->getIntersections().begin(); - it != intersector->getIntersections().end(); ++it) + if (tag) { - osgUtil::LineSegmentIntersector::Intersection intersection = *it; - - // reject back-facing polygons - osg::Vec3f normal = intersection.getWorldIntersectNormal(); - normal = osg::Matrix::transform3x3(normal, mView->getCamera()->getViewMatrix()); - if (normal.z() < 0) - continue; - - for (std::vector::iterator it = intersection.nodePath.begin(); it != intersection.nodePath.end(); ++it) + if (CSVRender::ObjectTag *objectTag = dynamic_cast (tag.get())) { - osg::Node* node = *it; - if (CSVRender::TagBase* tag = dynamic_cast(node->getUserData())) - { - if (!(tag->getElement() & mInteractionMask)) - break; // not interested -> continue looking - - // hit something marked with a tag - if (CSVRender::ObjectTag *objectTag = dynamic_cast (tag)) - { - // hit an Object, toggle its selection state - CSVRender::Object* object = objectTag->mObject; - object->setSelected (!object->getSelected()); - } - - return; - } + // hit an Object, toggle its selection state + CSVRender::Object* object = objectTag->mObject; + object->setSelected (!object->getSelected()); } - -// ignoring terrain for now - // must be terrain, report coordinates -// std::cout << "Terrain hit at " << intersection.getWorldIntersectPoint().x() << " " << intersection.getWorldIntersectPoint().y() << std::endl; -// return; } } diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 23f672fbd..90a85006f 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -25,6 +25,8 @@ namespace CSVWidget namespace CSVRender { + class TagBase; + class WorldspaceWidget : public SceneWidget { Q_OBJECT @@ -126,6 +128,8 @@ namespace CSVRender /// \return Is \a key a button mapping setting? (ignored otherwise) bool storeMappingSetting (const QString& key, const QString& value); + osg::ref_ptr mousePick (QMouseEvent *event); + virtual std::string getStartupInstruction() = 0; private slots: From 7bbc475bda71ea8d87ca63933c3d8c0c21dc2841 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 26 Sep 2015 18:01:49 +0200 Subject: [PATCH 22/84] apply button mapping --- apps/opencs/view/render/worldspacewidget.cpp | 37 +++++++++++++++----- apps/opencs/view/render/worldspacewidget.hpp | 2 ++ 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 15978e0e1..5b5219184 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -394,6 +395,20 @@ osg::ref_ptr CSVRender::WorldspaceWidget::mousePick (QMouseE return osg::ref_ptr(); } +std::string CSVRender::WorldspaceWidget::mapButton (QMouseEvent *event) +{ + std::pair phyiscal ( + event->button(), QApplication::keyboardModifiers() & Qt::ControlModifier); + + std::map, std::string>::const_iterator iter = + mButtonMapping.find (phyiscal); + + if (iter!=mButtonMapping.end()) + return iter->second; + + return ""; +} + void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event) { const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); @@ -480,18 +495,24 @@ void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event) void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event) { - if (event->button() != Qt::RightButton) - return; + std::string button = mapButton (event); - osg::ref_ptr tag = mousePick (event); + if (button=="p-navi" || button=="s-navi") + { - if (tag) + } + else if (button=="p-edit" || button=="s-edit" || button=="select") { - if (CSVRender::ObjectTag *objectTag = dynamic_cast (tag.get())) + osg::ref_ptr tag = mousePick (event); + + if (tag) { - // hit an Object, toggle its selection state - CSVRender::Object* object = objectTag->mObject; - object->setSelected (!object->getSelected()); + if (CSVRender::ObjectTag *objectTag = dynamic_cast (tag.get())) + { + // hit an Object, toggle its selection state + CSVRender::Object* object = objectTag->mObject; + object->setSelected (!object->getSelected()); + } } } } diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 90a85006f..ed5c5bcc8 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -130,6 +130,8 @@ namespace CSVRender osg::ref_ptr mousePick (QMouseEvent *event); + std::string mapButton (QMouseEvent *event); + virtual std::string getStartupInstruction() = 0; private slots: From 5d9863aec12429aa086d54012da7638a4eb663bc Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 27 Sep 2015 11:34:14 +0200 Subject: [PATCH 23/84] removed a redundant check --- apps/opencs/view/render/worldspacewidget.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 5b5219184..70def97b9 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -378,12 +378,7 @@ osg::ref_ptr CSVRender::WorldspaceWidget::mousePick (QMouseE { osg::Node* node = *it; if (osg::ref_ptr tag = dynamic_cast(node->getUserData())) - { - if (!(tag->getElement() & mInteractionMask)) - break; // not interested -> continue looking - return tag; - } } // ignoring terrain for now From 9bf27c7e371e4b1fdf01b356210a7bb9d02d58d5 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 27 Sep 2015 14:38:12 +0200 Subject: [PATCH 24/84] moved edit mode handling from SceneSubView to WorldspaceWidget --- apps/opencs/view/render/worldspacewidget.cpp | 23 ++++++++++++++++---- apps/opencs/view/render/worldspacewidget.hpp | 5 +++++ apps/opencs/view/world/scenesubview.cpp | 18 +++------------ apps/opencs/view/world/scenesubview.hpp | 4 ---- 4 files changed, 27 insertions(+), 23 deletions(-) diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 70def97b9..be4d32bb5 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -42,7 +42,7 @@ namespace CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent) : SceneWidget (document.getData().getResourceSystem(), parent), mSceneElements(0), mRun(0), mDocument(document), - mInteractionMask (0) + mInteractionMask (0), mEditMode (0), mLocked (false) { setAcceptDrops(true); @@ -199,11 +199,14 @@ CSVWidget::SceneToolRun *CSVRender::WorldspaceWidget::makeRunTool ( CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeEditModeSelector ( CSVWidget::SceneToolbar *parent) { - CSVWidget::SceneToolMode *tool = new CSVWidget::SceneToolMode (parent, "Edit Mode"); + mEditMode = new CSVWidget::SceneToolMode (parent, "Edit Mode"); - addEditModeSelectorButtons (tool); + addEditModeSelectorButtons (mEditMode); - return tool; + connect (mEditMode, SIGNAL (modeChanged (const std::string&)), + this, SLOT (editModeChanged (const std::string&))); + + return mEditMode; } CSVRender::WorldspaceWidget::DropType CSVRender::WorldspaceWidget::getDropType ( @@ -279,6 +282,13 @@ void CSVRender::WorldspaceWidget::updateUserSetting (const QString& name, const { if (!value.isEmpty() && storeMappingSetting (name, value.first())) return; + + dynamic_cast (*mEditMode->getCurrent()).updateUserSetting (name, value); +} + +void CSVRender::WorldspaceWidget::setEditLock (bool locked) +{ + dynamic_cast (*mEditMode->getCurrent()).setEditLock (locked); } void CSVRender::WorldspaceWidget::addVisibilitySelectorButtons ( @@ -468,6 +478,11 @@ void CSVRender::WorldspaceWidget::debugProfileAboutToBeRemoved (const QModelInde } } +void CSVRender::WorldspaceWidget::editModeChanged (const std::string& id) +{ + dynamic_cast (*mEditMode->getCurrent()).setEditLock (mLocked); +} + void CSVRender::WorldspaceWidget::elementSelectionChanged() { setVisibilityMask (getVisibilityMask()); diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index ed5c5bcc8..272987a05 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -36,6 +36,8 @@ namespace CSVRender CSMDoc::Document& mDocument; unsigned int mInteractionMask; std::map, std::string> mButtonMapping; + CSVWidget::SceneToolMode *mEditMode; + bool mLocked; public: @@ -100,6 +102,8 @@ namespace CSVRender virtual void updateUserSetting (const QString& name, const QStringList& value); + virtual void setEditLock (bool locked); + protected: virtual void addVisibilitySelectorButtons (CSVWidget::SceneToolToggle2 *tool); @@ -158,6 +162,7 @@ namespace CSVRender void debugProfileAboutToBeRemoved (const QModelIndex& parent, int start, int end); + void editModeChanged (const std::string& id); protected slots: diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index 967909969..753d791c0 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -27,8 +27,7 @@ #include "creator.hpp" CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) -: SubView (id), mScene(NULL), mLayout(new QHBoxLayout), mDocument(document), mToolbar(NULL), - mEditMode (0), mLocked (false) +: SubView (id), mScene(NULL), mLayout(new QHBoxLayout), mDocument(document), mToolbar(NULL) { QVBoxLayout *layout = new QVBoxLayout; @@ -123,16 +122,14 @@ CSVWidget::SceneToolbar* CSVWorld::SceneSubView::makeToolbar (CSVRender::Worldsp CSVWidget::SceneToolRun *runTool = widget->makeRunTool (toolbar); toolbar->addTool (runTool); - mEditMode = widget->makeEditModeSelector (toolbar); - toolbar->addTool (mEditMode); + toolbar->addTool (widget->makeEditModeSelector (toolbar)); return toolbar; } void CSVWorld::SceneSubView::setEditLock (bool locked) { - mLocked = locked; - dynamic_cast (*mEditMode->getCurrent()).setEditLock (locked); + mScene->setEditLock (locked); } void CSVWorld::SceneSubView::setStatusBar (bool show) @@ -153,7 +150,6 @@ std::string CSVWorld::SceneSubView::getTitle() const void CSVWorld::SceneSubView::updateUserSetting (const QString& name, const QStringList& value) { mScene->updateUserSetting (name, value); - dynamic_cast (*mEditMode->getCurrent()).updateUserSetting (name, value); CSVDoc::SubView::updateUserSetting (name, value); } @@ -259,12 +255,4 @@ void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceW mScene->selectDefaultNavigationMode(); setFocusProxy (mScene); - - connect (mEditMode, SIGNAL (modeChanged (const std::string&)), - this, SLOT (editModeChanged (const std::string&))); -} - -void CSVWorld::SceneSubView::editModeChanged (const std::string& id) -{ - dynamic_cast (*mEditMode->getCurrent()).setEditLock (mLocked); } diff --git a/apps/opencs/view/world/scenesubview.hpp b/apps/opencs/view/world/scenesubview.hpp index f59fee37f..2458d58f4 100644 --- a/apps/opencs/view/world/scenesubview.hpp +++ b/apps/opencs/view/world/scenesubview.hpp @@ -46,8 +46,6 @@ namespace CSVWorld CSMDoc::Document& mDocument; CSVWidget::SceneToolbar* mToolbar; std::string mTitle; - CSVWidget::SceneToolMode *mEditMode; - bool mLocked; public: @@ -86,8 +84,6 @@ namespace CSVWorld void cellSelectionChanged (const CSMWorld::UniversalId& id); void handleDrop(const std::vector& data); - - void editModeChanged (const std::string& id); }; } From 981a8a2cc2754fe5f9c9abc5e1b42b86f091dc3d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 27 Sep 2015 16:18:22 +0200 Subject: [PATCH 25/84] delegated editing and selection functions to mode objects --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/render/editmode.cpp | 6 ++++ apps/opencs/view/render/editmode.hpp | 12 +++++++ apps/opencs/view/render/instancemode.cpp | 35 ++++++++++++++++++++ apps/opencs/view/render/instancemode.hpp | 24 ++++++++++++++ apps/opencs/view/render/worldspacewidget.cpp | 22 ++++++------ 6 files changed, 88 insertions(+), 13 deletions(-) create mode 100644 apps/opencs/view/render/instancemode.cpp create mode 100644 apps/opencs/view/render/instancemode.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index cfa938473..2ed55218a 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -85,7 +85,7 @@ opencs_units (view/widget opencs_units (view/render scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget - previewwidget editmode + previewwidget editmode instancemode ) opencs_units_noqt (view/render diff --git a/apps/opencs/view/render/editmode.cpp b/apps/opencs/view/render/editmode.cpp index c3aad3f7a..2240318b6 100644 --- a/apps/opencs/view/render/editmode.cpp +++ b/apps/opencs/view/render/editmode.cpp @@ -26,3 +26,9 @@ void CSVRender::EditMode::setEditLock (bool locked) { } + +void CSVRender::EditMode::primaryEditPressed (osg::ref_ptr tag) {} + +void CSVRender::EditMode::secondaryEditPressed (osg::ref_ptr tag) {} + +void CSVRender::EditMode::selectPressed (osg::ref_ptr tag) {} diff --git a/apps/opencs/view/render/editmode.hpp b/apps/opencs/view/render/editmode.hpp index 1212cd285..c00669534 100644 --- a/apps/opencs/view/render/editmode.hpp +++ b/apps/opencs/view/render/editmode.hpp @@ -1,11 +1,14 @@ #ifndef CSV_RENDER_EDITMODE_H #define CSV_RENDER_EDITMODE_H +#include + #include "../widget/modebutton.hpp" namespace CSVRender { class WorldspaceWidget; + class TagBase; class EditMode : public CSVWidget::ModeButton { @@ -28,6 +31,15 @@ namespace CSVRender /// Default-implementation: Ignored. virtual void setEditLock (bool locked); + + /// Default-implementation: Ignored. + virtual void primaryEditPressed (osg::ref_ptr tag); + + /// Default-implementation: Ignored. + virtual void secondaryEditPressed (osg::ref_ptr tag); + + /// Default-implementation: Ignored. + virtual void selectPressed (osg::ref_ptr tag); }; } diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp new file mode 100644 index 000000000..ccff8c7c5 --- /dev/null +++ b/apps/opencs/view/render/instancemode.cpp @@ -0,0 +1,35 @@ + +#include "instancemode.hpp" + +#include "elements.hpp" +#include "object.hpp" + +CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent) +: EditMode (worldspaceWidget, QIcon (":placeholder"), Element_Reference, "Instance editing", + parent) +{ + +} + +void CSVRender::InstanceMode::primaryEditPressed (osg::ref_ptr tag) +{ + +} + +void CSVRender::InstanceMode::secondaryEditPressed (osg::ref_ptr tag) +{ + +} + +void CSVRender::InstanceMode::selectPressed (osg::ref_ptr tag) +{ + if (tag) + { + if (CSVRender::ObjectTag *objectTag = dynamic_cast (tag.get())) + { + // hit an Object, toggle its selection state + CSVRender::Object* object = objectTag->mObject; + object->setSelected (!object->getSelected()); + } + } +} diff --git a/apps/opencs/view/render/instancemode.hpp b/apps/opencs/view/render/instancemode.hpp new file mode 100644 index 000000000..6071aedf0 --- /dev/null +++ b/apps/opencs/view/render/instancemode.hpp @@ -0,0 +1,24 @@ +#ifndef CSV_RENDER_INSTANCEMODE_H +#define CSV_RENDER_INSTANCEMODE_H + +#include "editmode.hpp" + +namespace CSVRender +{ + class InstanceMode : public EditMode + { + Q_OBJECT + + public: + + InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent = 0); + + virtual void primaryEditPressed (osg::ref_ptr tag); + + virtual void secondaryEditPressed (osg::ref_ptr tag); + + virtual void selectPressed (osg::ref_ptr tag); + }; +} + +#endif diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index be4d32bb5..1c1dc4d6b 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -28,6 +28,7 @@ #include "object.hpp" #include "elements.hpp" #include "editmode.hpp" +#include "instancemode.hpp" namespace { @@ -302,9 +303,7 @@ void CSVRender::WorldspaceWidget::addVisibilitySelectorButtons ( void CSVRender::WorldspaceWidget::addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool) { /// \todo replace EditMode with suitable subclasses - tool->addButton ( - new EditMode (this, QIcon (":placeholder"), Element_Reference, "Instance editing"), - "object"); + tool->addButton (new InstanceMode (this, tool), "object"); tool->addButton ( new EditMode (this, QIcon (":placeholder"), Element_Pathgrid, "Pathgrid editing"), "pathgrid"); @@ -515,15 +514,14 @@ void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event) { osg::ref_ptr tag = mousePick (event); - if (tag) - { - if (CSVRender::ObjectTag *objectTag = dynamic_cast (tag.get())) - { - // hit an Object, toggle its selection state - CSVRender::Object* object = objectTag->mObject; - object->setSelected (!object->getSelected()); - } - } + EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); + + if (button=="p-edit") + editMode.primaryEditPressed (tag); + else if (button=="s-edit") + editMode.secondaryEditPressed (tag); + else if (button=="select") + editMode.selectPressed (tag); } } From 319e3f24a3d23e158adbc3e46f0f80dc55e5206f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 29 Sep 2015 13:48:04 +0200 Subject: [PATCH 26/84] on edit mode change clear selection of elements that are not affected by current edit mode (only support for instance for now since we do not have selection for other elements yet) --- apps/opencs/view/render/cell.cpp | 21 +++++++++++++++++++ apps/opencs/view/render/cell.hpp | 11 ++++++++++ apps/opencs/view/render/editmode.cpp | 1 + .../view/render/pagedworldspacewidget.cpp | 7 +++++++ .../view/render/pagedworldspacewidget.hpp | 3 +++ .../view/render/unpagedworldspacewidget.cpp | 5 +++++ .../view/render/unpagedworldspacewidget.hpp | 3 +++ apps/opencs/view/render/worldspacewidget.hpp | 10 ++++++--- 8 files changed, 58 insertions(+), 3 deletions(-) diff --git a/apps/opencs/view/render/cell.cpp b/apps/opencs/view/render/cell.cpp index 28a48cfbd..c4f744510 100644 --- a/apps/opencs/view/render/cell.cpp +++ b/apps/opencs/view/render/cell.cpp @@ -211,3 +211,24 @@ bool CSVRender::Cell::referenceAdded (const QModelIndex& parent, int start, int return addObjects (start, end); } + +void CSVRender::Cell::setSelection (int elementMask, Selection mode) +{ + if (elementMask & Element_Reference) + { + for (std::map::const_iterator iter (mObjects.begin()); + iter!=mObjects.end(); ++iter) + { + bool selected = false; + + switch (mode) + { + case Selection_Clear: selected = false; break; + case Selection_All: selected = true; break; + case Selection_Invert: selected = !iter->second->getSelected(); break; + } + + iter->second->setSelected (selected); + } + } +} diff --git a/apps/opencs/view/render/cell.hpp b/apps/opencs/view/render/cell.hpp index f4272b887..d26a2d9af 100644 --- a/apps/opencs/view/render/cell.hpp +++ b/apps/opencs/view/render/cell.hpp @@ -49,6 +49,15 @@ namespace CSVRender /// \return Have any objects been added? bool addObjects (int start, int end); + public: + + enum Selection + { + Selection_Clear, + Selection_All, + Selection_Invert + }; + public: Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id); @@ -75,6 +84,8 @@ namespace CSVRender /// \return Did this call result in a modification of the visual representation of /// this cell? bool referenceAdded (const QModelIndex& parent, int start, int end); + + void setSelection (int elementMask, Selection mode); }; } diff --git a/apps/opencs/view/render/editmode.cpp b/apps/opencs/view/render/editmode.cpp index 2240318b6..e1f69a63d 100644 --- a/apps/opencs/view/render/editmode.cpp +++ b/apps/opencs/view/render/editmode.cpp @@ -15,6 +15,7 @@ unsigned int CSVRender::EditMode::getInteractionMask() const void CSVRender::EditMode::activate (CSVWidget::SceneToolbar *toolbar) { mWorldspaceWidget->setInteractionMask (mMask); + mWorldspaceWidget->clearSelection (~mMask); } void CSVRender::EditMode::updateUserSetting (const QString& name, const QStringList& value) diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index b0c1e74a9..543f3788a 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -314,6 +314,13 @@ unsigned int CSVRender::PagedWorldspaceWidget::getVisibilityMask() const return WorldspaceWidget::getVisibilityMask() | mControlElements->getSelection(); } +void CSVRender::PagedWorldspaceWidget::clearSelection (int elementMask) +{ + for (std::map::iterator iter = mCells.begin(); + iter!=mCells.end(); ++iter) + iter->second->setSelection (elementMask, Cell::Selection_Clear); +} + CSVWidget::SceneToolToggle *CSVRender::PagedWorldspaceWidget::makeControlVisibilitySelector ( CSVWidget::SceneToolbar *parent) { diff --git a/apps/opencs/view/render/pagedworldspacewidget.hpp b/apps/opencs/view/render/pagedworldspacewidget.hpp index 64a0bccd1..d52efd90e 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.hpp +++ b/apps/opencs/view/render/pagedworldspacewidget.hpp @@ -79,6 +79,9 @@ namespace CSVRender virtual unsigned int getVisibilityMask() const; + /// \param elementMask Elements to be affected by the clear operation + virtual void clearSelection (int elementMask); + protected: virtual void addVisibilitySelectorButtons (CSVWidget::SceneToolToggle2 *tool); diff --git a/apps/opencs/view/render/unpagedworldspacewidget.cpp b/apps/opencs/view/render/unpagedworldspacewidget.cpp index 3e1733c81..989c976ff 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.cpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.cpp @@ -102,6 +102,11 @@ bool CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vectorsetSelection (elementMask, Cell::Selection_Clear); +} + void CSVRender::UnpagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight) { diff --git a/apps/opencs/view/render/unpagedworldspacewidget.hpp b/apps/opencs/view/render/unpagedworldspacewidget.hpp index d01c3e766..9e6fa97f4 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.hpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.hpp @@ -43,6 +43,9 @@ namespace CSVRender virtual bool handleDrop (const std::vector& data, DropType type); + /// \param elementMask Elements to be affected by the clear operation + virtual void clearSelection (int elementMask); + private: virtual void referenceableDataChanged (const QModelIndex& topLeft, diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 272987a05..ffdcf3bc3 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -5,10 +5,11 @@ #include -#include "scenewidget.hpp" +#include "../../model/doc/document.hpp" +#include "../../model/world/tablemimedata.hpp" -#include -#include +#include "scenewidget.hpp" +#include "elements.hpp" namespace CSMWorld { @@ -104,6 +105,9 @@ namespace CSVRender virtual void setEditLock (bool locked); + /// \param elementMask Elements to be affected by the clear operation + virtual void clearSelection (int elementMask) = 0; + protected: virtual void addVisibilitySelectorButtons (CSVWidget::SceneToolToggle2 *tool); From f28fa9fc16ec1477b1de18bf078a5d16af2b34aa Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 29 Sep 2015 13:53:47 +0200 Subject: [PATCH 27/84] clear instance selection on select click on nothing/something that isn't an instance --- apps/opencs/view/render/editmode.cpp | 5 +++++ apps/opencs/view/render/editmode.hpp | 4 ++++ apps/opencs/view/render/instancemode.cpp | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/apps/opencs/view/render/editmode.cpp b/apps/opencs/view/render/editmode.cpp index e1f69a63d..816067107 100644 --- a/apps/opencs/view/render/editmode.cpp +++ b/apps/opencs/view/render/editmode.cpp @@ -2,6 +2,11 @@ #include "worldspacewidget.hpp" +CSVRender::WorldspaceWidget& CSVRender::EditMode::getWorldspaceWidget() +{ + return *mWorldspaceWidget; +} + CSVRender::EditMode::EditMode (WorldspaceWidget *worldspaceWidget, const QIcon& icon, unsigned int mask, const QString& tooltip, QWidget *parent) : ModeButton (icon, tooltip, parent), mWorldspaceWidget (worldspaceWidget), mMask (mask) diff --git a/apps/opencs/view/render/editmode.hpp b/apps/opencs/view/render/editmode.hpp index c00669534..fa2beedd8 100644 --- a/apps/opencs/view/render/editmode.hpp +++ b/apps/opencs/view/render/editmode.hpp @@ -17,6 +17,10 @@ namespace CSVRender WorldspaceWidget *mWorldspaceWidget; unsigned int mMask; + protected: + + WorldspaceWidget& getWorldspaceWidget(); + public: EditMode (WorldspaceWidget *worldspaceWidget, const QIcon& icon, unsigned int mask, diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp index ccff8c7c5..2e8f8cda2 100644 --- a/apps/opencs/view/render/instancemode.cpp +++ b/apps/opencs/view/render/instancemode.cpp @@ -3,6 +3,7 @@ #include "elements.hpp" #include "object.hpp" +#include "worldspacewidget.hpp" CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent) : EditMode (worldspaceWidget, QIcon (":placeholder"), Element_Reference, "Instance editing", @@ -30,6 +31,9 @@ void CSVRender::InstanceMode::selectPressed (osg::ref_ptr tag) // hit an Object, toggle its selection state CSVRender::Object* object = objectTag->mObject; object->setSelected (!object->getSelected()); + return; } } + + getWorldspaceWidget().clearSelection (Element_Reference); } From 2cb106f6adfe5f8f7f94079077de0d43f41f8a44 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 29 Sep 2015 16:06:55 +0200 Subject: [PATCH 28/84] added missing flagAsModified calls --- apps/opencs/view/render/pagedworldspacewidget.cpp | 2 ++ apps/opencs/view/render/unpagedworldspacewidget.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index 543f3788a..7403113b3 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -319,6 +319,8 @@ void CSVRender::PagedWorldspaceWidget::clearSelection (int elementMask) for (std::map::iterator iter = mCells.begin(); iter!=mCells.end(); ++iter) iter->second->setSelection (elementMask, Cell::Selection_Clear); + + flagAsModified(); } CSVWidget::SceneToolToggle *CSVRender::PagedWorldspaceWidget::makeControlVisibilitySelector ( diff --git a/apps/opencs/view/render/unpagedworldspacewidget.cpp b/apps/opencs/view/render/unpagedworldspacewidget.cpp index 989c976ff..68f068dac 100644 --- a/apps/opencs/view/render/unpagedworldspacewidget.cpp +++ b/apps/opencs/view/render/unpagedworldspacewidget.cpp @@ -105,6 +105,7 @@ bool CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vectorsetSelection (elementMask, Cell::Selection_Clear); + flagAsModified(); } void CSVRender::UnpagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft, From 8e87b48866e66c1546c7d7f7914f9ab4f7fd015e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 29 Sep 2015 16:07:14 +0200 Subject: [PATCH 29/84] handle context-sensitive select mode in instance editing --- apps/opencs/view/render/instancemode.cpp | 23 ++++++++++++++++++++--- apps/opencs/view/render/instancemode.hpp | 6 ++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp index 2e8f8cda2..333d91656 100644 --- a/apps/opencs/view/render/instancemode.cpp +++ b/apps/opencs/view/render/instancemode.cpp @@ -1,25 +1,42 @@ #include "instancemode.hpp" +#include "../../model/settings/usersettings.hpp" + #include "elements.hpp" #include "object.hpp" #include "worldspacewidget.hpp" CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent) : EditMode (worldspaceWidget, QIcon (":placeholder"), Element_Reference, "Instance editing", - parent) + parent), mContextSelect (false) { } -void CSVRender::InstanceMode::primaryEditPressed (osg::ref_ptr tag) +void CSVRender::InstanceMode::activate (CSVWidget::SceneToolbar *toolbar) { + EditMode::activate (toolbar); + mContextSelect = CSMSettings::UserSettings::instance().setting ("scene-input/context-select")=="true"; } -void CSVRender::InstanceMode::secondaryEditPressed (osg::ref_ptr tag) +void CSVRender::InstanceMode::updateUserSetting (const QString& name, const QStringList& value) +{ + if (name=="scene-input/context-select") + mContextSelect = value.at (0)=="true"; +} + +void CSVRender::InstanceMode::primaryEditPressed (osg::ref_ptr tag) { + if (mContextSelect) + selectPressed (tag); +} +void CSVRender::InstanceMode::secondaryEditPressed (osg::ref_ptr tag) +{ + if (mContextSelect) + selectPressed (tag); } void CSVRender::InstanceMode::selectPressed (osg::ref_ptr tag) diff --git a/apps/opencs/view/render/instancemode.hpp b/apps/opencs/view/render/instancemode.hpp index 6071aedf0..cc4fd5434 100644 --- a/apps/opencs/view/render/instancemode.hpp +++ b/apps/opencs/view/render/instancemode.hpp @@ -9,10 +9,16 @@ namespace CSVRender { Q_OBJECT + bool mContextSelect; + public: InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent = 0); + virtual void activate (CSVWidget::SceneToolbar *toolbar); + + virtual void updateUserSetting (const QString& name, const QStringList& value); + virtual void primaryEditPressed (osg::ref_ptr tag); virtual void secondaryEditPressed (osg::ref_ptr tag); From 3f27c856300671083123d3027cf7b6299bc01438 Mon Sep 17 00:00:00 2001 From: "artemutin@yandex.ru" Date: Tue, 29 Sep 2015 10:46:03 +1000 Subject: [PATCH 30/84] Added StartScriptCreator class with redefined getErrors method. --- apps/opencs/view/world/startscriptcreator.cpp | 26 +++++++++++++++++++ apps/opencs/view/world/startscriptcreator.hpp | 25 ++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 apps/opencs/view/world/startscriptcreator.cpp create mode 100644 apps/opencs/view/world/startscriptcreator.hpp diff --git a/apps/opencs/view/world/startscriptcreator.cpp b/apps/opencs/view/world/startscriptcreator.cpp new file mode 100644 index 000000000..5812cd931 --- /dev/null +++ b/apps/opencs/view/world/startscriptcreator.cpp @@ -0,0 +1,26 @@ +#include "startscriptcreator.hpp" + +StartScriptCreator::StartScriptCreator() +{ + +} + + +CSVWORLD::StartScriptCreator::StartScriptCreator(CSMWorld::Data &data, QUndoStack &undoStack, const CSMWorld::UniversalId &id, bool relaxedIdRules): + GenericCreator (data, undoStack, id, true) +{} + +std::string CSVWORLD::StartScriptCreator::getErrors() const +{ + std::string errors; + + errors = getIdValidatorResult(); + if (errors.length() > 0) + return errors; + else if (getData().getScripts().searchId(getId()) == -1) + errors = "Script ID not found"; + else if (getData().getStartScripts().searchId(getId()) > -1 ) + errors = "Script with this ID already registered as Start Script"; + + return errors; +} diff --git a/apps/opencs/view/world/startscriptcreator.hpp b/apps/opencs/view/world/startscriptcreator.hpp new file mode 100644 index 000000000..4c91ad96a --- /dev/null +++ b/apps/opencs/view/world/startscriptcreator.hpp @@ -0,0 +1,25 @@ +#ifndef STARTSCRIPTCREATOR_HPP +#define STARTSCRIPTCREATOR_HPP + +#include "genericcreator.hpp" + +namespace CSVWORLD { + + class StartScriptCreator : public GenericCreator + { + Q_OBJECT + + public: + StartScriptCreator(CSMWorld::Data& data, QUndoStack& undoStack, + const CSMWorld::UniversalId& id, bool relaxedIdRules = false); + + virtual std::string getErrors() const; + ///< Return formatted error descriptions for the current state of the creator. if an empty + /// string is returned, there is no error. + }; + +} + + + +#endif // STARTSCRIPTCREATOR_HPP From e672880f644066716452d363b61eff1c56010b0f Mon Sep 17 00:00:00 2001 From: "artemutin@yandex.ru" Date: Tue, 29 Sep 2015 22:43:20 +1000 Subject: [PATCH 31/84] Fix namespace, add file to CMakeLists.txt --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/world/startscriptcreator.cpp | 10 ++-------- apps/opencs/view/world/startscriptcreator.hpp | 4 ++-- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index f9a73a09f..c428cd27a 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -67,7 +67,7 @@ opencs_hdrs_noqt (view/doc opencs_units (view/world table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator - cellcreator referenceablecreator referencecreator scenesubview + cellcreator referenceablecreator startscriptcreator referencecreator scenesubview infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable nestedtable dialoguespinbox recordbuttonbar tableeditidaction scripterrortable extendedcommandconfigurator ) diff --git a/apps/opencs/view/world/startscriptcreator.cpp b/apps/opencs/view/world/startscriptcreator.cpp index 5812cd931..69b1b3ff1 100644 --- a/apps/opencs/view/world/startscriptcreator.cpp +++ b/apps/opencs/view/world/startscriptcreator.cpp @@ -1,16 +1,10 @@ #include "startscriptcreator.hpp" -StartScriptCreator::StartScriptCreator() -{ - -} - - -CSVWORLD::StartScriptCreator::StartScriptCreator(CSMWorld::Data &data, QUndoStack &undoStack, const CSMWorld::UniversalId &id, bool relaxedIdRules): +CSVWorld::StartScriptCreator::StartScriptCreator(CSMWorld::Data &data, QUndoStack &undoStack, const CSMWorld::UniversalId &id, bool relaxedIdRules): GenericCreator (data, undoStack, id, true) {} -std::string CSVWORLD::StartScriptCreator::getErrors() const +std::string CSVWorld::StartScriptCreator::getErrors() const { std::string errors; diff --git a/apps/opencs/view/world/startscriptcreator.hpp b/apps/opencs/view/world/startscriptcreator.hpp index 4c91ad96a..07fe8ff3d 100644 --- a/apps/opencs/view/world/startscriptcreator.hpp +++ b/apps/opencs/view/world/startscriptcreator.hpp @@ -3,7 +3,7 @@ #include "genericcreator.hpp" -namespace CSVWORLD { +namespace CSVWorld { class StartScriptCreator : public GenericCreator { @@ -16,7 +16,7 @@ namespace CSVWORLD { virtual std::string getErrors() const; ///< Return formatted error descriptions for the current state of the creator. if an empty /// string is returned, there is no error. - }; + }; } From 903cd3322b2a24e4d0a757ede8e429583f34f2b4 Mon Sep 17 00:00:00 2001 From: "artemutin@yandex.ru" Date: Tue, 29 Sep 2015 22:44:25 +1000 Subject: [PATCH 32/84] add getIdValidatorResult method to GenericCreator, for use in subclass StartScriptCreator --- apps/opencs/view/world/genericcreator.cpp | 10 ++++++++++ apps/opencs/view/world/genericcreator.hpp | 2 ++ 2 files changed, 12 insertions(+) diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index 8ed52bf80..df7739941 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -47,6 +47,16 @@ std::string CSVWorld::GenericCreator::getId() const return mId->text().toUtf8().constData(); } +std::string CSVWorld::GenericCreator::getIdValidatorResult() const +{ + std::string errors; + + if (!mId->hasAcceptableInput()) + errors = mValidator->getError(); + + return errors; +} + void CSVWorld::GenericCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const {} void CSVWorld::GenericCreator::pushCommand (std::auto_ptr command, diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index 471d0622e..f63c45109 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -60,6 +60,8 @@ namespace CSVWorld virtual std::string getId() const; + virtual std::string getIdValidatorResult() const; + /// Allow subclasses to add additional data to \a command. virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const; From ecce3a197550cd8b689e7d2bf697461325a7c6b9 Mon Sep 17 00:00:00 2001 From: "artemutin@yandex.ru" Date: Tue, 29 Sep 2015 23:52:35 +1000 Subject: [PATCH 33/84] Add StartScriptCreator to a factory manager. --- apps/opencs/view/world/subviews.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index 299ac6ebe..88375caaf 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -10,6 +10,7 @@ #include "cellcreator.hpp" #include "referenceablecreator.hpp" #include "referencecreator.hpp" +#include "startscriptcreator.hpp" #include "scenesubview.hpp" #include "dialoguecreator.hpp" #include "infocreator.hpp" @@ -42,7 +43,6 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CSMWorld::UniversalId::Type_BodyParts, CSMWorld::UniversalId::Type_SoundGens, CSMWorld::UniversalId::Type_Pathgrids, - CSMWorld::UniversalId::Type_StartScripts, CSMWorld::UniversalId::Type_None // end marker }; @@ -51,6 +51,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) manager.add (sTableTypes[i], new CSVDoc::SubViewFactoryWithCreator >); + manager.add (CSMWorld::UniversalId::Type_StartScripts, + new CSVDoc::SubViewFactoryWithCreator >); + manager.add (CSMWorld::UniversalId::Type_Cells, new CSVDoc::SubViewFactoryWithCreator >); @@ -123,7 +126,6 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CSMWorld::UniversalId::Type_BodyPart, CSMWorld::UniversalId::Type_SoundGen, CSMWorld::UniversalId::Type_Pathgrid, - CSMWorld::UniversalId::Type_StartScript, CSMWorld::UniversalId::Type_None // end marker }; @@ -133,6 +135,10 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) new CSVDoc::SubViewFactoryWithCreator > (false)); + manager.add (CSMWorld::UniversalId::Type_StartScript, + new CSVDoc::SubViewFactoryWithCreator > (false)); + manager.add (CSMWorld::UniversalId::Type_Skill, new CSVDoc::SubViewFactoryWithCreator (false)); From 64902bf22112d0b44464f7657b12db86627cdd38 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 30 Sep 2015 09:44:05 +0200 Subject: [PATCH 34/84] updated credits file --- AUTHORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.md b/AUTHORS.md index 8e9d35cf2..e968d1d01 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -19,6 +19,7 @@ Programmers Alexander Nadeau (wareya) Alexander Olofsson (Ace) Artem Kotsynyak (greye) + artemutin Arthur Moore (EmperorArthur) athile Bret Curtis (psi29a) From 0a5bfb2107ddf46465ce74902470dc7056eb279b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 1 Oct 2015 12:46:01 +0200 Subject: [PATCH 35/84] added framework for drag operations --- apps/opencs/view/render/editmode.cpp | 21 ++++++ apps/opencs/view/render/editmode.hpp | 27 +++++++ apps/opencs/view/render/worldspacewidget.cpp | 75 +++++++++++++++++--- apps/opencs/view/render/worldspacewidget.hpp | 4 ++ 4 files changed, 116 insertions(+), 11 deletions(-) diff --git a/apps/opencs/view/render/editmode.cpp b/apps/opencs/view/render/editmode.cpp index 816067107..e1ab619cd 100644 --- a/apps/opencs/view/render/editmode.cpp +++ b/apps/opencs/view/render/editmode.cpp @@ -38,3 +38,24 @@ void CSVRender::EditMode::primaryEditPressed (osg::ref_ptr tag) {} void CSVRender::EditMode::secondaryEditPressed (osg::ref_ptr tag) {} void CSVRender::EditMode::selectPressed (osg::ref_ptr tag) {} + +bool CSVRender::EditMode::primaryEditStartDrag (osg::ref_ptr tag) +{ + return false; +} + +bool CSVRender::EditMode::secondaryEditStartDrag (osg::ref_ptr tag) +{ + return false; +} + +bool CSVRender::EditMode::selectStartDrag (osg::ref_ptr tag) +{ + return false; +} + +void CSVRender::EditMode::drag (int diffX, int diffY) {} + +void CSVRender::EditMode::dragCompleted() {} + +void CSVRender::EditMode::dragAborted() {} diff --git a/apps/opencs/view/render/editmode.hpp b/apps/opencs/view/render/editmode.hpp index fa2beedd8..361ffc5ed 100644 --- a/apps/opencs/view/render/editmode.hpp +++ b/apps/opencs/view/render/editmode.hpp @@ -44,6 +44,33 @@ namespace CSVRender /// Default-implementation: Ignored. virtual void selectPressed (osg::ref_ptr tag); + + /// Default-implementation: ignore and return false + /// + /// \return Drag accepted? + virtual bool primaryEditStartDrag (osg::ref_ptr tag); + + /// Default-implementation: ignore and return false + /// + /// \return Drag accepted? + virtual bool secondaryEditStartDrag (osg::ref_ptr tag); + + /// Default-implementation: ignore and return false + /// + /// \return Drag accepted? + virtual bool selectStartDrag (osg::ref_ptr tag); + + /// Default-implementation: ignored + virtual void drag (int diffX, int diffY); + + /// Default-implementation: ignored + virtual void dragCompleted(); + + /// Default-implementation: ignored + /// + /// \note dragAborted will not be called, if the drag is aborted via changing + /// editing mode + virtual void dragAborted(); }; } diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 1c1dc4d6b..25ee56a05 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -43,7 +43,7 @@ namespace CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent) : SceneWidget (document.getData().getResourceSystem(), parent), mSceneElements(0), mRun(0), mDocument(document), - mInteractionMask (0), mEditMode (0), mLocked (false) + mInteractionMask (0), mEditMode (0), mLocked (false), mDragging (false) { setAcceptDrops(true); @@ -480,6 +480,7 @@ void CSVRender::WorldspaceWidget::debugProfileAboutToBeRemoved (const QModelInde void CSVRender::WorldspaceWidget::editModeChanged (const std::string& id) { dynamic_cast (*mEditMode->getCurrent()).setEditLock (mLocked); + mDragging = false; } void CSVRender::WorldspaceWidget::elementSelectionChanged() @@ -495,10 +496,45 @@ void CSVRender::WorldspaceWidget::updateOverlay() void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event) { - if(event->buttons() & Qt::RightButton) + if (!mDragging) { - //mMouse->mouseMoveEvent(event); + if (mDragMode=="p-navi" || mDragMode=="s-navi") + { + + } + else if (mDragMode=="p-edit" || mDragMode=="s-edit" || mDragMode=="select") + { + osg::ref_ptr tag = mousePick (event); + + EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); + + if (mDragMode=="p-edit") + mDragging = editMode.primaryEditStartDrag (tag); + else if (mDragMode=="s-edit") + mDragging = editMode.secondaryEditStartDrag (tag); + else if (mDragMode=="select") + mDragging = editMode.selectStartDrag (tag); + + if (mDragging) + { + mDragX = event->posF().x(); + mDragY = height() - event->posF().y(); + } + } + } + else + { + int diffX = event->x() - mDragX; + int diffY = (height() - event->y()) - mDragY; + + mDragX = event->x(); + mDragY = height() - event->y(); + + EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); + + editMode.drag (diffX, diffY); } + RenderWidget::mouseMoveEvent(event); } @@ -506,6 +542,9 @@ void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event) { std::string button = mapButton (event); + if (!mDragging) + mDragMode = button; + if (button=="p-navi" || button=="s-navi") { @@ -527,17 +566,25 @@ void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event) void CSVRender::WorldspaceWidget::mouseReleaseEvent (QMouseEvent *event) { - if(event->button() == Qt::RightButton) + if (mDragging) { - /* - if(!getViewport()) + std::string button = mapButton (event); + + if (mDragMode=="p-navi" || mDragMode=="s-navi") { - SceneWidget::mouseReleaseEvent(event); - return; + + } + else if (mDragMode=="p-edit" || mDragMode=="s-edit" || mDragMode=="select") + { + EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); + + editMode.dragCompleted(); + mDragging = false; } - */ - //mMouse->mouseReleaseEvent(event); } + + mDragMode.clear(); + RenderWidget::mouseReleaseEvent(event); } @@ -560,7 +607,13 @@ void CSVRender::WorldspaceWidget::keyPressEvent (QKeyEvent *event) { if(event->key() == Qt::Key_Escape) { - //mMouse->cancelDrag(); + if (mDragging) + { + EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); + + editMode.dragAborted(); + mDragging = false; + } } else RenderWidget::keyPressEvent(event); diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index ffdcf3bc3..f51ce047e 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -39,6 +39,10 @@ namespace CSVRender std::map, std::string> mButtonMapping; CSVWidget::SceneToolMode *mEditMode; bool mLocked; + std::string mDragMode; + bool mDragging; + int mDragX; + int mDragY; public: From 1d4f8b2595b6f7d49d2dbc95590f5bdd2486dd68 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 1 Oct 2015 13:19:48 +0200 Subject: [PATCH 36/84] send mouse wheel input to active EditMode during drag operations --- apps/opencs/view/render/editmode.cpp | 2 ++ apps/opencs/view/render/editmode.hpp | 3 +++ apps/opencs/view/render/scenewidget.cpp | 2 ++ apps/opencs/view/render/worldspacewidget.cpp | 10 ++++++++-- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/render/editmode.cpp b/apps/opencs/view/render/editmode.cpp index e1ab619cd..cc76e3362 100644 --- a/apps/opencs/view/render/editmode.cpp +++ b/apps/opencs/view/render/editmode.cpp @@ -59,3 +59,5 @@ void CSVRender::EditMode::drag (int diffX, int diffY) {} void CSVRender::EditMode::dragCompleted() {} void CSVRender::EditMode::dragAborted() {} + +void CSVRender::EditMode::dragWheel (int diff) {} diff --git a/apps/opencs/view/render/editmode.hpp b/apps/opencs/view/render/editmode.hpp index 361ffc5ed..0a4bdf9b8 100644 --- a/apps/opencs/view/render/editmode.hpp +++ b/apps/opencs/view/render/editmode.hpp @@ -71,6 +71,9 @@ namespace CSVRender /// \note dragAborted will not be called, if the drag is aborted via changing /// editing mode virtual void dragAborted(); + + /// Default-implementation: ignored + virtual void dragWheel (int diff); }; } diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index fb3bcb3c3..76b3db348 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -110,6 +110,8 @@ bool RenderWidget::eventFilter(QObject* obj, QEvent* event) keyPressEvent(static_cast(event)); if (event->type() == QEvent::KeyRelease) keyReleaseEvent(static_cast(event)); + if (event->type() == QEvent::Wheel) + wheelEvent(static_cast(event)); // Always pass the event on to GLWidget, i.e. to OSG event queue return QObject::eventFilter(obj, event); diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 25ee56a05..3971f76fa 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -599,8 +599,14 @@ void CSVRender::WorldspaceWidget::mouseDoubleClickEvent (QMouseEvent *event) void CSVRender::WorldspaceWidget::wheelEvent (QWheelEvent *event) { - //if(!mMouse->wheelEvent(event)) - RenderWidget::wheelEvent(event); + if (mDragging) + { + EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); + + editMode.dragWheel (event->delta()); + } + + RenderWidget::wheelEvent(event); } void CSVRender::WorldspaceWidget::keyPressEvent (QKeyEvent *event) From 323f8bb29f04b7b48f0cbe4e5a04ac6a3f880e6e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 1 Oct 2015 13:42:21 +0200 Subject: [PATCH 37/84] sensitivity settings --- apps/opencs/model/settings/usersettings.cpp | 15 +++++++++++ apps/opencs/view/render/editmode.cpp | 4 +-- apps/opencs/view/render/editmode.hpp | 4 +-- apps/opencs/view/render/worldspacewidget.cpp | 27 +++++++++++++++++--- apps/opencs/view/render/worldspacewidget.hpp | 3 +++ 5 files changed, 46 insertions(+), 7 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 5cc60c318..3e5ab24d1 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -405,6 +405,21 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() Setting *contextSensitive = createSetting (Type_CheckBox, "context-select", "Context Sensitive Selection"); contextSensitive->setDefaultValue ("false"); + + Setting *dragMouseSensitivity = createSetting (Type_DoubleSpinBox, "drag-factor", + "Mouse sensitivity during drag operations"); + dragMouseSensitivity->setDefaultValue (1.0); + dragMouseSensitivity->setRange (0.001, 100.0); + + Setting *dragWheelSensitivity = createSetting (Type_DoubleSpinBox, "drag-wheel-factor", + "Mouse wheel sensitivity during drag operations"); + dragWheelSensitivity->setDefaultValue (1.0); + dragWheelSensitivity->setRange (0.001, 100.0); + + Setting *dragShiftFactor = createSetting (Type_DoubleSpinBox, "drag-shift-factor", + "Acceleration factor during drag operations while holding down shift"); + dragShiftFactor->setDefaultValue (4.0); + dragShiftFactor->setRange (0.001, 100.0); } { diff --git a/apps/opencs/view/render/editmode.cpp b/apps/opencs/view/render/editmode.cpp index cc76e3362..c35b4f354 100644 --- a/apps/opencs/view/render/editmode.cpp +++ b/apps/opencs/view/render/editmode.cpp @@ -54,10 +54,10 @@ bool CSVRender::EditMode::selectStartDrag (osg::ref_ptr tag) return false; } -void CSVRender::EditMode::drag (int diffX, int diffY) {} +void CSVRender::EditMode::drag (int diffX, int diffY, double speedFactor) {} void CSVRender::EditMode::dragCompleted() {} void CSVRender::EditMode::dragAborted() {} -void CSVRender::EditMode::dragWheel (int diff) {} +void CSVRender::EditMode::dragWheel (int diff, double speedFactor) {} diff --git a/apps/opencs/view/render/editmode.hpp b/apps/opencs/view/render/editmode.hpp index 0a4bdf9b8..77676d6a3 100644 --- a/apps/opencs/view/render/editmode.hpp +++ b/apps/opencs/view/render/editmode.hpp @@ -61,7 +61,7 @@ namespace CSVRender virtual bool selectStartDrag (osg::ref_ptr tag); /// Default-implementation: ignored - virtual void drag (int diffX, int diffY); + virtual void drag (int diffX, int diffY, double speedFactor); /// Default-implementation: ignored virtual void dragCompleted(); @@ -73,7 +73,7 @@ namespace CSVRender virtual void dragAborted(); /// Default-implementation: ignored - virtual void dragWheel (int diff); + virtual void dragWheel (int diff, double speedFactor); }; } diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 3971f76fa..2789cd9d5 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -81,6 +81,10 @@ CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidg key += sMappingSettings[i]; storeMappingSetting (key, CSMSettings::UserSettings::instance().settingValue (key)); } + + mDragFactor = CSMSettings::UserSettings::instance().settingValue ("scene-input/drag-factor").toDouble(); + mDragWheelFactor = CSMSettings::UserSettings::instance().settingValue ("scene-input/drag-wheel-factor").toDouble(); + mDragShiftFactor = CSMSettings::UserSettings::instance().settingValue ("scene-input/drag-shift-factor").toDouble(); } CSVRender::WorldspaceWidget::~WorldspaceWidget () @@ -284,7 +288,14 @@ void CSVRender::WorldspaceWidget::updateUserSetting (const QString& name, const if (!value.isEmpty() && storeMappingSetting (name, value.first())) return; - dynamic_cast (*mEditMode->getCurrent()).updateUserSetting (name, value); + if (name=="scene-input/drag-factor") + mDragFactor = value.at (0).toDouble(); + else if (name=="scene-input/drag-wheel-factor") + mDragWheelFactor = value.at (0).toDouble(); + else if (name=="scene-input/drag-shift-factor") + mDragShiftFactor = value.at (0).toDouble(); + else + dynamic_cast (*mEditMode->getCurrent()).updateUserSetting (name, value); } void CSVRender::WorldspaceWidget::setEditLock (bool locked) @@ -530,9 +541,14 @@ void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event) mDragX = event->x(); mDragY = height() - event->y(); + double factor = mDragFactor; + + if (QApplication::keyboardModifiers() & Qt::ShiftModifier) + factor *= mDragShiftFactor; + EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); - editMode.drag (diffX, diffY); + editMode.drag (diffX, diffY, factor); } RenderWidget::mouseMoveEvent(event); @@ -601,9 +617,14 @@ void CSVRender::WorldspaceWidget::wheelEvent (QWheelEvent *event) { if (mDragging) { + double factor = mDragWheelFactor; + + if (QApplication::keyboardModifiers() & Qt::ShiftModifier) + factor *= mDragShiftFactor; + EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); - editMode.dragWheel (event->delta()); + editMode.dragWheel (event->delta(), factor); } RenderWidget::wheelEvent(event); diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index f51ce047e..338ebcc97 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -43,6 +43,9 @@ namespace CSVRender bool mDragging; int mDragX; int mDragY; + double mDragFactor; + double mDragWheelFactor; + double mDragShiftFactor; public: From 4b0fa370e38f6791c5f48df9caf3d77719b62ad8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 2 Oct 2015 15:06:42 +0200 Subject: [PATCH 38/84] made WorldspaceWidget::getDocument public (EditModes will need the document later) --- apps/opencs/view/render/worldspacewidget.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 338ebcc97..f5e7970b6 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -112,6 +112,8 @@ namespace CSVRender virtual void setEditLock (bool locked); + CSMDoc::Document& getDocument(); + /// \param elementMask Elements to be affected by the clear operation virtual void clearSelection (int elementMask) = 0; @@ -121,8 +123,6 @@ namespace CSVRender virtual void addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool); - CSMDoc::Document& getDocument(); - virtual void updateOverlay(); virtual void mouseMoveEvent (QMouseEvent *event); From 0a8e2c0b215af1287f1d250a7f48fa2852e75610 Mon Sep 17 00:00:00 2001 From: Rohit Nirmal Date: Sat, 3 Oct 2015 00:07:08 -0500 Subject: [PATCH 39/84] Fix building OpenCS with Qt 5. --- apps/opencs/view/render/worldspacewidget.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 2789cd9d5..75dd800eb 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -528,8 +528,13 @@ void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event) if (mDragging) { +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + mDragX = event->localPos().x(); + mDragY = height() - event->localPos().y(); +#else mDragX = event->posF().x(); mDragY = height() - event->posF().y(); +#endif } } } From b4132faaea34d1d153735c80e84dcea715523b34 Mon Sep 17 00:00:00 2001 From: "Alexander \"Ace\" Olofsson" Date: Sun, 4 Oct 2015 16:27:05 +0200 Subject: [PATCH 40/84] Update editmode.cpp Fixes builds on Windows --- apps/opencs/view/render/editmode.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/opencs/view/render/editmode.cpp b/apps/opencs/view/render/editmode.cpp index c35b4f354..4235faf76 100644 --- a/apps/opencs/view/render/editmode.cpp +++ b/apps/opencs/view/render/editmode.cpp @@ -1,5 +1,6 @@ #include "editmode.hpp" +#include "tagbase.hpp" #include "worldspacewidget.hpp" CSVRender::WorldspaceWidget& CSVRender::EditMode::getWorldspaceWidget() From ec4fff588dd4c1222a1435e348a7e499482bdc92 Mon Sep 17 00:00:00 2001 From: "artemutin@yandex.ru" Date: Mon, 5 Oct 2015 23:07:13 +1000 Subject: [PATCH 41/84] uncomment updateActor call in buildPlayer for magicka recalc --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 12927101d..761c5ece9 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -295,7 +295,7 @@ namespace MWMechanics creatureStats.getSpells().add(*it); // forced update and current value adjustments - //mActors.updateActor (ptr, 0); + mActors.updateActor (ptr, 0); for (int i=0; i<3; ++i) { From 77cb438714963b70cee791ec5d592cf1c5fda2fb Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 5 Oct 2015 15:41:07 +0200 Subject: [PATCH 42/84] Fix potential case smashing issue --- apps/openmw/mwmechanics/spells.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index 6d7673a59..330d78a20 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -312,7 +312,7 @@ namespace MWMechanics bool Spells::canUsePower(const std::string &power) const { - std::map::const_iterator it = mUsedPowers.find(power); + std::map::const_iterator it = mUsedPowers.find(Misc::StringUtils::lowerCase(power)); if (it == mUsedPowers.end() || it->second + 24 <= MWBase::Environment::get().getWorld()->getTimeStamp()) return true; else @@ -321,7 +321,7 @@ namespace MWMechanics void Spells::usePower(const std::string &power) { - mUsedPowers[power] = MWBase::Environment::get().getWorld()->getTimeStamp(); + mUsedPowers[Misc::StringUtils::lowerCase(power)] = MWBase::Environment::get().getWorld()->getTimeStamp(); } void Spells::readState(const ESM::SpellState &state) From 7b6fe149f2770de7d019696b6e2f6d0bbb670c6e Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 5 Oct 2015 15:41:43 +0200 Subject: [PATCH 43/84] getSpellSuccessChance return 0 for used powers (Fixes #2944) --- apps/openmw/mwmechanics/spellcasting.cpp | 7 +++++++ apps/openmw/mwworld/worldimp.cpp | 4 ---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 6d6b9d950..70d097687 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -123,6 +123,9 @@ namespace MWMechanics } } + if (spell->mData.mType == ESM::Spell::ST_Power) + return stats.getSpells().canUsePower(spell->mId) ? 100 : 0; + if (spell->mData.mType != ESM::Spell::ST_Spell) return 100; @@ -817,6 +820,10 @@ namespace MWMechanics sndMgr->playSound3D(mCaster, "Spell Failure " + schools[school], 1.0f, 1.0f); return false; } + + // A power can be used once per 24h + if (spell->mData.mType == ESM::Spell::ST_Power) + stats.getSpells().usePower(spell->mId); } if (mCaster == getPlayer() && spellIncreasesSkill(spell)) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 585786136..d994a35ee 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2660,10 +2660,6 @@ namespace MWWorld { const ESM::Spell* spell = getStore().get().find(selectedSpell); - // A power can be used once per 24h - if (spell->mData.mType == ESM::Spell::ST_Power) - stats.getSpells().usePower(spell->mId); - cast.cast(spell); } else if (actor.getClass().hasInventoryStore(actor)) From e8f68973760e32e77b8488e916ff603c3edad2b1 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 6 Oct 2015 14:30:32 +0200 Subject: [PATCH 44/84] fixed a possible script bug regarding ID-access for instances that did not yet existed when the script was compiled --- apps/openmw/mwscript/compilercontext.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwscript/compilercontext.cpp b/apps/openmw/mwscript/compilercontext.cpp index 083f463bc..cf5eff9e7 100644 --- a/apps/openmw/mwscript/compilercontext.cpp +++ b/apps/openmw/mwscript/compilercontext.cpp @@ -12,6 +12,7 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/manualref.hpp" namespace MWScript { @@ -42,9 +43,9 @@ namespace MWScript } else { - MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPtr (id, false); + MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id); - script = ptr.getClass().getScript (ptr); + script = ref.getPtr().getClass().getScript (ref.getPtr()); reference = true; } From 91bf5ae237adc7016432b20b57e600e06c6cbb17 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 7 Oct 2015 02:43:21 +0200 Subject: [PATCH 45/84] Add new script instance when a container item is unstacked (Bug #2962) --- apps/openmw/mwworld/containerstore.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 5a26f09f5..bcaaeff94 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -140,7 +140,11 @@ void MWWorld::ContainerStore::unstack(const Ptr &ptr, const Ptr& container) { if (ptr.getRefData().getCount() <= 1) return; - addNewStack(ptr, ptr.getRefData().getCount()-1); + MWWorld::ContainerStoreIterator it = addNewStack(ptr, ptr.getRefData().getCount()-1); + const std::string script = it->getClass().getScript(*it); + if (!script.empty()) + MWBase::Environment::get().getWorld()->getLocalScripts().add(script, *it); + remove(ptr, ptr.getRefData().getCount()-1, container); } From 944dfa53727eb0f8e93a6805cad0195093efa5f9 Mon Sep 17 00:00:00 2001 From: Emmanuel Anne Date: Mon, 5 Oct 2015 11:53:12 +0200 Subject: [PATCH 46/84] a light without the carry flag can't be equipped ! it fixes Antares big mod teaching disciplines, it adds a light which should not be equipped to npcs which have learnt something. --- apps/openmw/mwclass/light.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index f1dd18acc..34d93da67 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -234,6 +234,11 @@ namespace MWClass std::pair Light::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const { + MWWorld::LiveCellRef *ref = + ptr.get(); + if (!(ref->mBase->mData.mFlags & ESM::Light::Carry)) + return std::make_pair(0,""); + MWWorld::InventoryStore& invStore = npc.getClass().getInventoryStore(npc); MWWorld::ContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); From b911abd7d8c1e1f14350b8155825970020957790 Mon Sep 17 00:00:00 2001 From: Emmanuel Anne Date: Wed, 7 Oct 2015 12:25:52 +0200 Subject: [PATCH 47/84] add a few more possible arguments to choice this fixes some travel dialogs for "Antares Big Mod" --- 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 cd645f0cf..6e65c3183 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -179,7 +179,7 @@ namespace Compiler extensions.registerInstruction ("setjournalindex", "cl", opcodeSetJournalIndex); extensions.registerFunction ("getjournalindex", 'l', "c", opcodeGetJournalIndex); extensions.registerInstruction ("addtopic", "S" , opcodeAddTopic); - extensions.registerInstruction ("choice", "j/SlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSl", opcodeChoice); + extensions.registerInstruction ("choice", "j/SlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSl", opcodeChoice); extensions.registerInstruction("forcegreeting","",opcodeForceGreeting, opcodeForceGreetingExplicit); extensions.registerInstruction("goodbye", "", opcodeGoodbye); From 998348e606182eb171dd82b99b647e3dff798b26 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Thu, 8 Oct 2015 12:35:09 +1100 Subject: [PATCH 48/84] Further rationalise the use of ColumnIds - Address Zini's review comments as per https://github.com/OpenMW/openmw/pull/755 --- apps/opencs/model/world/columnbase.cpp | 3 +-- apps/opencs/model/world/columnbase.hpp | 3 +-- apps/opencs/model/world/columns.cpp | 7 +++---- apps/opencs/model/world/columns.hpp | 6 +++--- apps/opencs/model/world/data.cpp | 10 +++++----- apps/opencs/model/world/refidcollection.cpp | 4 ++-- apps/opencs/view/doc/viewmanager.cpp | 2 +- 7 files changed, 16 insertions(+), 19 deletions(-) diff --git a/apps/opencs/model/world/columnbase.cpp b/apps/opencs/model/world/columnbase.cpp index 2143ec730..39232d442 100644 --- a/apps/opencs/model/world/columnbase.cpp +++ b/apps/opencs/model/world/columnbase.cpp @@ -77,7 +77,7 @@ bool CSMWorld::ColumnBase::isId (Display display) Display_Video, Display_Id, - Display_SkillImpact, + Display_SkillId, Display_EffectRange, Display_EffectId, Display_PartRefType, @@ -85,7 +85,6 @@ bool CSMWorld::ColumnBase::isId (Display display) Display_InfoCondFunc, Display_InfoCondVar, Display_InfoCondComp, - Display_RaceSkill, Display_None }; diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index 400e31333..e2871d4d8 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -113,7 +113,7 @@ namespace CSMWorld Display_SoundGeneratorType, Display_School, Display_Id, - Display_SkillImpact, + Display_SkillId, Display_EffectRange, Display_EffectId, Display_PartRefType, @@ -121,7 +121,6 @@ namespace CSMWorld Display_InfoCondFunc, Display_InfoCondVar, Display_InfoCondComp, - Display_RaceSkill, Display_String32, Display_LongString256, diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 2e0a697a5..78bee2195 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -268,7 +268,7 @@ namespace CSMWorld { ColumnId_LevelledItemChanceNone, "Chance None" }, { ColumnId_PowerList, "Powers" }, - { ColumnId_SkillImpact, "Skill" }, + { ColumnId_Skill, "Skill" }, { ColumnId_InfoList, "Info List" }, { ColumnId_InfoCondition, "Info Conditions" }, @@ -293,8 +293,7 @@ namespace CSMWorld { ColumnId_NpcPersistence, "Persistent" }, { ColumnId_RaceAttributes, "Race Attributes" }, - { ColumnId_RaceMaleValue, "Male Attrib" }, - { ColumnId_RaceFemaleValue, "Female Attrib" }, + { ColumnId_Male, "Male" }, { ColumnId_RaceSkillBonus, "Skill Bonus" }, { ColumnId_RaceBonus, "Bonus" }, @@ -572,7 +571,7 @@ namespace case CSMWorld::Columns::ColumnId_MeshType: return sMeshTypes; case CSMWorld::Columns::ColumnId_SoundGeneratorType: return sSoundGeneratorType; case CSMWorld::Columns::ColumnId_School: return sSchools; - case CSMWorld::Columns::ColumnId_SkillImpact: return sSkills; + case CSMWorld::Columns::ColumnId_Skill: return sSkills; case CSMWorld::Columns::ColumnId_EffectRange: return sEffectRange; case CSMWorld::Columns::ColumnId_EffectId: return sEffectId; case CSMWorld::Columns::ColumnId_PartRefType: return sPartRefType; diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index fb25004ec..b73f5e605 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -261,7 +261,7 @@ namespace CSMWorld ColumnId_LevelledItemChanceNone = 238, ColumnId_PowerList = 239, - ColumnId_SkillImpact = 240, // impact from magic effects + ColumnId_Skill = 240, ColumnId_InfoList = 241, ColumnId_InfoCondition = 242, @@ -288,8 +288,8 @@ namespace CSMWorld ColumnId_NpcPersistence = 261, ColumnId_RaceAttributes = 262, - ColumnId_RaceMaleValue = 263, - ColumnId_RaceFemaleValue = 264, + ColumnId_Male = 263, + // unused ColumnId_RaceSkillBonus = 265, // unused ColumnId_RaceBonus = 267, diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index a27ab5094..8acdac84f 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -143,15 +143,15 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute, ColumnBase::Flag_Dialogue, false)); mRaces.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_RaceMaleValue, ColumnBase::Display_Integer)); + new NestedChildColumn (Columns::ColumnId_Male, ColumnBase::Display_Integer)); mRaces.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_RaceFemaleValue, ColumnBase::Display_Integer)); + new NestedChildColumn (Columns::ColumnId_Female, ColumnBase::Display_Integer)); // Race skill bonus mRaces.addColumn (new NestedParentColumn (Columns::ColumnId_RaceSkillBonus)); index = mRaces.getColumns()-1; mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceSkillsBonusAdapter())); mRaces.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_SkillImpact, ColumnBase::Display_SkillImpact)); + new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_SkillId)); mRaces.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_RaceBonus, ColumnBase::Display_Integer)); @@ -213,7 +213,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mSpells.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_EffectId)); mSpells.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_SkillImpact, ColumnBase::Display_SkillImpact)); + new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_SkillId)); mSpells.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute)); mSpells.getNestableColumn(index)->addColumn( @@ -329,7 +329,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mEnchantments.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_EffectId)); mEnchantments.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_SkillImpact, ColumnBase::Display_SkillImpact)); + new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_SkillId)); mEnchantments.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute)); mEnchantments.getNestableColumn(index)->addColumn( diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index d7b7cedfa..eb4dce51e 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -83,7 +83,7 @@ CSMWorld::RefIdCollection::RefIdCollection() mColumns.back().addColumn( new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_EffectId)); mColumns.back().addColumn( - new NestedChildColumn (Columns::ColumnId_SkillImpact, ColumnBase::Display_SkillImpact)); + new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_SkillId)); mColumns.back().addColumn( new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute)); mColumns.back().addColumn( @@ -491,7 +491,7 @@ CSMWorld::RefIdCollection::RefIdCollection() skillsMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcSkillsRefIdAdapter())); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), skillsMap)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_SkillImpact, CSMWorld::ColumnBase::Display_SkillImpact, false, false)); + new RefIdColumn (Columns::ColumnId_Skill, CSMWorld::ColumnBase::Display_SkillId, false, false)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_UChar, CSMWorld::ColumnBase::Display_Integer)); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index ca4ad2d00..728e69a7a 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -97,7 +97,7 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) { CSMWorld::ColumnBase::Display_Gender, CSMWorld::Columns::ColumnId_Gender, true }, { CSMWorld::ColumnBase::Display_SoundGeneratorType, CSMWorld::Columns::ColumnId_SoundGeneratorType, false }, { CSMWorld::ColumnBase::Display_School, CSMWorld::Columns::ColumnId_School, false }, - { CSMWorld::ColumnBase::Display_SkillImpact, CSMWorld::Columns::ColumnId_SkillImpact, true }, + { CSMWorld::ColumnBase::Display_SkillId, CSMWorld::Columns::ColumnId_Skill, true }, { CSMWorld::ColumnBase::Display_EffectRange, CSMWorld::Columns::ColumnId_EffectRange, false }, { CSMWorld::ColumnBase::Display_EffectId, CSMWorld::Columns::ColumnId_EffectId, false }, { CSMWorld::ColumnBase::Display_PartRefType, CSMWorld::Columns::ColumnId_PartRefType, false }, From 3bbcf6a9169dc24d47c4d10e24f3818681fc34c0 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Thu, 8 Oct 2015 12:47:23 +1100 Subject: [PATCH 49/84] Fix AiWander sub-table editing. Should resolve bugs #2888 and #2930. --- apps/opencs/model/world/columns.cpp | 11 ++- apps/opencs/model/world/columns.hpp | 11 ++- apps/opencs/model/world/refidadapterimp.hpp | 98 +++++++++++++-------- apps/opencs/model/world/refidcollection.cpp | 18 +++- 4 files changed, 99 insertions(+), 39 deletions(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 78bee2195..d0d3a1671 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -249,7 +249,7 @@ namespace CSMWorld { ColumnId_AiWanderDist, "Wander Dist" }, { ColumnId_AiDuration, "Ai Duration" }, { ColumnId_AiWanderToD, "Wander ToD" }, - { ColumnId_AiWanderIdle, "Wander Idle" }, + //{ ColumnId_AiWanderIdle, "Wander Idle" }, { ColumnId_AiWanderRepeat, "Wander Repeat" }, { ColumnId_AiActivateName, "Activate" }, { ColumnId_AiTargetId, "Target ID" }, @@ -316,6 +316,15 @@ namespace CSMWorld { ColumnId_MaxAttack, "Max Attack" }, { ColumnId_CreatureMisc, "Creature Misc" }, + { ColumnId_Idle1, "Idle 1" }, + { ColumnId_Idle2, "Idle 2" }, + { ColumnId_Idle3, "Idle 3" }, + { ColumnId_Idle4, "Idle 4" }, + { ColumnId_Idle5, "Idle 5" }, + { ColumnId_Idle6, "Idle 6" }, + { ColumnId_Idle7, "Idle 7" }, + { ColumnId_Idle8, "Idle 8" }, + { ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue2, "Use value 2" }, { ColumnId_UseValue3, "Use value 3" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index b73f5e605..a504e5f65 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -241,7 +241,7 @@ namespace CSMWorld ColumnId_AiWanderDist = 221, ColumnId_AiDuration = 222, ColumnId_AiWanderToD = 223, - ColumnId_AiWanderIdle = 224, + // unused ColumnId_AiWanderRepeat = 225, ColumnId_AiActivateName = 226, // use ColumnId_PosX, etc for AI destinations @@ -316,6 +316,15 @@ namespace CSMWorld ColumnId_MaxAttack = 284, ColumnId_CreatureMisc = 285, + ColumnId_Idle1 = 286, + ColumnId_Idle2 = 287, + ColumnId_Idle3 = 288, + ColumnId_Idle4 = 289, + ColumnId_Idle5 = 290, + ColumnId_Idle6 = 291, + ColumnId_Idle7 = 292, + ColumnId_Idle8 = 293, + // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. ColumnId_UseValue1 = 0x10000, diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 53da63806..4ac27b6e9 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -1532,6 +1532,8 @@ namespace CSMWorld virtual ~ActorAiRefIdAdapter() {} + // FIXME: should check if the AI package type is already in the list and use a default + // that wasn't used already (in extreme case do not add anything at all? virtual void addNestedRow (const RefIdColumn *column, RefIdData& data, int index, int position) const { @@ -1615,6 +1617,7 @@ namespace CSMWorld switch (subColIndex) { case 0: + // FIXME: should more than one AI package type be allowed? Check vanilla switch (content.mType) { case ESM::AI_Wander: return 0; @@ -1642,47 +1645,52 @@ namespace CSMWorld else return QVariant(); case 4: // wander idle + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: if (content.mType == ESM::AI_Wander) - { - return static_cast(content.mWander.mIdle[0]); // FIXME: - } + return static_cast(content.mWander.mIdle[subColIndex-4]); else return QVariant(); - case 5: // wander repeat + case 12: // wander repeat if (content.mType == ESM::AI_Wander) return content.mWander.mShouldRepeat != 0; else return QVariant(); - case 6: // activate name + case 13: // activate name if (content.mType == ESM::AI_Activate) return QString(content.mActivate.mName.toString().c_str()); else return QVariant(); - case 7: // target id + case 14: // target id if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort) return QString(content.mTarget.mId.toString().c_str()); else return QVariant(); - case 8: // target cell + case 15: // target cell if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort) return QString::fromUtf8(content.mCellName.c_str()); else return QVariant(); - case 9: + case 16: if (content.mType == ESM::AI_Travel) return content.mTravel.mX; else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort) return content.mTarget.mX; else return QVariant(); - case 10: + case 17: if (content.mType == ESM::AI_Travel) return content.mTravel.mY; else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort) return content.mTarget.mY; else return QVariant(); - case 11: + case 18: if (content.mType == ESM::AI_Travel) return content.mTravel.mZ; else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort) @@ -1712,11 +1720,12 @@ namespace CSMWorld case 0: // ai package type switch (value.toInt()) { - case 0: content.mType = ESM::AI_Wander; - case 1: content.mType = ESM::AI_Travel; - case 2: content.mType = ESM::AI_Follow; - case 3: content.mType = ESM::AI_Escort; - case 4: content.mType = ESM::AI_Activate; + case 0: content.mType = ESM::AI_Wander; break; + case 1: content.mType = ESM::AI_Travel; break; + case 2: content.mType = ESM::AI_Follow; break; + case 3: content.mType = ESM::AI_Escort; break; + case 4: content.mType = ESM::AI_Activate; break; + default: return; // return without saving } break; // always save @@ -1725,6 +1734,8 @@ namespace CSMWorld content.mWander.mDistance = static_cast(value.toInt()); else return; // return without saving + + break; // always save case 2: if (content.mType == ESM::AI_Wander || content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort) @@ -1736,62 +1747,77 @@ namespace CSMWorld content.mWander.mTimeOfDay = static_cast(value.toInt()); else return; // return without saving + + break; // always save case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: if (content.mType == ESM::AI_Wander) - break; // FIXME: idle + content.mWander.mIdle[subColIndex-4] = static_cast(value.toInt()); else return; // return without saving - case 5: + + break; // always save + case 12: if (content.mType == ESM::AI_Wander) - { content.mWander.mShouldRepeat = static_cast(value.toInt()); - break; - } - case 6: // NAME32 + else + return; // return without saving + + break; // always save + case 13: // NAME32 if (content.mType == ESM::AI_Activate) - { content.mActivate.mName.assign(value.toString().toUtf8().constData()); - break; - } else return; // return without saving - case 7: // NAME32 + + break; // always save + case 14: // NAME32 if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort) - { content.mTarget.mId.assign(value.toString().toUtf8().constData()); - break; - } else return; // return without saving - case 8: + + break; // always save + case 15: if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort) - { content.mCellName = std::string(value.toString().toUtf8().constData()); - break; - } else return; // return without saving - case 9: + + break; // always save + case 16: if (content.mType == ESM::AI_Travel) content.mTravel.mZ = value.toFloat(); else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort) content.mTarget.mZ = value.toFloat(); else return; // return without saving - case 10: + + break; // always save + case 17: if (content.mType == ESM::AI_Travel) content.mTravel.mZ = value.toFloat(); else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort) content.mTarget.mZ = value.toFloat(); else return; // return without saving - case 11: + + break; // always save + case 18: if (content.mType == ESM::AI_Travel) content.mTravel.mZ = value.toFloat(); else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort) content.mTarget.mZ = value.toFloat(); else return; // return without saving + + break; // always save default: throw std::runtime_error("Trying to access non-existing column in the nested table!"); } @@ -1801,7 +1827,7 @@ namespace CSMWorld virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const { - return 12; + return 19; } virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index eb4dce51e..3b316bea3 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -193,8 +193,24 @@ CSMWorld::RefIdCollection::RefIdCollection() new RefIdColumn (Columns::ColumnId_AiDuration, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_AiWanderToD, CSMWorld::ColumnBase::Display_Integer)); + + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_Idle1, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_Idle2, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_Idle3, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_Idle4, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_AiWanderIdle, CSMWorld::ColumnBase::Display_Integer)); + new RefIdColumn (Columns::ColumnId_Idle5, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_Idle6, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_Idle7, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_Idle8, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_AiWanderRepeat, CSMWorld::ColumnBase::Display_Boolean)); mColumns.back().addColumn( From 2f808f957d6cb0f59e4eb40002c931bf1bbee60b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 8 Oct 2015 14:01:29 +0200 Subject: [PATCH 50/84] fixed for compiler not recognising script names in some situations --- apps/openmw/mwscript/compilercontext.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/compilercontext.cpp b/apps/openmw/mwscript/compilercontext.cpp index cf5eff9e7..4a7038e1c 100644 --- a/apps/openmw/mwscript/compilercontext.cpp +++ b/apps/openmw/mwscript/compilercontext.cpp @@ -83,7 +83,8 @@ namespace MWScript store.get().search (name) || store.get().search (name) || store.get().search (name) || - store.get().search (name); + store.get().search (name) || + store.get().search (name); } bool CompilerContext::isJournalId (const std::string& name) const From e7a3f059aafb643238d95de8d34554747d7e74f2 Mon Sep 17 00:00:00 2001 From: "artemutin@yandex.ru" Date: Wed, 7 Oct 2015 12:39:19 +1000 Subject: [PATCH 51/84] Implemented line and col calculations in scriptsubview --- apps/opencs/view/world/scriptsubview.cpp | 46 +++++++++++++++--------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/apps/opencs/view/world/scriptsubview.cpp b/apps/opencs/view/world/scriptsubview.cpp index d99f789b3..35b9ccf0c 100644 --- a/apps/opencs/view/world/scriptsubview.cpp +++ b/apps/opencs/view/world/scriptsubview.cpp @@ -198,26 +198,38 @@ void CSVWorld::ScriptSubView::useHint (const std::string& hint) if (hint.empty()) return; - if (hint[0]=='l') - { - std::istringstream stream (hint.c_str()+1); - - char ignore; - int line; - int column; - - if (stream >> ignore >> line >> column) + size_t line = 0, column = 0; + std::istringstream stream (hint.c_str()+2); + switch(hint[0]){ + case 'R': + case 'r': { - QTextCursor cursor = mEditor->textCursor(); - - cursor.movePosition (QTextCursor::Start); - if (cursor.movePosition (QTextCursor::Down, QTextCursor::MoveAnchor, line)) - cursor.movePosition (QTextCursor::Right, QTextCursor::MoveAnchor, column); - - mEditor->setFocus(); - mEditor->setTextCursor (cursor); + QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn); + QString source = mModel->data (index).toString(); + size_t pos; + stream >> pos >> pos; + + for (size_t i = 0; i <= pos; ++i){ + if (source[(unsigned) i] == '\n'){ + ++line; + column = i; + } + } + column = pos - column - (line > 0 ? 1 : 0); + break; } + case 'l': + stream >> line >> column; } + + QTextCursor cursor = mEditor->textCursor(); + + cursor.movePosition (QTextCursor::Start); + if (cursor.movePosition (QTextCursor::Down, QTextCursor::MoveAnchor, line)) + cursor.movePosition (QTextCursor::Right, QTextCursor::MoveAnchor, column); + + mEditor->setFocus(); + mEditor->setTextCursor (cursor); } void CSVWorld::ScriptSubView::textChanged() From 64821b0785a306f90e4f2f3be9c6a8fa61d440eb Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 9 Oct 2015 06:29:50 +1100 Subject: [PATCH 52/84] Disable toolbar context menu. Should resolve bug #2953. --- apps/opencs/view/doc/view.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index ea11bb0f9..38088c6d7 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -435,6 +435,8 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to mOperations = new Operations; addDockWidget (Qt::BottomDockWidgetArea, mOperations); + setContextMenuPolicy(Qt::NoContextMenu); + updateTitle(); setupUi(); From 8eb6d337d556dce2f64698ac30ad0df881bf84e0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 9 Oct 2015 12:14:22 +0200 Subject: [PATCH 53/84] deal with script execution from within a script (Fixes #2964) --- components/interpreter/interpreter.cpp | 55 +++++++++++++++++++++----- components/interpreter/interpreter.hpp | 7 ++++ 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/components/interpreter/interpreter.cpp b/components/interpreter/interpreter.cpp index 263cea9a5..1892e4a6f 100644 --- a/components/interpreter/interpreter.cpp +++ b/components/interpreter/interpreter.cpp @@ -132,7 +132,34 @@ namespace Interpreter throw std::runtime_error (error.str()); } - Interpreter::Interpreter() + void Interpreter::begin() + { + if (mRunning) + { + mCallstack.push (mRuntime); + mRuntime.clear(); + } + else + { + mRunning = true; + } + } + + void Interpreter::end() + { + if (mCallstack.empty()) + { + mRuntime.clear(); + mRunning = false; + } + else + { + mRuntime = mCallstack.top(); + mCallstack.pop(); + } + } + + Interpreter::Interpreter() : mRunning (false) {} Interpreter::~Interpreter() @@ -202,19 +229,29 @@ namespace Interpreter { assert (codeSize>=4); - mRuntime.configure (code, codeSize, context); + begin(); - int opcodes = static_cast (code[0]); + try + { + mRuntime.configure (code, codeSize, context); - const Type_Code *codeBlock = code + 4; + int opcodes = static_cast (code[0]); - while (mRuntime.getPC()>=0 && mRuntime.getPC()=0 && mRuntime.getPC() +#include #include "runtime.hpp" #include "types.hpp" @@ -14,6 +15,8 @@ namespace Interpreter class Interpreter { + std::stack mCallstack; + bool mRunning; Runtime mRuntime; std::map mSegment0; std::map mSegment1; @@ -32,6 +35,10 @@ namespace Interpreter void abortUnknownSegment (Type_Code code); + void begin(); + + void end(); + public: Interpreter(); From 4ca7b2660932efb06535f148a643a7e814f3a72d Mon Sep 17 00:00:00 2001 From: "artemutin@yandex.ru" Date: Fri, 9 Oct 2015 21:52:12 +1000 Subject: [PATCH 54/84] Stream error handling, and other minor changes. --- apps/opencs/view/world/scriptsubview.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/apps/opencs/view/world/scriptsubview.cpp b/apps/opencs/view/world/scriptsubview.cpp index 35b9ccf0c..eb0c70656 100644 --- a/apps/opencs/view/world/scriptsubview.cpp +++ b/apps/opencs/view/world/scriptsubview.cpp @@ -198,28 +198,31 @@ void CSVWorld::ScriptSubView::useHint (const std::string& hint) if (hint.empty()) return; - size_t line = 0, column = 0; - std::istringstream stream (hint.c_str()+2); + unsigned line = 0, column = 0; + char c; + std::istringstream stream (hint.c_str()+1); switch(hint[0]){ case 'R': case 'r': { QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn); QString source = mModel->data (index).toString(); - size_t pos; - stream >> pos >> pos; + unsigned pos, dummy; + if (!(stream >> c >> dummy >> pos) ) + return; - for (size_t i = 0; i <= pos; ++i){ - if (source[(unsigned) i] == '\n'){ + for (unsigned i = 0; i <= pos; ++i){ + if (source[i] == '\n'){ ++line; - column = i; + column = i+1; } } - column = pos - column - (line > 0 ? 1 : 0); + column = pos - column; break; } case 'l': - stream >> line >> column; + if (!(stream >> c >> line >> column)) + return; } QTextCursor cursor = mEditor->textCursor(); From 0d35938794f161a84ff66ae587e95fae8e0f2c12 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 12 Oct 2015 14:12:01 +0200 Subject: [PATCH 55/84] basic cell arrow rendering (shape is a placeholder) --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/render/cell.cpp | 24 +++++ apps/opencs/view/render/cell.hpp | 8 ++ apps/opencs/view/render/cellarrow.cpp | 93 +++++++++++++++++++ apps/opencs/view/render/cellarrow.hpp | 70 ++++++++++++++ .../view/render/pagedworldspacewidget.cpp | 32 +++++++ 6 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/view/render/cellarrow.cpp create mode 100644 apps/opencs/view/render/cellarrow.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 196e899b2..6af04e8fc 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -90,7 +90,7 @@ opencs_units (view/render opencs_units_noqt (view/render lighting lightingday lightingnight - lightingbright object cell terrainstorage tagbase + lightingbright object cell terrainstorage tagbase cellarrow ) opencs_hdrs_noqt (view/render diff --git a/apps/opencs/view/render/cell.cpp b/apps/opencs/view/render/cell.cpp index c4f744510..345bc79a7 100644 --- a/apps/opencs/view/render/cell.cpp +++ b/apps/opencs/view/render/cell.cpp @@ -9,6 +9,7 @@ #include "../../model/world/columns.hpp" #include "../../model/world/data.hpp" #include "../../model/world/refcollection.hpp" +#include "../../model/world/cellcoordinates.hpp" #include "elements.hpp" #include "terrainstorage.hpp" @@ -232,3 +233,26 @@ void CSVRender::Cell::setSelection (int elementMask, Selection mode) } } } + +void CSVRender::Cell::setCellArrows (int mask) +{ + for (int i=0; i<4; ++i) + { + CellArrow::Direction direction = static_cast (1< mTerrain; int mX; int mY; + std::auto_ptr mCellArrows[4]; /// Ignored if cell does not have an object with the given ID. /// @@ -86,6 +89,11 @@ namespace CSVRender bool referenceAdded (const QModelIndex& parent, int start, int end); void setSelection (int elementMask, Selection mode); + + void setCellArrows (int mask); + + /// Returns 0, 0 in case of an unpaged cell. + CSMWorld::CellCoordinates getCoordinates() const; }; } diff --git a/apps/opencs/view/render/cellarrow.cpp b/apps/opencs/view/render/cellarrow.cpp new file mode 100644 index 000000000..ee055a0b1 --- /dev/null +++ b/apps/opencs/view/render/cellarrow.cpp @@ -0,0 +1,93 @@ + +#include "cellarrow.hpp" + +#include +#include + +#include +#include +#include + + +#include "elements.hpp" + +CSVRender::CellArrowTag::CellArrowTag (CellArrow *arrow) +: TagBase (Element_CellArrow), mArrow (arrow) +{} + +CSVRender::CellArrow *CSVRender::CellArrowTag::getCellArrow() const +{ + return mArrow; +} + + +void CSVRender::CellArrow::adjustTransform() +{ + // position + const int cellSize = 8192; + const int offset = cellSize / 2 + 400; + + int x = mXIndex*cellSize + cellSize/2; + int y = mYIndex*cellSize + cellSize/2; + + switch (mDirection) + { + case Direction_North: y += offset; break; + case Direction_West: x -= offset; break; + case Direction_South: y -= offset; break; + case Direction_East: x += offset; break; + }; + + mBaseNode->setPosition (osg::Vec3f (x, y, 0)); + + // orientation + osg::Quat xr (0, osg::Vec3f (1,0,0)); + osg::Quat yr (0, osg::Vec3f (0,1,0)); + osg::Quat zr (0, osg::Vec3f (0,0,1)); + mBaseNode->setAttitude (zr*yr*xr); +} + +void CSVRender::CellArrow::buildShape() +{ + /// \todo placeholder shape -> replace + osg::ref_ptr shape(new osg::Box(osg::Vec3f(0,0,0), 200)); + osg::ref_ptr shapedrawable(new osg::ShapeDrawable); + shapedrawable->setShape(shape); + + osg::ref_ptr geode (new osg::Geode); + geode->addDrawable(shapedrawable); + + mBaseNode->addChild (geode); +} + +CSVRender::CellArrow::CellArrow (osg::Group *cellNode, Direction direction, + int xIndex, int yIndex) +: mDirection (direction), mParentNode (cellNode), mXIndex (xIndex), mYIndex (yIndex) +{ + mBaseNode = new osg::PositionAttitudeTransform; + + mBaseNode->setUserData (new CellArrowTag (this)); + + mParentNode->addChild (mBaseNode); + + // 0x1 reserved for separating cull and update visitors + mBaseNode->setNodeMask (Element_CellArrow<<1); + + adjustTransform(); + buildShape(); +} + +CSVRender::CellArrow::~CellArrow() +{ + mParentNode->removeChild (mBaseNode); +} + +int CSVRender::CellArrow::getXIndex() const +{ + return mXIndex; +} + +int CSVRender::CellArrow::getYIndex() const +{ + return mYIndex; +} diff --git a/apps/opencs/view/render/cellarrow.hpp b/apps/opencs/view/render/cellarrow.hpp new file mode 100644 index 000000000..822e63bdc --- /dev/null +++ b/apps/opencs/view/render/cellarrow.hpp @@ -0,0 +1,70 @@ +#ifndef OPENCS_VIEW_CELLARROW_H +#define OPENCS_VIEW_CELLARROW_H + +#include "tagbase.hpp" + +#include + +namespace osg +{ + class PositionAttitudeTransform; + class Group; +} + +namespace CSVRender +{ + class CellArrow; + + class CellArrowTag : public TagBase + { + CellArrow *mArrow; + + public: + + CellArrowTag (CellArrow *arrow); + + CellArrow *getCellArrow() const; + }; + + + class CellArrow + { + public: + + enum Direction + { + Direction_North = 1, + Direction_West = 2, + Direction_South = 4, + Direction_East = 8 + }; + + private: + + // not implemented + CellArrow (const CellArrow&); + CellArrow& operator= (const CellArrow&); + + Direction mDirection; + osg::Group* mParentNode; + osg::ref_ptr mBaseNode; + int mXIndex; + int mYIndex; + + void adjustTransform(); + + void buildShape(); + + public: + + CellArrow (osg::Group *cellNode, Direction direction, int xIndex, int yIndex); + + ~CellArrow(); + + int getXIndex() const; + + int getYIndex() const; + }; +} + +#endif diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index 7403113b3..070ce7d17 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -21,6 +21,7 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells() { bool modified = false; + bool wasEmpty = mCells.empty(); const CSMWorld::IdCollection& cells = mDocument.getData().getCells(); @@ -32,6 +33,7 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells() { int index = cells.searchId (iter->first.getId (mWorldspace)); + /// \todo handle cells that don't exist if (!mSelection.has (iter->first) || index==-1 || cells.getRecord (index).mState==CSMWorld::RecordBase::State_Deleted) { @@ -60,6 +62,7 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells() { int index = cells.searchId (iter->getId (mWorldspace)); + /// \todo handle cells that don't exist if (index > 0 && cells.getRecord (index).mState!=CSMWorld::RecordBase::State_Deleted && mCells.find (*iter)==mCells.end()) { @@ -72,6 +75,35 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells() } if (modified) + { + for (std::map::const_iterator iter (mCells.begin()); + iter!=mCells.end(); ++iter) + { + int mask = 0; + + for (int i=CellArrow::Direction_North; i<=CellArrow::Direction_East; i *= 2) + { + CSMWorld::CellCoordinates coordinates (iter->second->getCoordinates()); + + switch (i) + { + case CellArrow::Direction_North: coordinates = coordinates.move (0, 1); break; + case CellArrow::Direction_West: coordinates = coordinates.move (-1, 0); break; + case CellArrow::Direction_South: coordinates = coordinates.move (0, -1); break; + case CellArrow::Direction_East: coordinates = coordinates.move (1, 0); break; + } + + if (!mSelection.has (coordinates)) + mask |= i; + } + + iter->second->setCellArrows (mask); + } + } + + /// \todo do not overwrite manipulator object + /// \todo move code to useViewHint function + if (modified && wasEmpty) mView->setCameraManipulator(new osgGA::TrackballManipulator); return modified; From b81ee606c831f3a7b700165716f0df568d0a6ad3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 12 Oct 2015 14:31:55 +0200 Subject: [PATCH 56/84] use CellCoordinates instead of a pair of ints for cell coordinates --- apps/opencs/view/render/cell.cpp | 9 ++++----- apps/opencs/view/render/cell.hpp | 3 +-- apps/opencs/view/render/cellarrow.cpp | 18 ++++++------------ apps/opencs/view/render/cellarrow.hpp | 12 ++++++------ 4 files changed, 17 insertions(+), 25 deletions(-) diff --git a/apps/opencs/view/render/cell.cpp b/apps/opencs/view/render/cell.cpp index 345bc79a7..e0e63c8c9 100644 --- a/apps/opencs/view/render/cell.cpp +++ b/apps/opencs/view/render/cell.cpp @@ -52,7 +52,7 @@ bool CSVRender::Cell::addObjects (int start, int end) } CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id) -: mData (data), mId (Misc::StringUtils::lowerCase (id)), mX(0), mY(0) +: mData (data), mId (Misc::StringUtils::lowerCase (id)) { mCellNode = new osg::Group; rootNode->addChild(mCellNode); @@ -76,8 +76,7 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::st mTerrain->loadCell(esmLand.mX, esmLand.mY); - mX = esmLand.mX; - mY = esmLand.mY; + mCoordinates = CSMWorld::CellCoordinates (esmLand.mX, esmLand.mY); } } } @@ -245,7 +244,7 @@ void CSVRender::Cell::setCellArrows (int mask) if (enable!=(mCellArrows[i].get()!=0)) { if (enable) - mCellArrows[i].reset (new CellArrow (mCellNode, direction, mX, mY)); + mCellArrows[i].reset (new CellArrow (mCellNode, direction, mCoordinates)); else mCellArrows[i].reset (0); } @@ -254,5 +253,5 @@ void CSVRender::Cell::setCellArrows (int mask) CSMWorld::CellCoordinates CSVRender::Cell::getCoordinates() const { - return CSMWorld::CellCoordinates (mX, mY); + return mCoordinates; } diff --git a/apps/opencs/view/render/cell.hpp b/apps/opencs/view/render/cell.hpp index 5b1badcbe..7cced4fe3 100644 --- a/apps/opencs/view/render/cell.hpp +++ b/apps/opencs/view/render/cell.hpp @@ -38,8 +38,7 @@ namespace CSVRender osg::ref_ptr mCellNode; std::map mObjects; std::auto_ptr mTerrain; - int mX; - int mY; + CSMWorld::CellCoordinates mCoordinates; std::auto_ptr mCellArrows[4]; /// Ignored if cell does not have an object with the given ID. diff --git a/apps/opencs/view/render/cellarrow.cpp b/apps/opencs/view/render/cellarrow.cpp index ee055a0b1..443d398dd 100644 --- a/apps/opencs/view/render/cellarrow.cpp +++ b/apps/opencs/view/render/cellarrow.cpp @@ -8,7 +8,6 @@ #include #include - #include "elements.hpp" CSVRender::CellArrowTag::CellArrowTag (CellArrow *arrow) @@ -27,8 +26,8 @@ void CSVRender::CellArrow::adjustTransform() const int cellSize = 8192; const int offset = cellSize / 2 + 400; - int x = mXIndex*cellSize + cellSize/2; - int y = mYIndex*cellSize + cellSize/2; + int x = mCoordinates.getX()*cellSize + cellSize/2; + int y = mCoordinates.getY()*cellSize + cellSize/2; switch (mDirection) { @@ -61,8 +60,8 @@ void CSVRender::CellArrow::buildShape() } CSVRender::CellArrow::CellArrow (osg::Group *cellNode, Direction direction, - int xIndex, int yIndex) -: mDirection (direction), mParentNode (cellNode), mXIndex (xIndex), mYIndex (yIndex) + const CSMWorld::CellCoordinates& coordinates) +: mDirection (direction), mParentNode (cellNode), mCoordinates (coordinates) { mBaseNode = new osg::PositionAttitudeTransform; @@ -82,12 +81,7 @@ CSVRender::CellArrow::~CellArrow() mParentNode->removeChild (mBaseNode); } -int CSVRender::CellArrow::getXIndex() const -{ - return mXIndex; -} - -int CSVRender::CellArrow::getYIndex() const +CSMWorld::CellCoordinates CSVRender::CellArrow::getCoordinates() const { - return mYIndex; + return mCoordinates; } diff --git a/apps/opencs/view/render/cellarrow.hpp b/apps/opencs/view/render/cellarrow.hpp index 822e63bdc..4422ec890 100644 --- a/apps/opencs/view/render/cellarrow.hpp +++ b/apps/opencs/view/render/cellarrow.hpp @@ -5,6 +5,8 @@ #include +#include "../../model/world/cellcoordinates.hpp" + namespace osg { class PositionAttitudeTransform; @@ -48,8 +50,7 @@ namespace CSVRender Direction mDirection; osg::Group* mParentNode; osg::ref_ptr mBaseNode; - int mXIndex; - int mYIndex; + CSMWorld::CellCoordinates mCoordinates; void adjustTransform(); @@ -57,13 +58,12 @@ namespace CSVRender public: - CellArrow (osg::Group *cellNode, Direction direction, int xIndex, int yIndex); + CellArrow (osg::Group *cellNode, Direction direction, + const CSMWorld::CellCoordinates& coordinates); ~CellArrow(); - int getXIndex() const; - - int getYIndex() const; + CSMWorld::CellCoordinates getCoordinates() const; }; } From 3f9db7ba3cc12739a238207797c92c07b74332ab Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 12 Oct 2015 18:00:44 +0200 Subject: [PATCH 57/84] more reliable method of obtaining the cell coordinates in CSVRender::Cell --- apps/opencs/model/world/cellcoordinates.cpp | 17 +++++++++++++++++ apps/opencs/model/world/cellcoordinates.hpp | 6 ++++++ apps/opencs/view/render/cell.cpp | 7 +++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/cellcoordinates.cpp b/apps/opencs/model/world/cellcoordinates.cpp index 95e206e2d..3ef3e6c69 100644 --- a/apps/opencs/model/world/cellcoordinates.cpp +++ b/apps/opencs/model/world/cellcoordinates.cpp @@ -32,6 +32,23 @@ std::string CSMWorld::CellCoordinates::getId (const std::string& worldspace) con return stream.str(); } +std::pair CSMWorld::CellCoordinates::fromId ( + const std::string& id) +{ + // no worldspace for now, needs to be changed for 1.1 + if (!id.empty() && id[0]=='#') + { + int x, y; + char ignore; + + std::istringstream stream (id); + if (stream >> ignore >> x >> y) + return std::make_pair (CellCoordinates (x, y), true); + } + + return std::make_pair (CellCoordinates(), false); +} + bool CSMWorld::operator== (const CellCoordinates& left, const CellCoordinates& right) { return left.getX()==right.getX() && left.getY()==right.getY(); diff --git a/apps/opencs/model/world/cellcoordinates.hpp b/apps/opencs/model/world/cellcoordinates.hpp index ee395ea7e..63db60c29 100644 --- a/apps/opencs/model/world/cellcoordinates.hpp +++ b/apps/opencs/model/world/cellcoordinates.hpp @@ -28,6 +28,12 @@ namespace CSMWorld std::string getId (const std::string& worldspace) const; ///< Return the ID for the cell at these coordinates. + + /// \return first: CellCoordinates (or 0, 0 if cell does not have coordinates), + /// second: is cell paged? + /// + /// \note The worldspace part of \a id is ignored + static std::pair fromId (const std::string& id); }; bool operator== (const CellCoordinates& left, const CellCoordinates& right); diff --git a/apps/opencs/view/render/cell.cpp b/apps/opencs/view/render/cell.cpp index e0e63c8c9..5ec69a5f2 100644 --- a/apps/opencs/view/render/cell.cpp +++ b/apps/opencs/view/render/cell.cpp @@ -54,6 +54,11 @@ bool CSVRender::Cell::addObjects (int start, int end) CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id) : mData (data), mId (Misc::StringUtils::lowerCase (id)) { + std::pair result = CSMWorld::CellCoordinates::fromId (id); + + if (result.second) + mCoordinates = result.first; + mCellNode = new osg::Group; rootNode->addChild(mCellNode); @@ -75,8 +80,6 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::st mTerrain.reset(new Terrain::TerrainGrid(mCellNode, data.getResourceSystem().get(), NULL, new TerrainStorage(mData), Element_Terrain<<1)); mTerrain->loadCell(esmLand.mX, esmLand.mY); - - mCoordinates = CSMWorld::CellCoordinates (esmLand.mX, esmLand.mY); } } } From 6e140c9cb1c3cb3406295a57488f32e5d6acc288 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 13 Oct 2015 11:43:33 +0200 Subject: [PATCH 58/84] proper shape for cell arrows (kinda) --- apps/opencs/view/render/cellarrow.cpp | 95 ++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 17 deletions(-) diff --git a/apps/opencs/view/render/cellarrow.cpp b/apps/opencs/view/render/cellarrow.cpp index 443d398dd..8f03b489f 100644 --- a/apps/opencs/view/render/cellarrow.cpp +++ b/apps/opencs/view/render/cellarrow.cpp @@ -3,10 +3,9 @@ #include #include - -#include -#include #include +#include +#include #include "elements.hpp" @@ -24,37 +23,99 @@ void CSVRender::CellArrow::adjustTransform() { // position const int cellSize = 8192; - const int offset = cellSize / 2 + 400; + const int offset = cellSize / 2 + 800; int x = mCoordinates.getX()*cellSize + cellSize/2; int y = mCoordinates.getY()*cellSize + cellSize/2; + float xr = 0; + float yr = 0; + float zr = 0; + + float angle = osg::DegreesToRadians (90.0f); + switch (mDirection) { - case Direction_North: y += offset; break; - case Direction_West: x -= offset; break; - case Direction_South: y -= offset; break; - case Direction_East: x += offset; break; + case Direction_North: y += offset; xr = -angle; zr = angle; break; + case Direction_West: x -= offset; yr = -angle; break; + case Direction_South: y -= offset; xr = angle; zr = angle; break; + case Direction_East: x += offset; yr = angle; break; }; mBaseNode->setPosition (osg::Vec3f (x, y, 0)); // orientation - osg::Quat xr (0, osg::Vec3f (1,0,0)); - osg::Quat yr (0, osg::Vec3f (0,1,0)); - osg::Quat zr (0, osg::Vec3f (0,0,1)); - mBaseNode->setAttitude (zr*yr*xr); + osg::Quat xr2 (xr, osg::Vec3f (1,0,0)); + osg::Quat yr2 (yr, osg::Vec3f (0,1,0)); + osg::Quat zr2 (zr, osg::Vec3f (0,0,1)); + mBaseNode->setAttitude (zr2*yr2*xr2); } void CSVRender::CellArrow::buildShape() { - /// \todo placeholder shape -> replace - osg::ref_ptr shape(new osg::Box(osg::Vec3f(0,0,0), 200)); - osg::ref_ptr shapedrawable(new osg::ShapeDrawable); - shapedrawable->setShape(shape); + osg::ref_ptr geometry (new osg::Geometry); + + const int arrowWidth = 4000; + const int arrowLength = 1500; + const int arrowHeight = 500; + + osg::Vec3Array *vertices = new osg::Vec3Array; + for (int i2=0; i2<2; ++i2) + for (int i=0; i<2; ++i) + { + float height = i ? -arrowHeight/2 : arrowHeight/2; + vertices->push_back (osg::Vec3f (height, -arrowWidth/2, 0)); + vertices->push_back (osg::Vec3f (height, arrowWidth/2, 0)); + vertices->push_back (osg::Vec3f (height, 0, arrowLength)); + } + + geometry->setVertexArray (vertices); + + osg::DrawElementsUShort *top = new osg::DrawElementsUShort (osg::PrimitiveSet::TRIANGLES, 0); + top->push_back (0); + top->push_back (1); + top->push_back (2); + geometry->addPrimitiveSet (top); + + osg::DrawElementsUShort *bottom = new osg::DrawElementsUShort (osg::PrimitiveSet::TRIANGLES, 0); + bottom->push_back (5); + bottom->push_back (4); + bottom->push_back (3); + geometry->addPrimitiveSet (bottom); + + osg::DrawElementsUShort *back = new osg::DrawElementsUShort (osg::PrimitiveSet::QUADS, 0); + back->push_back (3+6); + back->push_back (4+6); + back->push_back (1+6); + back->push_back (0+6); + geometry->addPrimitiveSet (back); + + osg::DrawElementsUShort *side1 = new osg::DrawElementsUShort (osg::PrimitiveSet::QUADS, 0); + side1->push_back (0+6); + side1->push_back (2+6); + side1->push_back (5+6); + side1->push_back (3+6); + geometry->addPrimitiveSet (side1); + + osg::DrawElementsUShort *side2 = new osg::DrawElementsUShort (osg::PrimitiveSet::QUADS, 0); + side2->push_back (4+6); + side2->push_back (5+6); + side2->push_back (2+6); + side2->push_back (1+6); + geometry->addPrimitiveSet (side2); + + osg::Vec4Array *colours = new osg::Vec4Array; + + for (int i=0; i<6; ++i) + colours->push_back (osg::Vec4f (1.0f, 0.0f, 0.0f, 1.0f)); + for (int i=0; i<6; ++i) + colours->push_back (osg::Vec4f (1.0f, 0.0f, 0.4f, 1.0f)); + + geometry->setColorArray (colours); + geometry->setColorBinding (osg::Geometry::BIND_PER_VERTEX); osg::ref_ptr geode (new osg::Geode); - geode->addDrawable(shapedrawable); + geode->addDrawable (geometry); mBaseNode->addChild (geode); } From 0b1d6bddc8b1f2f16b61d51be7bc4fd09e618049 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 13 Oct 2015 16:11:47 +0200 Subject: [PATCH 59/84] merged primitives arrays --- apps/opencs/view/render/cellarrow.cpp | 71 +++++++++++++++------------ 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/apps/opencs/view/render/cellarrow.cpp b/apps/opencs/view/render/cellarrow.cpp index 8f03b489f..526c9a24c 100644 --- a/apps/opencs/view/render/cellarrow.cpp +++ b/apps/opencs/view/render/cellarrow.cpp @@ -71,38 +71,45 @@ void CSVRender::CellArrow::buildShape() geometry->setVertexArray (vertices); - osg::DrawElementsUShort *top = new osg::DrawElementsUShort (osg::PrimitiveSet::TRIANGLES, 0); - top->push_back (0); - top->push_back (1); - top->push_back (2); - geometry->addPrimitiveSet (top); - - osg::DrawElementsUShort *bottom = new osg::DrawElementsUShort (osg::PrimitiveSet::TRIANGLES, 0); - bottom->push_back (5); - bottom->push_back (4); - bottom->push_back (3); - geometry->addPrimitiveSet (bottom); - - osg::DrawElementsUShort *back = new osg::DrawElementsUShort (osg::PrimitiveSet::QUADS, 0); - back->push_back (3+6); - back->push_back (4+6); - back->push_back (1+6); - back->push_back (0+6); - geometry->addPrimitiveSet (back); - - osg::DrawElementsUShort *side1 = new osg::DrawElementsUShort (osg::PrimitiveSet::QUADS, 0); - side1->push_back (0+6); - side1->push_back (2+6); - side1->push_back (5+6); - side1->push_back (3+6); - geometry->addPrimitiveSet (side1); - - osg::DrawElementsUShort *side2 = new osg::DrawElementsUShort (osg::PrimitiveSet::QUADS, 0); - side2->push_back (4+6); - side2->push_back (5+6); - side2->push_back (2+6); - side2->push_back (1+6); - geometry->addPrimitiveSet (side2); + osg::DrawElementsUShort *primitives = new osg::DrawElementsUShort (osg::PrimitiveSet::TRIANGLES, 0); + + // top + primitives->push_back (0); + primitives->push_back (1); + primitives->push_back (2); + + // bottom + primitives->push_back (5); + primitives->push_back (4); + primitives->push_back (3); + + // back + primitives->push_back (3+6); + primitives->push_back (4+6); + primitives->push_back (1+6); + + primitives->push_back (3+6); + primitives->push_back (1+6); + primitives->push_back (0+6); + + // sides + primitives->push_back (0+6); + primitives->push_back (2+6); + primitives->push_back (5+6); + + primitives->push_back (0+6); + primitives->push_back (5+6); + primitives->push_back (3+6); + + primitives->push_back (4+6); + primitives->push_back (5+6); + primitives->push_back (2+6); + + primitives->push_back (4+6); + primitives->push_back (2+6); + primitives->push_back (1+6); + + geometry->addPrimitiveSet (primitives); osg::Vec4Array *colours = new osg::Vec4Array; From 68115c4e8aa3447e8848528b816c3fd4a8253e64 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 13 Oct 2015 16:15:53 +0200 Subject: [PATCH 60/84] (somewhat) improved the colour scheme --- apps/opencs/view/render/cellarrow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/view/render/cellarrow.cpp b/apps/opencs/view/render/cellarrow.cpp index 526c9a24c..59460b626 100644 --- a/apps/opencs/view/render/cellarrow.cpp +++ b/apps/opencs/view/render/cellarrow.cpp @@ -116,7 +116,7 @@ void CSVRender::CellArrow::buildShape() for (int i=0; i<6; ++i) colours->push_back (osg::Vec4f (1.0f, 0.0f, 0.0f, 1.0f)); for (int i=0; i<6; ++i) - colours->push_back (osg::Vec4f (1.0f, 0.0f, 0.4f, 1.0f)); + colours->push_back (osg::Vec4f (0.8f, (i==2 || i==5) ? 0.6f : 0.4f, 0.0f, 1.0f)); geometry->setColorArray (colours); geometry->setColorBinding (osg::Geometry::BIND_PER_VERTEX); From a88d56148b45a6ddb1c4cb95ab75f112550fac58 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 13 Oct 2015 16:35:31 +0200 Subject: [PATCH 61/84] Read the Sun Glare Fader ini settings --- apps/openmw/mwrender/sky.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 6f1b26733..a8aeeb930 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -724,7 +724,17 @@ private: , mTimeOfDayFade(1.f) , mGlareView(1.f) { - + const MWWorld::Fallback* fallback = MWBase::Environment::get().getWorld()->getFallback(); + mColor = fallback->getFallbackColour("Weather_Sun_Glare_Fader_Color"); + mSunGlareFaderMax = fallback->getFallbackFloat("Weather_Sun_Glare_Fader_Max"); + mSunGlareFaderAngleMax = fallback->getFallbackFloat("Weather_Sun_Glare_Fader_Angle_Max"); + + // Replicating a design flaw in MW. The color was being set on both ambient and emissive properties, which multiplies the result by two, + // then finally gets clamped by the fixed function pipeline. With the default INI settings, only the red component gets clamped, + // so the resulting color looks more orange than red. + mColor *= 2; + for (int i=0; i<3; ++i) + mColor[i] = std::min(1.f, mColor[i]); } virtual void operator ()(osg::Node* node, osg::NodeVisitor* nv) @@ -734,12 +744,10 @@ private: float angleRadians = getAngleToSunInRadians(cv->getCurrentCamera()); float visibleRatio = getVisibleRatio(cv->getCurrentCamera()); - const float angleMaxRadians = osg::DegreesToRadians(30.f); // Sun Glare Fader Angle Max + const float angleMaxRadians = osg::DegreesToRadians(mSunGlareFaderAngleMax); float value = 1.f - std::min(1.f, angleRadians / angleMaxRadians); - - const float sunGlareFaderMax = 0.5f; - float fade = value * sunGlareFaderMax; + float fade = value * mSunGlareFaderMax; fade *= mTimeOfDayFade * mGlareView * visibleRatio; @@ -754,17 +762,8 @@ private: osg::ref_ptr mat (createUnlitMaterial()); - osg::Vec4f sunGlareFaderColor (222/255.f, 95/255.f, 39/255.f, 1); - - // Replicating a design flaw in MW. The color was being set on both ambient and emissive properties, which multiplies the result by two, - // then finally gets clamped by the fixed function pipeline. With the default INI settings, only the red component gets clamped, - // so the resulting color looks more orange than red. - sunGlareFaderColor *= 2; - for (int i=0; i<3; ++i) - sunGlareFaderColor[i] = std::min(1.f, sunGlareFaderColor[i]); - mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0,0,0,fade)); - mat->setEmission(osg::Material::FRONT_AND_BACK, sunGlareFaderColor); + mat->setEmission(osg::Material::FRONT_AND_BACK, mColor); stateset->setAttributeAndModes(mat, osg::StateAttribute::ON); @@ -802,6 +801,9 @@ private: osg::ref_ptr mSunTransform; float mTimeOfDayFade; float mGlareView; + osg::Vec4f mColor; + float mSunGlareFaderMax; + float mSunGlareFaderAngleMax; }; osg::ref_ptr mUpdater; From 773df6fd22e756ec39f0ad516edd47286914eef0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 13 Oct 2015 16:53:40 +0200 Subject: [PATCH 62/84] some OSG fixes --- apps/opencs/view/render/cellarrow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/render/cellarrow.cpp b/apps/opencs/view/render/cellarrow.cpp index 59460b626..720db5327 100644 --- a/apps/opencs/view/render/cellarrow.cpp +++ b/apps/opencs/view/render/cellarrow.cpp @@ -118,8 +118,9 @@ void CSVRender::CellArrow::buildShape() for (int i=0; i<6; ++i) colours->push_back (osg::Vec4f (0.8f, (i==2 || i==5) ? 0.6f : 0.4f, 0.0f, 1.0f)); - geometry->setColorArray (colours); - geometry->setColorBinding (osg::Geometry::BIND_PER_VERTEX); + geometry->setColorArray (colours, osg::Array::BIND_PER_VERTEX); + + geometry->getOrCreateStateSet()->setMode (GL_LIGHTING, osg::StateAttribute::OFF); osg::ref_ptr geode (new osg::Geode); geode->addDrawable (geometry); From ee450471fdf4dbb276bbf6f3f7e7662237d84652 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 13 Oct 2015 17:55:57 +0200 Subject: [PATCH 63/84] Disable head controller for non-bipedal creatures (Fixes #2843, Fixes #2966) --- apps/openmw/mwrender/animation.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 37ec4c213..a0704a59a 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -1320,13 +1320,16 @@ namespace MWRender { mHeadController = NULL; - NodeMap::iterator found = mNodeMap.find("bip01 head"); - if (found != mNodeMap.end() && dynamic_cast(found->second.get())) + if (mPtr.getClass().isBipedal(mPtr)) { - osg::Node* node = found->second; - mHeadController = new RotateController(mObjectRoot.get()); - node->addUpdateCallback(mHeadController); - mActiveControllers.insert(std::make_pair(node, mHeadController)); + NodeMap::iterator found = mNodeMap.find("bip01 head"); + if (found != mNodeMap.end() && dynamic_cast(found->second.get())) + { + osg::Node* node = found->second; + mHeadController = new RotateController(mObjectRoot.get()); + node->addUpdateCallback(mHeadController); + mActiveControllers.insert(std::make_pair(node, mHeadController)); + } } } From f36d463617b0b9f29dd9edaf19bb122882b8b7e6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 13 Oct 2015 18:13:52 +0200 Subject: [PATCH 64/84] Enchantment error handling fix (Fixes #2959) Catch errors about missing enchantments before they propagate up the stack and interrupt the whole frame update. --- apps/openmw/mwgui/spellmodel.cpp | 11 +++++++++-- apps/openmw/mwworld/inventorystore.cpp | 11 +++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/spellmodel.cpp b/apps/openmw/mwgui/spellmodel.cpp index 91512a011..58ec05794 100644 --- a/apps/openmw/mwgui/spellmodel.cpp +++ b/apps/openmw/mwgui/spellmodel.cpp @@ -1,5 +1,7 @@ #include "spellmodel.hpp" +#include + #include #include "../mwbase/environment.hpp" @@ -79,8 +81,13 @@ namespace MWGui const std::string enchantId = item.getClass().getEnchantment(item); if (enchantId.empty()) continue; - const ESM::Enchantment* enchant = - esmStore.get().find(item.getClass().getEnchantment(item)); + const ESM::Enchantment* enchant = esmStore.get().search(enchantId); + if (!enchant) + { + std::cerr << "Can't find enchantment '" << enchantId << "' on item " << item.getCellRef().getRefId() << std::endl; + continue; + } + if (enchant->mData.mType != ESM::Enchantment::WhenUsed && enchant->mData.mType != ESM::Enchantment::CastOnce) continue; diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 0755c1555..ebba4ae30 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -645,8 +645,15 @@ void MWWorld::InventoryStore::updateRechargingItems() { if (it->getClass().getEnchantment(*it) != "") { - const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get().find( - it->getClass().getEnchantment(*it)); + std::string enchantmentId = it->getClass().getEnchantment(*it); + const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get().search( + enchantmentId); + if (!enchantment) + { + std::cerr << "Can't find enchantment '" << enchantmentId << "' on item " << it->getCellRef().getRefId() << std::endl; + continue; + } + if (enchantment->mData.mType == ESM::Enchantment::WhenUsed || enchantment->mData.mType == ESM::Enchantment::WhenStrikes) mRechargingItems.push_back(std::make_pair(it, static_cast(enchantment->mData.mCharge))); From 8459a79a2c1da69e3f215fb3d29b4999ad0a8b6f Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 13 Oct 2015 19:05:17 +0200 Subject: [PATCH 65/84] Fix AI being able to open locked doors (Fixes #2948) --- apps/openmw/mwmechanics/aipackage.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 1cd9649f7..bedff8bcd 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -88,7 +88,8 @@ void MWMechanics::AiPackage::evadeObstacles(const MWWorld::Ptr& actor, float dur MWWorld::Ptr door = getNearbyDoor(actor); if (door != MWWorld::Ptr()) // NOTE: checks interior cells only { - if (!door.getCellRef().getTeleport() && door.getCellRef().getTrap().empty() && door.getClass().getDoorState(door) == 0) { //Open the door if untrapped + if (!door.getCellRef().getTeleport() && door.getCellRef().getTrap().empty() + && door.getCellRef().getLockLevel() <= 0 && door.getClass().getDoorState(door) == 0) { MWBase::Environment::get().getWorld()->activateDoor(door, 1); } } From 33e12a99fad15ced87a9996c42ffeb84983be2a4 Mon Sep 17 00:00:00 2001 From: "artemutin@yandex.ru" Date: Sun, 11 Oct 2015 21:49:10 +1000 Subject: [PATCH 66/84] If table dont use any filter, filter update now dont cause a reapply of empty filter --- apps/opencs/view/filter/editwidget.cpp | 12 +++++++++++- apps/opencs/view/filter/editwidget.hpp | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/filter/editwidget.cpp b/apps/opencs/view/filter/editwidget.cpp index 657a47750..5fbc66464 100644 --- a/apps/opencs/view/filter/editwidget.cpp +++ b/apps/opencs/view/filter/editwidget.cpp @@ -7,7 +7,7 @@ #include "../../model/world/data.hpp" CSVFilter::EditWidget::EditWidget (CSMWorld::Data& data, QWidget *parent) -: QLineEdit (parent), mParser (data) +: QLineEdit (parent), mParser (data), mIsEmpty(true) { mPalette = palette(); connect (this, SIGNAL (textChanged (const QString&)), this, SLOT (textChanged (const QString&))); @@ -27,6 +27,16 @@ CSVFilter::EditWidget::EditWidget (CSMWorld::Data& data, QWidget *parent) void CSVFilter::EditWidget::textChanged (const QString& text) { + //no need to parse and apply filter if it was empty and now is empty too. + //e.g. - we modifiing content of filter with already opened some other (big) tables. + if (text.length() == 0){ + if (mIsEmpty) + return; + else + mIsEmpty = true; + }else + mIsEmpty = false; + if (mParser.parse (text.toUtf8().constData())) { setPalette (mPalette); diff --git a/apps/opencs/view/filter/editwidget.hpp b/apps/opencs/view/filter/editwidget.hpp index a0f9f8919..5c3f1b09e 100644 --- a/apps/opencs/view/filter/editwidget.hpp +++ b/apps/opencs/view/filter/editwidget.hpp @@ -25,6 +25,7 @@ namespace CSVFilter CSMFilter::Parser mParser; QPalette mPalette; + bool mIsEmpty; public: From 361634489ed7a1286919bef02b687fe3682cd619 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 15 Oct 2015 14:46:08 +0200 Subject: [PATCH 67/84] properly handle cells that don't exist --- apps/opencs/view/render/cell.cpp | 50 +++++++++++++------ apps/opencs/view/render/cell.hpp | 8 ++- .../view/render/pagedworldspacewidget.cpp | 47 +++++++++++------ 3 files changed, 72 insertions(+), 33 deletions(-) diff --git a/apps/opencs/view/render/cell.cpp b/apps/opencs/view/render/cell.cpp index 5ec69a5f2..da40f7e7c 100644 --- a/apps/opencs/view/render/cell.cpp +++ b/apps/opencs/view/render/cell.cpp @@ -51,8 +51,9 @@ bool CSVRender::Cell::addObjects (int start, int end) return modified; } -CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id) -: mData (data), mId (Misc::StringUtils::lowerCase (id)) +CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id, + bool deleted) +: mData (data), mId (Misc::StringUtils::lowerCase (id)), mDeleted (deleted) { std::pair result = CSMWorld::CellCoordinates::fromId (id); @@ -62,24 +63,27 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::st mCellNode = new osg::Group; rootNode->addChild(mCellNode); - CSMWorld::IdTable& references = dynamic_cast ( - *mData.getTableModel (CSMWorld::UniversalId::Type_References)); - - int rows = references.rowCount(); + if (!mDeleted) + { + CSMWorld::IdTable& references = dynamic_cast ( + *mData.getTableModel (CSMWorld::UniversalId::Type_References)); - addObjects (0, rows-1); + int rows = references.rowCount(); - const CSMWorld::IdCollection& land = mData.getLand(); - int landIndex = land.searchId(mId); - if (landIndex != -1) - { - const ESM::Land& esmLand = land.getRecord(mId).get(); + addObjects (0, rows-1); - if (esmLand.getLandData (ESM::Land::DATA_VHGT)) + const CSMWorld::IdCollection& land = mData.getLand(); + int landIndex = land.searchId(mId); + if (landIndex != -1) { - mTerrain.reset(new Terrain::TerrainGrid(mCellNode, data.getResourceSystem().get(), NULL, new TerrainStorage(mData), Element_Terrain<<1)); - mTerrain->loadCell(esmLand.mX, - esmLand.mY); + const ESM::Land& esmLand = land.getRecord(mId).get(); + + if (esmLand.getLandData (ESM::Land::DATA_VHGT)) + { + mTerrain.reset(new Terrain::TerrainGrid(mCellNode, data.getResourceSystem().get(), NULL, new TerrainStorage(mData), Element_Terrain<<1)); + mTerrain->loadCell(esmLand.mX, + esmLand.mY); + } } } } @@ -125,6 +129,9 @@ bool CSVRender::Cell::referenceableAboutToBeRemoved (const QModelIndex& parent, bool CSVRender::Cell::referenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight) { + if (mDeleted) + return false; + CSMWorld::IdTable& references = dynamic_cast ( *mData.getTableModel (CSMWorld::UniversalId::Type_References)); @@ -192,6 +199,9 @@ bool CSVRender::Cell::referenceAboutToBeRemoved (const QModelIndex& parent, int if (parent.isValid()) return false; + if (mDeleted) + return false; + CSMWorld::IdTable& references = dynamic_cast ( *mData.getTableModel (CSMWorld::UniversalId::Type_References)); @@ -212,6 +222,9 @@ bool CSVRender::Cell::referenceAdded (const QModelIndex& parent, int start, int if (parent.isValid()) return false; + if (mDeleted) + return false; + return addObjects (start, end); } @@ -258,3 +271,8 @@ CSMWorld::CellCoordinates CSVRender::Cell::getCoordinates() const { return mCoordinates; } + +bool CSVRender::Cell::isDeleted() const +{ + return mDeleted; +} diff --git a/apps/opencs/view/render/cell.hpp b/apps/opencs/view/render/cell.hpp index 7cced4fe3..59f4cafee 100644 --- a/apps/opencs/view/render/cell.hpp +++ b/apps/opencs/view/render/cell.hpp @@ -40,6 +40,7 @@ namespace CSVRender std::auto_ptr mTerrain; CSMWorld::CellCoordinates mCoordinates; std::auto_ptr mCellArrows[4]; + bool mDeleted; /// Ignored if cell does not have an object with the given ID. /// @@ -62,7 +63,10 @@ namespace CSVRender public: - Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id); + /// \note Deleted covers both cells that are deleted and cells that don't exist in + /// the first place. + Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id, + bool deleted = false); ~Cell(); @@ -93,6 +97,8 @@ namespace CSVRender /// Returns 0, 0 in case of an unpaged cell. CSMWorld::CellCoordinates getCoordinates() const; + + bool isDeleted() const; }; } diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index 070ce7d17..dd740ab9a 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -1,5 +1,6 @@ #include "pagedworldspacewidget.hpp" +#include #include #include @@ -26,17 +27,14 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells() const CSMWorld::IdCollection& cells = mDocument.getData().getCells(); { - // remove (or name/region modified) + // remove/update std::map::iterator iter (mCells.begin()); while (iter!=mCells.end()) { - int index = cells.searchId (iter->first.getId (mWorldspace)); - - /// \todo handle cells that don't exist - if (!mSelection.has (iter->first) || index==-1 || - cells.getRecord (index).mState==CSMWorld::RecordBase::State_Deleted) + if (!mSelection.has (iter->first)) { + // remove delete iter->second; mCells.erase (iter++); @@ -44,12 +42,33 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells() } else { - // check if name or region field has changed - // FIXME: config setting - //std::string name = cells.getRecord(index).get().mName; - //std::string region = cells.getRecord(index).get().mRegion; + // update + int index = cells.searchId (iter->first.getId (mWorldspace)); + + bool deleted = index==-1 || + cells.getRecord (index).mState==CSMWorld::RecordBase::State_Deleted; + + if (deleted!=iter->second->isDeleted()) + { + modified = true; - // cell marker update goes here + std::auto_ptr cell (new Cell (mDocument.getData(), mRootNode, + iter->first.getId (mWorldspace), deleted)); + + delete iter->second; + iter->second = cell.release(); + } + else if (!deleted) + { + // delete state has not changed -> just update + + // TODO check if name or region field has changed (cell marker) + // FIXME: config setting + //std::string name = cells.getRecord(index).get().mName; + //std::string region = cells.getRecord(index).get().mRegion; + + modified = true; + } ++iter; } @@ -60,11 +79,7 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells() for (CSMWorld::CellSelection::Iterator iter (mSelection.begin()); iter!=mSelection.end(); ++iter) { - int index = cells.searchId (iter->getId (mWorldspace)); - - /// \todo handle cells that don't exist - if (index > 0 && cells.getRecord (index).mState!=CSMWorld::RecordBase::State_Deleted && - mCells.find (*iter)==mCells.end()) + if (mCells.find (*iter)==mCells.end()) { Cell *cell = new Cell (mDocument.getData(), mRootNode, iter->getId (mWorldspace)); From eae36f800585a9347e778b36a1010b2a05f576c4 Mon Sep 17 00:00:00 2001 From: "artemutin@yandex.ru" Date: Tue, 13 Oct 2015 23:44:23 +1000 Subject: [PATCH 68/84] Fixed filter reapplication on Description column change and on State column change. Moved column index search to widget constructor, rewrite slot with respect to multiple columns data change. --- apps/opencs/view/filter/editwidget.cpp | 12 ++++++++++-- apps/opencs/view/filter/editwidget.hpp | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/filter/editwidget.cpp b/apps/opencs/view/filter/editwidget.cpp index 5fbc66464..600fa4f3b 100644 --- a/apps/opencs/view/filter/editwidget.cpp +++ b/apps/opencs/view/filter/editwidget.cpp @@ -5,6 +5,8 @@ #include #include "../../model/world/data.hpp" +#include "../../model/world/idtablebase.hpp" +#include "../../model/world/columns.hpp" CSVFilter::EditWidget::EditWidget (CSMWorld::Data& data, QWidget *parent) : QLineEdit (parent), mParser (data), mIsEmpty(true) @@ -12,7 +14,8 @@ CSVFilter::EditWidget::EditWidget (CSMWorld::Data& data, QWidget *parent) mPalette = palette(); connect (this, SIGNAL (textChanged (const QString&)), this, SLOT (textChanged (const QString&))); - QAbstractItemModel *model = data.getTableModel (CSMWorld::UniversalId::Type_Filters); + const CSMWorld::IdTableBase *model = + static_cast (data.getTableModel (CSMWorld::UniversalId::Type_Filters)); connect (model, SIGNAL (dataChanged (const QModelIndex &, const QModelIndex&)), this, SLOT (filterDataChanged (const QModelIndex &, const QModelIndex&)), @@ -23,6 +26,9 @@ CSVFilter::EditWidget::EditWidget (CSMWorld::Data& data, QWidget *parent) connect (model, SIGNAL (rowsInserted (const QModelIndex&, int, int)), this, SLOT (filterRowsInserted (const QModelIndex&, int, int)), Qt::QueuedConnection); + + mStateColumnIndex = model->findColumnIndex(CSMWorld::Columns::ColumnId_Modification); + mDescColumnIndex = model->findColumnIndex(CSMWorld::Columns::ColumnId_Description); } void CSVFilter::EditWidget::textChanged (const QString& text) @@ -55,7 +61,9 @@ void CSVFilter::EditWidget::textChanged (const QString& text) void CSVFilter::EditWidget::filterDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight) { - textChanged (text()); + for (int i = topLeft.column(); i <= bottomRight.column(); ++i) + if (i != mStateColumnIndex && i != mDescColumnIndex) + textChanged (text()); } void CSVFilter::EditWidget::filterRowsRemoved (const QModelIndex& parent, int start, int end) diff --git a/apps/opencs/view/filter/editwidget.hpp b/apps/opencs/view/filter/editwidget.hpp index 5c3f1b09e..f672877d9 100644 --- a/apps/opencs/view/filter/editwidget.hpp +++ b/apps/opencs/view/filter/editwidget.hpp @@ -26,6 +26,8 @@ namespace CSVFilter CSMFilter::Parser mParser; QPalette mPalette; bool mIsEmpty; + int mStateColumnIndex; + int mDescColumnIndex; public: From 04df656f54e9eda44cc1ff68b4f23678089d02f1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 18 Oct 2015 21:39:53 +0200 Subject: [PATCH 69/84] Remove some junk --- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 993dde6e4..1f06940c6 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -420,7 +420,6 @@ namespace MWDialogue { if(mDialogueMap.find(keyword) != mDialogueMap.end()) { - ESM::Dialogue ndialogue = mDialogueMap[keyword]; if (mDialogueMap[keyword].mType == ESM::Dialogue::Topic) { executeTopic (keyword); From 93565eccbff87bb3ef8beef9da7250611195a825 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 18 Oct 2015 21:40:16 +0200 Subject: [PATCH 70/84] Update the dialogue topic list after running greeting script --- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 1f06940c6..f8c9bb38e 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -139,9 +139,6 @@ namespace MWDialogue win->startDialogue(actor, actor.getClass().getName (actor), resetHistory); - //setup the list of topics known by the actor. Topics who are also on the knownTopics list will be added to the GUI - updateTopics(); - //greeting const MWWorld::Store &dialogs = MWBase::Environment::get().getWorld()->getStore().get(); @@ -165,12 +162,19 @@ namespace MWDialogue // TODO play sound } + // first topics update so that parseText knows the keywords to highlight + updateTopics(); + parseText (info->mResponse); MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor); win->addResponse (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext)); executeScript (info->mResultScript); mLastTopic = Misc::StringUtils::lowerCase(it->mId); + + // update topics again to accomodate changes resulting from executeScript + updateTopics(); + return; } } From 2ee6b41887b8dff5231f9925c6a0205a75d67159 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 19 Oct 2015 15:46:53 +0200 Subject: [PATCH 71/84] Handle NiAlphaProperty on a drawable basis Removes the RenderBin nesting complication. Also results in leaner StateSets, so the cull phase should be a bit faster. --- components/nifosg/nifloader.cpp | 92 ++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 42 deletions(-) diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 75a427c5a..2b73f779f 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -57,8 +57,8 @@ namespace } } - // Collect all properties affecting the given node that should be applied to an osg::Material. - void collectMaterialProperties(const Nif::Node* nifNode, std::vector& out) + // Collect all properties affecting the given drawable that should be handled on drawable basis rather than on the node hierarchy above it. + void collectDrawableProperties(const Nif::Node* nifNode, std::vector& out) { const Nif::PropertyList& props = nifNode->props; for (size_t i = 0; i parent) - collectMaterialProperties(nifNode->parent, out); + collectDrawableProperties(nifNode->parent, out); } class FrameSwitch : public osg::Group @@ -872,9 +873,9 @@ namespace NifOsg osg::ref_ptr geode (new osg::Geode); geode->addDrawable(partsys); - std::vector materialProps; - collectMaterialProperties(nifNode, materialProps); - applyMaterialProperties(parentNode, materialProps, composite, true, animflags); + std::vector drawableProps; + collectDrawableProperties(nifNode, drawableProps); + applyDrawableProperties(parentNode, drawableProps, composite, true, animflags); // Particles don't have normals, so can't be diffuse lit. osg::Material* mat = static_cast(parentNode->getStateSet()->getAttribute(osg::StateAttribute::MATERIAL)); @@ -934,9 +935,9 @@ namespace NifOsg // - if there are no vertex colors, we need to disable colorMode. // - there are 3 "overlapping" nif properties that all affect the osg::Material, handling them // above the actual renderable would be tedious. - std::vector materialProps; - collectMaterialProperties(triShape, materialProps); - applyMaterialProperties(parentNode, materialProps, composite, !data->colors->empty(), animflags); + std::vector drawableProps; + collectDrawableProperties(triShape, drawableProps); + applyDrawableProperties(parentNode, drawableProps, composite, !data->colors->empty(), animflags); } void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector& boundTextures, int animflags) @@ -1223,42 +1224,12 @@ namespace NifOsg case Nif::RC_NiVertexColorProperty: case Nif::RC_NiSpecularProperty: { - // Handled in handleTriShape so we know whether vertex colors are available + // Handled on drawable level so we know whether vertex colors are available break; } case Nif::RC_NiAlphaProperty: { - const Nif::NiAlphaProperty* alphaprop = static_cast(property); - osg::BlendFunc* blendfunc = new osg::BlendFunc; - osg::StateSet* stateset = node->getOrCreateStateSet(); - if (alphaprop->flags&1) - { - blendfunc->setFunction(getBlendMode((alphaprop->flags>>1)&0xf), - getBlendMode((alphaprop->flags>>5)&0xf)); - stateset->setAttributeAndModes(blendfunc, osg::StateAttribute::ON); - - bool noSort = (alphaprop->flags>>13)&1; - if (!noSort) - { - stateset->setNestRenderBins(false); - stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); - } - } - else - { - stateset->setAttributeAndModes(blendfunc, osg::StateAttribute::OFF); - stateset->setNestRenderBins(false); - stateset->setRenderingHint(osg::StateSet::OPAQUE_BIN); - } - - osg::AlphaFunc* alphafunc = new osg::AlphaFunc; - if((alphaprop->flags>>9)&1) - { - alphafunc->setFunction(getTestMode((alphaprop->flags>>10)&0x7), alphaprop->data.threshold/255.f); - stateset->setAttributeAndModes(alphafunc, osg::StateAttribute::ON); - } - else - stateset->setAttributeAndModes(alphafunc, osg::StateAttribute::OFF); + // Handled on drawable level to prevent RenderBin nesting issues break; } case Nif::RC_NiTexturingProperty: @@ -1388,7 +1359,7 @@ namespace NifOsg } } - void applyMaterialProperties(osg::Node* node, const std::vector& properties, SceneUtil::CompositeStateSetUpdater* composite, + void applyDrawableProperties(osg::Node* node, const std::vector& properties, SceneUtil::CompositeStateSetUpdater* composite, bool hasVertexColors, int animflags) { osg::StateSet* stateset = node->getOrCreateStateSet(); @@ -1444,6 +1415,43 @@ namespace NifOsg mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); break; } + break; + } + case Nif::RC_NiAlphaProperty: + { + const Nif::NiAlphaProperty* alphaprop = static_cast(property); + osg::BlendFunc* blendfunc = new osg::BlendFunc; + if (alphaprop->flags&1) + { + blendfunc->setFunction(getBlendMode((alphaprop->flags>>1)&0xf), + getBlendMode((alphaprop->flags>>5)&0xf)); + stateset->setAttributeAndModes(blendfunc, osg::StateAttribute::ON); + + bool noSort = (alphaprop->flags>>13)&1; + if (!noSort) + stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); + else + stateset->setRenderBinToInherit(); + } + else + { + stateset->removeAttribute(osg::StateAttribute::BLENDFUNC); + stateset->removeMode(GL_BLEND); + stateset->setRenderBinToInherit(); + } + + osg::AlphaFunc* alphafunc = new osg::AlphaFunc; + if((alphaprop->flags>>9)&1) + { + alphafunc->setFunction(getTestMode((alphaprop->flags>>10)&0x7), alphaprop->data.threshold/255.f); + stateset->setAttributeAndModes(alphafunc, osg::StateAttribute::ON); + } + else + { + stateset->removeAttribute(osg::StateAttribute::ALPHAFUNC); + stateset->removeMode(GL_ALPHA_TEST); + } + break; } } } From 6ef139e1d7de6f0a952009c523ccfc4ac9d20768 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 19 Oct 2015 22:17:04 +0200 Subject: [PATCH 72/84] Implement a custom RenderBin for first person models (Fixes #1612) --- apps/openmw/mwrender/animation.cpp | 17 ++++++++-- apps/openmw/mwrender/animation.hpp | 3 ++ apps/openmw/mwrender/npcanimation.cpp | 48 +++++++++++++++++++++++++++ apps/openmw/mwrender/npcanimation.hpp | 2 ++ apps/openmw/mwrender/renderbin.hpp | 9 ++--- 5 files changed, 72 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index a0704a59a..b2fa87310 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -1275,15 +1275,26 @@ namespace MWRender material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1)); stateset->setAttributeAndModes(material, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); - stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); - stateset->setRenderBinMode(osg::StateSet::OVERRIDE_RENDERBIN_DETAILS); - stateset->setNestRenderBins(false); mObjectRoot->setStateSet(stateset); } else { mObjectRoot->setStateSet(NULL); } + + setRenderBin(); + } + + void Animation::setRenderBin() + { + if (mAlpha != 1.f) + { + osg::StateSet* stateset = mObjectRoot->getOrCreateStateSet(); + stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); + stateset->setRenderBinMode(osg::StateSet::OVERRIDE_RENDERBIN_DETAILS); + } + else if (osg::StateSet* stateset = mObjectRoot->getStateSet()) + stateset->setRenderBinToInherit(); } void Animation::setLightEffect(float effect) diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 94b792c0d..1e46cc71a 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -307,6 +307,9 @@ protected: void addGlow(osg::ref_ptr node, osg::Vec4f glowColor); + /// Set the render bin for this animation's object root. May be customized by subclasses. + virtual void setRenderBin(); + public: Animation(const MWWorld::Ptr &ptr, osg::ref_ptr parentNode, Resource::ResourceSystem* resourceSystem); diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 99ee886e1..cba6c5696 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -2,6 +2,9 @@ #include #include +#include + +#include #include @@ -28,6 +31,7 @@ #include "camera.hpp" #include "rotatecontroller.hpp" +#include "renderbin.hpp" namespace { @@ -303,6 +307,50 @@ void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode) mViewMode = viewMode; rebuild(); + + setRenderBin(); +} + +/// @brief A RenderBin callback to clear the depth buffer before rendering. +class DepthClearCallback : public osgUtil::RenderBin::DrawCallback +{ +public: + DepthClearCallback() + { + mDepth = new osg::Depth; + mDepth->setWriteMask(true); + } + + virtual void drawImplementation(osgUtil::RenderBin* bin, osg::RenderInfo& renderInfo, osgUtil::RenderLeaf*& previous) + { + renderInfo.getState()->applyAttribute(mDepth); + + glClear(GL_DEPTH_BUFFER_BIT); + + bin->drawImplementation(renderInfo, previous); + } + + osg::ref_ptr mDepth; +}; + +void NpcAnimation::setRenderBin() +{ + if (mViewMode == VM_FirstPerson) + { + static bool prototypeAdded = false; + if (!prototypeAdded) + { + osg::ref_ptr depthClearBin (new osgUtil::RenderBin); + depthClearBin->setDrawCallback(new DepthClearCallback); + osgUtil::RenderBin::addRenderBinPrototype("DepthClear", depthClearBin); + prototypeAdded = true; + } + + osg::StateSet* stateset = mObjectRoot->getOrCreateStateSet(); + stateset->setRenderBinDetails(RenderBin_FirstPerson, "DepthClear", osg::StateSet::OVERRIDE_RENDERBIN_DETAILS); + } + else + Animation::setRenderBin(); } void NpcAnimation::rebuild() diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 06f40f847..b4272226d 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -81,6 +81,8 @@ private: void addPartGroup(int group, int priority, const std::vector &parts, bool enchantedGlow=false, osg::Vec4f* glowColor=NULL); + virtual void setRenderBin(); + osg::ref_ptr mFirstPersonNeckController; protected: diff --git a/apps/openmw/mwrender/renderbin.hpp b/apps/openmw/mwrender/renderbin.hpp index 63ccdd259..c14f61142 100644 --- a/apps/openmw/mwrender/renderbin.hpp +++ b/apps/openmw/mwrender/renderbin.hpp @@ -5,14 +5,15 @@ namespace MWRender { /// Defines the render bin numbers used in the OpenMW scene graph. The bin with the lowest number is rendered first. - /// Beware of RenderBin nesting, in most cases you will want to use setNestRenderBins(false). enum RenderBins { RenderBin_Sky = -1, - RenderBin_Default = 0, + RenderBin_Default = 0, // osg::StateSet::OPAQUE_BIN RenderBin_Water = 9, - RenderBin_OcclusionQuery = 10, - RenderBin_SunGlare = 11 + RenderBin_DepthSorted = 10, // osg::StateSet::TRANSPARENT_BIN + RenderBin_OcclusionQuery = 11, + RenderBin_FirstPerson = 12, + RenderBin_SunGlare = 13 }; } From 8552a9d82c8e9f01e9d843745664788f9d460976 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 23 Oct 2015 01:58:22 +0200 Subject: [PATCH 73/84] Add multiple camera support to LightManager --- components/sceneutil/lightmanager.cpp | 56 ++++++++++++++------------- components/sceneutil/lightmanager.hpp | 16 +++++--- 2 files changed, 41 insertions(+), 31 deletions(-) diff --git a/components/sceneutil/lightmanager.cpp b/components/sceneutil/lightmanager.cpp index 07ec0aff6..77551e006 100644 --- a/components/sceneutil/lightmanager.cpp +++ b/components/sceneutil/lightmanager.cpp @@ -126,15 +126,13 @@ namespace SceneUtil }; LightManager::LightManager() - : mLightsInViewSpace(false) - , mStartLight(0) + : mStartLight(0) { setUpdateCallback(new LightManagerUpdateCallback); } LightManager::LightManager(const LightManager ©, const osg::CopyOp ©op) : osg::Group(copy, copyop) - , mLightsInViewSpace(false) , mStartLight(copy.mStartLight) { @@ -142,8 +140,8 @@ namespace SceneUtil void LightManager::update() { - mLightsInViewSpace = false; mLights.clear(); + mLightsInViewSpace.clear(); // do an occasional cleanup for orphaned lights if (mStateSetCache.size() > 5000) @@ -161,22 +159,6 @@ namespace SceneUtil mLights.push_back(l); } - void LightManager::prepareForCamera(osg::Camera *cam) - { - // later on we need to store this per camera - if (!mLightsInViewSpace) - { - for (std::vector::iterator it = mLights.begin(); it != mLights.end(); ++it) - { - LightSourceTransform& l = *it; - osg::Matrix worldViewMat = l.mWorldMatrix * cam->getViewMatrix(); - l.mViewBound = osg::BoundingSphere(osg::Vec3f(0,0,0), l.mLightSource->getRadius()); - transformBoundingSphere(worldViewMat, l.mViewBound); - } - mLightsInViewSpace = true; - } - } - osg::ref_ptr LightManager::getLightListStateSet(const LightList &lightList) { // possible optimization: return a StateSet containing all requested lights plus some extra lights (if a suitable one exists) @@ -212,6 +194,30 @@ namespace SceneUtil return mLights; } + const std::vector& LightManager::getLightsInViewSpace(osg::Camera *camera) + { + osg::observer_ptr camPtr (camera); + std::map, LightSourceViewBoundCollection>::iterator it = mLightsInViewSpace.find(camPtr); + + if (it == mLightsInViewSpace.end()) + { + it = mLightsInViewSpace.insert(std::make_pair(camPtr, LightSourceViewBoundCollection())).first; + + for (std::vector::iterator lightIt = mLights.begin(); lightIt != mLights.end(); ++lightIt) + { + osg::Matrix worldViewMat = lightIt->mWorldMatrix * camera->getViewMatrix(); + osg::BoundingSphere viewBound = osg::BoundingSphere(osg::Vec3f(0,0,0), lightIt->mLightSource->getRadius()); + transformBoundingSphere(worldViewMat, viewBound); + + LightSourceViewBound l; + l.mLightSource = lightIt->mLightSource; + l.mViewBound = viewBound; + it->second.push_back(l); + } + } + return it->second; + } + void LightManager::setStartLight(int start) { mStartLight = start; @@ -241,7 +247,7 @@ namespace SceneUtil } - bool sortLights (const LightManager::LightSourceTransform* left, const LightManager::LightSourceTransform* right) + bool sortLights (const LightManager::LightSourceViewBound* left, const LightManager::LightSourceViewBound* right) { return left->mViewBound.center().length2() - left->mViewBound.radius2()/4.f < right->mViewBound.center().length2() - right->mViewBound.radius2()/4.f; } @@ -273,13 +279,11 @@ namespace SceneUtil } } - mLightManager->prepareForCamera(cv->getCurrentCamera()); - // Possible optimizations: // - cull list of lights by the camera frustum // - organize lights in a quad tree - const std::vector& lights = mLightManager->getLights(); + const std::vector& lights = mLightManager->getLightsInViewSpace(cv->getCurrentCamera()); if (lights.size()) { @@ -288,10 +292,10 @@ namespace SceneUtil osg::Matrixf mat = *cv->getModelViewMatrix(); transformBoundingSphere(mat, nodeBound); - std::vector lightList; + LightManager::LightList lightList; for (unsigned int i=0; i& getLights() const; - typedef std::vector LightList; + struct LightSourceViewBound + { + LightSource* mLightSource; + osg::BoundingSphere mViewBound; + }; + + const std::vector& getLightsInViewSpace(osg::Camera* camera); + + typedef std::vector LightList; osg::ref_ptr getLightListStateSet(const LightList& lightList); @@ -98,7 +103,8 @@ namespace SceneUtil // Lights collected from the scene graph. Only valid during the cull traversal. std::vector mLights; - bool mLightsInViewSpace; + typedef std::vector LightSourceViewBoundCollection; + std::map, LightSourceViewBoundCollection> mLightsInViewSpace; // < Light list hash , StateSet > typedef std::map > LightStateSetMap; From 69f234d97b04f2263455a65c221c981f3482cb53 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 23 Oct 2015 16:50:08 +0200 Subject: [PATCH 74/84] Small delay before the loading screen shows Kinda irritating to have the loading bar pop up for a fraction of a second. --- apps/openmw/mwgui/loadingscreen.cpp | 74 +++++++++++++++++++---------- apps/openmw/mwgui/loadingscreen.hpp | 1 + 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 9b99ad7bf..9afce6873 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -235,40 +235,64 @@ namespace MWGui draw(); } - void LoadingScreen::draw() + bool LoadingScreen::needToDrawLoadingScreen() { - if (mTimer.time_m() > mLastRenderTime + (1.0/mTargetFrameRate) * 1000.0) + if ( mTimer.time_m() <= mLastRenderTime + (1.0/mTargetFrameRate) * 1000.0) + return false; + + // the minimal delay before a loading screen shows + const float initialDelay = 0.05; + + bool alreadyShown = (mLastRenderTime > mLoadingOnTime); + float diff = (mTimer.time_m() - mLoadingOnTime); + + if (!alreadyShown) { - bool showWallpaper = (MWBase::Environment::get().getStateManager()->getState() - == MWBase::StateManager::State_NoGame); + // bump the delay by the current progress - i.e. if during the initial delay the loading + // has almost finished, no point showing the loading screen now + diff -= mProgress / static_cast(mProgressBar->getScrollRange()) * 100.f; + } - if (showWallpaper && mTimer.time_m() > mLastWallpaperChangeTime + 5000*1) - { - mLastWallpaperChangeTime = mTimer.time_m(); - changeWallpaper(); - } + bool showWallpaper = (MWBase::Environment::get().getStateManager()->getState() + == MWBase::StateManager::State_NoGame); + if (!showWallpaper && diff < initialDelay*1000) + return false; + return true; + } - // Turn off rendering except the GUI - int oldUpdateMask = mViewer->getUpdateVisitor()->getTraversalMask(); - int oldCullMask = mViewer->getCamera()->getCullMask(); - mViewer->getUpdateVisitor()->setTraversalMask(MWRender::Mask_GUI); - mViewer->getCamera()->setCullMask(MWRender::Mask_GUI); + void LoadingScreen::draw() + { + if (!needToDrawLoadingScreen()) + return; + + bool showWallpaper = (MWBase::Environment::get().getStateManager()->getState() + == MWBase::StateManager::State_NoGame); + if (showWallpaper && mTimer.time_m() > mLastWallpaperChangeTime + 5000*1) + { + mLastWallpaperChangeTime = mTimer.time_m(); + changeWallpaper(); + } - MWBase::Environment::get().getInputManager()->update(0, true, true); + // Turn off rendering except the GUI + int oldUpdateMask = mViewer->getUpdateVisitor()->getTraversalMask(); + int oldCullMask = mViewer->getCamera()->getCullMask(); + mViewer->getUpdateVisitor()->setTraversalMask(MWRender::Mask_GUI); + mViewer->getCamera()->setCullMask(MWRender::Mask_GUI); - //osg::Timer timer; - mViewer->frame(mViewer->getFrameStamp()->getSimulationTime()); - //std::cout << "frame took " << timer.time_m() << std::endl; + MWBase::Environment::get().getInputManager()->update(0, true, true); - //if (mViewer->getIncrementalCompileOperation()) - //std::cout << "num to compile " << mViewer->getIncrementalCompileOperation()->getToCompile().size() << std::endl; + //osg::Timer timer; + mViewer->frame(mViewer->getFrameStamp()->getSimulationTime()); + //std::cout << "frame took " << timer.time_m() << std::endl; - // resume 3d rendering - mViewer->getUpdateVisitor()->setTraversalMask(oldUpdateMask); - mViewer->getCamera()->setCullMask(oldCullMask); + //if (mViewer->getIncrementalCompileOperation()) + //std::cout << "num to compile " << mViewer->getIncrementalCompileOperation()->getToCompile().size() << std::endl; - mLastRenderTime = mTimer.time_m(); - } + // resume 3d rendering + mViewer->getUpdateVisitor()->setTraversalMask(oldUpdateMask); + mViewer->getCamera()->setCullMask(oldCullMask); + + mLastRenderTime = mTimer.time_m(); } } diff --git a/apps/openmw/mwgui/loadingscreen.hpp b/apps/openmw/mwgui/loadingscreen.hpp index 194535eee..f0f354223 100644 --- a/apps/openmw/mwgui/loadingscreen.hpp +++ b/apps/openmw/mwgui/loadingscreen.hpp @@ -52,6 +52,7 @@ namespace MWGui private: void findSplashScreens(); + bool needToDrawLoadingScreen(); const VFS::Manager* mVFS; osg::ref_ptr mViewer; From 6dff11f8475c7dbc5aea5d7307e79d5e8d807e98 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 23 Oct 2015 18:16:26 +0200 Subject: [PATCH 75/84] Duplicate code fix --- components/sceneutil/lightmanager.cpp | 29 ++++++++++++--------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/components/sceneutil/lightmanager.cpp b/components/sceneutil/lightmanager.cpp index 77551e006..92fa83537 100644 --- a/components/sceneutil/lightmanager.cpp +++ b/components/sceneutil/lightmanager.cpp @@ -64,6 +64,16 @@ namespace SceneUtil std::vector > mLights; }; + LightManager* findLightManager(const osg::NodePath& path) + { + for (unsigned int i=0;i(path[i])) + return lightManager; + } + return NULL; + } + // Set on a LightSource. Adds the light source to its light manager for the current frame. // This allows us to keep track of the current lights in the scene graph without tying creation & destruction to the manager. class CollectLightCallback : public osg::NodeCallback @@ -82,14 +92,8 @@ namespace SceneUtil { if (!mLightManager) { - for (unsigned int i=0;igetNodePath().size(); ++i) - { - if (LightManager* lightManager = dynamic_cast(nv->getNodePath()[i])) - { - mLightManager = lightManager; - break; - } - } + mLightManager = findLightManager(nv->getNodePath()); + if (!mLightManager) throw std::runtime_error("can't find parent LightManager"); } @@ -264,14 +268,7 @@ namespace SceneUtil if (!mLightManager) { - for (unsigned int i=0;igetNodePath().size(); ++i) - { - if (LightManager* lightManager = dynamic_cast(nv->getNodePath()[i])) - { - mLightManager = lightManager; - break; - } - } + mLightManager = findLightManager(nv->getNodePath()); if (!mLightManager) { traverse(node, nv); From 49df6b7450cc46e6d895d58d0a7a0701a5513f52 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 23 Oct 2015 21:25:56 +0200 Subject: [PATCH 76/84] LightManager: fix incorrect view matrix for RELATIVE_RF cameras --- components/sceneutil/lightmanager.cpp | 9 ++++++--- components/sceneutil/lightmanager.hpp | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/components/sceneutil/lightmanager.cpp b/components/sceneutil/lightmanager.cpp index 92fa83537..18d7ddd46 100644 --- a/components/sceneutil/lightmanager.cpp +++ b/components/sceneutil/lightmanager.cpp @@ -198,7 +198,7 @@ namespace SceneUtil return mLights; } - const std::vector& LightManager::getLightsInViewSpace(osg::Camera *camera) + const std::vector& LightManager::getLightsInViewSpace(osg::Camera *camera, const osg::RefMatrix* viewMatrix) { osg::observer_ptr camPtr (camera); std::map, LightSourceViewBoundCollection>::iterator it = mLightsInViewSpace.find(camPtr); @@ -209,7 +209,7 @@ namespace SceneUtil for (std::vector::iterator lightIt = mLights.begin(); lightIt != mLights.end(); ++lightIt) { - osg::Matrix worldViewMat = lightIt->mWorldMatrix * camera->getViewMatrix(); + osg::Matrix worldViewMat = lightIt->mWorldMatrix * (*viewMatrix); osg::BoundingSphere viewBound = osg::BoundingSphere(osg::Vec3f(0,0,0), lightIt->mLightSource->getRadius()); transformBoundingSphere(worldViewMat, viewBound); @@ -280,7 +280,10 @@ namespace SceneUtil // - cull list of lights by the camera frustum // - organize lights in a quad tree - const std::vector& lights = mLightManager->getLightsInViewSpace(cv->getCurrentCamera()); + // Don't use Camera::getViewMatrix, that one might be relative to another camera! + const osg::RefMatrix* viewMatrix = cv->getCurrentRenderStage()->getInitialViewMatrix(); + + const std::vector& lights = mLightManager->getLightsInViewSpace(cv->getCurrentCamera(), viewMatrix); if (lights.size()) { diff --git a/components/sceneutil/lightmanager.hpp b/components/sceneutil/lightmanager.hpp index 454eeeefe..3e0329c8b 100644 --- a/components/sceneutil/lightmanager.hpp +++ b/components/sceneutil/lightmanager.hpp @@ -88,7 +88,7 @@ namespace SceneUtil osg::BoundingSphere mViewBound; }; - const std::vector& getLightsInViewSpace(osg::Camera* camera); + const std::vector& getLightsInViewSpace(osg::Camera* camera, const osg::RefMatrix* viewMatrix); typedef std::vector LightList; From ef5838df7eb70fb9eddeef448244171dac548caa Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 24 Oct 2015 15:46:15 +0200 Subject: [PATCH 77/84] SunGlareCallback: Fix incorrect view matrix for RELATIVE_RF cameras --- apps/openmw/mwrender/sky.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index a8aeeb930..8de8a61fc 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -741,7 +741,7 @@ private: { osgUtil::CullVisitor* cv = static_cast(nv); - float angleRadians = getAngleToSunInRadians(cv->getCurrentCamera()); + float angleRadians = getAngleToSunInRadians(*cv->getCurrentRenderStage()->getInitialViewMatrix()); float visibleRatio = getVisibleRatio(cv->getCurrentCamera()); const float angleMaxRadians = osg::DegreesToRadians(mSunGlareFaderAngleMax); @@ -784,10 +784,10 @@ private: } private: - float getAngleToSunInRadians(osg::Camera* camera) const + float getAngleToSunInRadians(const osg::Matrix& viewMatrix) const { osg::Vec3d eye, center, up; - camera->getViewMatrixAsLookAt(eye, center, up); + viewMatrix.getLookAt(eye, center, up); osg::Vec3d forward = center - eye; osg::Vec3d sun = mSunTransform->getPosition(); From 7b954e8cc30bbceb33bacfea42726694d40807ed Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 24 Oct 2015 16:04:08 +0200 Subject: [PATCH 78/84] Remove unnecessary dependency on MWScrollBar --- apps/openmw/mwgui/waitdialog.hpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/waitdialog.hpp b/apps/openmw/mwgui/waitdialog.hpp index e8f58c574..13df1f8ae 100644 --- a/apps/openmw/mwgui/waitdialog.hpp +++ b/apps/openmw/mwgui/waitdialog.hpp @@ -8,11 +8,6 @@ namespace MWGui { - namespace Widgets - { - class MWScrollBar; - } - class WaitDialogProgressBar : public WindowBase { public: @@ -51,7 +46,7 @@ namespace MWGui MyGUI::Button* mUntilHealedButton; MyGUI::Button* mWaitButton; MyGUI::Button* mCancelButton; - MWGui::Widgets::MWScrollBar* mHourSlider; + MyGUI::ScrollBar* mHourSlider; TimeAdvancer mTimeAdvancer; bool mSleeping; From e34af4c4b5fe860c033dd4f55cd7aae0279d4bbc Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 25 Oct 2015 15:16:22 +0100 Subject: [PATCH 79/84] handle primary and secondary edit button clicks on cell arrows --- apps/opencs/view/render/cellarrow.cpp | 5 + apps/opencs/view/render/cellarrow.hpp | 2 + .../view/render/pagedworldspacewidget.cpp | 142 +++++++++++++++++- .../view/render/pagedworldspacewidget.hpp | 16 ++ apps/opencs/view/render/worldspacewidget.cpp | 21 ++- apps/opencs/view/render/worldspacewidget.hpp | 3 + 6 files changed, 177 insertions(+), 12 deletions(-) diff --git a/apps/opencs/view/render/cellarrow.cpp b/apps/opencs/view/render/cellarrow.cpp index 720db5327..fce5ffda5 100644 --- a/apps/opencs/view/render/cellarrow.cpp +++ b/apps/opencs/view/render/cellarrow.cpp @@ -154,3 +154,8 @@ CSMWorld::CellCoordinates CSVRender::CellArrow::getCoordinates() const { return mCoordinates; } + +CSVRender::CellArrow::Direction CSVRender::CellArrow::getDirection() const +{ + return mDirection; +} diff --git a/apps/opencs/view/render/cellarrow.hpp b/apps/opencs/view/render/cellarrow.hpp index 4422ec890..cbbcc9d5e 100644 --- a/apps/opencs/view/render/cellarrow.hpp +++ b/apps/opencs/view/render/cellarrow.hpp @@ -64,6 +64,8 @@ namespace CSVRender ~CellArrow(); CSMWorld::CellCoordinates getCoordinates() const; + + Direction getDirection() const; }; } diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index dd740ab9a..6e5c2587d 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -4,6 +4,7 @@ #include #include +#include #include @@ -81,10 +82,7 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells() { if (mCells.find (*iter)==mCells.end()) { - Cell *cell = new Cell (mDocument.getData(), mRootNode, - iter->getId (mWorldspace)); - mCells.insert (std::make_pair (*iter, cell)); - + addCellToScene (*iter); modified = true; } } @@ -152,6 +150,76 @@ void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons ( "terrain-move"); } +void CSVRender::PagedWorldspaceWidget::handleMouseClick (osg::ref_ptr tag, const std::string& button) +{ + if (tag && tag->getElement()==Element_CellArrow) + { + if (button=="p-edit" || button=="s-edit") + { + if (CellArrowTag *cellArrowTag = + dynamic_cast (tag.get())) + { + CellArrow *arrow = cellArrowTag->getCellArrow(); + + CSMWorld::CellCoordinates coordinates = arrow->getCoordinates(); + + CellArrow::Direction direction = arrow->getDirection(); + + int x = 0; + int y = 0; + + switch (direction) + { + case CellArrow::Direction_North: y = 1; break; + case CellArrow::Direction_West: x = -1; break; + case CellArrow::Direction_South: y = -1; break; + case CellArrow::Direction_East: x = 1; break; + } + + bool modified = false; + + if (QApplication::keyboardModifiers() & Qt::ShiftModifier) + { + if (button=="p-edit") + addCellSelection (x, y); + else + moveCellSelection (x, y); + + modified = true; + } + else + { + CSMWorld::CellCoordinates newCoordinates = coordinates.move (x, y); + + if (mCells.find (newCoordinates)==mCells.end()) + { + addCellToScene (newCoordinates); + mSelection.add (newCoordinates); + modified = true; + } + + if (button=="s-edit") + { + if (mCells.find (coordinates)!=mCells.end()) + { + removeCellFromScene (coordinates); + mSelection.remove (coordinates); + modified = true; + } + } + } + + if (modified) + adjustCells(); + + return; + } + } + } + + WorldspaceWidget::handleMouseClick (tag, button); +} + void CSVRender::PagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight) { @@ -231,6 +299,72 @@ std::string CSVRender::PagedWorldspaceWidget::getStartupInstruction() return stream.str(); } +void CSVRender::PagedWorldspaceWidget::addCellToScene ( + const CSMWorld::CellCoordinates& coordinates) +{ + const CSMWorld::IdCollection& cells = mDocument.getData().getCells(); + + int index = cells.searchId (coordinates.getId (mWorldspace)); + + bool deleted = index==-1 || + cells.getRecord (index).mState==CSMWorld::RecordBase::State_Deleted; + + Cell *cell = new Cell (mDocument.getData(), mRootNode, coordinates.getId (mWorldspace), + deleted); + + mCells.insert (std::make_pair (coordinates, cell)); +} + +void CSVRender::PagedWorldspaceWidget::removeCellFromScene ( + const CSMWorld::CellCoordinates& coordinates) +{ + std::map::iterator iter = mCells.find (coordinates); + + if (iter!=mCells.end()) + { + delete iter->second; + mCells.erase (iter); + } +} + +void CSVRender::PagedWorldspaceWidget::addCellSelection (int x, int y) +{ + CSMWorld::CellSelection newSelection = mSelection; + newSelection.move (x, y); + + for (CSMWorld::CellSelection::Iterator iter (newSelection.begin()); iter!=newSelection.end(); + ++iter) + { + if (mCells.find (*iter)==mCells.end()) + { + addCellToScene (*iter); + mSelection.add (*iter); + } + } +} + +void CSVRender::PagedWorldspaceWidget::moveCellSelection (int x, int y) +{ + CSMWorld::CellSelection newSelection = mSelection; + newSelection.move (x, y); + + for (CSMWorld::CellSelection::Iterator iter (mSelection.begin()); iter!=mSelection.end(); + ++iter) + { + if (!newSelection.has (*iter)) + removeCellFromScene (*iter); + } + + for (CSMWorld::CellSelection::Iterator iter (newSelection.begin()); iter!=newSelection.end(); + ++iter) + { + if (!mSelection.has (*iter)) + addCellToScene (*iter); + } + + mSelection = newSelection; +} + CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc::Document& document) : WorldspaceWidget (document, parent), mDocument (document), mWorldspace ("std::default"), mControlElements(NULL), mDisplayCellCoord(true) diff --git a/apps/opencs/view/render/pagedworldspacewidget.hpp b/apps/opencs/view/render/pagedworldspacewidget.hpp index d52efd90e..e1a43ba7c 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.hpp +++ b/apps/opencs/view/render/pagedworldspacewidget.hpp @@ -53,6 +53,20 @@ namespace CSVRender virtual std::string getStartupInstruction(); + /// \note Does not update the view or any cell marker + void addCellToScene (const CSMWorld::CellCoordinates& coordinates); + + /// \note Does not update the view or any cell marker + /// + /// \note Calling this function for a cell that is not in the selection is a no-op. + void removeCellFromScene (const CSMWorld::CellCoordinates& coordinates); + + /// \note Does not update the view or any cell marker + void addCellSelection (int x, int y); + + /// \note Does not update the view or any cell marker + void moveCellSelection (int x, int y); + public: PagedWorldspaceWidget (QWidget *parent, CSMDoc::Document& document); @@ -88,6 +102,8 @@ namespace CSVRender virtual void addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool); + virtual void handleMouseClick (osg::ref_ptr tag, const std::string& button); + signals: void cellSelectionChanged (const CSMWorld::CellSelection& selection); diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 75dd800eb..a542a3c59 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -574,14 +574,7 @@ void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event) { osg::ref_ptr tag = mousePick (event); - EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); - - if (button=="p-edit") - editMode.primaryEditPressed (tag); - else if (button=="s-edit") - editMode.secondaryEditPressed (tag); - else if (button=="select") - editMode.selectPressed (tag); + handleMouseClick (tag, button); } } @@ -650,3 +643,15 @@ void CSVRender::WorldspaceWidget::keyPressEvent (QKeyEvent *event) else RenderWidget::keyPressEvent(event); } + +void CSVRender::WorldspaceWidget::handleMouseClick (osg::ref_ptr tag, const std::string& button) +{ + EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); + + if (button=="p-edit") + editMode.primaryEditPressed (tag); + else if (button=="s-edit") + editMode.secondaryEditPressed (tag); + else if (button=="select") + editMode.selectPressed (tag); +} diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index f5e7970b6..fe766cf87 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -27,6 +27,7 @@ namespace CSVWidget namespace CSVRender { class TagBase; + class CellArrow; class WorldspaceWidget : public SceneWidget { @@ -132,6 +133,8 @@ namespace CSVRender virtual void wheelEvent (QWheelEvent *event); virtual void keyPressEvent (QKeyEvent *event); + virtual void handleMouseClick (osg::ref_ptr tag, const std::string& button); + private: void dragEnterEvent(QDragEnterEvent *event); From 515c52211e9bce049d6412e8e434ce7c907ca8ad Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 25 Oct 2015 18:28:50 +0100 Subject: [PATCH 80/84] Disable mipmaps for temporary screenshot texture --- apps/openmw/mwrender/renderingmanager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index f4b8aa451..cae6541af 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -493,6 +493,8 @@ namespace MWRender texture->setInternalFormat(GL_RGB); texture->setTextureSize(w, h); texture->setResizeNonPowerOfTwoHint(false); + texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); + texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); rttCamera->attach(osg::Camera::COLOR_BUFFER, texture); image->setDataType(GL_UNSIGNED_BYTE); From 944e6d0844158d67c3a6041db1b29c4685ef2797 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 26 Oct 2015 14:25:44 +0100 Subject: [PATCH 81/84] Fix adjustment of inventory preview size when guimode changes (Fixes #2973) --- apps/openmw/mwgui/inventorywindow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index f5a5f023f..c1e202bc0 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -167,11 +167,12 @@ namespace MWGui MyGUI::IntSize size(static_cast(Settings::Manager::getFloat(setting + " w", "Windows") * viewSize.width), static_cast(Settings::Manager::getFloat(setting + " h", "Windows") * viewSize.height)); + mMainWidget->setPosition(pos); + mMainWidget->setSize(size); + if (size.width != mMainWidget->getWidth() || size.height != mMainWidget->getHeight()) updatePreviewSize(); - mMainWidget->setPosition(pos); - mMainWidget->setSize(size); adjustPanes(); } From f3ee3f5be1d529698177655ebc6103a8f9847cde Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 27 Oct 2015 15:25:46 +0100 Subject: [PATCH 82/84] Do not call base class event functions in WorldspaceWidget This avoids some event function being triggered twice. I do not fully understand why calling the base class function causes this problem, which is more than a bit disconcerting, but let's roll with it for now. --- apps/opencs/view/render/worldspacewidget.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index a542a3c59..e539c14b9 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -555,8 +555,6 @@ void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event) editMode.drag (diffX, diffY, factor); } - - RenderWidget::mouseMoveEvent(event); } void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event) @@ -598,8 +596,6 @@ void CSVRender::WorldspaceWidget::mouseReleaseEvent (QMouseEvent *event) } mDragMode.clear(); - - RenderWidget::mouseReleaseEvent(event); } void CSVRender::WorldspaceWidget::mouseDoubleClickEvent (QMouseEvent *event) @@ -608,7 +604,6 @@ void CSVRender::WorldspaceWidget::mouseDoubleClickEvent (QMouseEvent *event) { //mMouse->mouseDoubleClickEvent(event); } - //SceneWidget::mouseDoubleClickEvent(event); } void CSVRender::WorldspaceWidget::wheelEvent (QWheelEvent *event) @@ -624,8 +619,6 @@ void CSVRender::WorldspaceWidget::wheelEvent (QWheelEvent *event) editMode.dragWheel (event->delta(), factor); } - - RenderWidget::wheelEvent(event); } void CSVRender::WorldspaceWidget::keyPressEvent (QKeyEvent *event) From d2e92fd36f8bd6bb54724abf36acd918edcf6875 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 27 Oct 2015 15:30:51 +0100 Subject: [PATCH 83/84] trigger mouse click actions on release instead of on press (avoids problems with dragging) --- apps/opencs/view/render/worldspacewidget.cpp | 28 +++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index e539c14b9..3f4b77383 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -563,25 +563,14 @@ void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event) if (!mDragging) mDragMode = button; - - if (button=="p-navi" || button=="s-navi") - { - - } - else if (button=="p-edit" || button=="s-edit" || button=="select") - { - osg::ref_ptr tag = mousePick (event); - - handleMouseClick (tag, button); - } } void CSVRender::WorldspaceWidget::mouseReleaseEvent (QMouseEvent *event) { + std::string button = mapButton (event); + if (mDragging) { - std::string button = mapButton (event); - if (mDragMode=="p-navi" || mDragMode=="s-navi") { @@ -594,6 +583,19 @@ void CSVRender::WorldspaceWidget::mouseReleaseEvent (QMouseEvent *event) mDragging = false; } } + else + { + if (button=="p-navi" || button=="s-navi") + { + + } + else if (button=="p-edit" || button=="s-edit" || button=="select") + { + osg::ref_ptr tag = mousePick (event); + + handleMouseClick (tag, button); + } + } mDragMode.clear(); } From 843225996cc4d8573be7d4a70b71333ab2baf319 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 27 Oct 2015 15:43:52 +0100 Subject: [PATCH 84/84] get modifiers from event instead of from the application --- apps/opencs/view/render/pagedworldspacewidget.cpp | 6 +++--- apps/opencs/view/render/pagedworldspacewidget.hpp | 2 +- apps/opencs/view/render/worldspacewidget.cpp | 10 +++++----- apps/opencs/view/render/worldspacewidget.hpp | 3 ++- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index 6e5c2587d..dae5990e6 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -150,7 +150,7 @@ void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons ( "terrain-move"); } -void CSVRender::PagedWorldspaceWidget::handleMouseClick (osg::ref_ptr tag, const std::string& button) +void CSVRender::PagedWorldspaceWidget::handleMouseClick (osg::ref_ptr tag, const std::string& button, bool shift) { if (tag && tag->getElement()==Element_CellArrow) { @@ -178,7 +178,7 @@ void CSVRender::PagedWorldspaceWidget::handleMouseClick (osg::ref_ptr t bool modified = false; - if (QApplication::keyboardModifiers() & Qt::ShiftModifier) + if (shift) { if (button=="p-edit") addCellSelection (x, y); @@ -217,7 +217,7 @@ void CSVRender::PagedWorldspaceWidget::handleMouseClick (osg::ref_ptr t } } - WorldspaceWidget::handleMouseClick (tag, button); + WorldspaceWidget::handleMouseClick (tag, button, shift); } void CSVRender::PagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft, diff --git a/apps/opencs/view/render/pagedworldspacewidget.hpp b/apps/opencs/view/render/pagedworldspacewidget.hpp index e1a43ba7c..e983fddd5 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.hpp +++ b/apps/opencs/view/render/pagedworldspacewidget.hpp @@ -102,7 +102,7 @@ namespace CSVRender virtual void addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool); - virtual void handleMouseClick (osg::ref_ptr tag, const std::string& button); + virtual void handleMouseClick (osg::ref_ptr tag, const std::string& button, bool shift); signals: diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 3f4b77383..46c5867eb 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -413,7 +413,7 @@ osg::ref_ptr CSVRender::WorldspaceWidget::mousePick (QMouseE std::string CSVRender::WorldspaceWidget::mapButton (QMouseEvent *event) { std::pair phyiscal ( - event->button(), QApplication::keyboardModifiers() & Qt::ControlModifier); + event->button(), event->modifiers() & Qt::ControlModifier); std::map, std::string>::const_iterator iter = mButtonMapping.find (phyiscal); @@ -548,7 +548,7 @@ void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event) double factor = mDragFactor; - if (QApplication::keyboardModifiers() & Qt::ShiftModifier) + if (event->modifiers() & Qt::ShiftModifier) factor *= mDragShiftFactor; EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); @@ -593,7 +593,7 @@ void CSVRender::WorldspaceWidget::mouseReleaseEvent (QMouseEvent *event) { osg::ref_ptr tag = mousePick (event); - handleMouseClick (tag, button); + handleMouseClick (tag, button, event->modifiers() & Qt::ShiftModifier); } } @@ -614,7 +614,7 @@ void CSVRender::WorldspaceWidget::wheelEvent (QWheelEvent *event) { double factor = mDragWheelFactor; - if (QApplication::keyboardModifiers() & Qt::ShiftModifier) + if (event->modifiers() & Qt::ShiftModifier) factor *= mDragShiftFactor; EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); @@ -639,7 +639,7 @@ void CSVRender::WorldspaceWidget::keyPressEvent (QKeyEvent *event) RenderWidget::keyPressEvent(event); } -void CSVRender::WorldspaceWidget::handleMouseClick (osg::ref_ptr tag, const std::string& button) +void CSVRender::WorldspaceWidget::handleMouseClick (osg::ref_ptr tag, const std::string& button, bool shift) { EditMode& editMode = dynamic_cast (*mEditMode->getCurrent()); diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index fe766cf87..c2d61e75b 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -133,7 +133,8 @@ namespace CSVRender virtual void wheelEvent (QWheelEvent *event); virtual void keyPressEvent (QKeyEvent *event); - virtual void handleMouseClick (osg::ref_ptr tag, const std::string& button); + virtual void handleMouseClick (osg::ref_ptr tag, const std::string& button, + bool shift); private: