From 843afc5e24559d2944a5e2113776826cdaf0089b Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 30 Jun 2015 03:54:56 +0200 Subject: [PATCH 01/81] Increment save file version and mark it as used, will be used in next commit (cherry picked from commit 4eaaa5e855d8a362b1385ade296835abf26f298c) --- apps/openmw/mwstate/statemanagerimp.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 83f1d7406a..ac3ade4a9b 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -203,8 +203,9 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot writer.setFormat (ESM::Header::CurrentFormat); + writer.setVersion(1); + // all unused - writer.setVersion(0); writer.setType(0); writer.setAuthor(""); writer.setDescription(""); From b9ba1067bfb5306b05e544693a87fefbc38185de Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 30 Jun 2015 03:58:23 +0200 Subject: [PATCH 02/81] Savegame loading optimization (cherry picked from commit 463775060148a6b9a53676846a5ea31c4b38b423) --- apps/openmw/mwclass/creature.cpp | 30 ++++++++++++++---------------- apps/openmw/mwclass/npc.cpp | 19 +++++++++---------- components/esm/objectstate.cpp | 2 ++ components/esm/objectstate.hpp | 4 +++- 4 files changed, 28 insertions(+), 27 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 49291be2d9..13fd22a0ce 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -807,27 +807,25 @@ namespace MWClass const ESM::CreatureState& state2 = dynamic_cast (state); - ensureCustomData(ptr); - - // If we do the following instead we get a sizable speedup, but this causes compatibility issues - // with 0.30 savegames, where some state in CreatureStats was not saved yet, - // and therefore needs to be loaded from ESM records. TODO: re-enable this in a future release. - /* - if (!ptr.getRefData().getCustomData()) + if (state.mVersion > 0) { - // Create a CustomData, but don't fill it from ESM records (not needed) - std::auto_ptr data (new CreatureCustomData); + if (!ptr.getRefData().getCustomData()) + { + // Create a CustomData, but don't fill it from ESM records (not needed) + std::auto_ptr data (new CreatureCustomData); - MWWorld::LiveCellRef *ref = ptr.get(); + MWWorld::LiveCellRef *ref = ptr.get(); - if (ref->mBase->mFlags & ESM::Creature::Weapon) - data->mContainerStore = new MWWorld::InventoryStore(); - else - data->mContainerStore = new MWWorld::ContainerStore(); + if (ref->mBase->mFlags & ESM::Creature::Weapon) + data->mContainerStore = new MWWorld::InventoryStore(); + else + data->mContainerStore = new MWWorld::ContainerStore(); - ptr.getRefData().setCustomData (data.release()); + ptr.getRefData().setCustomData (data.release()); + } } - */ + else + ensureCustomData(ptr); // in openmw 0.30 savegames not all state was saved yet, so need to load it regardless. CreatureCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 746099ae5f..bc806078af 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -1103,18 +1103,17 @@ namespace MWClass const ESM::NpcState& state2 = dynamic_cast (state); - ensureCustomData(ptr); - // If we do the following instead we get a sizable speedup, but this causes compatibility issues - // with 0.30 savegames, where some state in CreatureStats was not saved yet, - // and therefore needs to be loaded from ESM records. TODO: re-enable this in a future release. - /* - if (!ptr.getRefData().getCustomData()) + if (state.mVersion > 0) { - // Create a CustomData, but don't fill it from ESM records (not needed) - std::auto_ptr data (new NpcCustomData); - ptr.getRefData().setCustomData (data.release()); + if (!ptr.getRefData().getCustomData()) + { + // Create a CustomData, but don't fill it from ESM records (not needed) + std::auto_ptr data (new NpcCustomData); + ptr.getRefData().setCustomData (data.release()); + } } - */ + else + ensureCustomData(ptr); // in openmw 0.30 savegames not all state was saved yet, so need to load it regardless. NpcCustomData& customData = dynamic_cast (*ptr.getRefData().getCustomData()); diff --git a/components/esm/objectstate.cpp b/components/esm/objectstate.cpp index 3b5288c772..f8c479ff6c 100644 --- a/components/esm/objectstate.cpp +++ b/components/esm/objectstate.cpp @@ -5,6 +5,8 @@ void ESM::ObjectState::load (ESMReader &esm) { + mVersion = esm.getVer(); + mRef.loadData(esm); mHasLocals = 0; diff --git a/components/esm/objectstate.hpp b/components/esm/objectstate.hpp index d1077733a5..674bcb8fc1 100644 --- a/components/esm/objectstate.hpp +++ b/components/esm/objectstate.hpp @@ -29,7 +29,9 @@ namespace ESM // Is there any class-specific state following the ObjectState bool mHasCustomState; - ObjectState() : mHasCustomState(true) + unsigned int mVersion; + + ObjectState() : mHasCustomState(true), mVersion(0) {} /// @note Does not load the CellRef ID, it should already be loaded before calling this method From 05fd4e123e5f5d9f34c950564b5d08bfa27aaaed Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 30 Jun 2015 17:26:33 +0200 Subject: [PATCH 03/81] Use the format field instead of version field (cherry picked from commit a081d402c571c88ea69d8e6044a862f781fbf3f3) --- apps/openmw/mwstate/statemanagerimp.cpp | 5 ++--- components/esm/objectstate.cpp | 2 +- components/esm/savedgame.cpp | 1 + components/esm/savedgame.hpp | 2 ++ 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index ac3ade4a9b..cf2c079e30 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -201,11 +201,10 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot ++iter) writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0 - writer.setFormat (ESM::Header::CurrentFormat); - - writer.setVersion(1); + writer.setFormat (ESM::SavedGame::sCurrentFormat); // all unused + writer.setVersion(0); writer.setType(0); writer.setAuthor(""); writer.setDescription(""); diff --git a/components/esm/objectstate.cpp b/components/esm/objectstate.cpp index f8c479ff6c..62aa0452a8 100644 --- a/components/esm/objectstate.cpp +++ b/components/esm/objectstate.cpp @@ -5,7 +5,7 @@ void ESM::ObjectState::load (ESMReader &esm) { - mVersion = esm.getVer(); + mVersion = esm.getFormat(); mRef.loadData(esm); diff --git a/components/esm/savedgame.cpp b/components/esm/savedgame.cpp index 4211bb14e2..2e5509b7a5 100644 --- a/components/esm/savedgame.cpp +++ b/components/esm/savedgame.cpp @@ -5,6 +5,7 @@ #include "defs.hpp" unsigned int ESM::SavedGame::sRecordId = ESM::REC_SAVE; +int ESM::SavedGame::sCurrentFormat = 1; void ESM::SavedGame::load (ESMReader &esm) { diff --git a/components/esm/savedgame.hpp b/components/esm/savedgame.hpp index 3e7cae775a..aa0429657b 100644 --- a/components/esm/savedgame.hpp +++ b/components/esm/savedgame.hpp @@ -15,6 +15,8 @@ namespace ESM { static unsigned int sRecordId; + static int sCurrentFormat; + struct TimeStamp { float mGameHour; From 65bd5d8492f864afc97296706f382cbf2a6885e6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 30 Jun 2015 17:26:42 +0200 Subject: [PATCH 04/81] Refuse loading save games of unknown format (cherry picked from commit 20d03c7e39ebf9f09570be0a5a3e1029a8001bd4) --- apps/openmw/mwstate/character.cpp | 3 --- apps/openmw/mwstate/statemanagerimp.cpp | 5 +++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwstate/character.cpp b/apps/openmw/mwstate/character.cpp index f8eb0410c7..733ac1171c 100644 --- a/apps/openmw/mwstate/character.cpp +++ b/apps/openmw/mwstate/character.cpp @@ -28,9 +28,6 @@ void MWState::Character::addSlot (const boost::filesystem::path& path, const std ESM::ESMReader reader; reader.open (slot.mPath.string()); - if (reader.getFormat()>ESM::Header::CurrentFormat) - return; // format is too new -> ignore - if (reader.getRecName()!=ESM::REC_SAVE) return; // invalid save file -> ignore diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index cf2c079e30..3e8bc4d235 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -310,8 +310,6 @@ void MWState::StateManager::loadGame(const std::string& filepath) // have to peek into the save file to get the player name ESM::ESMReader reader; reader.open (filepath); - if (reader.getFormat()>ESM::Header::CurrentFormat) - return; // format is too new -> ignore if (reader.getRecName()!=ESM::REC_SAVE) return; // invalid save file -> ignore reader.getRecHeader(); @@ -333,6 +331,9 @@ void MWState::StateManager::loadGame (const Character *character, const std::str ESM::ESMReader reader; reader.open (filepath); + if (reader.getFormat() > ESM::SavedGame::sCurrentFormat) + throw std::runtime_error("This save file was created using a newer version of OpenMW and is thus not supported. Please upgrade to the newest OpenMW version to load this file."); + std::map contentFileMap = buildContentFileIndexMap (reader); Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen(); From 52dfc0e9c760cd87b67c165d6335a2e3ffcf793b Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 30 Jun 2015 17:43:22 +0200 Subject: [PATCH 05/81] Use the correct format specifier for ess-imported savegames (cherry picked from commit 2065e0fa2d700163bbf9bbeb8eec5e0ccf84976a) --- apps/essimporter/importer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/essimporter/importer.cpp b/apps/essimporter/importer.cpp index 35b92a4d08..b9468ed870 100644 --- a/apps/essimporter/importer.cpp +++ b/apps/essimporter/importer.cpp @@ -296,7 +296,7 @@ namespace ESSImport ESM::ESMWriter writer; - writer.setFormat (ESM::Header::CurrentFormat); + writer.setFormat (ESM::SavedGame::sCurrentFormat); std::ofstream stream(mOutFile.c_str(), std::ios::binary); // all unused From 6fb658daa4b31c93643b34a96361b0033f821a52 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 30 Jul 2015 11:49:24 +0200 Subject: [PATCH 06/81] replaced State_Compiling (not requried anymore) with State_Merging (cherry picked from commit 6a9218ee07a81c9ca56faf8661c9d38e84ba3028) --- apps/opencs/model/doc/state.hpp | 2 +- apps/opencs/view/doc/operation.cpp | 3 ++- apps/opencs/view/doc/view.cpp | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/doc/state.hpp b/apps/opencs/model/doc/state.hpp index 78f4681010..7352b4b999 100644 --- a/apps/opencs/model/doc/state.hpp +++ b/apps/opencs/model/doc/state.hpp @@ -12,7 +12,7 @@ namespace CSMDoc State_Saving = 16, State_Verifying = 32, - State_Compiling = 64, // not implemented yet + State_Merging = 64, State_Searching = 128, State_Loading = 256 // pseudo-state; can not be encountered in a loaded document }; diff --git a/apps/opencs/view/doc/operation.cpp b/apps/opencs/view/doc/operation.cpp index 95cbf012d6..e5c1e7b89e 100644 --- a/apps/opencs/view/doc/operation.cpp +++ b/apps/opencs/view/doc/operation.cpp @@ -19,6 +19,7 @@ void CSVDoc::Operation::updateLabel (int threads) case CSMDoc::State_Saving: name = "saving"; break; case CSMDoc::State_Verifying: name = "verifying"; break; case CSMDoc::State_Searching: name = "searching"; break; + case CSMDoc::State_Merging: name = "merging"; break; } std::ostringstream stream; @@ -122,7 +123,7 @@ void CSVDoc::Operation::setBarColor (int type) bottomColor = "#9ECB2D"; //green gloss break; - case CSMDoc::State_Compiling: + case CSMDoc::State_Merging: topColor = "#F3E2C7"; midTopColor = "#C19E67"; diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 173a78e9de..bf92ccf28a 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -510,6 +510,7 @@ void CSVDoc::View::updateDocumentState() static const int operations[] = { CSMDoc::State_Saving, CSMDoc::State_Verifying, CSMDoc::State_Searching, + CSMDoc::State_Merging, -1 // end marker }; From ef1e01639e4459feb2261fb6ef38b6a5b09c6b34 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 6 Aug 2015 12:52:10 +0200 Subject: [PATCH 07/81] added UI for merge tool (merge tool itself is still missing) (cherry picked from commit b83f9445a96fda4dc14e43a2db363a748344227f) Conflicts: apps/opencs/editor.cpp apps/opencs/editor.hpp --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/editor.cpp | 16 +++ apps/opencs/editor.hpp | 12 +++ apps/opencs/model/doc/documentmanager.cpp | 2 + apps/opencs/model/doc/documentmanager.hpp | 2 + apps/opencs/view/doc/filewidget.cpp | 8 ++ apps/opencs/view/doc/filewidget.hpp | 4 + apps/opencs/view/doc/view.cpp | 11 ++ apps/opencs/view/doc/view.hpp | 5 + apps/opencs/view/doc/viewmanager.cpp | 1 + apps/opencs/view/doc/viewmanager.hpp | 2 + apps/opencs/view/tools/merge.cpp | 123 ++++++++++++++++++++++ apps/opencs/view/tools/merge.hpp | 60 +++++++++++ 13 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/view/tools/merge.cpp create mode 100644 apps/opencs/view/tools/merge.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index ff6e0506c6..9cc9a2971c 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -94,7 +94,7 @@ opencs_hdrs_noqt (view/render opencs_units (view/tools - reportsubview reporttable searchsubview searchbox + reportsubview reporttable searchsubview searchbox merge ) opencs_units_noqt (view/tools diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index bca21ff242..1de1e18652 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -48,9 +48,12 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) mNewGame.setLocalData (mLocal); mFileDialog.setLocalData (mLocal); + mMerge.setLocalData (mLocal); connect (&mDocumentManager, SIGNAL (documentAdded (CSMDoc::Document *)), this, SLOT (documentAdded (CSMDoc::Document *))); + connect (&mDocumentManager, SIGNAL (documentAboutToBeRemoved (CSMDoc::Document *)), + this, SLOT (documentAboutToBeRemoved (CSMDoc::Document *))); connect (&mDocumentManager, SIGNAL (lastDocumentDeleted()), this, SLOT (lastDocumentDeleted())); @@ -58,6 +61,7 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) connect (&mViewManager, SIGNAL (newAddonRequest ()), this, SLOT (createAddon ())); connect (&mViewManager, SIGNAL (loadDocumentRequest ()), this, SLOT (loadDocument ())); connect (&mViewManager, SIGNAL (editSettingsRequest()), this, SLOT (showSettings ())); + connect (&mViewManager, SIGNAL (mergeDocument (CSMDoc::Document *)), this, SLOT (mergeDocument (CSMDoc::Document *))); connect (&mStartup, SIGNAL (createGame()), this, SLOT (createGame ())); connect (&mStartup, SIGNAL (createAddon()), this, SLOT (createAddon ())); @@ -490,6 +494,12 @@ void CS::Editor::documentAdded (CSMDoc::Document *document) showSplashMessage(); } +void CS::Editor::documentAboutToBeRemoved (CSMDoc::Document *document) +{ + if (mMerge.getDocument()==document) + mMerge.cancel(); +} + void CS::Editor::lastDocumentDeleted() { QApplication::quit(); @@ -535,3 +545,9 @@ void CS::Editor::showSplashMessage() splash->raise(); // for X windows } } + +void CS::Editor::mergeDocument (CSMDoc::Document *document) +{ + mMerge.configure (document); + mMerge.show(); +} diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index 040ca963f3..33f5fd3b32 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -32,11 +32,18 @@ #include "view/settings/dialog.hpp" #include "view/render/overlaysystem.hpp" +#include "view/tools/merge.hpp" + namespace OgreInit { class OgreInit; } +namespace CSMDoc +{ + class Document; +} + namespace CS { class Editor : public QObject @@ -59,6 +66,7 @@ namespace CS boost::interprocess::file_lock mLock; boost::filesystem::ofstream mPidFile; bool mFsStrict; + CSVTools::Merge mMerge; void showSplashMessage(); @@ -103,8 +111,12 @@ namespace CS void documentAdded (CSMDoc::Document *document); + void documentAboutToBeRemoved (CSMDoc::Document *document); + void lastDocumentDeleted(); + void mergeDocument (CSMDoc::Document *document); + private: QString mIpcServerName; diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index 070c15f9a9..e8668d3ef5 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -72,6 +72,8 @@ void CSMDoc::DocumentManager::removeDocument (CSMDoc::Document *document) if (iter==mDocuments.end()) throw std::runtime_error ("removing invalid document"); + emit documentAboutToBeRemoved (document); + mDocuments.erase (iter); document->deleteLater(); diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index f3fcbf8ec6..5a892cc45c 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -83,6 +83,8 @@ namespace CSMDoc void documentAdded (CSMDoc::Document *document); + void documentAboutToBeRemoved (CSMDoc::Document *document); + void loadRequest (CSMDoc::Document *document); void lastDocumentDeleted(); diff --git a/apps/opencs/view/doc/filewidget.cpp b/apps/opencs/view/doc/filewidget.cpp index bbb824823a..110d561c17 100644 --- a/apps/opencs/view/doc/filewidget.cpp +++ b/apps/opencs/view/doc/filewidget.cpp @@ -55,3 +55,11 @@ void CSVDoc::FileWidget::extensionLabelIsVisible(bool visible) { mType->setVisible(visible); } + +void CSVDoc::FileWidget::setName (const std::string& text) +{ + QString text2 = QString::fromUtf8 (text.c_str()); + + mInput->setText (text2); + textChanged (text2); +} diff --git a/apps/opencs/view/doc/filewidget.hpp b/apps/opencs/view/doc/filewidget.hpp index ff09d71a39..ab06f37f18 100644 --- a/apps/opencs/view/doc/filewidget.hpp +++ b/apps/opencs/view/doc/filewidget.hpp @@ -3,6 +3,8 @@ #include +#include + class QLabel; class QString; class QLineEdit; @@ -29,6 +31,8 @@ namespace CSVDoc void extensionLabelIsVisible(bool visible); + void setName (const std::string& text); + private slots: void textChanged (const QString& text); diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index bf92ccf28a..9eb891c489 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -83,6 +83,10 @@ void CSVDoc::View::setupFileMenu() connect (mVerify, SIGNAL (triggered()), this, SLOT (verify())); file->addAction (mVerify); + mMerge = new QAction (tr ("Merge"), this); + connect (mMerge, SIGNAL (triggered()), this, SLOT (merge())); + file->addAction (mMerge); + QAction *loadErrors = new QAction (tr ("Load Error Log"), this); connect (loadErrors, SIGNAL (triggered()), this, SLOT (loadErrorLog())); file->addAction (loadErrors); @@ -418,6 +422,8 @@ void CSVDoc::View::updateActions() mGlobalDebugProfileMenu->updateActions (running); mStopDebug->setEnabled (running); + + mMerge->setEnabled (mDocument->getContentFiles().size()>1); } CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) @@ -1054,3 +1060,8 @@ void CSVDoc::View::updateScrollbar() else mSubViewWindow.setMinimumWidth(0); } + +void CSVDoc::View::merge() +{ + emit mergeDocument (mDocument); +} diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 7f465c8f36..04d31dea56 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -43,6 +43,7 @@ namespace CSVDoc QAction *mVerify; QAction *mShowStatusBar; QAction *mStopDebug; + QAction *mMerge; std::vector mEditingActions; Operations *mOperations; SubViewFactoryManager mSubViewFactory; @@ -137,6 +138,8 @@ namespace CSVDoc void editSettingsRequest(); + void mergeDocument (CSMDoc::Document *document); + public slots: void addSubView (const CSMWorld::UniversalId& id, const std::string& hint = ""); @@ -251,6 +254,8 @@ namespace CSVDoc void saveWindowState(); void moveScrollBarToEnd(int min, int max); + + void merge(); }; } diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 8ffd7335d0..25949ef15e 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -173,6 +173,7 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) connect (view, SIGNAL (newAddonRequest ()), this, SIGNAL (newAddonRequest())); connect (view, SIGNAL (loadDocumentRequest ()), this, SIGNAL (loadDocumentRequest())); connect (view, SIGNAL (editSettingsRequest()), this, SIGNAL (editSettingsRequest())); + connect (view, SIGNAL (mergeDocument (CSMDoc::Document *)), this, SIGNAL (mergeDocument (CSMDoc::Document *))); connect (&CSMSettings::UserSettings::instance(), SIGNAL (userSettingUpdated(const QString &, const QStringList &)), diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index cdd5ac7686..70431107f6 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -77,6 +77,8 @@ namespace CSVDoc void editSettingsRequest(); + void mergeDocument (CSMDoc::Document *document); + public slots: void exitApplication (CSVDoc::View *view); diff --git a/apps/opencs/view/tools/merge.cpp b/apps/opencs/view/tools/merge.cpp new file mode 100644 index 0000000000..baadd91799 --- /dev/null +++ b/apps/opencs/view/tools/merge.cpp @@ -0,0 +1,123 @@ + +#include "merge.hpp" + +#include +#include +#include +#include +#include +#include + +#include "../../model/doc/document.hpp" + +#include "../doc/filewidget.hpp" +#include "../doc/adjusterwidget.hpp" + +CSVTools::Merge::Merge (QWidget *parent) +: QDialog (parent), mDocument (0) +{ + setWindowTitle ("Merge Content Files into a new Game File"); + + QVBoxLayout *mainLayout = new QVBoxLayout; + setLayout (mainLayout); + + QSplitter *splitter = new QSplitter (Qt::Horizontal, this); + + mainLayout->addWidget (splitter, 1); + + // left panel (files to be merged) + QWidget *left = new QWidget (this); + left->setContentsMargins (0, 0, 0, 0); + splitter->addWidget (left); + + QVBoxLayout *leftLayout = new QVBoxLayout; + left->setLayout (leftLayout); + + leftLayout->addWidget (new QLabel ("Files to be merged", this)); + + mFiles = new QListWidget (this); + leftLayout->addWidget (mFiles, 1); + + // right panel (new game file) + QWidget *right = new QWidget (this); + right->setContentsMargins (0, 0, 0, 0); + splitter->addWidget (right); + + QVBoxLayout *rightLayout = new QVBoxLayout; + rightLayout->setAlignment (Qt::AlignTop); + right->setLayout (rightLayout); + + rightLayout->addWidget (new QLabel ("New game file", this)); + + mNewFile = new CSVDoc::FileWidget (this); + mNewFile->setType (false); + mNewFile->extensionLabelIsVisible (true); + rightLayout->addWidget (mNewFile); + + mAdjuster = new CSVDoc::AdjusterWidget (this); + + rightLayout->addWidget (mAdjuster); + + connect (mNewFile, SIGNAL (nameChanged (const QString&, bool)), + mAdjuster, SLOT (setName (const QString&, bool))); + connect (mAdjuster, SIGNAL (stateChanged (bool)), this, SLOT (stateChanged (bool))); + + // buttons + QDialogButtonBox *buttons = new QDialogButtonBox (QDialogButtonBox::Cancel, Qt::Horizontal, this); + + connect (buttons->button (QDialogButtonBox::Cancel), SIGNAL (clicked()), this, SLOT (reject())); + mOkay = new QPushButton ("Merge", this); + mOkay->setDefault (true); + buttons->addButton (mOkay, QDialogButtonBox::AcceptRole); + + mainLayout->addWidget (buttons); +} + +void CSVTools::Merge::configure (CSMDoc::Document *document) +{ + mDocument = document; + + mNewFile->setName (""); + + // content files + while (mFiles->count()) + delete mFiles->takeItem (0); + + std::vector files = document->getContentFiles(); + + for (std::vector::const_iterator iter (files.begin()); + iter!=files.end(); ++iter) + mFiles->addItem (QString::fromUtf8 (iter->filename().string().c_str())); +} + +void CSVTools::Merge::setLocalData (const boost::filesystem::path& localData) +{ + mAdjuster->setLocalData (localData); +} + +CSMDoc::Document *CSVTools::Merge::getDocument() const +{ + return mDocument; +} + +void CSVTools::Merge::cancel() +{ + mDocument = 0; + hide(); +} + +void CSVTools::Merge::accept() +{ + QDialog::accept(); +} + +void CSVTools::Merge::reject() +{ + QDialog::reject(); + cancel(); +} + +void CSVTools::Merge::stateChanged (bool valid) +{ + mOkay->setEnabled (valid); +} diff --git a/apps/opencs/view/tools/merge.hpp b/apps/opencs/view/tools/merge.hpp new file mode 100644 index 0000000000..4538baebe6 --- /dev/null +++ b/apps/opencs/view/tools/merge.hpp @@ -0,0 +1,60 @@ +#ifndef CSV_TOOLS_REPORTTABLE_H +#define CSV_TOOLS_REPORTTABLE_H + +#include + +#include + +class QPushButton; +class QListWidget; + +namespace CSMDoc +{ + class Document; +} + +namespace CSVDoc +{ + class FileWidget; + class AdjusterWidget; +} + +namespace CSVTools +{ + class Merge : public QDialog + { + Q_OBJECT + + CSMDoc::Document *mDocument; + QPushButton *mOkay; + QListWidget *mFiles; + CSVDoc::FileWidget *mNewFile; + CSVDoc::AdjusterWidget *mAdjuster; + + public: + + Merge (QWidget *parent = 0); + + /// Configure dialogue for a new merge + void configure (CSMDoc::Document *document); + + void setLocalData (const boost::filesystem::path& localData); + + CSMDoc::Document *getDocument() const; + + void cancel(); + + public slots: + + virtual void accept(); + + virtual void reject(); + + private slots: + + void stateChanged (bool valid); + + }; +} + +#endif From a5a0990d3c4d91f8b8a4bb549906020a010f21c2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 6 Aug 2015 12:58:52 +0200 Subject: [PATCH 08/81] improved adjuster widget problem reporting (cherry picked from commit 4fd3097c1cf2329cef071aee7a1b149e280e4974) --- apps/opencs/view/doc/adjusterwidget.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/doc/adjusterwidget.cpp b/apps/opencs/view/doc/adjusterwidget.cpp index ba5dd90f83..620d853ac4 100644 --- a/apps/opencs/view/doc/adjusterwidget.cpp +++ b/apps/opencs/view/doc/adjusterwidget.cpp @@ -63,6 +63,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon) QString message; mValid = (!name.isEmpty()); + bool warning = false; if (!mValid) { @@ -105,13 +106,14 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon) { /// \todo add an user setting to make this an error. message += "

A file with the same name already exists. If you continue, it will be overwritten."; + warning = true; } } } mMessage->setText (message); mIcon->setPixmap (style()->standardIcon ( - mValid ? QStyle::SP_MessageBoxInformation : QStyle::SP_MessageBoxWarning). + mValid ? (warning ? QStyle::SP_MessageBoxWarning : QStyle::SP_MessageBoxInformation) : QStyle::SP_MessageBoxCritical). pixmap (QSize (16, 16))); emit stateChanged (mValid); From c2ed475950191349c789613e174834864cea8108 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 8 Aug 2015 16:47:58 +0200 Subject: [PATCH 09/81] disable merge menu item when a merge is already in progress (cherry picked from commit 708cacdec403793a0337c6e536a1ecf53a58bd6e) --- apps/opencs/view/doc/view.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 9eb891c489..47a2ffd51b 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -423,7 +423,8 @@ void CSVDoc::View::updateActions() mGlobalDebugProfileMenu->updateActions (running); mStopDebug->setEnabled (running); - mMerge->setEnabled (mDocument->getContentFiles().size()>1); + mMerge->setEnabled (mDocument->getContentFiles().size()>1 && + !(mDocument->getState() & CSMDoc::State_Merging)); } CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) From e4381c3ec80008ccbff90590000e913bbbb7c0fe Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 13 Aug 2015 12:03:20 +0200 Subject: [PATCH 10/81] added merge operation (doesn't do anything yet) (cherry picked from commit 904ad949524864239f4b1f428d03a947360728a0) Conflicts: apps/opencs/CMakeLists.txt apps/opencs/model/tools/tools.cpp --- apps/opencs/CMakeLists.txt | 1 + apps/opencs/model/doc/document.cpp | 6 +++++ apps/opencs/model/doc/document.hpp | 5 ++-- apps/opencs/model/tools/mergeoperation.cpp | 15 +++++++++++ apps/opencs/model/tools/mergeoperation.hpp | 28 +++++++++++++++++++ apps/opencs/model/tools/tools.cpp | 31 +++++++++++++++++++--- apps/opencs/model/tools/tools.hpp | 11 ++++++-- apps/opencs/view/tools/merge.cpp | 8 ++++++ 8 files changed, 97 insertions(+), 8 deletions(-) create mode 100644 apps/opencs/model/tools/mergeoperation.cpp create mode 100644 apps/opencs/model/tools/mergeoperation.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 9cc9a2971c..eb378f5dda 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -42,6 +42,7 @@ opencs_units_noqt (model/tools mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck startscriptcheck search searchoperation searchstage pathgridcheck soundgencheck magiceffectcheck + mergeoperation ) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index b4d873245a..87e3679c53 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2385,6 +2385,12 @@ void CSMDoc::Document::runSearch (const CSMWorld::UniversalId& searchId, const C emit stateChanged (getState(), this); } +void CSMDoc::Document::runMerge (const boost::filesystem::path& target) +{ + mTools.runMerge (target); + emit stateChanged (getState(), this); +} + void CSMDoc::Document::abortOperation (int type) { if (type==State_Saving) diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 557f3cb23c..706fc3a81d 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -125,7 +125,9 @@ namespace CSMDoc CSMWorld::UniversalId newSearch(); void runSearch (const CSMWorld::UniversalId& searchId, const CSMTools::Search& search); - + + void runMerge (const boost::filesystem::path& target); + void abortOperation (int type); const CSMWorld::Data& getData() const; @@ -171,4 +173,3 @@ namespace CSMDoc } #endif - diff --git a/apps/opencs/model/tools/mergeoperation.cpp b/apps/opencs/model/tools/mergeoperation.cpp new file mode 100644 index 0000000000..65cfdb4ff4 --- /dev/null +++ b/apps/opencs/model/tools/mergeoperation.cpp @@ -0,0 +1,15 @@ + +#include "mergeoperation.hpp" + +#include "../doc/state.hpp" + +CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document) +: CSMDoc::Operation (CSMDoc::State_Merging, true) +{ + +} + +void CSMTools::MergeOperation::setTarget (const boost::filesystem::path& target) +{ + +} diff --git a/apps/opencs/model/tools/mergeoperation.hpp b/apps/opencs/model/tools/mergeoperation.hpp new file mode 100644 index 0000000000..84526b2f20 --- /dev/null +++ b/apps/opencs/model/tools/mergeoperation.hpp @@ -0,0 +1,28 @@ +#ifndef CSM_TOOLS_MERGEOPERATION_H +#define CSM_TOOLS_MERGEOPERATION_H + +#include + +#include "../doc/operation.hpp" + +namespace CSMDoc +{ + class Document; +} + +namespace CSMTools +{ + class MergeOperation : public CSMDoc::Operation + { + + + public: + + MergeOperation (CSMDoc::Document& document); + + /// \attention Do not call this function while a merge is running. + void setTarget (const boost::filesystem::path& target); + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 0c6e36a61f..e9165451d6 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -28,6 +28,7 @@ #include "pathgridcheck.hpp" #include "soundgencheck.hpp" #include "magiceffectcheck.hpp" +#include "mergeoperation.hpp" CSMDoc::OperationHolder *CSMTools::Tools::get (int type) { @@ -35,6 +36,7 @@ CSMDoc::OperationHolder *CSMTools::Tools::get (int type) { case CSMDoc::State_Verifying: return &mVerifier; case CSMDoc::State_Searching: return &mSearch; + case CSMDoc::State_Merging: return &mMerge; } return 0; @@ -53,7 +55,7 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() std::vector settings; settings.push_back ("script-editor/warnings"); - + mVerifierOperation->configureSettings (settings); connect (&mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); @@ -122,7 +124,7 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() CSMTools::Tools::Tools (CSMDoc::Document& document) : mDocument (document), mData (document.getData()), mVerifierOperation (0), - mSearchOperation (0), mNextReportNumber (0) + mSearchOperation (0), mMergeOperation (0), mNextReportNumber (0) { // index 0: load error log mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel)); @@ -148,6 +150,12 @@ CSMTools::Tools::~Tools() delete mSearchOperation; } + if (mMergeOperation) + { + mMerge.abortAndWait(); + delete mMergeOperation; + } + for (std::map::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter) delete iter->second; } @@ -159,7 +167,7 @@ CSMWorld::UniversalId CSMTools::Tools::runVerifier (const CSMWorld::UniversalId& if (mReports.find (reportNumber)==mReports.end()) mReports.insert (std::make_pair (reportNumber, new ReportModel)); - + mActiveReports[CSMDoc::State_Verifying] = reportNumber; getVerifier()->start(); @@ -189,6 +197,21 @@ void CSMTools::Tools::runSearch (const CSMWorld::UniversalId& searchId, const Se mSearch.start(); } +void CSMTools::Tools::runMerge (const boost::filesystem::path& target) +{ + // not setting an active report, because merge does not produce messages + + if (!mMergeOperation) + { + mMergeOperation = new MergeOperation (mDocument); + mMerge.setOperation (mMergeOperation); + } + + mMergeOperation->setTarget (target); + + mMerge.start(); +} + void CSMTools::Tools::abortOperation (int type) { if (CSMDoc::OperationHolder *operation = get (type)) @@ -201,6 +224,7 @@ int CSMTools::Tools::getRunningOperations() const { CSMDoc::State_Verifying, CSMDoc::State_Searching, + CSMDoc::State_Merging, -1 }; @@ -231,4 +255,3 @@ void CSMTools::Tools::verifierMessage (const CSMDoc::Message& message, int type) if (iter!=mActiveReports.end()) mReports[iter->second]->add (message); } - diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index 78484d15d9..9520999280 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -1,9 +1,11 @@ #ifndef CSM_TOOLS_TOOLS_H #define CSM_TOOLS_TOOLS_H +#include + #include -#include +#include #include "../doc/operationholder.hpp" @@ -24,6 +26,7 @@ namespace CSMTools class ReportModel; class Search; class SearchOperation; + class MergeOperation; class Tools : public QObject { @@ -35,6 +38,8 @@ namespace CSMTools CSMDoc::OperationHolder mVerifier; SearchOperation *mSearchOperation; CSMDoc::OperationHolder mSearch; + MergeOperation *mMergeOperation; + CSMDoc::OperationHolder mMerge; std::map mReports; int mNextReportNumber; std::map mActiveReports; // type, report number @@ -67,7 +72,9 @@ namespace CSMTools CSMWorld::UniversalId newSearch(); void runSearch (const CSMWorld::UniversalId& searchId, const Search& search); - + + void runMerge (const boost::filesystem::path& target); + void abortOperation (int type); ///< \attention The operation is not aborted immediately. diff --git a/apps/opencs/view/tools/merge.cpp b/apps/opencs/view/tools/merge.cpp index baadd91799..faf7be3b43 100644 --- a/apps/opencs/view/tools/merge.cpp +++ b/apps/opencs/view/tools/merge.cpp @@ -66,7 +66,9 @@ CSVTools::Merge::Merge (QWidget *parent) QDialogButtonBox *buttons = new QDialogButtonBox (QDialogButtonBox::Cancel, Qt::Horizontal, this); connect (buttons->button (QDialogButtonBox::Cancel), SIGNAL (clicked()), this, SLOT (reject())); + mOkay = new QPushButton ("Merge", this); + connect (mOkay, SIGNAL (clicked()), this, SLOT (accept())); mOkay->setDefault (true); buttons->addButton (mOkay, QDialogButtonBox::AcceptRole); @@ -109,6 +111,12 @@ void CSVTools::Merge::cancel() void CSVTools::Merge::accept() { QDialog::accept(); + + if ((mDocument->getState() & CSMDoc::State_Merging)==0) + { + mDocument->runMerge (mAdjuster->getPath()); + hide(); + } } void CSVTools::Merge::reject() From 9423603e9431eab36ed6f53a4bdca680879848ab Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 13 Aug 2015 12:53:00 +0200 Subject: [PATCH 11/81] inheriting Merge from QWidget instead of QDialog, because QDialog is bloody useless for non-modal dialogues (which makes the class completely useless, since modal dialogues are the spawn of Satan) (cherry picked from commit e2377396a7cf7b9cd1ec91e0f385721a124a49cc) --- apps/opencs/editor.cpp | 2 ++ apps/opencs/view/tools/merge.cpp | 24 ++++++++++++++---------- apps/opencs/view/tools/merge.hpp | 15 +++++++-------- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 1de1e18652..e680f5a853 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -550,4 +550,6 @@ void CS::Editor::mergeDocument (CSMDoc::Document *document) { mMerge.configure (document); mMerge.show(); + mMerge.raise(); + mMerge.activateWindow(); } diff --git a/apps/opencs/view/tools/merge.cpp b/apps/opencs/view/tools/merge.cpp index faf7be3b43..f775390ee8 100644 --- a/apps/opencs/view/tools/merge.cpp +++ b/apps/opencs/view/tools/merge.cpp @@ -7,14 +7,26 @@ #include #include #include +#include #include "../../model/doc/document.hpp" #include "../doc/filewidget.hpp" #include "../doc/adjusterwidget.hpp" +void CSVTools::Merge::keyPressEvent (QKeyEvent *event) +{ + if (event->key()==Qt::Key_Escape) + { + event->accept(); + cancel(); + } + else + QWidget::keyPressEvent (event); +} + CSVTools::Merge::Merge (QWidget *parent) -: QDialog (parent), mDocument (0) +: QWidget (parent), mDocument (0) { setWindowTitle ("Merge Content Files into a new Game File"); @@ -65,7 +77,7 @@ CSVTools::Merge::Merge (QWidget *parent) // buttons QDialogButtonBox *buttons = new QDialogButtonBox (QDialogButtonBox::Cancel, Qt::Horizontal, this); - connect (buttons->button (QDialogButtonBox::Cancel), SIGNAL (clicked()), this, SLOT (reject())); + connect (buttons->button (QDialogButtonBox::Cancel), SIGNAL (clicked()), this, SLOT (cancel())); mOkay = new QPushButton ("Merge", this); connect (mOkay, SIGNAL (clicked()), this, SLOT (accept())); @@ -110,8 +122,6 @@ void CSVTools::Merge::cancel() void CSVTools::Merge::accept() { - QDialog::accept(); - if ((mDocument->getState() & CSMDoc::State_Merging)==0) { mDocument->runMerge (mAdjuster->getPath()); @@ -119,12 +129,6 @@ void CSVTools::Merge::accept() } } -void CSVTools::Merge::reject() -{ - QDialog::reject(); - cancel(); -} - void CSVTools::Merge::stateChanged (bool valid) { mOkay->setEnabled (valid); diff --git a/apps/opencs/view/tools/merge.hpp b/apps/opencs/view/tools/merge.hpp index 4538baebe6..b8369ffa32 100644 --- a/apps/opencs/view/tools/merge.hpp +++ b/apps/opencs/view/tools/merge.hpp @@ -1,7 +1,7 @@ #ifndef CSV_TOOLS_REPORTTABLE_H #define CSV_TOOLS_REPORTTABLE_H -#include +#include #include @@ -21,7 +21,7 @@ namespace CSVDoc namespace CSVTools { - class Merge : public QDialog + class Merge : public QWidget { Q_OBJECT @@ -31,6 +31,8 @@ namespace CSVTools CSVDoc::FileWidget *mNewFile; CSVDoc::AdjusterWidget *mAdjuster; + void keyPressEvent (QKeyEvent *event); + public: Merge (QWidget *parent = 0); @@ -42,18 +44,15 @@ namespace CSVTools CSMDoc::Document *getDocument() const; - void cancel(); - public slots: - virtual void accept(); - - virtual void reject(); + void cancel(); private slots: - void stateChanged (bool valid); + void accept(); + void stateChanged (bool valid); }; } From 0b8e04d6a8911c7b3a149c194ccf80ca8918b6ce Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 13 Aug 2015 14:49:32 +0200 Subject: [PATCH 12/81] forgot to connect merge operation signals (cherry picked from commit d8655f2ff862dbaf90fb285ef01cdf6891cdbea6) --- apps/opencs/model/tools/tools.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index e9165451d6..67c917b7f7 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -134,6 +134,10 @@ CSMTools::Tools::Tools (CSMDoc::Document& document) connect (&mSearch, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool))); connect (&mSearch, SIGNAL (reportMessage (const CSMDoc::Message&, int)), this, SLOT (verifierMessage (const CSMDoc::Message&, int))); + + connect (&mMerge, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); + connect (&mMerge, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool))); + // don't need to connect report message, since there are no messages for merge } CSMTools::Tools::~Tools() From 3eef192e4d4a052d17af686ba469ff7ed07b4a22 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 16 Aug 2015 15:24:48 +0200 Subject: [PATCH 13/81] create merged document and open a view for it (document is still empty at this point) (cherry picked from commit 1b663f01aff94811a46825467cad8f38ed025b24) Conflicts: apps/opencs/CMakeLists.txt apps/opencs/model/doc/documentmanager.cpp --- apps/opencs/CMakeLists.txt | 8 +++++-- apps/opencs/editor.cpp | 3 ++- apps/opencs/model/doc/document.cpp | 4 +++- apps/opencs/model/doc/document.hpp | 6 ++++- apps/opencs/model/doc/documentmanager.cpp | 16 ++++++++++++- apps/opencs/model/doc/documentmanager.hpp | 13 +++++++++++ apps/opencs/model/doc/operation.hpp | 4 +++- apps/opencs/model/tools/mergeoperation.cpp | 19 ++++++++++++---- apps/opencs/model/tools/mergeoperation.hpp | 19 ++++++++++++++-- apps/opencs/model/tools/mergestages.cpp | 18 +++++++++++++++ apps/opencs/model/tools/mergestages.hpp | 26 ++++++++++++++++++++++ apps/opencs/model/tools/mergestate.hpp | 20 +++++++++++++++++ apps/opencs/model/tools/tools.cpp | 4 +++- apps/opencs/model/tools/tools.hpp | 7 +++++- apps/opencs/view/tools/merge.cpp | 13 ++++++++--- apps/opencs/view/tools/merge.hpp | 4 +++- 16 files changed, 165 insertions(+), 19 deletions(-) create mode 100644 apps/opencs/model/tools/mergestages.cpp create mode 100644 apps/opencs/model/tools/mergestages.hpp create mode 100644 apps/opencs/model/tools/mergestate.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index eb378f5dda..3b756495df 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -35,14 +35,18 @@ opencs_hdrs_noqt (model/world opencs_units (model/tools - tools reportmodel + tools reportmodel mergeoperation ) opencs_units_noqt (model/tools mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck startscriptcheck search searchoperation searchstage pathgridcheck soundgencheck magiceffectcheck - mergeoperation + mergestages + ) + +opencs_hdrs_noqt (model/tools + mergestate ) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index e680f5a853..3721936ce9 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -26,7 +26,8 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) : mUserSettings (mCfgMgr), mOverlaySystem (0), mDocumentManager (mCfgMgr), mViewManager (mDocumentManager), mPid(""), - mLock(), mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL) + mLock(), mMerge (mDocumentManager), + mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL) { std::pair > config = readConfig(); diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 87e3679c53..9cfdb57956 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2296,6 +2296,8 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int))); connect (&mTools, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool))); + connect (&mTools, SIGNAL (mergeDone (CSMDoc::Document*)), + this, SIGNAL (mergeDone (CSMDoc::Document*))); connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int))); connect (&mSaving, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool))); @@ -2385,7 +2387,7 @@ void CSMDoc::Document::runSearch (const CSMWorld::UniversalId& searchId, const C emit stateChanged (getState(), this); } -void CSMDoc::Document::runMerge (const boost::filesystem::path& target) +void CSMDoc::Document::runMerge (std::auto_ptr target) { mTools.runMerge (target); emit stateChanged (getState(), this); diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 706fc3a81d..e9059f629c 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -126,7 +126,7 @@ namespace CSMDoc void runSearch (const CSMWorld::UniversalId& searchId, const CSMTools::Search& search); - void runMerge (const boost::filesystem::path& target); + void runMerge (std::auto_ptr target); void abortOperation (int type); @@ -156,6 +156,10 @@ namespace CSMDoc void progress (int current, int max, int type, int threads, CSMDoc::Document *document); + /// \attention When this signal is emitted, *this hands over the ownership of the + /// document. This signal must be handled to avoid a leak. + void mergeDone (CSMDoc::Document *document); + private slots: void modificationStateChanged (bool clean); diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index e8668d3ef5..af10dc9d67 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -56,10 +56,24 @@ bool CSMDoc::DocumentManager::isEmpty() void CSMDoc::DocumentManager::addDocument (const std::vector& files, const boost::filesystem::path& savePath, bool new_) { - Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager, mBlacklistedScripts); + Document *document = makeDocument (files, savePath, new_); + insertDocument (document); +} +CSMDoc::Document *CSMDoc::DocumentManager::makeDocument ( + const std::vector< boost::filesystem::path >& files, + const boost::filesystem::path& savePath, bool new_) +{ + return new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager, mBlacklistedScripts); +} + +void CSMDoc::DocumentManager::insertDocument (CSMDoc::Document *document) +{ mDocuments.push_back (document); + connect (document, SIGNAL (mergeDone (CSMDoc::Document*)), + this, SLOT (insertDocument (CSMDoc::Document*))); + emit loadRequest (document); mLoader.hasThingsToDo().wakeAll(); diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index 5a892cc45c..1e84928285 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -50,6 +50,15 @@ namespace CSMDoc ///< \param new_ Do not load the last content file in \a files and instead create in an /// appropriate way. + /// Create a new document. The ownership of the created document is transferred to + /// the calling function. The DocumentManager does not manage it. Loading has not + /// taken place at the point when the document is returned. + /// + /// \param new_ Do not load the last content file in \a files and instead create in an + /// appropriate way. + Document *makeDocument (const std::vector< boost::filesystem::path >& files, + const boost::filesystem::path& savePath, bool new_); + void setResourceDir (const boost::filesystem::path& parResDir); void setEncoding (ToUTF8::FromType encoding); @@ -79,6 +88,10 @@ namespace CSMDoc void removeDocument (CSMDoc::Document *document); ///< Emits the lastDocumentDeleted signal, if applicable. + /// Hand over document to *this. The ownership is transferred. The DocumentManager + /// will initiate the load procedure, if necessary + void insertDocument (CSMDoc::Document *document); + signals: void documentAdded (CSMDoc::Document *document); diff --git a/apps/opencs/model/doc/operation.hpp b/apps/opencs/model/doc/operation.hpp index 703f9d44b7..3c86a6e235 100644 --- a/apps/opencs/model/doc/operation.hpp +++ b/apps/opencs/model/doc/operation.hpp @@ -83,7 +83,9 @@ namespace CSMDoc void executeStage(); - void operationDone(); + protected slots: + + virtual void operationDone(); }; } diff --git a/apps/opencs/model/tools/mergeoperation.cpp b/apps/opencs/model/tools/mergeoperation.cpp index 65cfdb4ff4..c93452dad9 100644 --- a/apps/opencs/model/tools/mergeoperation.cpp +++ b/apps/opencs/model/tools/mergeoperation.cpp @@ -2,14 +2,25 @@ #include "mergeoperation.hpp" #include "../doc/state.hpp" +#include "../doc/document.hpp" + +#include "mergestages.hpp" CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document) -: CSMDoc::Operation (CSMDoc::State_Merging, true) +: CSMDoc::Operation (CSMDoc::State_Merging, true), mState (document) { - + appendStage (new FinishMergedDocumentStage (mState)); } -void CSMTools::MergeOperation::setTarget (const boost::filesystem::path& target) +void CSMTools::MergeOperation::setTarget (std::auto_ptr document) { - + mState.mTarget = document; +} + +void CSMTools::MergeOperation::operationDone() +{ + CSMDoc::Operation::operationDone(); + + if (mState.mCompleted) + emit mergeDone (mState.mTarget.release()); } diff --git a/apps/opencs/model/tools/mergeoperation.hpp b/apps/opencs/model/tools/mergeoperation.hpp index 84526b2f20..dc958d31b0 100644 --- a/apps/opencs/model/tools/mergeoperation.hpp +++ b/apps/opencs/model/tools/mergeoperation.hpp @@ -1,10 +1,12 @@ #ifndef CSM_TOOLS_MERGEOPERATION_H #define CSM_TOOLS_MERGEOPERATION_H -#include +#include #include "../doc/operation.hpp" +#include "mergestate.hpp" + namespace CSMDoc { class Document; @@ -14,14 +16,27 @@ namespace CSMTools { class MergeOperation : public CSMDoc::Operation { + Q_OBJECT + MergeState mState; public: MergeOperation (CSMDoc::Document& document); /// \attention Do not call this function while a merge is running. - void setTarget (const boost::filesystem::path& target); + void setTarget (std::auto_ptr document); + + protected slots: + + virtual void operationDone(); + + signals: + + /// \attention When this signal is emitted, *this hands over the ownership of the + /// document. This signal must be handled to avoid a leak. + void mergeDone (CSMDoc::Document *document); + }; } diff --git a/apps/opencs/model/tools/mergestages.cpp b/apps/opencs/model/tools/mergestages.cpp new file mode 100644 index 0000000000..16ea0495a7 --- /dev/null +++ b/apps/opencs/model/tools/mergestages.cpp @@ -0,0 +1,18 @@ + +#include "mergestages.hpp" + +#include "mergestate.hpp" + +CSMTools::FinishMergedDocumentStage::FinishMergedDocumentStage (MergeState& state) +: mState (state) +{} + +int CSMTools::FinishMergedDocumentStage::setup() +{ + return 1; +} + +void CSMTools::FinishMergedDocumentStage::perform (int stage, CSMDoc::Messages& messages) +{ + mState.mCompleted = true; +} diff --git a/apps/opencs/model/tools/mergestages.hpp b/apps/opencs/model/tools/mergestages.hpp new file mode 100644 index 0000000000..138b89d72e --- /dev/null +++ b/apps/opencs/model/tools/mergestages.hpp @@ -0,0 +1,26 @@ +#ifndef CSM_TOOLS_MERGESTAGES_H +#define CSM_TOOLS_MERGESTAGES_H + +#include "../doc/stage.hpp" + +namespace CSMTools +{ + struct MergeState; + + class FinishMergedDocumentStage : public CSMDoc::Stage + { + MergeState& mState; + + public: + + FinishMergedDocumentStage (MergeState& state); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, CSMDoc::Messages& messages); + ///< Messages resulting from this stage will be appended to \a messages. + }; +} + +#endif diff --git a/apps/opencs/model/tools/mergestate.hpp b/apps/opencs/model/tools/mergestate.hpp new file mode 100644 index 0000000000..4482ba6f4a --- /dev/null +++ b/apps/opencs/model/tools/mergestate.hpp @@ -0,0 +1,20 @@ +#ifndef CSM_TOOLS_MERGESTATE_H +#define CSM_TOOLS_MERGESTATE_H + +#include + +#include "../doc/document.hpp" + +namespace CSMTools +{ + struct MergeState + { + std::auto_ptr mTarget; + CSMDoc::Document& mSource; + bool mCompleted; + + MergeState (CSMDoc::Document& source) : mSource (source), mCompleted (false) {} + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 67c917b7f7..43a31cdccf 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -201,7 +201,7 @@ void CSMTools::Tools::runSearch (const CSMWorld::UniversalId& searchId, const Se mSearch.start(); } -void CSMTools::Tools::runMerge (const boost::filesystem::path& target) +void CSMTools::Tools::runMerge (std::auto_ptr target) { // not setting an active report, because merge does not produce messages @@ -209,6 +209,8 @@ void CSMTools::Tools::runMerge (const boost::filesystem::path& target) { mMergeOperation = new MergeOperation (mDocument); mMerge.setOperation (mMergeOperation); + connect (mMergeOperation, SIGNAL (mergeDone (CSMDoc::Document*)), + this, SIGNAL (mergeDone (CSMDoc::Document*))); } mMergeOperation->setTarget (target); diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index 9520999280..2302fe2e05 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -1,6 +1,7 @@ #ifndef CSM_TOOLS_TOOLS_H #define CSM_TOOLS_TOOLS_H +#include #include #include @@ -73,7 +74,7 @@ namespace CSMTools void runSearch (const CSMWorld::UniversalId& searchId, const Search& search); - void runMerge (const boost::filesystem::path& target); + void runMerge (std::auto_ptr target); void abortOperation (int type); ///< \attention The operation is not aborted immediately. @@ -92,6 +93,10 @@ namespace CSMTools void progress (int current, int max, int type); void done (int type, bool failed); + + /// \attention When this signal is emitted, *this hands over the ownership of the + /// document. This signal must be handled to avoid a leak. + void mergeDone (CSMDoc::Document *document); }; } diff --git a/apps/opencs/view/tools/merge.cpp b/apps/opencs/view/tools/merge.cpp index f775390ee8..566a5ee062 100644 --- a/apps/opencs/view/tools/merge.cpp +++ b/apps/opencs/view/tools/merge.cpp @@ -10,6 +10,7 @@ #include #include "../../model/doc/document.hpp" +#include "../../model/doc/documentmanager.hpp" #include "../doc/filewidget.hpp" #include "../doc/adjusterwidget.hpp" @@ -25,8 +26,8 @@ void CSVTools::Merge::keyPressEvent (QKeyEvent *event) QWidget::keyPressEvent (event); } -CSVTools::Merge::Merge (QWidget *parent) -: QWidget (parent), mDocument (0) +CSVTools::Merge::Merge (CSMDoc::DocumentManager& documentManager, QWidget *parent) +: QWidget (parent), mDocument (0), mDocumentManager (documentManager) { setWindowTitle ("Merge Content Files into a new Game File"); @@ -124,7 +125,13 @@ void CSVTools::Merge::accept() { if ((mDocument->getState() & CSMDoc::State_Merging)==0) { - mDocument->runMerge (mAdjuster->getPath()); + std::vector< boost::filesystem::path > files (1, mAdjuster->getPath()); + + std::auto_ptr target ( + mDocumentManager.makeDocument (files, files[0], true)); + + mDocument->runMerge (target); + hide(); } } diff --git a/apps/opencs/view/tools/merge.hpp b/apps/opencs/view/tools/merge.hpp index b8369ffa32..d4ed7e34b8 100644 --- a/apps/opencs/view/tools/merge.hpp +++ b/apps/opencs/view/tools/merge.hpp @@ -11,6 +11,7 @@ class QListWidget; namespace CSMDoc { class Document; + class DocumentManager; } namespace CSVDoc @@ -30,12 +31,13 @@ namespace CSVTools QListWidget *mFiles; CSVDoc::FileWidget *mNewFile; CSVDoc::AdjusterWidget *mAdjuster; + CSMDoc::DocumentManager& mDocumentManager; void keyPressEvent (QKeyEvent *event); public: - Merge (QWidget *parent = 0); + Merge (CSMDoc::DocumentManager& documentManager, QWidget *parent = 0); /// Configure dialogue for a new merge void configure (CSMDoc::Document *document); From 55dfe48ef71d866e5da528b1b34c384adb3dcaee Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 16 Aug 2015 18:27:17 +0200 Subject: [PATCH 14/81] copy meta data from game file when merging (cherry picked from commit 47dd9505a9464dc5c947f409c3c4a80cf4d8e395) Conflicts: apps/opencs/model/doc/document.cpp apps/opencs/model/world/data.cpp --- apps/opencs/model/doc/document.cpp | 2 +- apps/opencs/model/tools/mergeoperation.cpp | 4 ++-- apps/opencs/model/tools/mergeoperation.hpp | 4 +++- apps/opencs/model/tools/mergestages.cpp | 27 ++++++++++++++++++++-- apps/opencs/model/tools/mergestages.hpp | 5 +++- apps/opencs/model/tools/tools.cpp | 6 ++--- apps/opencs/model/tools/tools.hpp | 5 +++- apps/opencs/model/world/data.cpp | 6 +++++ apps/opencs/model/world/data.hpp | 2 ++ 9 files changed, 50 insertions(+), 11 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 9cfdb57956..184a0e38ae 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2251,7 +2251,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager, const std::vector& blacklistedScripts) : mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, resourcesManager), - mTools (*this), + mTools (*this, encoding), mProjectPath ((configuration.getUserDataPath() / "projects") / (savePath.filename().string() + ".project")), mSavingOperation (*this, mProjectPath, encoding), diff --git a/apps/opencs/model/tools/mergeoperation.cpp b/apps/opencs/model/tools/mergeoperation.cpp index c93452dad9..9e5fb27456 100644 --- a/apps/opencs/model/tools/mergeoperation.cpp +++ b/apps/opencs/model/tools/mergeoperation.cpp @@ -6,10 +6,10 @@ #include "mergestages.hpp" -CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document) +CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document, ToUTF8::FromType encoding) : CSMDoc::Operation (CSMDoc::State_Merging, true), mState (document) { - appendStage (new FinishMergedDocumentStage (mState)); + appendStage (new FinishMergedDocumentStage (mState, encoding)); } void CSMTools::MergeOperation::setTarget (std::auto_ptr document) diff --git a/apps/opencs/model/tools/mergeoperation.hpp b/apps/opencs/model/tools/mergeoperation.hpp index dc958d31b0..bdaeb2ccda 100644 --- a/apps/opencs/model/tools/mergeoperation.hpp +++ b/apps/opencs/model/tools/mergeoperation.hpp @@ -3,6 +3,8 @@ #include +#include + #include "../doc/operation.hpp" #include "mergestate.hpp" @@ -22,7 +24,7 @@ namespace CSMTools public: - MergeOperation (CSMDoc::Document& document); + MergeOperation (CSMDoc::Document& document, ToUTF8::FromType encoding); /// \attention Do not call this function while a merge is running. void setTarget (std::auto_ptr document); diff --git a/apps/opencs/model/tools/mergestages.cpp b/apps/opencs/model/tools/mergestages.cpp index 16ea0495a7..776808b269 100644 --- a/apps/opencs/model/tools/mergestages.cpp +++ b/apps/opencs/model/tools/mergestages.cpp @@ -3,8 +3,11 @@ #include "mergestate.hpp" -CSMTools::FinishMergedDocumentStage::FinishMergedDocumentStage (MergeState& state) -: mState (state) +#include "../doc/document.hpp" +#include "../world/data.hpp" + +CSMTools::FinishMergedDocumentStage::FinishMergedDocumentStage (MergeState& state, ToUTF8::FromType encoding) +: mState (state), mEncoder (encoding) {} int CSMTools::FinishMergedDocumentStage::setup() @@ -14,5 +17,25 @@ int CSMTools::FinishMergedDocumentStage::setup() void CSMTools::FinishMergedDocumentStage::perform (int stage, CSMDoc::Messages& messages) { + // We know that the content file list contains at least two entries and that the first one + // does exist on disc (otherwise it would have been impossible to initiate a merge on that + // document). + boost::filesystem::path path = mState.mSource.getContentFiles()[0]; + + ESM::ESMReader reader; + reader.setEncoder (&mEncoder); + reader.open (path.string()); + + CSMWorld::MetaData source; + source.mId = "sys::meta"; + source.load (reader); + + CSMWorld::MetaData target = mState.mTarget->getData().getMetaData(); + + target.mAuthor = source.mAuthor; + target.mDescription = source.mDescription; + + mState.mTarget->getData().setMetaData (target); + mState.mCompleted = true; } diff --git a/apps/opencs/model/tools/mergestages.hpp b/apps/opencs/model/tools/mergestages.hpp index 138b89d72e..9844feaca3 100644 --- a/apps/opencs/model/tools/mergestages.hpp +++ b/apps/opencs/model/tools/mergestages.hpp @@ -1,6 +1,8 @@ #ifndef CSM_TOOLS_MERGESTAGES_H #define CSM_TOOLS_MERGESTAGES_H +#include + #include "../doc/stage.hpp" namespace CSMTools @@ -10,10 +12,11 @@ namespace CSMTools class FinishMergedDocumentStage : public CSMDoc::Stage { MergeState& mState; + ToUTF8::Utf8Encoder mEncoder; public: - FinishMergedDocumentStage (MergeState& state); + FinishMergedDocumentStage (MergeState& state, ToUTF8::FromType encoding); virtual int setup(); ///< \return number of steps diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 43a31cdccf..8759f9c319 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -122,9 +122,9 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() return &mVerifier; } -CSMTools::Tools::Tools (CSMDoc::Document& document) +CSMTools::Tools::Tools (CSMDoc::Document& document, ToUTF8::FromType encoding) : mDocument (document), mData (document.getData()), mVerifierOperation (0), - mSearchOperation (0), mMergeOperation (0), mNextReportNumber (0) + mSearchOperation (0), mMergeOperation (0), mNextReportNumber (0), mEncoding (encoding) { // index 0: load error log mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel)); @@ -207,7 +207,7 @@ void CSMTools::Tools::runMerge (std::auto_ptr target) if (!mMergeOperation) { - mMergeOperation = new MergeOperation (mDocument); + mMergeOperation = new MergeOperation (mDocument, mEncoding); mMerge.setOperation (mMergeOperation); connect (mMergeOperation, SIGNAL (mergeDone (CSMDoc::Document*)), this, SIGNAL (mergeDone (CSMDoc::Document*))); diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index 2302fe2e05..e16a3854cc 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -4,6 +4,8 @@ #include #include +#include + #include #include @@ -44,6 +46,7 @@ namespace CSMTools std::map mReports; int mNextReportNumber; std::map mActiveReports; // type, report number + ToUTF8::FromType mEncoding; // not implemented Tools (const Tools&); @@ -59,7 +62,7 @@ namespace CSMTools public: - Tools (CSMDoc::Document& document); + Tools (CSMDoc::Document& document, ToUTF8::FromType encoding); virtual ~Tools(); diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index b6b7f689ea..b5722ab57a 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -928,6 +928,12 @@ const CSMWorld::MetaData& CSMWorld::Data::getMetaData() const return mMetaData.getRecord (0).get(); } +void CSMWorld::Data::setMetaData (const MetaData& metaData) +{ + Record record (RecordBase::State_ModifiedOnly, 0, &metaData); + mMetaData.setRecord (0, record); +} + QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 1aa9db0b12..c9fe956b13 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -247,6 +247,8 @@ namespace CSMWorld const MetaData& getMetaData() const; + void setMetaData (const MetaData& metaData); + QAbstractItemModel *getTableModel (const UniversalId& id); ///< If no table model is available for \a id, an exception is thrown. /// From 973c65bc822945b69e405f55f8608b29c4a7d256 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 21 Aug 2015 14:02:32 +0200 Subject: [PATCH 15/81] merge id collections (cherry picked from commit 3902513e65206908c0f0f54db213a7c9ea7f2fd0) --- apps/opencs/model/tools/mergeoperation.cpp | 23 ++++++++++ apps/opencs/model/tools/mergestages.hpp | 53 +++++++++++++++++++++- 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/tools/mergeoperation.cpp b/apps/opencs/model/tools/mergeoperation.cpp index 9e5fb27456..4a85eca798 100644 --- a/apps/opencs/model/tools/mergeoperation.cpp +++ b/apps/opencs/model/tools/mergeoperation.cpp @@ -10,6 +10,29 @@ CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document, ToUTF8::Fr : CSMDoc::Operation (CSMDoc::State_Merging, true), mState (document) { appendStage (new FinishMergedDocumentStage (mState, encoding)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getGlobals)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getGmsts)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getSkills)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getClasses)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getFactions)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getRaces)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getSounds)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getScripts)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getRegions)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getBirthsigns)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getSpells)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getTopics)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getJournals)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getCells)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getFilters)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getEnchantments)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getBodyParts)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getDebugProfiles)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getSoundGens)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getMagicEffects)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getStartScripts)); + + /// \todo TopicInfo, JournalInfo, Referencables, References, Land, LandTextures, Pathgrids } void CSMTools::MergeOperation::setTarget (std::auto_ptr document) diff --git a/apps/opencs/model/tools/mergestages.hpp b/apps/opencs/model/tools/mergestages.hpp index 9844feaca3..749fab18c7 100644 --- a/apps/opencs/model/tools/mergestages.hpp +++ b/apps/opencs/model/tools/mergestages.hpp @@ -5,10 +5,12 @@ #include "../doc/stage.hpp" +#include "../world/data.hpp" + +#include "mergestate.hpp" + namespace CSMTools { - struct MergeState; - class FinishMergedDocumentStage : public CSMDoc::Stage { MergeState& mState; @@ -24,6 +26,53 @@ namespace CSMTools virtual void perform (int stage, CSMDoc::Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; + + template + class MergeIdCollectionStage : public CSMDoc::Stage + { + typedef typename CSMWorld::IdCollection Collection; + + MergeState& mState; + Collection& (CSMWorld::Data::*mAccessor)(); + + public: + + MergeIdCollectionStage (MergeState& state, Collection& (CSMWorld::Data::*accessor)()); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, CSMDoc::Messages& messages); + ///< Messages resulting from this stage will be appended to \a messages. + }; + + template + MergeIdCollectionStage::MergeIdCollectionStage (MergeState& state, Collection& (CSMWorld::Data::*accessor)()) + : mState (state), mAccessor (accessor) + {} + + template + int MergeIdCollectionStage::setup() + { + return 1; + } + + template + void MergeIdCollectionStage::perform (int stage, CSMDoc::Messages& messages) + { + const Collection& source = (mState.mSource.getData().*mAccessor)(); + Collection& target = (mState.mTarget->getData().*mAccessor)(); + + int size = source.getSize(); + + for (int i=0; i& record = source.getRecord (i); + + if (!record.isDeleted()) + target.appendRecord (CSMWorld::Record (CSMWorld::RecordBase::State_BaseOnly, &record.get())); + } + } } #endif From 024a5405e0995c4695604491f93a907641db3e8f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 23 Aug 2015 12:37:45 +0200 Subject: [PATCH 16/81] flag newly merged documents as dirty (triggering an 'are you sure' dialogue when closing without saving first) (cherry picked from commit c92898a5bc18584708bd9c0e1e76c517adb3499b) Conflicts: apps/opencs/model/doc/document.cpp apps/opencs/model/doc/document.hpp --- apps/opencs/model/doc/document.cpp | 12 ++++++++++-- apps/opencs/model/doc/document.hpp | 4 ++++ apps/opencs/model/tools/tools.cpp | 2 ++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 184a0e38ae..55034cb4ea 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2258,7 +2258,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, mSaving (&mSavingOperation), mResDir(resDir), mRunner (mProjectPath), mPhysics(boost::shared_ptr()), - mIdCompletionManager(mData) + mIdCompletionManager(mData), mDirty (false) { if (mContentFiles.empty()) throw std::runtime_error ("Empty content file sequence"); @@ -2322,7 +2322,7 @@ int CSMDoc::Document::getState() const { int state = 0; - if (!mUndoStack.isClean()) + if (!mUndoStack.isClean() || mDirty) state |= State_Modified; if (mSaving.isRunning()) @@ -2414,6 +2414,9 @@ void CSMDoc::Document::reportMessage (const CSMDoc::Message& message, int type) void CSMDoc::Document::operationDone (int type, bool failed) { + if (type==CSMDoc::State_Saving && !failed) + mDirty = false; + emit stateChanged (getState(), this); } @@ -2498,3 +2501,8 @@ CSMWorld::IdCompletionManager &CSMDoc::Document::getIdCompletionManager() { return mIdCompletionManager; } + +void CSMDoc::Document::flagAsDirty() +{ + mDirty = true; +} diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index e9059f629c..e737bb1c44 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -67,6 +67,8 @@ namespace CSMDoc Blacklist mBlacklist; Runner mRunner; boost::shared_ptr mPhysics; + bool mDirty; + CSMWorld::IdCompletionManager mIdCompletionManager; // It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is @@ -150,6 +152,8 @@ namespace CSMDoc CSMWorld::IdCompletionManager &getIdCompletionManager(); + void flagAsDirty(); + signals: void stateChanged (int state, CSMDoc::Document *document); diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 8759f9c319..fdbf406f1c 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -213,6 +213,8 @@ void CSMTools::Tools::runMerge (std::auto_ptr target) this, SIGNAL (mergeDone (CSMDoc::Document*))); } + target->flagAsDirty(); + mMergeOperation->setTarget (target); mMerge.start(); From 98cac624a93fc039f055a788fe19ba8e2e46656e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 23 Aug 2015 12:58:49 +0200 Subject: [PATCH 17/81] added info tables and pathgrid table to merge operation (cherry picked from commit 103073150e87d62582649ea6943fdc510eb5ca59) --- apps/opencs/model/tools/mergeoperation.cpp | 5 ++++- apps/opencs/model/tools/mergestages.hpp | 16 +++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/apps/opencs/model/tools/mergeoperation.cpp b/apps/opencs/model/tools/mergeoperation.cpp index 4a85eca798..d010e343b7 100644 --- a/apps/opencs/model/tools/mergeoperation.cpp +++ b/apps/opencs/model/tools/mergeoperation.cpp @@ -31,8 +31,11 @@ CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document, ToUTF8::Fr appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getSoundGens)); appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getMagicEffects)); appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getStartScripts)); + appendStage (new MergeIdCollectionStage > (mState, &CSMWorld::Data::getPathgrids)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getTopicInfos)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getJournalInfos)); - /// \todo TopicInfo, JournalInfo, Referencables, References, Land, LandTextures, Pathgrids + /// \todo Referencables, References, Land, LandTextures } void CSMTools::MergeOperation::setTarget (std::auto_ptr document) diff --git a/apps/opencs/model/tools/mergestages.hpp b/apps/opencs/model/tools/mergestages.hpp index 749fab18c7..f9d29420bc 100644 --- a/apps/opencs/model/tools/mergestages.hpp +++ b/apps/opencs/model/tools/mergestages.hpp @@ -27,11 +27,9 @@ namespace CSMTools ///< Messages resulting from this stage will be appended to \a messages. }; - template + template > class MergeIdCollectionStage : public CSMDoc::Stage { - typedef typename CSMWorld::IdCollection Collection; - MergeState& mState; Collection& (CSMWorld::Data::*mAccessor)(); @@ -46,19 +44,19 @@ namespace CSMTools ///< Messages resulting from this stage will be appended to \a messages. }; - template - MergeIdCollectionStage::MergeIdCollectionStage (MergeState& state, Collection& (CSMWorld::Data::*accessor)()) + template + MergeIdCollectionStage::MergeIdCollectionStage (MergeState& state, Collection& (CSMWorld::Data::*accessor)()) : mState (state), mAccessor (accessor) {} - template - int MergeIdCollectionStage::setup() + template + int MergeIdCollectionStage::setup() { return 1; } - template - void MergeIdCollectionStage::perform (int stage, CSMDoc::Messages& messages) + template + void MergeIdCollectionStage::perform (int stage, CSMDoc::Messages& messages) { const Collection& source = (mState.mSource.getData().*mAccessor)(); Collection& target = (mState.mTarget->getData().*mAccessor)(); From e33314ad813350f982b4f713cb9bed7d741e927e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 23 Aug 2015 13:04:42 +0200 Subject: [PATCH 18/81] made merge operation more fluent (cherry picked from commit 16dda281cee3fb1bab7276cc21448b754d5db3c5) --- apps/opencs/model/tools/mergestages.hpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/tools/mergestages.hpp b/apps/opencs/model/tools/mergestages.hpp index f9d29420bc..af7f06d606 100644 --- a/apps/opencs/model/tools/mergestages.hpp +++ b/apps/opencs/model/tools/mergestages.hpp @@ -1,6 +1,8 @@ #ifndef CSM_TOOLS_MERGESTAGES_H #define CSM_TOOLS_MERGESTAGES_H +#include + #include #include "../doc/stage.hpp" @@ -33,6 +35,8 @@ namespace CSMTools MergeState& mState; Collection& (CSMWorld::Data::*mAccessor)(); + static const int stepSize = 1000; + public: MergeIdCollectionStage (MergeState& state, Collection& (CSMWorld::Data::*accessor)()); @@ -52,7 +56,16 @@ namespace CSMTools template int MergeIdCollectionStage::setup() { - return 1; + const Collection& source = (mState.mSource.getData().*mAccessor)(); + + int size = source.getSize(); + + int steps = size / stepSize; + + if (size % stepSize) + ++steps; + + return steps; } template @@ -61,9 +74,10 @@ namespace CSMTools const Collection& source = (mState.mSource.getData().*mAccessor)(); Collection& target = (mState.mTarget->getData().*mAccessor)(); - int size = source.getSize(); + int begin = stage * stepSize; + int end = std::min ((stage+1) * stepSize, source.getSize()); - for (int i=0; i& record = source.getRecord (i); From 72aa99826161f34d0f49775c4cff316757f8ef89 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 25 Aug 2015 08:43:03 +0200 Subject: [PATCH 19/81] simplifying merge stage (cherry picked from commit 40753aa9a3759e247b1fc907f5ef61af2656d533) --- apps/opencs/model/tools/mergestages.hpp | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/apps/opencs/model/tools/mergestages.hpp b/apps/opencs/model/tools/mergestages.hpp index af7f06d606..c0ed167876 100644 --- a/apps/opencs/model/tools/mergestages.hpp +++ b/apps/opencs/model/tools/mergestages.hpp @@ -35,8 +35,6 @@ namespace CSMTools MergeState& mState; Collection& (CSMWorld::Data::*mAccessor)(); - static const int stepSize = 1000; - public: MergeIdCollectionStage (MergeState& state, Collection& (CSMWorld::Data::*accessor)()); @@ -56,16 +54,7 @@ namespace CSMTools template int MergeIdCollectionStage::setup() { - const Collection& source = (mState.mSource.getData().*mAccessor)(); - - int size = source.getSize(); - - int steps = size / stepSize; - - if (size % stepSize) - ++steps; - - return steps; + return (mState.mSource.getData().*mAccessor)().getSize(); } template @@ -74,16 +63,10 @@ namespace CSMTools const Collection& source = (mState.mSource.getData().*mAccessor)(); Collection& target = (mState.mTarget->getData().*mAccessor)(); - int begin = stage * stepSize; - int end = std::min ((stage+1) * stepSize, source.getSize()); + const CSMWorld::Record& record = source.getRecord (stage); - for (int i=begin; i& record = source.getRecord (i); - - if (!record.isDeleted()) - target.appendRecord (CSMWorld::Record (CSMWorld::RecordBase::State_BaseOnly, &record.get())); - } + if (!record.isDeleted()) + target.appendRecord (CSMWorld::Record (CSMWorld::RecordBase::State_BaseOnly, &record.get())); } } From 81188a345639903c0ea301fab3a8856a40825106 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 25 Aug 2015 11:39:43 +0200 Subject: [PATCH 20/81] silenced a warning (cherry picked from commit 9cf793c0b519143fd7d3ac3cfb7beb82f65b72f3) Conflicts: apps/opencs/model/doc/document.cpp --- apps/opencs/model/doc/document.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 55034cb4ea..925eef659e 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2258,7 +2258,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, mSaving (&mSavingOperation), mResDir(resDir), mRunner (mProjectPath), mPhysics(boost::shared_ptr()), - mIdCompletionManager(mData), mDirty (false) + mDirty (false), mIdCompletionManager(mData) { if (mContentFiles.empty()) throw std::runtime_error ("Empty content file sequence"); From 9230c62884d54722ed35962afc162162a7fb54fa Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 25 Aug 2015 11:54:16 +0200 Subject: [PATCH 21/81] merge referenceables table (cherry picked from commit f95950e8d815997da34eb9939b81cd27afb62dbb) --- apps/opencs/model/tools/mergeoperation.cpp | 3 ++- apps/opencs/model/tools/mergestages.cpp | 14 ++++++++++++++ apps/opencs/model/tools/mergestages.hpp | 16 ++++++++++++++++ apps/opencs/model/world/refidcollection.cpp | 5 +++++ apps/opencs/model/world/refidcollection.hpp | 1 + apps/opencs/model/world/refiddata.cpp | 11 +++++++++++ apps/opencs/model/world/refiddata.hpp | 6 ++---- 7 files changed, 51 insertions(+), 5 deletions(-) diff --git a/apps/opencs/model/tools/mergeoperation.cpp b/apps/opencs/model/tools/mergeoperation.cpp index d010e343b7..0f128e86e9 100644 --- a/apps/opencs/model/tools/mergeoperation.cpp +++ b/apps/opencs/model/tools/mergeoperation.cpp @@ -34,8 +34,9 @@ CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document, ToUTF8::Fr appendStage (new MergeIdCollectionStage > (mState, &CSMWorld::Data::getPathgrids)); appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getTopicInfos)); appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getJournalInfos)); + appendStage (new MergeRefIdsStage (mState)); - /// \todo Referencables, References, Land, LandTextures + /// \todo References, Land, LandTextures } void CSMTools::MergeOperation::setTarget (std::auto_ptr document) diff --git a/apps/opencs/model/tools/mergestages.cpp b/apps/opencs/model/tools/mergestages.cpp index 776808b269..d8bd93824c 100644 --- a/apps/opencs/model/tools/mergestages.cpp +++ b/apps/opencs/model/tools/mergestages.cpp @@ -39,3 +39,17 @@ void CSMTools::FinishMergedDocumentStage::perform (int stage, CSMDoc::Messages& mState.mCompleted = true; } + + +CSMTools::MergeRefIdsStage::MergeRefIdsStage (MergeState& state) : mState (state) {} + +int CSMTools::MergeRefIdsStage::setup() +{ + return mState.mSource.getData().getReferenceables().getSize(); +} + +void CSMTools::MergeRefIdsStage::perform (int stage, CSMDoc::Messages& messages) +{ + mState.mSource.getData().getReferenceables().copyTo ( + stage, mState.mTarget->getData().getReferenceables()); +} diff --git a/apps/opencs/model/tools/mergestages.hpp b/apps/opencs/model/tools/mergestages.hpp index c0ed167876..308ebe1c35 100644 --- a/apps/opencs/model/tools/mergestages.hpp +++ b/apps/opencs/model/tools/mergestages.hpp @@ -68,6 +68,22 @@ namespace CSMTools if (!record.isDeleted()) target.appendRecord (CSMWorld::Record (CSMWorld::RecordBase::State_BaseOnly, &record.get())); } + + + class MergeRefIdsStage : public CSMDoc::Stage + { + MergeState& mState; + + public: + + MergeRefIdsStage (MergeState& state); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, CSMDoc::Messages& messages); + ///< Messages resulting from this stage will be appended to \a messages. + }; } #endif diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index 8ea2bb30a1..3644fc264b 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -924,3 +924,8 @@ const CSMWorld::NestedRefIdAdapterBase& CSMWorld::RefIdCollection::getNestedAdap } throw std::runtime_error("No such column in the nestedadapters"); } + +void CSMWorld::RefIdCollection::copyTo (int index, RefIdCollection& target) const +{ + mData.copyTo (index, target.mData); +} diff --git a/apps/opencs/model/world/refidcollection.hpp b/apps/opencs/model/world/refidcollection.hpp index e8e6336635..4db39348e3 100644 --- a/apps/opencs/model/world/refidcollection.hpp +++ b/apps/opencs/model/world/refidcollection.hpp @@ -140,6 +140,7 @@ namespace CSMWorld void save (int index, ESM::ESMWriter& writer) const; const RefIdData& getDataSet() const; //I can't figure out a better name for this one :( + void copyTo (int index, RefIdCollection& target) const; }; } diff --git a/apps/opencs/model/world/refiddata.cpp b/apps/opencs/model/world/refiddata.cpp index c391201e6d..a7dc955194 100644 --- a/apps/opencs/model/world/refiddata.cpp +++ b/apps/opencs/model/world/refiddata.cpp @@ -357,3 +357,14 @@ void CSMWorld::RefIdData::insertRecord(CSMWorld::RecordBase& record, CSMWorld::U mIndex.insert (std::make_pair (Misc::StringUtils::lowerCase (id), LocalIndex (iter->second->getSize()-1, type))); } + +void CSMWorld::RefIdData::copyTo (int index, RefIdData& target) const +{ + LocalIndex localIndex = globalToLocalIndex (index); + + RefIdDataContainerBase *source = mRecordContainers.find (localIndex.second)->second; + + std::string id = source->getId (localIndex.first); + + target.insertRecord (source->getRecord (localIndex.first), localIndex.second, id); +} diff --git a/apps/opencs/model/world/refiddata.hpp b/apps/opencs/model/world/refiddata.hpp index 85d16a6eb2..4507f6028d 100644 --- a/apps/opencs/model/world/refiddata.hpp +++ b/apps/opencs/model/world/refiddata.hpp @@ -252,11 +252,9 @@ namespace CSMWorld const RefIdDataContainer& getProbes() const; const RefIdDataContainer& getRepairs() const; const RefIdDataContainer& getStatics() const; + + void copyTo (int index, RefIdData& target) const; }; } #endif - - - - From 62daecadf57081140e15e24ec4460499e9059b00 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 25 Aug 2015 12:40:40 +0200 Subject: [PATCH 22/81] fixed record state issues after merge (cherry picked from commit 845cafd61c12142a353119a6304845370037d7a5) --- apps/opencs/model/tools/mergestages.hpp | 2 +- apps/opencs/model/world/refiddata.cpp | 7 +++++-- apps/opencs/model/world/refiddata.hpp | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/tools/mergestages.hpp b/apps/opencs/model/tools/mergestages.hpp index 308ebe1c35..5c2243d438 100644 --- a/apps/opencs/model/tools/mergestages.hpp +++ b/apps/opencs/model/tools/mergestages.hpp @@ -66,7 +66,7 @@ namespace CSMTools const CSMWorld::Record& record = source.getRecord (stage); if (!record.isDeleted()) - target.appendRecord (CSMWorld::Record (CSMWorld::RecordBase::State_BaseOnly, &record.get())); + target.appendRecord (CSMWorld::Record (CSMWorld::RecordBase::State_ModifiedOnly, 0, &record.get())); } diff --git a/apps/opencs/model/world/refiddata.cpp b/apps/opencs/model/world/refiddata.cpp index a7dc955194..7696c3763b 100644 --- a/apps/opencs/model/world/refiddata.cpp +++ b/apps/opencs/model/world/refiddata.cpp @@ -1,6 +1,7 @@ #include "refiddata.hpp" #include +#include #include @@ -344,7 +345,7 @@ const CSMWorld::RefIdDataContainer< ESM::Static >& CSMWorld::RefIdData::getStati return mStatics; } -void CSMWorld::RefIdData::insertRecord(CSMWorld::RecordBase& record, CSMWorld::UniversalId::Type type, const std::string& id) +void CSMWorld::RefIdData::insertRecord (CSMWorld::RecordBase& record, CSMWorld::UniversalId::Type type, const std::string& id) { std::map::iterator iter = mRecordContainers.find (type); @@ -366,5 +367,7 @@ void CSMWorld::RefIdData::copyTo (int index, RefIdData& target) const std::string id = source->getId (localIndex.first); - target.insertRecord (source->getRecord (localIndex.first), localIndex.second, id); + std::auto_ptr newRecord (source->getRecord (localIndex.first).modifiedCopy()); + + target.insertRecord (*newRecord, localIndex.second, id); } diff --git a/apps/opencs/model/world/refiddata.hpp b/apps/opencs/model/world/refiddata.hpp index 4507f6028d..8909ae4fb0 100644 --- a/apps/opencs/model/world/refiddata.hpp +++ b/apps/opencs/model/world/refiddata.hpp @@ -210,7 +210,8 @@ namespace CSMWorld void erase (int index, int count); - void insertRecord(CSMWorld::RecordBase& record, CSMWorld::UniversalId::Type type, const std::string& id); + void insertRecord (CSMWorld::RecordBase& record, CSMWorld::UniversalId::Type type, + const std::string& id); const RecordBase& getRecord (const LocalIndex& index) const; From 73ab89bf70f53ef7f5d2e9417d15f703a91794d6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 26 Aug 2015 17:21:24 +0200 Subject: [PATCH 23/81] merge references tables (cherry picked from commit a97a632aa76c3b7499ae170b689676d2f32b8550) --- apps/opencs/model/tools/mergeoperation.cpp | 3 +- apps/opencs/model/tools/mergestages.cpp | 34 ++++++++++++++++++++++ apps/opencs/model/tools/mergestages.hpp | 18 +++++++++++- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/tools/mergeoperation.cpp b/apps/opencs/model/tools/mergeoperation.cpp index 0f128e86e9..f9a89aaa16 100644 --- a/apps/opencs/model/tools/mergeoperation.cpp +++ b/apps/opencs/model/tools/mergeoperation.cpp @@ -35,8 +35,9 @@ CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document, ToUTF8::Fr appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getTopicInfos)); appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getJournalInfos)); appendStage (new MergeRefIdsStage (mState)); + appendStage (new MergeReferencesStage (mState)); - /// \todo References, Land, LandTextures + /// \todo Land, LandTextures } void CSMTools::MergeOperation::setTarget (std::auto_ptr document) diff --git a/apps/opencs/model/tools/mergestages.cpp b/apps/opencs/model/tools/mergestages.cpp index d8bd93824c..80f16ec146 100644 --- a/apps/opencs/model/tools/mergestages.cpp +++ b/apps/opencs/model/tools/mergestages.cpp @@ -1,6 +1,8 @@ #include "mergestages.hpp" +#include + #include "mergestate.hpp" #include "../doc/document.hpp" @@ -53,3 +55,35 @@ void CSMTools::MergeRefIdsStage::perform (int stage, CSMDoc::Messages& messages) mState.mSource.getData().getReferenceables().copyTo ( stage, mState.mTarget->getData().getReferenceables()); } + + +CSMTools::MergeReferencesStage::MergeReferencesStage (MergeState& state) +: mState (state) +{} + +int CSMTools::MergeReferencesStage::setup() +{ + mIndex.clear(); + return mState.mSource.getData().getReferences().getSize(); +} + +void CSMTools::MergeReferencesStage::perform (int stage, CSMDoc::Messages& messages) +{ + const CSMWorld::Record& record = + mState.mSource.getData().getReferences().getRecord (stage); + + if (!record.isDeleted()) + { + CSMWorld::CellRef ref = record.get(); + + ref.mOriginalCell = ref.mCell; + + ref.mRefNum.mIndex = mIndex[Misc::StringUtils::lowerCase (ref.mCell)]++; + ref.mRefNum.mContentFile = 0; + + CSMWorld::Record newRecord ( + CSMWorld::RecordBase::State_ModifiedOnly, 0, &ref); + + mState.mTarget->getData().getReferences().appendRecord (newRecord); + } +} diff --git a/apps/opencs/model/tools/mergestages.hpp b/apps/opencs/model/tools/mergestages.hpp index 5c2243d438..e1cc17a3e6 100644 --- a/apps/opencs/model/tools/mergestages.hpp +++ b/apps/opencs/model/tools/mergestages.hpp @@ -2,6 +2,7 @@ #define CSM_TOOLS_MERGESTAGES_H #include +#include #include @@ -69,7 +70,6 @@ namespace CSMTools target.appendRecord (CSMWorld::Record (CSMWorld::RecordBase::State_ModifiedOnly, 0, &record.get())); } - class MergeRefIdsStage : public CSMDoc::Stage { MergeState& mState; @@ -84,6 +84,22 @@ namespace CSMTools virtual void perform (int stage, CSMDoc::Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; + + class MergeReferencesStage : public CSMDoc::Stage + { + MergeState& mState; + std::map mIndex; + + public: + + MergeReferencesStage (MergeState& state); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, CSMDoc::Messages& messages); + ///< Messages resulting from this stage will be appended to \a messages. + }; } #endif From e5038cbece18f4be320dfdffddcd046fe97e29d4 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 30 Aug 2015 11:08:56 +0200 Subject: [PATCH 24/81] fixed merge stage order; added proper initialisation (cherry picked from commit b7983d08ba3f238f0cddad467049c87b17a3745f) --- apps/opencs/model/tools/mergeoperation.cpp | 5 ++++- apps/opencs/model/tools/mergestages.cpp | 17 +++++++++++++++++ apps/opencs/model/tools/mergestages.hpp | 15 +++++++++++++++ apps/opencs/model/tools/mergestate.hpp | 2 ++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/tools/mergeoperation.cpp b/apps/opencs/model/tools/mergeoperation.cpp index f9a89aaa16..89f22ef1a6 100644 --- a/apps/opencs/model/tools/mergeoperation.cpp +++ b/apps/opencs/model/tools/mergeoperation.cpp @@ -9,7 +9,8 @@ CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document, ToUTF8::FromType encoding) : CSMDoc::Operation (CSMDoc::State_Merging, true), mState (document) { - appendStage (new FinishMergedDocumentStage (mState, encoding)); + appendStage (new StartMergeStage (mState)); + appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getGlobals)); appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getGmsts)); appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getSkills)); @@ -37,6 +38,8 @@ CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document, ToUTF8::Fr appendStage (new MergeRefIdsStage (mState)); appendStage (new MergeReferencesStage (mState)); + appendStage (new FinishMergedDocumentStage (mState, encoding)); + /// \todo Land, LandTextures } diff --git a/apps/opencs/model/tools/mergestages.cpp b/apps/opencs/model/tools/mergestages.cpp index 80f16ec146..349cc29259 100644 --- a/apps/opencs/model/tools/mergestages.cpp +++ b/apps/opencs/model/tools/mergestages.cpp @@ -8,6 +8,23 @@ #include "../doc/document.hpp" #include "../world/data.hpp" + +CSMTools::StartMergeStage::StartMergeStage (MergeState& state) +: mState (state) +{} + +int CSMTools::StartMergeStage::setup() +{ + return 1; +} + +void CSMTools::StartMergeStage::perform (int stage, CSMDoc::Messages& messages) +{ + mState.mCompleted = false; + mState.mTextureIndices.clear(); +} + + CSMTools::FinishMergedDocumentStage::FinishMergedDocumentStage (MergeState& state, ToUTF8::FromType encoding) : mState (state), mEncoder (encoding) {} diff --git a/apps/opencs/model/tools/mergestages.hpp b/apps/opencs/model/tools/mergestages.hpp index e1cc17a3e6..7d62058f00 100644 --- a/apps/opencs/model/tools/mergestages.hpp +++ b/apps/opencs/model/tools/mergestages.hpp @@ -14,6 +14,21 @@ namespace CSMTools { + class StartMergeStage : public CSMDoc::Stage + { + MergeState& mState; + + public: + + StartMergeStage (MergeState& state); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, CSMDoc::Messages& messages); + ///< Messages resulting from this stage will be appended to \a messages. + }; + class FinishMergedDocumentStage : public CSMDoc::Stage { MergeState& mState; diff --git a/apps/opencs/model/tools/mergestate.hpp b/apps/opencs/model/tools/mergestate.hpp index 4482ba6f4a..077edc9d9d 100644 --- a/apps/opencs/model/tools/mergestate.hpp +++ b/apps/opencs/model/tools/mergestate.hpp @@ -2,6 +2,7 @@ #define CSM_TOOLS_MERGESTATE_H #include +#include #include "../doc/document.hpp" @@ -12,6 +13,7 @@ namespace CSMTools std::auto_ptr mTarget; CSMDoc::Document& mSource; bool mCompleted; + std::map, int> mTextureIndices; // (texture, content file) -> new texture MergeState (CSMDoc::Document& source) : mSource (source), mCompleted (false) {} }; From a2d4957d2af1b18147f7c563b3b764b01d2ebc2c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 30 Aug 2015 14:27:22 +0200 Subject: [PATCH 25/81] merge land texture tables (cherry picked from commit 890bbb6b119bab1b9a7b5724ab3e6a769ede761a) --- apps/opencs/model/tools/mergeoperation.cpp | 5 +- apps/opencs/model/tools/mergestages.cpp | 79 ++++++++++++++++++++++ apps/opencs/model/tools/mergestages.hpp | 31 +++++++++ apps/opencs/model/tools/mergestate.hpp | 4 +- apps/opencs/model/world/data.cpp | 5 ++ apps/opencs/model/world/data.hpp | 2 + 6 files changed, 124 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/tools/mergeoperation.cpp b/apps/opencs/model/tools/mergeoperation.cpp index 89f22ef1a6..9e791683cc 100644 --- a/apps/opencs/model/tools/mergeoperation.cpp +++ b/apps/opencs/model/tools/mergeoperation.cpp @@ -37,10 +37,13 @@ CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document, ToUTF8::Fr appendStage (new MergeIdCollectionStage (mState, &CSMWorld::Data::getJournalInfos)); appendStage (new MergeRefIdsStage (mState)); appendStage (new MergeReferencesStage (mState)); + appendStage (new MergeReferencesStage (mState)); + appendStage (new ListLandTexturesMergeStage (mState)); + appendStage (new MergeLandTexturesStage (mState)); appendStage (new FinishMergedDocumentStage (mState, encoding)); - /// \todo Land, LandTextures + /// \todo Land } void CSMTools::MergeOperation::setTarget (std::auto_ptr document) diff --git a/apps/opencs/model/tools/mergestages.cpp b/apps/opencs/model/tools/mergestages.cpp index 349cc29259..f34ba8eb41 100644 --- a/apps/opencs/model/tools/mergestages.cpp +++ b/apps/opencs/model/tools/mergestages.cpp @@ -1,6 +1,8 @@ #include "mergestages.hpp" +#include + #include #include "mergestate.hpp" @@ -104,3 +106,80 @@ void CSMTools::MergeReferencesStage::perform (int stage, CSMDoc::Messages& messa mState.mTarget->getData().getReferences().appendRecord (newRecord); } } + + +CSMTools::ListLandTexturesMergeStage::ListLandTexturesMergeStage (MergeState& state) +: mState (state) +{} + +int CSMTools::ListLandTexturesMergeStage::setup() +{ + return mState.mSource.getData().getLand().getSize(); +} + +void CSMTools::ListLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& messages) +{ + const CSMWorld::Record& record = + mState.mSource.getData().getLand().getRecord (stage); + + if (!record.isDeleted()) + { + ESM::Land& land = *record.get().mLand; + + // make sure record is loaded + land.loadData (ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | + ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM); + + if (land.mLandData) + { + // list texture indices + std::pair key; + key.second = land.mPlugin; + + for (int i=0; imTextures[i]; + + mState.mTextureIndices[key] = -1; + } + } + } +} + + +CSMTools::MergeLandTexturesStage::MergeLandTexturesStage (MergeState& state) +: mState (state), mNext (mState.mTextureIndices.end()) +{} + +int CSMTools::MergeLandTexturesStage::setup() +{ + mNext = mState.mTextureIndices.begin(); + return mState.mTextureIndices.size(); +} + +void CSMTools::MergeLandTexturesStage::perform (int stage, CSMDoc::Messages& messages) +{ + mNext->second = stage; + + std::ostringstream stream; + stream << mNext->first.first << "_" << mNext->first.second; + + int index = mState.mSource.getData().getLandTextures().searchId (stream.str()); + + if (index!=-1) + { + CSMWorld::LandTexture texture = + mState.mSource.getData().getLandTextures().getRecord (index).get(); + + texture.mIndex = mNext->second; + texture.mId = stream.str(); + + CSMWorld::Record newRecord ( + CSMWorld::RecordBase::State_ModifiedOnly, 0, &texture); + + mState.mTarget->getData().getLandTextures().appendRecord (newRecord); + } + /// \todo deal with missing textures (either abort merge or report and make sure OpenMW can deal with missing textures) + + ++mNext; +} diff --git a/apps/opencs/model/tools/mergestages.hpp b/apps/opencs/model/tools/mergestages.hpp index 7d62058f00..f0ae99842c 100644 --- a/apps/opencs/model/tools/mergestages.hpp +++ b/apps/opencs/model/tools/mergestages.hpp @@ -115,6 +115,37 @@ namespace CSMTools virtual void perform (int stage, CSMDoc::Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; + + class ListLandTexturesMergeStage : public CSMDoc::Stage + { + MergeState& mState; + + public: + + ListLandTexturesMergeStage (MergeState& state); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, CSMDoc::Messages& messages); + ///< Messages resulting from this stage will be appended to \a messages. + }; + + class MergeLandTexturesStage : public CSMDoc::Stage + { + MergeState& mState; + std::map, int>::iterator mNext; + + public: + + MergeLandTexturesStage (MergeState& state); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, CSMDoc::Messages& messages); + ///< Messages resulting from this stage will be appended to \a messages. + }; } #endif diff --git a/apps/opencs/model/tools/mergestate.hpp b/apps/opencs/model/tools/mergestate.hpp index 077edc9d9d..29e1bbda72 100644 --- a/apps/opencs/model/tools/mergestate.hpp +++ b/apps/opencs/model/tools/mergestate.hpp @@ -1,6 +1,8 @@ #ifndef CSM_TOOLS_MERGESTATE_H #define CSM_TOOLS_MERGESTATE_H +#include + #include #include @@ -13,7 +15,7 @@ namespace CSMTools std::auto_ptr mTarget; CSMDoc::Document& mSource; bool mCompleted; - std::map, int> mTextureIndices; // (texture, content file) -> new texture + std::map, int> mTextureIndices; // (texture, content file) -> new texture MergeState (CSMDoc::Document& source) : mSource (source), mCompleted (false) {} }; diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index b5722ab57a..c78cc383c6 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -878,6 +878,11 @@ const CSMWorld::IdCollection& CSMWorld::Data::getLandText return mLandTextures; } +CSMWorld::IdCollection& CSMWorld::Data::getLandTextures() +{ + return mLandTextures; +} + const CSMWorld::IdCollection& CSMWorld::Data::getSoundGens() const { return mSoundGens; diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index c9fe956b13..97be947dcc 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -226,6 +226,8 @@ namespace CSMWorld const IdCollection& getLandTextures() const; + IdCollection& getLandTextures(); + const IdCollection& getSoundGens() const; IdCollection& getSoundGens(); From 35c4af9476a0ddc06eaa9058b466699e57f34fb9 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 31 Aug 2015 11:06:32 +0200 Subject: [PATCH 26/81] added copy constructor and assignment operator for Land record struct (cherry picked from commit b0641934d4a34b4e462932aa715cc0ca9d854cae) --- components/esm/loadland.cpp | 27 +++++++++++++++++++++++++++ components/esm/loadland.hpp | 8 ++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index b0897ec67d..baeca34de1 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -1,5 +1,7 @@ #include "loadland.hpp" +#include + #include "esmreader.hpp" #include "esmwriter.hpp" #include "defs.hpp" @@ -215,4 +217,29 @@ bool Land::isDataLoaded(int flags) const return (mDataLoaded & flags) == (flags & mDataTypes); } + Land::Land (const Land& land) + : mFlags (land.mFlags), mX (land.mX), mY (land.mY), mPlugin (land.mPlugin), + mEsm (land.mEsm), mContext (land.mContext), mDataTypes (land.mDataTypes), + mDataLoaded (land.mDataLoaded), + mLandData (land.mLandData ? new LandData (*land.mLandData) : 0) + {} + + Land& Land::operator= (Land land) + { + swap (land); + return *this; + } + + void Land::swap (Land& land) + { + std::swap (mFlags, land.mFlags); + std::swap (mX, land.mX); + std::swap (mY, land.mY); + std::swap (mPlugin, land.mPlugin); + std::swap (mEsm, land.mEsm); + std::swap (mContext, land.mContext); + std::swap (mDataTypes, land.mDataTypes); + std::swap (mDataLoaded, land.mDataLoaded); + std::swap (mLandData, land.mLandData); + } } diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index 7dc5e8adb3..b3d27293a2 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -116,9 +116,13 @@ struct Land /// @note We only check data types that *can* be loaded (present in mDataTypes) bool isDataLoaded(int flags) const; + Land (const Land& land); + + Land& operator= (Land land); + + void swap (Land& land); + private: - Land(const Land& land); - Land& operator=(const Land& land); /// Loads data and marks it as loaded /// \return true if data is actually loaded from file, false otherwise From 8cb1f4ffe9cf95acaad3b6136847505212c77330 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 31 Aug 2015 11:10:58 +0200 Subject: [PATCH 27/81] additional safety check for land texture listing merge stage (cherry picked from commit 69045d7ec9d293f2bb5626b2ac4a8517a0cf67e4) --- apps/opencs/model/tools/mergestages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/tools/mergestages.cpp b/apps/opencs/model/tools/mergestages.cpp index f34ba8eb41..a4072e4bce 100644 --- a/apps/opencs/model/tools/mergestages.cpp +++ b/apps/opencs/model/tools/mergestages.cpp @@ -130,7 +130,7 @@ void CSMTools::ListLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& land.loadData (ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM); - if (land.mLandData) + if (land.mLandData && land.mDataLoaded & ESM::Land::DATA_VTEX) { // list texture indices std::pair key; From 44020df65f29551dd50956c39902709fa08c5a72 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 31 Aug 2015 14:17:11 +0200 Subject: [PATCH 28/81] made return type of ESMTerrain::Storage::getLand const (cherry picked from commit febf611c827a257a4d4000b601f9ef413f2f8012) --- apps/opencs/view/render/terrainstorage.cpp | 2 +- apps/opencs/view/render/terrainstorage.hpp | 2 +- apps/openmw/mwrender/terrainstorage.cpp | 2 +- apps/openmw/mwrender/terrainstorage.hpp | 2 +- components/esmterrain/storage.cpp | 10 +++++----- components/esmterrain/storage.hpp | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/opencs/view/render/terrainstorage.cpp b/apps/opencs/view/render/terrainstorage.cpp index 9998daeeee..da962313ae 100644 --- a/apps/opencs/view/render/terrainstorage.cpp +++ b/apps/opencs/view/render/terrainstorage.cpp @@ -8,7 +8,7 @@ namespace CSVRender { } - ESM::Land* TerrainStorage::getLand(int cellX, int cellY) + const ESM::Land* TerrainStorage::getLand(int cellX, int cellY) { std::ostringstream stream; stream << "#" << cellX << " " << cellY; diff --git a/apps/opencs/view/render/terrainstorage.hpp b/apps/opencs/view/render/terrainstorage.hpp index 97782ad17e..16b0f3ec7a 100644 --- a/apps/opencs/view/render/terrainstorage.hpp +++ b/apps/opencs/view/render/terrainstorage.hpp @@ -18,7 +18,7 @@ namespace CSVRender private: const CSMWorld::Data& mData; - virtual ESM::Land* getLand (int cellX, int cellY); + virtual const ESM::Land* getLand (int cellX, int cellY); virtual const ESM::LandTexture* getLandTexture(int index, short plugin); virtual void getBounds(float& minX, float& maxX, float& minY, float& maxY); diff --git a/apps/openmw/mwrender/terrainstorage.cpp b/apps/openmw/mwrender/terrainstorage.cpp index 8ad2ea3213..2808187a10 100644 --- a/apps/openmw/mwrender/terrainstorage.cpp +++ b/apps/openmw/mwrender/terrainstorage.cpp @@ -50,7 +50,7 @@ namespace MWRender maxY += 1; } - ESM::Land* TerrainStorage::getLand(int cellX, int cellY) + const ESM::Land* TerrainStorage::getLand(int cellX, int cellY) { const MWWorld::ESMStore &esmStore = MWBase::Environment::get().getWorld()->getStore(); diff --git a/apps/openmw/mwrender/terrainstorage.hpp b/apps/openmw/mwrender/terrainstorage.hpp index e6f4a04ad3..4aa5a188e6 100644 --- a/apps/openmw/mwrender/terrainstorage.hpp +++ b/apps/openmw/mwrender/terrainstorage.hpp @@ -10,7 +10,7 @@ namespace MWRender class TerrainStorage : public ESMTerrain::Storage { private: - virtual ESM::Land* getLand (int cellX, int cellY); + virtual const ESM::Land* getLand (int cellX, int cellY); virtual const ESM::LandTexture* getLandTexture(int index, short plugin); public: diff --git a/components/esmterrain/storage.cpp b/components/esmterrain/storage.cpp index 763f0f4e05..20692f53a7 100644 --- a/components/esmterrain/storage.cpp +++ b/components/esmterrain/storage.cpp @@ -72,7 +72,7 @@ namespace ESMTerrain --cellX; row += ESM::Land::LAND_SIZE-1; } - ESM::Land* land = getLand(cellX, cellY); + const ESM::Land* land = getLand(cellX, cellY); if (land && land->mDataTypes&ESM::Land::DATA_VNML) { normal.x = land->mLandData->mNormals[col*ESM::Land::LAND_SIZE*3+row*3]; @@ -107,7 +107,7 @@ namespace ESMTerrain ++cellX; row = 0; } - ESM::Land* land = getLand(cellX, cellY); + const ESM::Land* land = getLand(cellX, cellY); if (land && land->mDataTypes&ESM::Land::DATA_VCLR) { color.r = land->mLandData->mColours[col*ESM::Land::LAND_SIZE*3+row*3] / 255.f; @@ -156,7 +156,7 @@ namespace ESMTerrain float vertX_ = 0; // of current cell corner for (int cellX = startX; cellX < startX + std::ceil(size); ++cellX) { - ESM::Land* land = getLand(cellX, cellY); + const ESM::Land* land = getLand(cellX, cellY); if (land && !(land->mDataTypes&ESM::Land::DATA_VHGT)) land = NULL; @@ -261,7 +261,7 @@ namespace ESMTerrain assert(xmDataTypes&ESM::Land::DATA_VTEX)) { int tex = land->mLandData->mTextures[y * ESM::Land::LAND_TEXTURE_SIZE + x]; @@ -382,7 +382,7 @@ namespace ESMTerrain int cellX = static_cast(std::floor(worldPos.x / 8192.f)); int cellY = static_cast(std::floor(worldPos.y / 8192.f)); - ESM::Land* land = getLand(cellX, cellY); + const ESM::Land* land = getLand(cellX, cellY); if (!land || !(land->mDataTypes&ESM::Land::DATA_VHGT)) return -2048; diff --git a/components/esmterrain/storage.hpp b/components/esmterrain/storage.hpp index e184cbc4cd..698bcf99c9 100644 --- a/components/esmterrain/storage.hpp +++ b/components/esmterrain/storage.hpp @@ -16,7 +16,7 @@ namespace ESMTerrain private: // Not implemented in this class, because we need different Store implementations for game and editor - virtual ESM::Land* getLand (int cellX, int cellY) = 0; + virtual const ESM::Land* getLand (int cellX, int cellY) = 0; virtual const ESM::LandTexture* getLandTexture(int index, short plugin) = 0; public: From 4f24c6a7c88ea47b30867175887b64e324f1337a Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 1 Nov 2015 17:07:40 +1100 Subject: [PATCH 29/81] more const-ness fixes --- apps/opencs/view/world/physicssystem.cpp | 2 +- apps/opencs/view/world/physicssystem.hpp | 2 +- apps/openmw/mwworld/physicssystem.cpp | 2 +- apps/openmw/mwworld/physicssystem.hpp | 2 +- libs/openengine/bullet/physic.cpp | 2 +- libs/openengine/bullet/physic.hpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/opencs/view/world/physicssystem.cpp b/apps/opencs/view/world/physicssystem.cpp index 891b175d5e..7dce611c48 100644 --- a/apps/opencs/view/world/physicssystem.cpp +++ b/apps/opencs/view/world/physicssystem.cpp @@ -181,7 +181,7 @@ namespace CSVWorld } void PhysicsSystem::addHeightField(Ogre::SceneManager *sceneManager, - float* heights, int x, int y, float yoffset, float triSize, float sqrtVerts) + const float* heights, int x, int y, float yoffset, float triSize, float sqrtVerts) { std::string name = "HeightField_" + QString::number(x).toStdString() + "_" + QString::number(y).toStdString(); diff --git a/apps/opencs/view/world/physicssystem.hpp b/apps/opencs/view/world/physicssystem.hpp index 0036bf769d..17661caa80 100644 --- a/apps/opencs/view/world/physicssystem.hpp +++ b/apps/opencs/view/world/physicssystem.hpp @@ -63,7 +63,7 @@ namespace CSVWorld void moveSceneNodes(const std::string sceneNodeName, const Ogre::Vector3 &position); void addHeightField(Ogre::SceneManager *sceneManager, - float* heights, int x, int y, float yoffset, float triSize, float sqrtVerts); + const float* heights, int x, int y, float yoffset, float triSize, float sqrtVerts); void removeHeightField(Ogre::SceneManager *sceneManager, int x, int y); diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index bec4c6db32..50212afea9 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -660,7 +660,7 @@ namespace MWWorld return MovementSolver::traceDown(ptr, mEngine, maxHeight); } - void PhysicsSystem::addHeightField (float* heights, + void PhysicsSystem::addHeightField (const float* heights, int x, int y, float yoffset, float triSize, float sqrtVerts) { diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index c1046aacb4..21d712109c 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -42,7 +42,7 @@ namespace MWWorld void addActor (const MWWorld::Ptr& ptr, const std::string& mesh); - void addHeightField (float* heights, + void addHeightField (const float* heights, int x, int y, float yoffset, float triSize, float sqrtVerts); diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 15be7665a8..44a928121e 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -363,7 +363,7 @@ namespace Physic //delete BulletShapeManager::getSingletonPtr(); } - void PhysicEngine::addHeightField(float* heights, + void PhysicEngine::addHeightField(const float* heights, int x, int y, float yoffset, float triSize, float sqrtVerts) { diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 7784e8941d..2c7ac8f053 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -227,7 +227,7 @@ namespace Physic /** * Add a HeightField to the simulation */ - void addHeightField(float* heights, + void addHeightField(const float* heights, int x, int y, float yoffset, float triSize, float sqrtVerts); From c4b34a077ebd118606b6a09d516162000ebd5140 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 31 Aug 2015 16:13:26 +0200 Subject: [PATCH 30/81] refactored loading of land data (cherry picked from commit 69b9eadb52cf24398d64b6399341d9e6b5d40bdf) Conflicts: apps/openmw/mwworld/scene.cpp components/esmterrain/storage.cpp --- apps/esmtool/record.cpp | 14 +--- apps/opencs/model/doc/savingstages.cpp | 5 +- apps/opencs/model/tools/mergestages.cpp | 4 +- apps/openmw/mwrender/globalmap.cpp | 8 +- apps/openmw/mwworld/scene.cpp | 14 +--- components/esm/loadland.cpp | 22 +++++- components/esm/loadland.hpp | 23 ++++-- components/esmterrain/storage.cpp | 97 ++++++++++++++----------- components/esmterrain/storage.hpp | 7 +- 9 files changed, 111 insertions(+), 83 deletions(-) diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index 2ee6c54bbf..76c14e728d 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -841,19 +841,13 @@ void Record::print() std::cout << " Flags: " << landFlags(mData.mFlags) << std::endl; std::cout << " DataTypes: " << mData.mDataTypes << std::endl; - // Seems like this should done with reference counting in the - // loader to me. But I'm not really knowledgable about this - // record type yet. --Cory - bool wasLoaded = (mData.mDataLoaded != 0); - if (mData.mDataTypes) mData.loadData(mData.mDataTypes); - if (mData.mDataLoaded) + if (const ESM::Land::LandData *data = mData.getLandData (mData.mDataTypes)) { - std::cout << " Height Offset: " << mData.mLandData->mHeightOffset << std::endl; + std::cout << " Height Offset: " << data->mHeightOffset << std::endl; // Lots of missing members. - std::cout << " Unknown1: " << mData.mLandData->mUnk1 << std::endl; - std::cout << " Unknown2: " << mData.mLandData->mUnk2 << std::endl; + std::cout << " Unknown1: " << data->mUnk1 << std::endl; + std::cout << " Unknown2: " << data->mUnk2 << std::endl; } - if (!wasLoaded) mData.unloadData(); } template<> diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 01d260d681..62ac48805a 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -420,8 +420,9 @@ void CSMDoc::WriteLandCollectionStage::perform (int stage, Messages& messages) mState.getWriter().startRecord (record.mLand->sRecordId); record.mLand->save (mState.getWriter()); - if(record.mLand->mLandData) - record.mLand->mLandData->save (mState.getWriter()); + + if (const ESM::Land::LandData *data = record.mLand->getLandData (record.mLand->mDataTypes)) + data->save (mState.getWriter()); mState.getWriter().endRecord (record.mLand->sRecordId); } diff --git a/apps/opencs/model/tools/mergestages.cpp b/apps/opencs/model/tools/mergestages.cpp index a4072e4bce..5bf0241ac2 100644 --- a/apps/opencs/model/tools/mergestages.cpp +++ b/apps/opencs/model/tools/mergestages.cpp @@ -130,7 +130,7 @@ void CSMTools::ListLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& land.loadData (ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM); - if (land.mLandData && land.mDataLoaded & ESM::Land::DATA_VTEX) + if (const ESM::Land::LandData *data = land.getLandData (ESM::Land::DATA_VTEX)) { // list texture indices std::pair key; @@ -138,7 +138,7 @@ void CSMTools::ListLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& for (int i=0; imTextures[i]; + key.first = data->mTextures[i]; mState.mTextureIndices[key] = -1; } diff --git a/apps/openmw/mwrender/globalmap.cpp b/apps/openmw/mwrender/globalmap.cpp index 90cf270497..2a1556c7c6 100644 --- a/apps/openmw/mwrender/globalmap.cpp +++ b/apps/openmw/mwrender/globalmap.cpp @@ -83,6 +83,9 @@ namespace MWRender land->loadData(mask); } + const ESM::Land::LandData *landData = + land ? land->getLandData (ESM::Land::DATA_WNAM) : 0; + for (int cellY=0; cellY(float(cellX)/float(mCellSize) * 9); int vertexY = static_cast(float(cellY) / float(mCellSize) * 9); - int texelX = (x-mMinX) * mCellSize + cellX; int texelY = (mHeight-1) - ((y-mMinY) * mCellSize + cellY); unsigned char r,g,b; float y = 0; - if (land && land->mDataTypes & ESM::Land::DATA_WNAM) - y = (land->mLandData->mWnam[vertexY * 9 + vertexX] << 4) / 2048.f; + if (landData) + y = (landData->mWnam[vertexY * 9 + vertexX] << 4) / 2048.f; else y = (SCHAR_MIN << 4) / 2048.f; if (y < 0) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index f5a9b8960d..c3daafb625 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -236,16 +236,10 @@ namespace MWWorld // Actually only VHGT is needed here, but we'll need the rest for rendering anyway. // Load everything now to reduce IO overhead. const int flags = ESM::Land::DATA_VCLR|ESM::Land::DATA_VHGT|ESM::Land::DATA_VNML|ESM::Land::DATA_VTEX; - if (!land->isDataLoaded(flags)) - land->loadData(flags); - mPhysics->addHeightField ( - land->mLandData->mHeights, - cell->getCell()->getGridX(), - cell->getCell()->getGridY(), - 0, - worldsize / (verts-1), - verts) - ; + + const ESM::Land::LandData *data = land->getLandData (flags); + mPhysics->addHeightField (data->mHeights, cell->getCell()->getGridX(), cell->getCell()->getGridY(), + 0, worldsize / (verts-1), verts); } } diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index baeca34de1..770830fddb 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -10,7 +10,7 @@ namespace ESM { unsigned int Land::sRecordId = REC_LAND; -void Land::LandData::save(ESMWriter &esm) +void Land::LandData::save(ESMWriter &esm) const { if (mDataTypes & Land::DATA_VNML) { esm.writeHNT("VNML", mNormals, sizeof(mNormals)); @@ -55,7 +55,7 @@ void Land::LandData::save(ESMWriter &esm) } } -void Land::LandData::transposeTextureData(uint16_t *in, uint16_t *out) +void Land::LandData::transposeTextureData(const uint16_t *in, uint16_t *out) { int readPos = 0; //bit ugly, but it works for ( int y1 = 0; y1 < 4; y1++ ) @@ -139,7 +139,7 @@ void Land::save(ESMWriter &esm) const esm.writeHNT("DATA", mFlags); } -void Land::loadData(int flags) +void Land::loadData(int flags) const { // Try to load only available data flags = flags & mDataTypes; @@ -201,7 +201,7 @@ void Land::unloadData() } } -bool Land::condLoad(int flags, int dataFlag, void *ptr, unsigned int size) +bool Land::condLoad(int flags, int dataFlag, void *ptr, unsigned int size) const { if ((mDataLoaded & dataFlag) == 0 && (flags & dataFlag) != 0) { mEsm->getHExact(ptr, size); @@ -242,4 +242,18 @@ bool Land::isDataLoaded(int flags) const std::swap (mDataLoaded, land.mDataLoaded); std::swap (mLandData, land.mLandData); } + + const Land::LandData *Land::getLandData (int flags) const + { + if (!(flags & mDataTypes)) + return 0; + + loadData (flags); + return mLandData; + } + + const Land::LandData *Land::getLandData() const + { + return mLandData; + } } diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index b3d27293a2..78646a5341 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -35,7 +35,6 @@ struct Land ESM_Context mContext; int mDataTypes; - int mDataLoaded; enum { @@ -91,12 +90,10 @@ struct Land short mUnk1; uint8_t mUnk2; - void save(ESMWriter &esm); - static void transposeTextureData(uint16_t *in, uint16_t *out); + void save(ESMWriter &esm) const; + static void transposeTextureData(const uint16_t *in, uint16_t *out); }; - LandData *mLandData; - void load(ESMReader &esm); void save(ESMWriter &esm) const; @@ -105,7 +102,7 @@ struct Land /** * Actually loads data */ - void loadData(int flags); + void loadData(int flags) const; /** * Frees memory allocated for land data @@ -122,12 +119,24 @@ struct Land void swap (Land& land); + /// Return land data with at least the data types specified in \a flags loaded (if they + /// are available). Will return a 0-pointer if there is no data for any of the + /// specified types. + const LandData *getLandData (int flags) const; + + /// Return land data without loading first anything. Can return a 0-pointer. + const LandData *getLandData() const; + private: /// Loads data and marks it as loaded /// \return true if data is actually loaded from file, false otherwise /// including the case when data is already loaded - bool condLoad(int flags, int dataFlag, void *ptr, unsigned int size); + bool condLoad(int flags, int dataFlag, void *ptr, unsigned int size) const; + + mutable int mDataLoaded; + + mutable LandData *mLandData; }; } diff --git a/components/esmterrain/storage.cpp b/components/esmterrain/storage.cpp index 20692f53a7..83fa858900 100644 --- a/components/esmterrain/storage.cpp +++ b/components/esmterrain/storage.cpp @@ -16,6 +16,14 @@ namespace ESMTerrain { + const ESM::Land::LandData *Storage::getLandData (int cellX, int cellY, int flags) + { + if (const ESM::Land *land = getLand (cellX, cellY)) + return land->getLandData (flags); + + return 0; + } + bool Storage::getMinMaxHeights(float size, const Ogre::Vector2 ¢er, float &min, float &max) { assert (size <= 1 && "Storage::getMinMaxHeights, chunk size should be <= 1 cell"); @@ -30,24 +38,25 @@ namespace ESMTerrain int cellX = static_cast(origin.x); int cellY = static_cast(origin.y); - const ESM::Land* land = getLand(cellX, cellY); - if (!land || !(land->mDataTypes&ESM::Land::DATA_VHGT)) - return false; - - min = std::numeric_limits::max(); - max = -std::numeric_limits::max(); - for (int row=0; row::max(); + max = -std::numeric_limits::max(); + for (int row=0; rowmLandData->mHeights[col*ESM::Land::LAND_SIZE+row]; - if (h > max) - max = h; - if (h < min) - min = h; + for (int col=0; colmHeights[col*ESM::Land::LAND_SIZE+row]; + if (h > max) + max = h; + if (h < min) + min = h; + } } + return true; } - return true; + + return false; } void Storage::fixNormal (Ogre::Vector3& normal, int cellX, int cellY, int col, int row) @@ -72,12 +81,12 @@ namespace ESMTerrain --cellX; row += ESM::Land::LAND_SIZE-1; } - const ESM::Land* land = getLand(cellX, cellY); - if (land && land->mDataTypes&ESM::Land::DATA_VNML) + + if (const ESM::Land::LandData *data = getLandData (cellX, cellY, ESM::Land::DATA_VNML)) { - normal.x = land->mLandData->mNormals[col*ESM::Land::LAND_SIZE*3+row*3]; - normal.y = land->mLandData->mNormals[col*ESM::Land::LAND_SIZE*3+row*3+1]; - normal.z = land->mLandData->mNormals[col*ESM::Land::LAND_SIZE*3+row*3+2]; + normal.x = data->mNormals[col*ESM::Land::LAND_SIZE*3+row*3]; + normal.y = data->mNormals[col*ESM::Land::LAND_SIZE*3+row*3+1]; + normal.z = data->mNormals[col*ESM::Land::LAND_SIZE*3+row*3+2]; normal.normalise(); } else @@ -107,12 +116,12 @@ namespace ESMTerrain ++cellX; row = 0; } - const ESM::Land* land = getLand(cellX, cellY); - if (land && land->mDataTypes&ESM::Land::DATA_VCLR) + + if (const ESM::Land::LandData *data = getLandData (cellX, cellY, ESM::Land::DATA_VCLR)) { - color.r = land->mLandData->mColours[col*ESM::Land::LAND_SIZE*3+row*3] / 255.f; - color.g = land->mLandData->mColours[col*ESM::Land::LAND_SIZE*3+row*3+1] / 255.f; - color.b = land->mLandData->mColours[col*ESM::Land::LAND_SIZE*3+row*3+2] / 255.f; + color.r = data->mColours[col*ESM::Land::LAND_SIZE*3+row*3] / 255.f; + color.g = data->mColours[col*ESM::Land::LAND_SIZE*3+row*3+1] / 255.f; + color.b = data->mColours[col*ESM::Land::LAND_SIZE*3+row*3+2] / 255.f; } else { @@ -156,9 +165,9 @@ namespace ESMTerrain float vertX_ = 0; // of current cell corner for (int cellX = startX; cellX < startX + std::ceil(size); ++cellX) { - const ESM::Land* land = getLand(cellX, cellY); - if (land && !(land->mDataTypes&ESM::Land::DATA_VHGT)) - land = NULL; + const ESM::Land::LandData *heightData = getLandData (cellX, cellY, ESM::Land::DATA_VHGT); + const ESM::Land::LandData *normalData = getLandData (cellX, cellY, ESM::Land::DATA_VNML); + const ESM::Land::LandData *colourData = getLandData (cellX, cellY, ESM::Land::DATA_VCLR); int rowStart = 0; int colStart = 0; @@ -177,16 +186,17 @@ namespace ESMTerrain { positions[static_cast(vertX*numVerts * 3 + vertY * 3)] = ((vertX / float(numVerts - 1) - 0.5f) * size * 8192); positions[static_cast(vertX*numVerts * 3 + vertY * 3 + 1)] = ((vertY / float(numVerts - 1) - 0.5f) * size * 8192); - if (land) - positions[static_cast(vertX*numVerts * 3 + vertY * 3 + 2)] = land->mLandData->mHeights[col*ESM::Land::LAND_SIZE + row]; - else - positions[static_cast(vertX*numVerts * 3 + vertY * 3 + 2)] = -2048; - if (land && land->mDataTypes&ESM::Land::DATA_VNML) + float height = -2048; + if (heightData) + height = heightData->mHeights[col*ESM::Land::LAND_SIZE + row]; + positions[static_cast(vertX*numVerts * 3 + vertY * 3 + 2)] = height; + + if (normalData) { - normal.x = land->mLandData->mNormals[col*ESM::Land::LAND_SIZE*3+row*3]; - normal.y = land->mLandData->mNormals[col*ESM::Land::LAND_SIZE*3+row*3+1]; - normal.z = land->mLandData->mNormals[col*ESM::Land::LAND_SIZE*3+row*3+2]; + normal.x = normalData->mNormals[col*ESM::Land::LAND_SIZE*3+row*3]; + normal.y = normalData->mNormals[col*ESM::Land::LAND_SIZE*3+row*3+1]; + normal.z = normalData->mNormals[col*ESM::Land::LAND_SIZE*3+row*3+2]; normal.normalise(); } else @@ -206,11 +216,11 @@ namespace ESMTerrain normals[static_cast(vertX*numVerts * 3 + vertY * 3 + 1)] = normal.y; normals[static_cast(vertX*numVerts * 3 + vertY * 3 + 2)] = normal.z; - if (land && land->mDataTypes&ESM::Land::DATA_VCLR) + if (colourData) { - color.r = land->mLandData->mColours[col*ESM::Land::LAND_SIZE*3+row*3] / 255.f; - color.g = land->mLandData->mColours[col*ESM::Land::LAND_SIZE*3+row*3+1] / 255.f; - color.b = land->mLandData->mColours[col*ESM::Land::LAND_SIZE*3+row*3+2] / 255.f; + color.r = colourData->mColours[col*ESM::Land::LAND_SIZE*3+row*3] / 255.f; + color.g = colourData->mColours[col*ESM::Land::LAND_SIZE*3+row*3+1] / 255.f; + color.b = colourData->mColours[col*ESM::Land::LAND_SIZE*3+row*3+2] / 255.f; } else { @@ -261,13 +271,12 @@ namespace ESMTerrain assert(xmDataTypes&ESM::Land::DATA_VTEX)) + if (const ESM::Land::LandData *data = getLandData (cellX, cellY, ESM::Land::DATA_VTEX)) { - int tex = land->mLandData->mTextures[y * ESM::Land::LAND_TEXTURE_SIZE + x]; + int tex = data->mTextures[y * ESM::Land::LAND_TEXTURE_SIZE + x]; if (tex == 0) return std::make_pair(0,0); // vtex 0 is always the base texture, regardless of plugin - return std::make_pair(tex, land->mPlugin); + return std::make_pair(tex, getLand (cellX, cellY)->mPlugin); } else return std::make_pair(0,0); @@ -459,7 +468,7 @@ namespace ESMTerrain { assert(x < ESM::Land::LAND_SIZE); assert(y < ESM::Land::LAND_SIZE); - return land->mLandData->mHeights[y * ESM::Land::LAND_SIZE + x]; + return land->getLandData()->mHeights[y * ESM::Land::LAND_SIZE + x]; } Terrain::LayerInfo Storage::getLayerInfo(const std::string& texture) diff --git a/components/esmterrain/storage.hpp b/components/esmterrain/storage.hpp index 698bcf99c9..af1b0d5c38 100644 --- a/components/esmterrain/storage.hpp +++ b/components/esmterrain/storage.hpp @@ -16,11 +16,16 @@ namespace ESMTerrain private: // Not implemented in this class, because we need different Store implementations for game and editor - virtual const ESM::Land* getLand (int cellX, int cellY) = 0; + virtual const ESM::Land* getLand (int cellX, int cellY)= 0; virtual const ESM::LandTexture* getLandTexture(int index, short plugin) = 0; public: + /// Data is loaded first, if necessary. Will return a 0-pointer if there is no data for + /// any of the data types specified via \a flags. Will also return a 0-pointer if there + /// is no land record for the coordinates \a cellX / \a cellY. + const ESM::Land::LandData *getLandData (int cellX, int cellY, int flags); + // Not implemented in this class, because we need different Store implementations for game and editor /// Get bounds of the whole terrain in cell units virtual void getBounds(float& minX, float& maxX, float& minY, float& maxY) = 0; From ce34daa64b679ce870623f959748236765cd3df8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 31 Aug 2015 18:13:27 +0200 Subject: [PATCH 31/81] removed indirection in OpenMW-CS land record (cherry picked from commit 85f6bb892b7f61b95d297efcf67cfccaee134e54) Conflicts: apps/opencs/view/render/cell.cpp --- apps/opencs/model/doc/savingstages.cpp | 10 +++++----- apps/opencs/model/tools/mergestages.cpp | 2 +- apps/opencs/model/world/data.cpp | 7 ++++++- apps/opencs/model/world/data.hpp | 2 ++ apps/opencs/model/world/land.cpp | 16 ++-------------- apps/opencs/model/world/land.hpp | 10 ++-------- apps/opencs/view/render/cell.cpp | 18 ++++++++++-------- apps/opencs/view/render/terrainstorage.cpp | 7 +++---- 8 files changed, 31 insertions(+), 41 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 62ac48805a..c6d8a8cb34 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -415,16 +415,16 @@ void CSMDoc::WriteLandCollectionStage::perform (int stage, Messages& messages) if (land.mState==CSMWorld::RecordBase::State_Modified || land.mState==CSMWorld::RecordBase::State_ModifiedOnly) { - CSMWorld::Land record = land.get(); + const CSMWorld::Land& record = land.get(); - mState.getWriter().startRecord (record.mLand->sRecordId); + mState.getWriter().startRecord (record.sRecordId); - record.mLand->save (mState.getWriter()); + record.save (mState.getWriter()); - if (const ESM::Land::LandData *data = record.mLand->getLandData (record.mLand->mDataTypes)) + if (const ESM::Land::LandData *data = record.getLandData (record.mDataTypes)) data->save (mState.getWriter()); - mState.getWriter().endRecord (record.mLand->sRecordId); + mState.getWriter().endRecord (record.sRecordId); } else if (land.mState==CSMWorld::RecordBase::State_Deleted) { diff --git a/apps/opencs/model/tools/mergestages.cpp b/apps/opencs/model/tools/mergestages.cpp index 5bf0241ac2..c624ff548e 100644 --- a/apps/opencs/model/tools/mergestages.cpp +++ b/apps/opencs/model/tools/mergestages.cpp @@ -124,7 +124,7 @@ void CSMTools::ListLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& if (!record.isDeleted()) { - ESM::Land& land = *record.get().mLand; + const ESM::Land& land = record.get(); // make sure record is loaded land.loadData (ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index c78cc383c6..9f48bcfdfd 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -873,6 +873,11 @@ const CSMWorld::IdCollection& CSMWorld::Data::getLand() const return mLand; } +CSMWorld::IdCollection& CSMWorld::Data::getLand() +{ + return mLand; +} + const CSMWorld::IdCollection& CSMWorld::Data::getLandTextures() const { return mLandTextures; @@ -1051,7 +1056,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) int index = mLand.load(*mReader, mBase); if (index!=-1 && !mBase) - mLand.getRecord (index).mModified.mLand->loadData ( + mLand.getRecord (index).mModified.loadData ( ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM); diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 97be947dcc..944a636f0a 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -224,6 +224,8 @@ namespace CSMWorld const IdCollection& getLand() const; + IdCollection& getLand(); + const IdCollection& getLandTextures() const; IdCollection& getLandTextures(); diff --git a/apps/opencs/model/world/land.cpp b/apps/opencs/model/world/land.cpp index 119e187616..222f9bc023 100644 --- a/apps/opencs/model/world/land.cpp +++ b/apps/opencs/model/world/land.cpp @@ -4,25 +4,13 @@ namespace CSMWorld { - - Land::Land() - { - mLand.reset(new ESM::Land()); - } - void Land::load(ESM::ESMReader &esm) { - mLand->load(esm); + ESM::Land::load(esm); std::ostringstream stream; - stream << "#" << mLand->mX << " " << mLand->mY; + stream << "#" << mX << " " << mY; mId = stream.str(); } - - void Land::blank() - { - /// \todo - } - } diff --git a/apps/opencs/model/world/land.hpp b/apps/opencs/model/world/land.hpp index e97a2d7dd8..22cedb56db 100644 --- a/apps/opencs/model/world/land.hpp +++ b/apps/opencs/model/world/land.hpp @@ -2,7 +2,7 @@ #define CSM_WORLD_LAND_H #include -#include + #include namespace CSMWorld @@ -11,18 +11,12 @@ namespace CSMWorld /// /// \todo Add worldspace support to the Land record. /// \todo Add a proper copy constructor (currently worked around using shared_ptr) - struct Land + struct Land : public ESM::Land { - Land(); - - boost::shared_ptr mLand; - std::string mId; /// Loads the metadata and ID void load (ESM::ESMReader &esm); - - void blank(); }; } diff --git a/apps/opencs/view/render/cell.cpp b/apps/opencs/view/render/cell.cpp index 156d9728b6..c6da1bef8e 100644 --- a/apps/opencs/view/render/cell.cpp +++ b/apps/opencs/view/render/cell.cpp @@ -33,7 +33,7 @@ bool CSVRender::Cell::addObjects (int start, int end) bool modified = false; const CSMWorld::RefCollection& collection = mData.getReferences(); - + for (int i=start; i<=end; ++i) { std::string cell = Misc::StringUtils::lowerCase (collection.getRecord (i).get().mCell); @@ -70,20 +70,22 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager, int landIndex = land.searchId(mId); if (landIndex != -1) { - const ESM::Land* esmLand = land.getRecord(mId).get().mLand.get(); - if(esmLand && esmLand->mDataTypes&ESM::Land::DATA_VHGT) + const ESM::Land& esmLand = land.getRecord(mId).get(); + + if (esmLand.getLandData (ESM::Land::DATA_VHGT)) { mTerrain.reset(new Terrain::TerrainGrid(sceneManager, new TerrainStorage(mData), Element_Terrain, true, Terrain::Align_XY)); - mTerrain->loadCell(esmLand->mX, - esmLand->mY); + mTerrain->loadCell(esmLand.mX, + esmLand.mY); float verts = ESM::Land::LAND_SIZE; float worldsize = ESM::Land::REAL_SIZE; - mX = esmLand->mX; - mY = esmLand->mY; + mX = esmLand.mX; + mY = esmLand.mY; + mPhysics->addHeightField(sceneManager, - esmLand->mLandData->mHeights, mX, mY, 0, worldsize / (verts-1), verts); + esmLand.getLandData(ESM::Land::DATA_VHGT)->mHeights, mX, mY, 0, worldsize / (verts-1), verts); } } } diff --git a/apps/opencs/view/render/terrainstorage.cpp b/apps/opencs/view/render/terrainstorage.cpp index da962313ae..41fe70c011 100644 --- a/apps/opencs/view/render/terrainstorage.cpp +++ b/apps/opencs/view/render/terrainstorage.cpp @@ -19,11 +19,10 @@ namespace CSVRender if (index == -1) return NULL; - ESM::Land* land = mData.getLand().getRecord(index).get().mLand.get(); + const ESM::Land& land = mData.getLand().getRecord(index).get(); int mask = ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX; - if (!land->isDataLoaded(mask)) - land->loadData(mask); - return land; + land.loadData (mask); + return &land; } const ESM::LandTexture* TerrainStorage::getLandTexture(int index, short plugin) From 25952369aefe6908b2a59ca7bf60793c951d5e61 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 3 Sep 2015 16:15:00 +0200 Subject: [PATCH 32/81] merge land tables (cherry picked from commit a8dc1c119859abd0ad4cf16765abbf1f70fe6013) --- apps/opencs/model/tools/mergeoperation.cpp | 3 +- apps/opencs/model/tools/mergestages.cpp | 64 +++++++++++++++++++++- apps/opencs/model/tools/mergestages.hpp | 15 +++++ components/esm/loadland.cpp | 26 +++++++++ components/esm/loadland.hpp | 11 ++++ 5 files changed, 115 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/tools/mergeoperation.cpp b/apps/opencs/model/tools/mergeoperation.cpp index 9e791683cc..907d742edf 100644 --- a/apps/opencs/model/tools/mergeoperation.cpp +++ b/apps/opencs/model/tools/mergeoperation.cpp @@ -40,10 +40,9 @@ CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document, ToUTF8::Fr appendStage (new MergeReferencesStage (mState)); appendStage (new ListLandTexturesMergeStage (mState)); appendStage (new MergeLandTexturesStage (mState)); + appendStage (new MergeLandStage (mState)); appendStage (new FinishMergedDocumentStage (mState, encoding)); - - /// \todo Land } void CSMTools::MergeOperation::setTarget (std::auto_ptr document) diff --git a/apps/opencs/model/tools/mergestages.cpp b/apps/opencs/model/tools/mergestages.cpp index c624ff548e..f4cb42aa4c 100644 --- a/apps/opencs/model/tools/mergestages.cpp +++ b/apps/opencs/model/tools/mergestages.cpp @@ -153,12 +153,20 @@ CSMTools::MergeLandTexturesStage::MergeLandTexturesStage (MergeState& state) int CSMTools::MergeLandTexturesStage::setup() { - mNext = mState.mTextureIndices.begin(); - return mState.mTextureIndices.size(); + // Should use the size of mState.mTextureIndices instead, but that is not available at this + // point. Unless there are any errors in the land and land texture records this will not + // make a difference. + return mState.mSource.getData().getLandTextures().getSize(); } void CSMTools::MergeLandTexturesStage::perform (int stage, CSMDoc::Messages& messages) { + if (stage==0) + mNext = mState.mTextureIndices.begin(); + + if (mNext==mState.mTextureIndices.end()) + return; + mNext->second = stage; std::ostringstream stream; @@ -183,3 +191,55 @@ void CSMTools::MergeLandTexturesStage::perform (int stage, CSMDoc::Messages& mes ++mNext; } + + +CSMTools::MergeLandStage::MergeLandStage (MergeState& state) : mState (state) {} + +int CSMTools::MergeLandStage::setup() +{ + return mState.mSource.getData().getLand().getSize(); +} + +void CSMTools::MergeLandStage::perform (int stage, CSMDoc::Messages& messages) +{ + const CSMWorld::Record& record = + mState.mSource.getData().getLand().getRecord (stage); + + if (!record.isDeleted()) + { + const CSMWorld::Land& land = record.get(); + + land.loadData (ESM::Land::DATA_VCLR | ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | + ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM); + + CSMWorld::Land newLand (land); + + newLand.mEsm = 0; // avoid potential dangling pointer (ESMReader isn't needed anyway, + // because record is already fully loaded) + newLand.mPlugin = 0; + + // adjust land texture references + if (ESM::Land::LandData *data = newLand.getLandData()) + { + std::pair key; + key.second = land.mPlugin; + + for (int i=0; imTextures[i]; + std::map, int>::const_iterator iter = + mState.mTextureIndices.find (key); + + if (iter!=mState.mTextureIndices.end()) + data->mTextures[i] = iter->second; + else + data->mTextures[i] = 0; + } + } + + CSMWorld::Record newRecord ( + CSMWorld::RecordBase::State_ModifiedOnly, 0, &newLand); + + mState.mTarget->getData().getLand().appendRecord (newRecord); + } +} diff --git a/apps/opencs/model/tools/mergestages.hpp b/apps/opencs/model/tools/mergestages.hpp index f0ae99842c..f88f5be9f6 100644 --- a/apps/opencs/model/tools/mergestages.hpp +++ b/apps/opencs/model/tools/mergestages.hpp @@ -146,6 +146,21 @@ namespace CSMTools virtual void perform (int stage, CSMDoc::Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; + + class MergeLandStage : public CSMDoc::Stage + { + MergeState& mState; + + public: + + MergeLandStage (MergeState& state); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, CSMDoc::Messages& messages); + ///< Messages resulting from this stage will be appended to \a messages. + }; } #endif diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index 770830fddb..784cfd4078 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -256,4 +256,30 @@ bool Land::isDataLoaded(int flags) const { return mLandData; } + + Land::LandData *Land::getLandData() + { + return mLandData; + } + + void Land::add (int flags) + { + if (!mLandData) + mLandData = new LandData; + + mDataTypes |= flags; + mDataLoaded |= flags; + } + + void Land::remove (int flags) + { + mDataTypes &= ~flags; + mDataLoaded &= ~flags; + + if (!mDataLoaded) + { + delete mLandData; + mLandData = 0; + } + } } diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index 78646a5341..ef7e677f5d 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -127,6 +127,17 @@ struct Land /// Return land data without loading first anything. Can return a 0-pointer. const LandData *getLandData() const; + /// Return land data without loading first anything. Can return a 0-pointer. + LandData *getLandData(); + + /// \attention Must not be called on objects that aren't fully loaded. + /// + /// \note Added data fields will be uninitialised + void add (int flags); + + /// \attention Must not be called on objects that aren't fully loaded. + void remove (int flags); + private: /// Loads data and marks it as loaded From 1784701b47627f86ee376176a7445d671d27bffa Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 8 Sep 2015 15:33:15 +0200 Subject: [PATCH 33/81] fixed a texture indexing bug (only affects the editor) (cherry picked from commit 73f6efddcc1b6f5816f9f775418c6317cf74ee20) --- apps/opencs/model/tools/mergestages.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/opencs/model/tools/mergestages.cpp b/apps/opencs/model/tools/mergestages.cpp index f4cb42aa4c..e24d1f9118 100644 --- a/apps/opencs/model/tools/mergestages.cpp +++ b/apps/opencs/model/tools/mergestages.cpp @@ -179,6 +179,9 @@ void CSMTools::MergeLandTexturesStage::perform (int stage, CSMDoc::Messages& mes CSMWorld::LandTexture texture = mState.mSource.getData().getLandTextures().getRecord (index).get(); + std::ostringstream stream; + stream << mNext->second << "_0"; + texture.mIndex = mNext->second; texture.mId = stream.str(); From dcf1f1515a82afc5332ac21372bb027a962471fb Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 8 Sep 2015 16:01:34 +0200 Subject: [PATCH 34/81] handle missing land texture records properly during merge (cherry picked from commit 09ec60fe2a7b2cce91ee5f2271db4479b97ae228) --- apps/opencs/model/tools/mergestages.cpp | 49 ++++++++++++++----------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/apps/opencs/model/tools/mergestages.cpp b/apps/opencs/model/tools/mergestages.cpp index e24d1f9118..fab5fae71f 100644 --- a/apps/opencs/model/tools/mergestages.cpp +++ b/apps/opencs/model/tools/mergestages.cpp @@ -164,35 +164,42 @@ void CSMTools::MergeLandTexturesStage::perform (int stage, CSMDoc::Messages& mes if (stage==0) mNext = mState.mTextureIndices.begin(); - if (mNext==mState.mTextureIndices.end()) - return; + bool found = false; - mNext->second = stage; - - std::ostringstream stream; - stream << mNext->first.first << "_" << mNext->first.second; - - int index = mState.mSource.getData().getLandTextures().searchId (stream.str()); - - if (index!=-1) + do { - CSMWorld::LandTexture texture = - mState.mSource.getData().getLandTextures().getRecord (index).get(); + if (mNext==mState.mTextureIndices.end()) + return; + + mNext->second = stage; std::ostringstream stream; - stream << mNext->second << "_0"; + stream << mNext->first.first << "_" << mNext->first.second; - texture.mIndex = mNext->second; - texture.mId = stream.str(); + int index = mState.mSource.getData().getLandTextures().searchId (stream.str()); - CSMWorld::Record newRecord ( - CSMWorld::RecordBase::State_ModifiedOnly, 0, &texture); + if (index!=-1) + { + CSMWorld::LandTexture texture = + mState.mSource.getData().getLandTextures().getRecord (index).get(); - mState.mTarget->getData().getLandTextures().appendRecord (newRecord); + std::ostringstream stream; + stream << mNext->second << "_0"; + + texture.mIndex = mNext->second; + texture.mId = stream.str(); + + CSMWorld::Record newRecord ( + CSMWorld::RecordBase::State_ModifiedOnly, 0, &texture); + + mState.mTarget->getData().getLandTextures().appendRecord (newRecord); + + found = true; + } + + ++mNext; } - /// \todo deal with missing textures (either abort merge or report and make sure OpenMW can deal with missing textures) - - ++mNext; + while (!found); } From 4aa6d7d1d1b78f4891751eddff069418580db24f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 10 Sep 2015 12:41:31 +0200 Subject: [PATCH 35/81] various minor fixes (cherry picked from commit 584a7a66b97739c91c38cf8f17922ba29d5536e2) --- apps/opencs/model/tools/mergestages.cpp | 31 ++++++++++++++----------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/apps/opencs/model/tools/mergestages.cpp b/apps/opencs/model/tools/mergestages.cpp index fab5fae71f..f7c3b8dc05 100644 --- a/apps/opencs/model/tools/mergestages.cpp +++ b/apps/opencs/model/tools/mergestages.cpp @@ -124,7 +124,7 @@ void CSMTools::ListLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& if (!record.isDeleted()) { - const ESM::Land& land = record.get(); + const CSMWorld::Land& land = record.get(); // make sure record is loaded land.loadData (ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | @@ -228,22 +228,25 @@ void CSMTools::MergeLandStage::perform (int stage, CSMDoc::Messages& messages) // because record is already fully loaded) newLand.mPlugin = 0; - // adjust land texture references - if (ESM::Land::LandData *data = newLand.getLandData()) + if (land.mDataTypes & ESM::Land::DATA_VTEX) { - std::pair key; - key.second = land.mPlugin; - - for (int i=0; imTextures[i]; - std::map, int>::const_iterator iter = - mState.mTextureIndices.find (key); + std::pair key; + key.second = land.mPlugin; - if (iter!=mState.mTextureIndices.end()) - data->mTextures[i] = iter->second; - else - data->mTextures[i] = 0; + for (int i=0; imTextures[i]; + std::map, int>::const_iterator iter = + mState.mTextureIndices.find (key); + + if (iter!=mState.mTextureIndices.end()) + data->mTextures[i] = iter->second; + else + data->mTextures[i] = 0; + } } } From 453c3ee7607d6fcc287a7134275c1802cc5964da Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 11 Sep 2015 10:50:19 +0200 Subject: [PATCH 36/81] fixed an indexing error (cherry picked from commit 23fde87816644912c9896920b80348429a045003) --- apps/opencs/model/tools/mergestages.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/tools/mergestages.cpp b/apps/opencs/model/tools/mergestages.cpp index f7c3b8dc05..52e1e69649 100644 --- a/apps/opencs/model/tools/mergestages.cpp +++ b/apps/opencs/model/tools/mergestages.cpp @@ -171,10 +171,10 @@ void CSMTools::MergeLandTexturesStage::perform (int stage, CSMDoc::Messages& mes if (mNext==mState.mTextureIndices.end()) return; - mNext->second = stage; + mNext->second = stage+1; std::ostringstream stream; - stream << mNext->first.first << "_" << mNext->first.second; + stream << mNext->first.first-1 << "_" << mNext->first.second; int index = mState.mSource.getData().getLandTextures().searchId (stream.str()); @@ -184,9 +184,9 @@ void CSMTools::MergeLandTexturesStage::perform (int stage, CSMDoc::Messages& mes mState.mSource.getData().getLandTextures().getRecord (index).get(); std::ostringstream stream; - stream << mNext->second << "_0"; + stream << mNext->second-1 << "_0"; - texture.mIndex = mNext->second; + texture.mIndex = mNext->second-1; texture.mId = stream.str(); CSMWorld::Record newRecord ( From 5031d1fbcba1a817da514113d1abfc56a9076017 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 11 Sep 2015 13:02:24 +0200 Subject: [PATCH 37/81] disable on-demand loading of land data (for now, maybe) (cherry picked from commit 5be176ee85da349163e161f86693f836fb1b5fdc) --- apps/opencs/model/world/data.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 9f48bcfdfd..01596af7c7 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -1055,8 +1055,10 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) { int index = mLand.load(*mReader, mBase); - if (index!=-1 && !mBase) - mLand.getRecord (index).mModified.loadData ( + // Load all land data for now. A future optimisation may only load non-base data + // if a suitable mechanism for avoiding race conditions can be established. + if (index!=-1/* && !mBase*/) + mLand.getRecord (index).get().loadData ( ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM); From 03ee1ec8cbbccf8e72e3aa759f35ea7f05cc67ad Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Sun, 6 Sep 2015 21:46:05 +0200 Subject: [PATCH 38/81] adjust FindMyGUI.cmake to correctly handle REQUIRED and QUIETLY (cherry picked from commit b68f64ed97aff7c48d6878241ecd64d6acaba2f5) --- cmake/FindMyGUI.cmake | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cmake/FindMyGUI.cmake b/cmake/FindMyGUI.cmake index 2829a74d35..694cf3505d 100644 --- a/cmake/FindMyGUI.cmake +++ b/cmake/FindMyGUI.cmake @@ -182,11 +182,12 @@ IF (MYGUI_FOUND) IF (NOT MYGUI_FIND_QUIETLY) MESSAGE(STATUS "MyGUI version: ${MYGUI_VERSION}") ENDIF (NOT MYGUI_FIND_QUIETLY) - -ELSE (MYGUI_FOUND) - IF (MYGUI_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find MYGUI") - ENDIF (MYGUI_FIND_REQUIRED) ENDIF (MYGUI_FOUND) +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(MyGUI DEFAULT_MSG + MYGUI_INCLUDE_DIRS + FREETYPE_LIBRARIES + MYGUI_LIBRARIES) + CMAKE_POLICY(POP) From c0f21bfb775f668f1567c77df10bd3b8166a9ac6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 11 Sep 2015 21:09:54 +0200 Subject: [PATCH 39/81] Add some comments to ESM::Land (cherry picked from commit 5252dbcf1f4dc311419ca9f7d5f32a765771d1e0) Conflicts: components/esm/loadland.hpp --- components/esm/loadland.hpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index ef7e677f5d..8ec4f74ea0 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -76,17 +76,29 @@ struct Land struct LandData { + // Initial reference height for the first vertex, only needed for filling mHeights float mHeightOffset; + // Height in world space for each vertex float mHeights[LAND_NUM_VERTS]; + + // 24-bit normals, these aren't always correct though. Edge and corner normals may be garbage. VNML mNormals[LAND_NUM_VERTS * 3]; + + // 2D array of texture indices. An index can be used to look up an ESM::LandTexture, + // but to do so you must subtract 1 from the index first! + // An index of 0 indicates the default texture. uint16_t mTextures[LAND_NUM_TEXTURES]; - char mColours[3 * LAND_NUM_VERTS]; + // 24-bit RGB color for each vertex + unsigned char mColours[3 * LAND_NUM_VERTS]; + + // DataTypes available in this LandData, accessing data that is not available is an undefined operation int mDataTypes; // low-LOD heightmap (used for rendering the global map) signed char mWnam[81]; + // ??? short mUnk1; uint8_t mUnk2; From c40e68cc5b972fb72de0880137378890da180e47 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 14 Sep 2015 15:14:18 +0200 Subject: [PATCH 40/81] Add CONTRIBUTING.md (cherry picked from commit 6c6fc662ef80b5c99fc2b3723faa410edb37868c) --- CONTRIBUTING.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..879113a515 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,16 @@ +Description +=========== + +Your pull request description should include: + +* Summary of the changes made +* Reasoning / motivation behind the change +* What testing you have carried out to verify the change +* If applicable, a link back to the bug report or forum discussion that prompted the change + +Other notes +=========== + +* Separate your work into multiple pull requests whenever possible. As a rule of thumb, each feature and each bugfix should go into a separate PR, unless they are closely related or dependent upon each other. Small pull requests are easier to review, and are less likely to require further changes before we can merge them. A "mega" pull request with lots of unrelated commits in it is likely to get held up in review for a long time. +* Feel free to submit incomplete pull requests. Even if the work can not be merged yet, pull requests are a great place to collect early feedback. Just make sure to mark it as *[Incomplete]* or *[Do not merge yet]* in the title. +* If you plan on contributing often, please read the [Developer Reference](https://wiki.openmw.org/index.php?title=Developer_Reference) on our wiki, especially the [Policies and Standards](https://wiki.openmw.org/index.php?title=Policies_and_Standards). From 7c347a590856dce3de6dc40e872f544dc8066382 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 14 Sep 2015 17:17:38 +0200 Subject: [PATCH 41/81] CONTRIBUTING.md: clarify "if applicable" (cherry picked from commit 5fde9149594f6503c192f9d949d8f0bb3f3df5ba) --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 879113a515..a9cd6a6903 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,12 +1,12 @@ Description =========== -Your pull request description should include: +Your pull request description should include (if applicable): +* A link back to the bug report or forum discussion that prompted the change * Summary of the changes made * Reasoning / motivation behind the change * What testing you have carried out to verify the change -* If applicable, a link back to the bug report or forum discussion that prompted the change Other notes =========== From 496cdcb51b47784953cb11028b8449071cdcac25 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 12 Sep 2015 09:04:43 +1000 Subject: [PATCH 42/81] Ensure ColumnId names are unique. Filter parser calls Columns::getId() which implies that these should be unique. (cherry picked from commit 258b2ba29abedf329db1db2c5660cf213445c999) --- apps/opencs/model/world/columns.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index af26a6901d..d6d2abe923 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -265,7 +265,7 @@ namespace CSMWorld { ColumnId_LevelledList,"Levelled List" }, { ColumnId_LevelledItemId,"Levelled Item" }, - { ColumnId_LevelledItemLevel,"Level" }, + { ColumnId_LevelledItemLevel,"Item Level" }, { ColumnId_LevelledItemType, "Calculate all levels <= player" }, { ColumnId_LevelledItemTypeEach, "Select a new item each instance" }, { ColumnId_LevelledItemChanceNone, "Chance None" }, @@ -281,26 +281,26 @@ namespace CSMWorld { ColumnId_InfoCondValue, "Values" }, { ColumnId_OriginalCell, "Original Cell" }, - { ColumnId_NpcAttributes, "Attributes" }, - { ColumnId_NpcSkills, "Skills" }, + { ColumnId_NpcAttributes, "NPC Attributes" }, + { ColumnId_NpcSkills, "NPC Skill" }, { ColumnId_UChar, "Value [0..255]" }, - { ColumnId_NpcMisc, "Misc" }, + { ColumnId_NpcMisc, "NPC Misc" }, { ColumnId_NpcLevel, "Level" }, { ColumnId_NpcFactionID, "Faction ID" }, - { ColumnId_NpcHealth, "Health" }, + { ColumnId_NpcHealth, "NPC Health" }, { ColumnId_NpcMana, "Mana" }, { ColumnId_NpcFatigue, "Fatigue" }, - { ColumnId_NpcDisposition, "Disposition" }, + { ColumnId_NpcDisposition, "NPC Disposition" }, { ColumnId_NpcReputation, "Reputation" }, - { ColumnId_NpcRank, "Rank" }, + { ColumnId_NpcRank, "NPC Rank" }, { ColumnId_NpcGold, "Gold" }, { ColumnId_NpcPersistence, "Persistent" }, - { ColumnId_RaceAttributes, "Attributes" }, - { ColumnId_RaceMaleValue, "Male" }, - { ColumnId_RaceFemaleValue, "Female" }, + { ColumnId_RaceAttributes, "Race Attributes" }, + { ColumnId_RaceMaleValue, "Male Attrib" }, + { ColumnId_RaceFemaleValue, "Female Attrib" }, { ColumnId_RaceSkillBonus, "Skill Bonus" }, - { ColumnId_RaceSkill, "Skills" }, + { ColumnId_RaceSkill, "Race Skill" }, { ColumnId_RaceBonus, "Bonus" }, { ColumnId_Interior, "Interior" }, From 41f2ffdebb9c70850bbf713ee99ea0fcd5a4f64d Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 12 Sep 2015 09:33:11 +1000 Subject: [PATCH 43/81] Rationalise the use of ColumnIds (cherry picked from commit c4a900ca2c9b98267c9a507bb887829373fc9193) Conflicts: apps/opencs/model/world/refidcollection.cpp --- apps/opencs/model/world/columns.cpp | 15 +++++---------- apps/opencs/model/world/columns.hpp | 14 +++++++------- apps/opencs/model/world/data.cpp | 4 ++-- apps/opencs/model/world/nestedcoladapterimp.cpp | 2 +- apps/opencs/model/world/refidadapterimp.cpp | 15 ++------------- apps/opencs/model/world/refidcollection.cpp | 14 +++++++------- apps/opencs/view/doc/viewmanager.cpp | 1 - 7 files changed, 24 insertions(+), 41 deletions(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index d6d2abe923..563cc1615c 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -199,8 +199,6 @@ namespace CSMWorld { ColumnId_RotY, "Rotation Y"}, { ColumnId_RotZ, "Rotation Z"}, - { ColumnId_Skill, "Skill" }, - { ColumnId_OwnerGlobal, "Owner Global" }, { ColumnId_DefaultProfile, "Default Profile" }, { ColumnId_BypassNewGame, "Bypass New Game" }, @@ -271,7 +269,7 @@ namespace CSMWorld { ColumnId_LevelledItemChanceNone, "Chance None" }, { ColumnId_PowerList, "Powers" }, - { ColumnId_SkillImpact, "Skills" }, + { ColumnId_SkillImpact, "Skill" }, { ColumnId_InfoList, "Info List" }, { ColumnId_InfoCondition, "Info Conditions" }, @@ -285,22 +283,20 @@ namespace CSMWorld { ColumnId_NpcSkills, "NPC Skill" }, { ColumnId_UChar, "Value [0..255]" }, { ColumnId_NpcMisc, "NPC Misc" }, - { ColumnId_NpcLevel, "Level" }, + { ColumnId_Level, "Level" }, { ColumnId_NpcFactionID, "Faction ID" }, - { ColumnId_NpcHealth, "NPC Health" }, - { ColumnId_NpcMana, "Mana" }, - { ColumnId_NpcFatigue, "Fatigue" }, + { ColumnId_Mana, "Mana" }, + { ColumnId_Fatigue, "Fatigue" }, { ColumnId_NpcDisposition, "NPC Disposition" }, { ColumnId_NpcReputation, "Reputation" }, { ColumnId_NpcRank, "NPC Rank" }, - { ColumnId_NpcGold, "Gold" }, + { ColumnId_Gold, "Gold" }, { ColumnId_NpcPersistence, "Persistent" }, { ColumnId_RaceAttributes, "Race Attributes" }, { ColumnId_RaceMaleValue, "Male Attrib" }, { ColumnId_RaceFemaleValue, "Female Attrib" }, { ColumnId_RaceSkillBonus, "Skill Bonus" }, - { ColumnId_RaceSkill, "Race Skill" }, { ColumnId_RaceBonus, "Bonus" }, { ColumnId_Interior, "Interior" }, @@ -583,7 +579,6 @@ namespace // FIXME: don't have dynamic value enum delegate, use Display_String for now //case CSMWorld::Columns::ColumnId_InfoCond: return sInfoCond; case CSMWorld::Columns::ColumnId_InfoCondComp: return sInfoCondComp; - case CSMWorld::Columns::ColumnId_RaceSkill: return sSkills; default: return 0; } diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 61b796581b..0d8064e6aa 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -189,7 +189,7 @@ namespace CSMWorld ColumnId_RotX = 174, ColumnId_RotY = 175, ColumnId_RotZ = 176, - ColumnId_Skill = 177, + // unused ColumnId_OwnerGlobal = 178, ColumnId_DefaultProfile = 179, ColumnId_BypassNewGame = 180, @@ -276,22 +276,22 @@ namespace CSMWorld ColumnId_NpcSkills = 249, ColumnId_UChar = 250, ColumnId_NpcMisc = 251, - ColumnId_NpcLevel = 252, + ColumnId_Level = 252, ColumnId_NpcFactionID = 253, - ColumnId_NpcHealth = 254, - ColumnId_NpcMana = 255, - ColumnId_NpcFatigue = 256, + // unused + ColumnId_Mana = 255, + ColumnId_Fatigue = 256, ColumnId_NpcDisposition = 257, ColumnId_NpcReputation = 258, ColumnId_NpcRank = 259, - ColumnId_NpcGold = 260, + ColumnId_Gold = 260, ColumnId_NpcPersistence = 261, ColumnId_RaceAttributes = 262, ColumnId_RaceMaleValue = 263, ColumnId_RaceFemaleValue = 264, ColumnId_RaceSkillBonus = 265, - ColumnId_RaceSkill = 266, + // unused ColumnId_RaceBonus = 267, ColumnId_Interior = 268, diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 01596af7c7..fee1cf2b40 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -209,7 +209,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc index = mRaces.getColumns()-1; mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceAttributeAdapter())); mRaces.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_RaceAttributes, ColumnBase::Display_String, + new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute, ColumnBase::Flag_Dialogue, false)); mRaces.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_RaceMaleValue, ColumnBase::Display_Integer)); @@ -220,7 +220,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc index = mRaces.getColumns()-1; mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceSkillsBonusAdapter())); mRaces.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_RaceSkill, ColumnBase::Display_RaceSkill)); + new NestedChildColumn (Columns::ColumnId_SkillImpact, ColumnBase::Display_SkillImpact)); mRaces.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_RaceBonus, ColumnBase::Display_Integer)); diff --git a/apps/opencs/model/world/nestedcoladapterimp.cpp b/apps/opencs/model/world/nestedcoladapterimp.cpp index 14a436c838..3ebc637b5b 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.cpp +++ b/apps/opencs/model/world/nestedcoladapterimp.cpp @@ -923,7 +923,7 @@ namespace CSMWorld switch (subColIndex) { - case 0: return QString(ESM::Attribute::sAttributeNames[subRowIndex].c_str()); + case 0: return subRowIndex; case 1: return race.mData.mAttributeValues[subRowIndex].mMale; case 2: return race.mData.mAttributeValues[subRowIndex].mFemale; default: throw std::runtime_error("Race Attribute subcolumn index out of range"); diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index 16579c2c77..e4cf396038 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -744,18 +744,7 @@ QVariant CSMWorld::NpcAttributesRefIdAdapter::getNestedData (const RefIdColumn * const ESM::NPC::NPDTstruct52& npcStruct = npc.mNpdt52; if (subColIndex == 0) - switch (subRowIndex) - { - case 0: return QString("Strength"); - case 1: return QString("Intelligence"); - case 2: return QString("Willpower"); - case 3: return QString("Agility"); - case 4: return QString("Speed"); - case 5: return QString("Endurance"); - case 6: return QString("Personality"); - case 7: return QString("Luck"); - default: return QVariant(); // throw an exception here? - } + return subRowIndex; else if (subColIndex == 1) if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) { @@ -886,7 +875,7 @@ QVariant CSMWorld::NpcSkillsRefIdAdapter::getNestedData (const RefIdColumn *colu throw std::runtime_error ("index out of range"); if (subColIndex == 0) - return QString(ESM::Skill::sSkillNames[subRowIndex].c_str()); + return subRowIndex; else if (subColIndex == 1) { if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index 3644fc264b..d29225d53c 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -449,7 +449,7 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data) attrMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcAttributesRefIdAdapter(data))); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), attrMap)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_NpcAttributes, CSMWorld::ColumnBase::Display_String, false, false)); + new RefIdColumn (Columns::ColumnId_Attribute, CSMWorld::ColumnBase::Display_Attribute, false, false)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_UChar, CSMWorld::ColumnBase::Display_Integer)); @@ -461,7 +461,7 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data) skillsMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcSkillsRefIdAdapter(data))); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), skillsMap)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_NpcSkills, CSMWorld::ColumnBase::Display_String, false, false)); + new RefIdColumn (Columns::ColumnId_SkillImpact, CSMWorld::ColumnBase::Display_SkillImpact, false, false)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_UChar, CSMWorld::ColumnBase::Display_Integer)); @@ -473,16 +473,16 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data) miscMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcMiscRefIdAdapter(data))); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), miscMap)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_NpcLevel, CSMWorld::ColumnBase::Display_Integer, + new RefIdColumn (Columns::ColumnId_Level, CSMWorld::ColumnBase::Display_Integer, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_NpcFactionID, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_NpcHealth, CSMWorld::ColumnBase::Display_Integer)); + new RefIdColumn (Columns::ColumnId_Health, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_NpcMana, CSMWorld::ColumnBase::Display_Integer)); + new RefIdColumn (Columns::ColumnId_Mana, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_NpcFatigue, CSMWorld::ColumnBase::Display_Integer)); + new RefIdColumn (Columns::ColumnId_Fatigue, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_NpcDisposition, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn( @@ -490,7 +490,7 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data) mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_NpcRank, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_NpcGold, CSMWorld::ColumnBase::Display_Integer)); + new RefIdColumn (Columns::ColumnId_Gold, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_NpcPersistence, CSMWorld::ColumnBase::Display_Boolean)); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 25949ef15e..4590a2dd05 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -104,7 +104,6 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) { CSMWorld::ColumnBase::Display_AiPackageType, CSMWorld::Columns::ColumnId_AiPackageType, false }, { CSMWorld::ColumnBase::Display_InfoCondFunc, CSMWorld::Columns::ColumnId_InfoCondFunc, false }, { CSMWorld::ColumnBase::Display_InfoCondComp, CSMWorld::Columns::ColumnId_InfoCondComp, false }, - { CSMWorld::ColumnBase::Display_RaceSkill, CSMWorld::Columns::ColumnId_RaceSkill, true }, }; for (std::size_t i=0; i Date: Sat, 12 Sep 2015 10:00:23 +1000 Subject: [PATCH 44/81] Add missing fields for editing creatures. - Should resolve resolve bugs #2878 (level), #2901 (gold) and #2889 (health). - Moved Soul, Combat, Magic and Stealth editing to dialogue only (to be consistent with editing NPCs) (cherry picked from commit 5a5e1a3b22e21d8fb847f4ab04497c2d4fdaf4c5) Conflicts: apps/opencs/model/world/columns.cpp apps/opencs/model/world/columns.hpp --- apps/opencs/model/world/columns.cpp | 8 + apps/opencs/model/world/columns.hpp | 19 +- apps/opencs/model/world/refidadapterimp.cpp | 313 ++++++++++++++++++-- apps/opencs/model/world/refidadapterimp.hpp | 98 +++++- apps/opencs/model/world/refidcollection.cpp | 64 +++- 5 files changed, 460 insertions(+), 42 deletions(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 563cc1615c..398fe29183 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -285,6 +285,7 @@ namespace CSMWorld { ColumnId_NpcMisc, "NPC Misc" }, { ColumnId_Level, "Level" }, { ColumnId_NpcFactionID, "Faction ID" }, + { ColumnId_Mana, "Mana" }, { ColumnId_Fatigue, "Fatigue" }, { ColumnId_NpcDisposition, "NPC Disposition" }, @@ -311,6 +312,13 @@ namespace CSMWorld { ColumnId_FileDescription, "File Description" }, { ColumnId_Author, "Author" }, + { ColumnId_CreatureAttributes, "Creature Attributes" }, + { ColumnId_AttributeValue, "Attrib Value" }, + { ColumnId_CreatureAttack, "Creature Attack" }, + { ColumnId_MinAttack, "Min Attack" }, + { ColumnId_MaxAttack, "Max Attack" }, + { ColumnId_CreatureMisc, "Creature Misc" }, + { ColumnId_SpellSrc, "From Race" }, { ColumnId_SpellCost, "Cast Cost" }, { ColumnId_SpellChance, "Cast Chance" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 0d8064e6aa..a8b8cf2d6c 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -102,7 +102,7 @@ namespace CSMWorld ColumnId_OriginalCreature = 87, ColumnId_Biped = 88, ColumnId_HasWeapon = 89, - // unused + // used for SpellSrc ColumnId_Swims = 91, ColumnId_Flies = 92, ColumnId_Walks = 93, @@ -189,7 +189,7 @@ namespace CSMWorld ColumnId_RotX = 174, ColumnId_RotY = 175, ColumnId_RotZ = 176, - // unused + // used for SpellCost ColumnId_OwnerGlobal = 178, ColumnId_DefaultProfile = 179, ColumnId_BypassNewGame = 180, @@ -278,7 +278,7 @@ namespace CSMWorld ColumnId_NpcMisc = 251, ColumnId_Level = 252, ColumnId_NpcFactionID = 253, - // unused + // used for SpellChance ColumnId_Mana = 255, ColumnId_Fatigue = 256, ColumnId_NpcDisposition = 257, @@ -309,9 +309,16 @@ namespace CSMWorld ColumnId_MinMagnitude = 278, ColumnId_MaxMagnitude = 279, - ColumnId_SpellSrc = 280, - ColumnId_SpellCost = 281, - ColumnId_SpellChance = 282, + ColumnId_CreatureAttributes = 280, + ColumnId_AttributeValue = 281, + ColumnId_CreatureAttack = 282, + ColumnId_MinAttack = 283, + ColumnId_MaxAttack = 284, + ColumnId_CreatureMisc = 285, + + ColumnId_SpellSrc = 90, + ColumnId_SpellCost = 177, + ColumnId_SpellChance = 254, // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index e4cf396038..3b0008d183 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -301,12 +301,11 @@ void CSMWorld::ContainerRefIdAdapter::setData (const RefIdColumn *column, RefIdD CSMWorld::CreatureColumns::CreatureColumns (const ActorColumns& actorColumns) : ActorColumns (actorColumns), mType(NULL), - mSoul(NULL), mScale(NULL), mOriginal(NULL), - mCombat(NULL), - mMagic(NULL), - mStealth(NULL) + mAttributes(NULL), + mAttacks(NULL), + mMisc(NULL) {} CSMWorld::CreatureRefIdAdapter::CreatureRefIdAdapter (const CreatureColumns& columns) @@ -322,23 +321,20 @@ QVariant CSMWorld::CreatureRefIdAdapter::getData (const RefIdColumn *column, con if (column==mColumns.mType) return record.get().mData.mType; - if (column==mColumns.mSoul) - return record.get().mData.mSoul; - if (column==mColumns.mScale) return record.get().mScale; if (column==mColumns.mOriginal) return QString::fromUtf8 (record.get().mOriginal.c_str()); - if (column==mColumns.mCombat) - return static_cast (record.get().mData.mCombat); + if (column==mColumns.mAttributes) + return true; // Required to show nested tables in dialogue subview - if (column==mColumns.mMagic) - return static_cast (record.get().mData.mMagic); + if (column==mColumns.mAttacks) + return true; // Required to show nested tables in dialogue subview - if (column==mColumns.mStealth) - return static_cast (record.get().mData.mStealth); + if (column==mColumns.mMisc) + return true; // Required to show nested items in dialogue subview std::map::const_iterator iter = mColumns.mFlags.find (column); @@ -359,18 +355,10 @@ void CSMWorld::CreatureRefIdAdapter::setData (const RefIdColumn *column, RefIdDa if (column==mColumns.mType) creature.mData.mType = value.toInt(); - else if (column==mColumns.mSoul) - creature.mData.mSoul = value.toInt(); else if (column==mColumns.mScale) creature.mScale = value.toFloat(); else if (column==mColumns.mOriginal) creature.mOriginal = value.toString().toUtf8().constData(); - else if (column==mColumns.mCombat) - creature.mData.mCombat = value.toInt(); - else if (column==mColumns.mMagic) - creature.mData.mMagic = value.toInt(); - else if (column==mColumns.mStealth) - creature.mData.mStealth = value.toInt(); else { std::map::const_iterator iter = @@ -1077,6 +1065,289 @@ int CSMWorld::NpcMiscRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, return 1; // fixed at size 1 } +CSMWorld::CreatureAttributesRefIdAdapter::CreatureAttributesRefIdAdapter() +{} + +void CSMWorld::CreatureAttributesRefIdAdapter::addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const +{ + // Do nothing, this table cannot be changed by the user +} + +void CSMWorld::CreatureAttributesRefIdAdapter::removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const +{ + // Do nothing, this table cannot be changed by the user +} + +void CSMWorld::CreatureAttributesRefIdAdapter::setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const +{ + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature))); + ESM::Creature creature = record.get(); + + // store the whole struct + creature.mData = + static_cast > &>(nestedTable).mNestedTable.at(0); + + record.setModified (creature); +} + +CSMWorld::NestedTableWrapperBase* CSMWorld::CreatureAttributesRefIdAdapter::nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const +{ + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature))); + + // return the whole struct + std::vector wrap; + wrap.push_back(record.get().mData); + // deleted by dtor of NestedTableStoring + return new NestedTableWrapper >(wrap); +} + +QVariant CSMWorld::CreatureAttributesRefIdAdapter::getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const +{ + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature))); + + const ESM::Creature creature = record.get(); + + if (subColIndex == 0) + return subRowIndex; + else if (subColIndex == 1) + switch (subRowIndex) + { + case 0: return creature.mData.mStrength; + case 1: return creature.mData.mIntelligence; + case 2: return creature.mData.mWillpower; + case 3: return creature.mData.mAgility; + case 4: return creature.mData.mSpeed; + case 5: return creature.mData.mEndurance; + case 6: return creature.mData.mPersonality; + case 7: return creature.mData.mLuck; + default: return QVariant(); // throw an exception here? + } + else + return QVariant(); // throw an exception here? +} + +void CSMWorld::CreatureAttributesRefIdAdapter::setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const +{ + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Creature))); + ESM::Creature creature = record.get(); + + if (subColIndex == 1) + switch(subRowIndex) + { + case 0: creature.mData.mStrength = value.toInt(); break; + case 1: creature.mData.mIntelligence = value.toInt(); break; + case 2: creature.mData.mWillpower = value.toInt(); break; + case 3: creature.mData.mAgility = value.toInt(); break; + case 4: creature.mData.mSpeed = value.toInt(); break; + case 5: creature.mData.mEndurance = value.toInt(); break; + case 6: creature.mData.mPersonality = value.toInt(); break; + case 7: creature.mData.mLuck = value.toInt(); break; + default: return; // throw an exception here? + } + else + return; // throw an exception here? + + record.setModified (creature); +} + +int CSMWorld::CreatureAttributesRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const +{ + return 2; +} + +int CSMWorld::CreatureAttributesRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const +{ + // There are 8 attributes + return 8; +} + +CSMWorld::CreatureAttackRefIdAdapter::CreatureAttackRefIdAdapter() +{} + +void CSMWorld::CreatureAttackRefIdAdapter::addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const +{ + // Do nothing, this table cannot be changed by the user +} + +void CSMWorld::CreatureAttackRefIdAdapter::removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const +{ + // Do nothing, this table cannot be changed by the user +} + +void CSMWorld::CreatureAttackRefIdAdapter::setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const +{ + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature))); + ESM::Creature creature = record.get(); + + // store the whole struct + creature.mData = + static_cast > &>(nestedTable).mNestedTable.at(0); + + record.setModified (creature); +} + +CSMWorld::NestedTableWrapperBase* CSMWorld::CreatureAttackRefIdAdapter::nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const +{ + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature))); + + // return the whole struct + std::vector wrap; + wrap.push_back(record.get().mData); + // deleted by dtor of NestedTableStoring + return new NestedTableWrapper >(wrap); +} + +QVariant CSMWorld::CreatureAttackRefIdAdapter::getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const +{ + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature))); + + const ESM::Creature creature = record.get(); + + if (subRowIndex < 0 || subRowIndex > 2 || subColIndex < 0 || subColIndex > 2) + throw std::runtime_error ("index out of range"); + + if (subColIndex == 0) + return subRowIndex + 1; + else if (subColIndex < 3) // 1 or 2 + return creature.mData.mAttack[(subRowIndex * 2) + (subColIndex - 1)]; + else + return QVariant(); // throw an exception here? +} + +void CSMWorld::CreatureAttackRefIdAdapter::setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const +{ + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Creature))); + ESM::Creature creature = record.get(); + + if (subRowIndex < 0 || subRowIndex > 2) + throw std::runtime_error ("index out of range"); + + if (subColIndex == 1 || subColIndex == 2) + creature.mData.mAttack[(subRowIndex * 2) + (subColIndex - 1)] = value.toInt(); + else + return; // throw an exception here? + + record.setModified (creature); +} + +int CSMWorld::CreatureAttackRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const +{ + return 3; +} + +int CSMWorld::CreatureAttackRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const +{ + // There are 3 attacks + return 3; +} + +CSMWorld::CreatureMiscRefIdAdapter::CreatureMiscRefIdAdapter() +{} + +CSMWorld::CreatureMiscRefIdAdapter::~CreatureMiscRefIdAdapter() +{} + +void CSMWorld::CreatureMiscRefIdAdapter::addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const +{ + throw std::logic_error ("cannot add a row to a fixed table"); +} + +void CSMWorld::CreatureMiscRefIdAdapter::removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const +{ + throw std::logic_error ("cannot remove a row to a fixed table"); +} + +void CSMWorld::CreatureMiscRefIdAdapter::setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const +{ + throw std::logic_error ("table operation not supported"); +} + +CSMWorld::NestedTableWrapperBase* CSMWorld::CreatureMiscRefIdAdapter::nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const +{ + throw std::logic_error ("table operation not supported"); +} + +QVariant CSMWorld::CreatureMiscRefIdAdapter::getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const +{ + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature))); + + const ESM::Creature creature = record.get(); + + switch (subColIndex) + { + case 0: return creature.mData.mLevel; + case 1: return creature.mData.mHealth; + case 2: return creature.mData.mMana; + case 3: return creature.mData.mFatigue; + case 4: return creature.mData.mSoul; + case 5: return creature.mData.mCombat; + case 6: return creature.mData.mMagic; + case 7: return creature.mData.mStealth; + case 8: return creature.mData.mGold; + default: return QVariant(); // throw an exception here? + } +} + +void CSMWorld::CreatureMiscRefIdAdapter::setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const +{ + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Creature))); + ESM::Creature creature = record.get(); + + switch(subColIndex) + { + case 0: creature.mData.mLevel = value.toInt(); break; + case 1: creature.mData.mHealth = value.toInt(); break; + case 2: creature.mData.mMana = value.toInt(); break; + case 3: creature.mData.mFatigue = value.toInt(); break; + case 4: creature.mData.mSoul = value.toInt(); break; + case 5: creature.mData.mCombat = value.toInt(); break; + case 6: creature.mData.mMagic = value.toInt(); break; + case 7: creature.mData.mStealth = value.toInt(); break; + case 8: creature.mData.mGold = value.toInt(); break; + default: return; // throw an exception here? + } + + record.setModified (creature); +} + +int CSMWorld::CreatureMiscRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const +{ + return 9; // Level, Health, Mana, Fatigue, Soul, Combat, Magic, Steath, Gold +} + +int CSMWorld::CreatureMiscRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const +{ + return 1; // fixed at size 1 +} + CSMWorld::WeaponColumns::WeaponColumns (const EnchantableColumns& columns) : EnchantableColumns (columns) {} diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 9d1c1907b1..0ce12a62fd 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -659,12 +659,11 @@ namespace CSMWorld { std::map mFlags; const RefIdColumn *mType; - const RefIdColumn *mSoul; const RefIdColumn *mScale; const RefIdColumn *mOriginal; - const RefIdColumn *mCombat; - const RefIdColumn *mMagic; - const RefIdColumn *mStealth; + const RefIdColumn *mAttributes; + const RefIdColumn *mAttack; + const RefIdColumn *mMisc; CreatureColumns (const ActorColumns& actorColumns); }; @@ -908,6 +907,97 @@ namespace CSMWorld virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const; }; + class CreatureAttributesRefIdAdapter : public NestedRefIdAdapterBase + { + public: + + CreatureAttributesRefIdAdapter (); + + virtual void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const; + + virtual void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const; + + virtual void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const; + + virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const; + + virtual QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const; + + virtual void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const; + + virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const; + + virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const; + }; + + class CreatureAttackRefIdAdapter : public NestedRefIdAdapterBase + { + public: + + CreatureAttackRefIdAdapter (); + + virtual void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const; + + virtual void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const; + + virtual void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const; + + virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const; + + virtual QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const; + + virtual void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const; + + virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const; + + virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const; + }; + + class CreatureMiscRefIdAdapter : public NestedRefIdAdapterBase + { + CreatureMiscRefIdAdapter (const CreatureMiscRefIdAdapter&); + CreatureMiscRefIdAdapter& operator= (const CreatureMiscRefIdAdapter&); + + public: + + CreatureMiscRefIdAdapter (); + virtual ~CreatureMiscRefIdAdapter(); + + virtual void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const; + + virtual void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const; + + virtual void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const; + + virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const; + + virtual QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const; + + virtual void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const; + + virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const; + + virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const; + }; + template class EffectsListAdapter; diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index d29225d53c..1a7db882b0 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -307,21 +307,10 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data) mColumns.push_back (RefIdColumn (Columns::ColumnId_CreatureType, ColumnBase::Display_CreatureType)); creatureColumns.mType = &mColumns.back(); - mColumns.push_back (RefIdColumn (Columns::ColumnId_SoulPoints, ColumnBase::Display_Integer)); - creatureColumns.mSoul = &mColumns.back(); mColumns.push_back (RefIdColumn (Columns::ColumnId_Scale, ColumnBase::Display_Float)); creatureColumns.mScale = &mColumns.back(); mColumns.push_back (RefIdColumn (Columns::ColumnId_OriginalCreature, ColumnBase::Display_Creature)); creatureColumns.mOriginal = &mColumns.back(); - mColumns.push_back ( - RefIdColumn (Columns::ColumnId_CombatState, ColumnBase::Display_Integer)); - creatureColumns.mCombat = &mColumns.back(); - mColumns.push_back ( - RefIdColumn (Columns::ColumnId_MagicState, ColumnBase::Display_Integer)); - creatureColumns.mMagic = &mColumns.back(); - mColumns.push_back ( - RefIdColumn (Columns::ColumnId_StealthState, ColumnBase::Display_Integer)); - creatureColumns.mStealth = &mColumns.back(); static const struct { @@ -360,6 +349,59 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data) creatureColumns.mFlags.insert (std::make_pair (respawn, ESM::Creature::Respawn)); + // Nested table + mColumns.push_back(RefIdColumn (Columns::ColumnId_CreatureAttributes, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + creatureColumns.mAttributes = &mColumns.back(); + std::map creaAttrMap; + creaAttrMap.insert(std::make_pair(UniversalId::Type_Creature, new CreatureAttributesRefIdAdapter())); + mNestedAdapters.push_back (std::make_pair(&mColumns.back(), creaAttrMap)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_Attribute, CSMWorld::ColumnBase::Display_Attribute, false, false)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_AttributeValue, CSMWorld::ColumnBase::Display_Integer)); + + // Nested table + mColumns.push_back(RefIdColumn (Columns::ColumnId_CreatureAttack, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + creatureColumns.mAttacks = &mColumns.back(); + std::map attackMap; + attackMap.insert(std::make_pair(UniversalId::Type_Creature, new CreatureAttackRefIdAdapter())); + mNestedAdapters.push_back (std::make_pair(&mColumns.back(), attackMap)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_CreatureAttack, CSMWorld::ColumnBase::Display_Integer, false, false)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_MinAttack, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_MaxAttack, CSMWorld::ColumnBase::Display_Integer)); + + // Nested list + mColumns.push_back(RefIdColumn (Columns::ColumnId_CreatureMisc, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_List)); + creatureColumns.mMisc = &mColumns.back(); + std::map creaMiscMap; + creaMiscMap.insert(std::make_pair(UniversalId::Type_Creature, new CreatureMiscRefIdAdapter())); + mNestedAdapters.push_back (std::make_pair(&mColumns.back(), creaMiscMap)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_Level, CSMWorld::ColumnBase::Display_Integer, + ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_Health, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_Mana, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_Fatigue, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_SoulPoints, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_CombatState, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_MagicState, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_StealthState, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_Gold, CSMWorld::ColumnBase::Display_Integer)); + mColumns.push_back (RefIdColumn (Columns::ColumnId_OpenSound, ColumnBase::Display_Sound)); const RefIdColumn *openSound = &mColumns.back(); From 2f76a1510e3791c530cc5877d51afae74cfc94e1 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 12 Sep 2015 10:15:32 +1000 Subject: [PATCH 45/81] Remove AI flag from the UI and instead auto-detect whether to save AIDT records. Should resolve bug #2879. (cherry picked from commit 45aee1b5088cb110e06540356670b806887f7372) Conflicts: apps/opencs/model/world/refidadapterimp.hpp --- apps/opencs/model/world/columns.cpp | 1 - apps/opencs/model/world/columns.hpp | 2 +- apps/opencs/model/world/refidadapterimp.cpp | 6 ------ apps/opencs/model/world/refidadapterimp.hpp | 5 +---- apps/opencs/model/world/refidcollection.cpp | 2 -- components/esm/loadcrea.cpp | 7 ++++++- components/esm/loadnpc.cpp | 7 ++++++- 7 files changed, 14 insertions(+), 16 deletions(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 398fe29183..28e6fd050c 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -71,7 +71,6 @@ namespace CSMWorld { ColumnId_Weight, "Weight" }, { ColumnId_EnchantmentPoints, "Enchantment Points" }, { ColumnId_Quality, "Quality" }, - { ColumnId_Ai, "AI" }, { ColumnId_AiHello, "AI Hello" }, { ColumnId_AiFlee, "AI Flee" }, { ColumnId_AiFight, "AI Fight" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index a8b8cf2d6c..ea50822b96 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -65,7 +65,7 @@ namespace CSMWorld ColumnId_Weight = 50, ColumnId_EnchantmentPoints = 51, ColumnId_Quality = 52, - ColumnId_Ai = 53, + // unused ColumnId_AiHello = 54, ColumnId_AiFlee = 55, ColumnId_AiFight = 56, diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index 3b0008d183..64c18a99be 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -1447,9 +1447,6 @@ QVariant ActorRefIdAdapter::getData (const RefIdColumn *column, const const Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter::getType()))); - if (column==mActors.mHasAi) - return record.get().mHasAI!=0; - if (column==mActors.mHello) return record.get().mAiData.mHello; @@ -1631,9 +1628,6 @@ QVariant ActorRefIdAdapter::getData (const RefIdColumn *column, c const Record& record = static_cast&> ( data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter::getType()))); - if (column==mActors.mHasAi) - return record.get().mHasAI!=0; - if (column==mActors.mHello) return record.get().mAiData.mHello; diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 0ce12a62fd..aac5ec7811 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -485,7 +485,6 @@ namespace CSMWorld struct ActorColumns : public NameColumns { - const RefIdColumn *mHasAi; const RefIdColumn *mHello; const RefIdColumn *mFlee; const RefIdColumn *mFight; @@ -531,9 +530,7 @@ namespace CSMWorld data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter::getType()))); RecordT record2 = record.get(); - if (column==mActors.mHasAi) - record2.mHasAI = value.toInt(); - else if (column==mActors.mHello) + if (column==mActors.mHello) record2.mAiData.mHello = value.toInt(); else if (column==mActors.mFlee) record2.mAiData.mFlee = value.toInt(); diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index 1a7db882b0..588cdcd911 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -114,8 +114,6 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data) ActorColumns actorsColumns (nameColumns); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Ai, ColumnBase::Display_Boolean)); - actorsColumns.mHasAi = &mColumns.back(); mColumns.push_back (RefIdColumn (Columns::ColumnId_AiHello, ColumnBase::Display_Integer)); actorsColumns.mHello = &mColumns.back(); mColumns.push_back (RefIdColumn (Columns::ColumnId_AiFlee, ColumnBase::Display_Integer)); diff --git a/components/esm/loadcrea.cpp b/components/esm/loadcrea.cpp index 50c47349ca..8c4f49e452 100644 --- a/components/esm/loadcrea.cpp +++ b/components/esm/loadcrea.cpp @@ -96,7 +96,12 @@ namespace ESM { mInventory.save(esm); mSpells.save(esm); - if (mHasAI) { + if (mAiData.mHello != 0 + || mAiData.mFight != 0 + || mAiData.mFlee != 0 + || mAiData.mAlarm != 0 + || mAiData.mServices != 0) + { esm.writeHNT("AIDT", mAiData, sizeof(mAiData)); } mTransport.save(esm); diff --git a/components/esm/loadnpc.cpp b/components/esm/loadnpc.cpp index 44d2987853..67a437176c 100644 --- a/components/esm/loadnpc.cpp +++ b/components/esm/loadnpc.cpp @@ -121,7 +121,12 @@ namespace ESM mInventory.save(esm); mSpells.save(esm); - if (mHasAI) { + if (mAiData.mHello != 0 + || mAiData.mFight != 0 + || mAiData.mFlee != 0 + || mAiData.mAlarm != 0 + || mAiData.mServices != 0) + { esm.writeHNT("AIDT", mAiData, sizeof(mAiData)); } From 148ccb79e8fc117ca84f32bf894604285aae31e6 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 12 Sep 2015 10:17:14 +1000 Subject: [PATCH 46/81] Set default creature scale to 1. Partially resolves bug #2880. (no creature verifier yet) (cherry picked from commit 192f01e3ac5db4f0d1d9d78c2a419b274f307bb1) --- components/esm/loadcrea.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esm/loadcrea.cpp b/components/esm/loadcrea.cpp index 8c4f49e452..fb235e6b3d 100644 --- a/components/esm/loadcrea.cpp +++ b/components/esm/loadcrea.cpp @@ -120,7 +120,7 @@ namespace ESM { for (int i=0; i<6; ++i) mData.mAttack[i] = 0; mData.mGold = 0; mFlags = 0; - mScale = 0; + mScale = 1.f; mModel.clear(); mName.clear(); mScript.clear(); From ae1439f22380ecf6abc0e924da48bc42b4d22772 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 12 Sep 2015 11:18:07 +1000 Subject: [PATCH 47/81] Fix typo. (cherry picked from commit 1365b8edd1f0a20e97ccb9a30cd74a6dc97c44bd) --- apps/opencs/model/world/refidadapterimp.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index aac5ec7811..3da273c890 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -659,7 +659,7 @@ namespace CSMWorld const RefIdColumn *mScale; const RefIdColumn *mOriginal; const RefIdColumn *mAttributes; - const RefIdColumn *mAttack; + const RefIdColumn *mAttacks; const RefIdColumn *mMisc; CreatureColumns (const ActorColumns& actorColumns); From a2294117cdcd209edf993898d1af6abf180753aa Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 15 Sep 2015 14:57:07 +0200 Subject: [PATCH 48/81] replaced context-sensitive implementation of allowing digits at the beginning of names with a more general implementation (Fixes #1730) (cherry picked from commit 4d94f38f4b7255fd1abbcdc8d2bd388e604bec04) --- components/compiler/fileparser.cpp | 2 -- components/compiler/scanner.cpp | 38 +++++++++++++++++------------- components/compiler/scanner.hpp | 3 --- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/components/compiler/fileparser.cpp b/components/compiler/fileparser.cpp index 423841ac3e..e90e9a8f6e 100644 --- a/components/compiler/fileparser.cpp +++ b/components/compiler/fileparser.cpp @@ -65,7 +65,6 @@ namespace Compiler if (mState==BeginState && keyword==Scanner::K_begin) { mState = NameState; - scanner.allowNameStartingwithDigit(); return true; } @@ -112,7 +111,6 @@ namespace Compiler scanner.scan (mScriptParser); mState = EndNameState; - scanner.allowNameStartingwithDigit(); return true; } diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index 5af396d275..f25e69e399 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -47,9 +47,6 @@ namespace Compiler bool Scanner::scanToken (Parser& parser) { - bool allowDigit = mNameStartingWithDigit; - mNameStartingWithDigit = false; - switch (mPutback) { case Putback_Special: @@ -114,7 +111,6 @@ namespace Compiler else if (isWhitespace (c)) { mLoc.mLiteral.clear(); - mNameStartingWithDigit = allowDigit; return true; } else if (c==':') @@ -123,7 +119,7 @@ namespace Compiler mLoc.mLiteral.clear(); return true; } - else if (std::isalpha (c) || c=='_' || c=='"' || (allowDigit && std::isdigit (c))) + else if (std::isalpha (c) || c=='_' || c=='"') { bool cont = false; @@ -179,10 +175,18 @@ namespace Compiler { value += c; } - else if (std::isalpha (c) || c=='_') - error = true; - else if (c=='.' && !error) + else if (isStringCharacter (c)) { + error = true; + value += c; + } + else if (c=='.') + { + if (error) + { + putback (c); + break; + } return scanFloat (value, parser, cont); } else @@ -193,7 +197,15 @@ namespace Compiler } if (error) - return false; + { + /// workaround that allows names to begin with digits + /// \todo disable + TokenLoc loc (mLoc); + mLoc.mLiteral.clear(); + cont = parser.parseName (value, loc, *this); + return true; +// return false; + } TokenLoc loc (mLoc); mLoc.mLiteral.clear(); @@ -555,8 +567,7 @@ namespace Compiler Scanner::Scanner (ErrorHandler& errorHandler, std::istream& inputStream, const Extensions *extensions) : mErrorHandler (errorHandler), mStream (inputStream), mExtensions (extensions), - mPutback (Putback_None), mPutbackCode(0), mPutbackInteger(0), mPutbackFloat(0), - mNameStartingWithDigit (false) + mPutback (Putback_None), mPutbackCode(0), mPutbackInteger(0), mPutbackFloat(0) { } @@ -608,9 +619,4 @@ namespace Compiler if (mExtensions) mExtensions->listKeywords (keywords); } - - void Scanner::allowNameStartingwithDigit() - { - mNameStartingWithDigit = true; - } } diff --git a/components/compiler/scanner.hpp b/components/compiler/scanner.hpp index ed01bbe44e..8478959785 100644 --- a/components/compiler/scanner.hpp +++ b/components/compiler/scanner.hpp @@ -124,9 +124,6 @@ namespace Compiler void listKeywords (std::vector& keywords); ///< Append all known keywords to \a kaywords. - - /// For the next token allow names to start with a digit. - void allowNameStartingwithDigit(); }; } From fcb9068c198b315567d9dc53b31ed8e1e6cf1cee Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 Sep 2015 20:45:37 +0200 Subject: [PATCH 49/81] Fix tab indentations in apps/ and components/ (cherry picked from commit a47617c21f11c33e10b8a635292c3b1a4d8d5769) Conflicts: apps/openmw/mwinput/inputmanagerimp.cpp apps/openmw/mwmechanics/aicombat.cpp apps/openmw/mwphysics/physicssystem.cpp --- apps/esmtool/record.cpp | 30 +++++++++---------- apps/esmtool/record.hpp | 2 +- .../model/world/infotableproxymodel.cpp | 2 +- apps/opencs/view/widget/droplineedit.cpp | 2 +- apps/openmw/android_commandLine.cpp | 26 ++++++++-------- apps/openmw/android_main.c | 20 ++++++------- apps/openmw/crashcatcher.cpp | 4 +-- apps/openmw/mwgui/debugwindow.cpp | 8 ++--- apps/openmw/mwgui/tooltips.hpp | 2 +- apps/openmw/mwgui/widgets.cpp | 4 +-- apps/openmw/mwinput/inputmanagerimp.cpp | 14 ++++----- apps/openmw/mwmechanics/aicombat.cpp | 2 +- apps/openmw/mwworld/worldimp.cpp | 2 +- components/compiler/extensions0.hpp | 2 +- components/esm/loadmgef.hpp | 4 +-- components/files/configurationmanager.hpp | 10 +++---- extern/sdl4ogre/sdlinputwrapper.hpp | 4 +-- 17 files changed, 69 insertions(+), 69 deletions(-) diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index 76c14e728d..5fe6471b0f 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -493,14 +493,14 @@ void Record::print() std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl; if (mPrintPlain) { - std::cout << " Text:" << std::endl; - std::cout << "START--------------------------------------" << std::endl; - std::cout << mData.mText << std::endl; - std::cout << "END----------------------------------------" << std::endl; + std::cout << " Text:" << std::endl; + std::cout << "START--------------------------------------" << std::endl; + std::cout << mData.mText << std::endl; + std::cout << "END----------------------------------------" << std::endl; } else { - std::cout << " Text: [skipped]" << std::endl; + std::cout << " Text: [skipped]" << std::endl; } } @@ -799,14 +799,14 @@ void Record::print() { if (mPrintPlain) { - std::cout << " Result Script:" << std::endl; - std::cout << "START--------------------------------------" << std::endl; - std::cout << mData.mResultScript << std::endl; - std::cout << "END----------------------------------------" << std::endl; + std::cout << " Result Script:" << std::endl; + std::cout << "START--------------------------------------" << std::endl; + std::cout << mData.mResultScript << std::endl; + std::cout << "END----------------------------------------" << std::endl; } else { - std::cout << " Result Script: [skipped]" << std::endl; + std::cout << " Result Script: [skipped]" << std::endl; } } } @@ -1201,14 +1201,14 @@ void Record::print() if (mPrintPlain) { - std::cout << " Script:" << std::endl; - std::cout << "START--------------------------------------" << std::endl; - std::cout << mData.mScriptText << std::endl; - std::cout << "END----------------------------------------" << std::endl; + std::cout << " Script:" << std::endl; + std::cout << "START--------------------------------------" << std::endl; + std::cout << mData.mScriptText << std::endl; + std::cout << "END----------------------------------------" << std::endl; } else { - std::cout << " Script: [skipped]" << std::endl; + std::cout << " Script: [skipped]" << std::endl; } } diff --git a/apps/esmtool/record.hpp b/apps/esmtool/record.hpp index c1b90ac2bc..5e03c64dba 100644 --- a/apps/esmtool/record.hpp +++ b/apps/esmtool/record.hpp @@ -53,7 +53,7 @@ namespace EsmTool } void setPrintPlain(bool plain) { - mPrintPlain = plain; + mPrintPlain = plain; } virtual void load(ESM::ESMReader &esm) = 0; diff --git a/apps/opencs/model/world/infotableproxymodel.cpp b/apps/opencs/model/world/infotableproxymodel.cpp index f55f775ab3..4f0b2e7528 100644 --- a/apps/opencs/model/world/infotableproxymodel.cpp +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -16,7 +16,7 @@ namespace CSMWorld::InfoTableProxyModel::InfoTableProxyModel(CSMWorld::UniversalId::Type type, QObject *parent) : IdTableProxyModel(parent), mType(type), - mInfoColumnId(type == UniversalId::Type_TopicInfos ? Columns::ColumnId_Topic : + mInfoColumnId(type == UniversalId::Type_TopicInfos ? Columns::ColumnId_Topic : Columns::ColumnId_Journal), mInfoColumnIndex(-1), mLastAddedSourceRow(-1) diff --git a/apps/opencs/view/widget/droplineedit.cpp b/apps/opencs/view/widget/droplineedit.cpp index 1df598cb8d..2ca3064613 100644 --- a/apps/opencs/view/widget/droplineedit.cpp +++ b/apps/opencs/view/widget/droplineedit.cpp @@ -35,7 +35,7 @@ void CSVWidget::DropLineEdit::dropEvent(QDropEvent *event) if (CSVWorld::DragDropUtils::canAcceptData(*event, mDropType)) { CSMWorld::UniversalId id = CSVWorld::DragDropUtils::getAcceptedData(*event, mDropType); - setText(QString::fromUtf8(id.getId().c_str())); + setText(QString::fromUtf8(id.getId().c_str())); emit tableMimeDataDropped(id, CSVWorld::DragDropUtils::getTableMimeData(*event)->getDocumentPtr()); } } diff --git a/apps/openmw/android_commandLine.cpp b/apps/openmw/android_commandLine.cpp index ebfff28ca2..7e7f368e05 100644 --- a/apps/openmw/android_commandLine.cpp +++ b/apps/openmw/android_commandLine.cpp @@ -7,21 +7,21 @@ int argcData; extern "C" void releaseArgv(); void releaseArgv() { - delete[] argvData; + delete[] argvData; } JNIEXPORT void JNICALL Java_ui_activity_GameActivity_commandLine(JNIEnv *env, - jobject obj, jint argc, jobjectArray stringArray) { - jboolean iscopy; - argcData = (int) argc; - argvData = new const char *[argcData + 1]; - argvData[0] = "openmw"; - for (int i = 1; i < argcData + 1; i++) { - jstring string = (jstring) (env)->GetObjectArrayElement(stringArray, - i - 1); - argvData[i] = (env)->GetStringUTFChars(string, &iscopy); - (env)->DeleteLocalRef(string); - } - (env)->DeleteLocalRef(stringArray); + jobject obj, jint argc, jobjectArray stringArray) { + jboolean iscopy; + argcData = (int) argc; + argvData = new const char *[argcData + 1]; + argvData[0] = "openmw"; + for (int i = 1; i < argcData + 1; i++) { + jstring string = (jstring) (env)->GetObjectArrayElement(stringArray, + i - 1); + argvData[i] = (env)->GetStringUTFChars(string, &iscopy); + (env)->DeleteLocalRef(string); + } + (env)->DeleteLocalRef(stringArray); } diff --git a/apps/openmw/android_main.c b/apps/openmw/android_main.c index 1b28395199..47b77a8b38 100644 --- a/apps/openmw/android_main.c +++ b/apps/openmw/android_main.c @@ -16,22 +16,22 @@ extern const char **argvData; void releaseArgv(); int Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls, - jobject obj) { + jobject obj) { - SDL_Android_Init(env, cls); + SDL_Android_Init(env, cls); - SDL_SetMainReady(); + SDL_SetMainReady(); - /* Run the application code! */ + /* Run the application code! */ - int status; + int status; - status = main(argcData+1, argvData); - releaseArgv(); - /* Do not issue an exit or the whole application will terminate instead of just the SDL thread */ - /* exit(status); */ + status = main(argcData+1, argvData); + releaseArgv(); + /* Do not issue an exit or the whole application will terminate instead of just the SDL thread */ + /* exit(status); */ - return status; + return status; } #endif /* __ANDROID__ */ diff --git a/apps/openmw/crashcatcher.cpp b/apps/openmw/crashcatcher.cpp index 8f25d041cb..373d78746c 100644 --- a/apps/openmw/crashcatcher.cpp +++ b/apps/openmw/crashcatcher.cpp @@ -37,8 +37,8 @@ static const char pipe_err[] = "!!! Failed to create pipe\n"; static const char fork_err[] = "!!! Failed to fork debug process\n"; static const char exec_err[] = "!!! Failed to exec debug process\n"; -#ifndef PATH_MAX /* Not all platforms (GNU Hurd) have this. */ -# define PATH_MAX 256 +#ifndef PATH_MAX /* Not all platforms (GNU Hurd) have this. */ +# define PATH_MAX 256 #endif static char argv0[PATH_MAX]; diff --git a/apps/openmw/mwgui/debugwindow.cpp b/apps/openmw/mwgui/debugwindow.cpp index a6dab66c10..37ea3470d4 100644 --- a/apps/openmw/mwgui/debugwindow.cpp +++ b/apps/openmw/mwgui/debugwindow.cpp @@ -18,9 +18,9 @@ namespace float accumulated_time=0,parent_time = pit->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : pit->Get_Current_Parent_Total_Time(); int i,j; int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset(); - for (i=0;iGet_Current_Parent_Name())+" (total running time: "+MyGUI::utility::toString(parent_time,3)+" ms) ---\n"; os << s; @@ -35,7 +35,7 @@ namespace accumulated_time += current_total_time; float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f; - for (j=0;jGet_Current_Name()+" ("+MyGUI::utility::toString(fraction,2)+" %) :: "+MyGUI::utility::toString(ms,3)+" ms / frame ("+MyGUI::utility::toString(pit->Get_Current_Total_Calls())+" calls)\n"; os << s; @@ -47,7 +47,7 @@ namespace { os << "what's wrong\n"; } - for (i=0;i SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f; s = "Unaccounted: ("+MyGUI::utility::toString(unaccounted,3)+" %) :: "+MyGUI::utility::toString(parent_time - accumulated_time,3)+" ms\n"; os << s; diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index cf5bb14a25..84bd15e128 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -106,7 +106,7 @@ namespace MWGui static std::string sSchoolNames[6]; - int mHorizontalScrollIndex; + int mHorizontalScrollIndex; float mDelay; diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index 718624a16f..f373ce2c42 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -607,7 +607,7 @@ namespace MWGui controller->eventRepeatClick += newDelegate(this, &MWScrollBar::repeatClick); controller->setEnabled(mEnableRepeat); controller->setRepeat(mRepeatTriggerTime, mRepeatStepTime); - MyGUI::ControllerManager::getInstance().addItem(this, controller); + MyGUI::ControllerManager::getInstance().addItem(this, controller); } void MWScrollBar::onDecreaseButtonReleased(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) @@ -623,7 +623,7 @@ namespace MWGui controller->eventRepeatClick += newDelegate(this, &MWScrollBar::repeatClick); controller->setEnabled(mEnableRepeat); controller->setRepeat(mRepeatTriggerTime, mRepeatStepTime); - MyGUI::ControllerManager::getInstance().addItem(this, controller); + MyGUI::ControllerManager::getInstance().addItem(this, controller); } void MWScrollBar::onIncreaseButtonReleased(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 2e82faa6dc..795d81ff9f 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -159,9 +159,9 @@ namespace MWInput mControlSwitch["playerviewswitch"] = true; mControlSwitch["vanitymode"] = true; - /* Joystick Init */ + /* Joystick Init */ - //Load controller mappings + // Load controller mappings #if SDL_VERSION_ATLEAST(2,0,2) if(controllerBindingsFile!="") { @@ -169,10 +169,10 @@ namespace MWInput } #endif - //Open all presently connected sticks - int numSticks = SDL_NumJoysticks(); - for(int i = 0; i < numSticks; i++) - { + // Open all presently connected sticks + int numSticks = SDL_NumJoysticks(); + for(int i = 0; i < numSticks; i++) + { if(SDL_IsGameController(i)) { SDL_ControllerDeviceEvent evt; @@ -183,7 +183,7 @@ namespace MWInput { //ICS_LOG(std::string("Unusable controller plugged in: ")+SDL_JoystickNameForIndex(i)); } - } + } } void InputManager::clear() diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 8f43c6280d..5f0eff4e97 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -65,7 +65,7 @@ namespace Ogre::Vector3 dir = to - from; dir.z = 0; dir.normalise(); - float verticalOffset = 200; // instead of '200' here we want the height of the actor + float verticalOffset = 200; // instead of '200' here we want the height of the actor Ogre::Vector3 _from = from + dir*offsetXY + Ogre::Vector3::UNIT_Z * verticalOffset; // cast up-down ray and find height in world space of hit diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index a1aa0166de..b6d5c8e932 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -287,7 +287,7 @@ namespace MWWorld if (mPlayer) { - mPlayer->clear(); + mPlayer->clear(); mPlayer->setCell(0); mPlayer->getPlayer().getRefData() = RefData(); mPlayer->set(mStore.get().find ("player")); diff --git a/components/compiler/extensions0.hpp b/components/compiler/extensions0.hpp index 83f3a44fa6..e9ce6a6d6a 100644 --- a/components/compiler/extensions0.hpp +++ b/components/compiler/extensions0.hpp @@ -44,7 +44,7 @@ namespace Compiler namespace Gui { - void registerExtensions (Extensions& extensions); + void registerExtensions (Extensions& extensions); } namespace Misc diff --git a/components/esm/loadmgef.hpp b/components/esm/loadmgef.hpp index 32b8a85a6d..eeb4268c2c 100644 --- a/components/esm/loadmgef.hpp +++ b/components/esm/loadmgef.hpp @@ -31,9 +31,9 @@ struct MagicEffect CastTouch = 0x80, // Allows range - cast on touch. CastTarget = 0x100, // Allows range - cast on target. UncappedDamage = 0x1000, // Negates multiple cap behaviours. Allows an effect to reduce an attribute below zero; removes the normal minimum effect duration of 1 second. - NonRecastable = 0x4000, // Does not land if parent spell is already affecting target. Shows "you cannot re-cast" message for self target. + NonRecastable = 0x4000, // Does not land if parent spell is already affecting target. Shows "you cannot re-cast" message for self target. Unreflectable = 0x10000, // Cannot be reflected, the effect always lands normally. - CasterLinked = 0x20000, // Must quench if caster is dead, or not an NPC/creature. Not allowed in containter/door trap spells. + CasterLinked = 0x20000, // Must quench if caster is dead, or not an NPC/creature. Not allowed in containter/door trap spells. // Originally modifiable flags AllowSpellmaking = 0x200, // Can be used for spellmaking diff --git a/components/files/configurationmanager.hpp b/components/files/configurationmanager.hpp index 63ae3c6a4c..c7c738b19e 100644 --- a/components/files/configurationmanager.hpp +++ b/components/files/configurationmanager.hpp @@ -56,11 +56,11 @@ struct ConfigurationManager typedef Files::FixedPath<> FixedPathType; typedef const boost::filesystem::path& (FixedPathType::*path_type_f)() const; - #if defined HAVE_UNORDERED_MAP - typedef std::unordered_map TokensMappingContainer; - #else - typedef std::tr1::unordered_map TokensMappingContainer; - #endif + #if defined HAVE_UNORDERED_MAP + typedef std::unordered_map TokensMappingContainer; + #else + typedef std::tr1::unordered_map TokensMappingContainer; + #endif void loadConfig(const boost::filesystem::path& path, boost::program_options::variables_map& variables, diff --git a/extern/sdl4ogre/sdlinputwrapper.hpp b/extern/sdl4ogre/sdlinputwrapper.hpp index a7023207c6..4b57a1c95c 100644 --- a/extern/sdl4ogre/sdlinputwrapper.hpp +++ b/extern/sdl4ogre/sdlinputwrapper.hpp @@ -27,8 +27,8 @@ namespace SFO void setControllerEventCallback(ControllerListener* listen) { mConListener = listen; } void capture(bool windowEventsOnly); - bool isModifierHeld(SDL_Keymod mod); - bool isKeyDown(SDL_Scancode key); + bool isModifierHeld(SDL_Keymod mod); + bool isKeyDown(SDL_Scancode key); void setMouseVisible (bool visible); void setMouseRelative(bool relative); From 9179782002492fe5637a67cfa3527fac59024717 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 Sep 2015 20:50:57 +0200 Subject: [PATCH 50/81] Add travis-ci script to detect tab characters in the code (cherry picked from commit ab97a90c760fb3a558f25bd49527bf69fbba8d64) --- .travis.yml | 2 +- CI/check_tabs.sh | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100755 CI/check_tabs.sh diff --git a/.travis.yml b/.travis.yml index 6b03be1141..bd4aefbdbb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,8 +40,8 @@ script: - cd ./build - if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j2; fi - if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi -after_script: - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi + - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi notifications: recipients: - corrmage+travis-ci@gmail.com diff --git a/CI/check_tabs.sh b/CI/check_tabs.sh new file mode 100755 index 0000000000..91f81e2a1e --- /dev/null +++ b/CI/check_tabs.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +OUTPUT=$(grep -nRP '\t' --include=\*.{cpp,hpp,c,h} apps components) + +if [[ $OUTPUT ]] ; then + echo "Error: Tab characters found!" + echo $OUTPUT + exit 1 +fi From 46c6092e99642efed263812766c61ec697b0dba8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 17 Sep 2015 09:39:42 +0200 Subject: [PATCH 51/81] updated credits file (cherry picked from commit 56163dcb2a33fdf67bd78dc63a6134c4f408505a) --- AUTHORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.md b/AUTHORS.md index 8ad420baf6..a5d4d4ea87 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -110,6 +110,7 @@ Programmers viadanna Vincent Heuken vocollapse + zelurker Manual ------ From 6f294d0d25b99d81a95d1b6123645047aa4ded48 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 17 Sep 2015 11:27:55 +0200 Subject: [PATCH 52/81] removed some left-over signal slot stuff that shouldn't have been there in the first place (cherry picked from commit b3b4fb3efbaf84a31b9a62203f9767b08328b671) --- apps/opencs/view/world/scenesubview.cpp | 7 ------- apps/opencs/view/world/scenesubview.hpp | 8 -------- 2 files changed, 15 deletions(-) diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index 2ca2548c0c..b698d9034a 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -247,8 +247,6 @@ void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceW mToolbar = toolbar; connect (mScene, SIGNAL (focusToolbarRequest()), mToolbar, SLOT (setFocus())); - connect (this, SIGNAL (updateSceneUserSetting(const QString &, const QStringList &)), - mScene, SLOT (updateUserSetting(const QString &, const QStringList &))); connect (mToolbar, SIGNAL (focusSceneRequest()), mScene, SLOT (setFocus())); mLayout->addWidget (mToolbar, 0); @@ -257,8 +255,3 @@ void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceW mScene->selectDefaultNavigationMode(); setFocusProxy (mScene); } - -void CSVWorld::SceneSubView::updateUserSetting (const QString &key, const QStringList &list) -{ - emit updateSceneUserSetting(key, list); -} diff --git a/apps/opencs/view/world/scenesubview.hpp b/apps/opencs/view/world/scenesubview.hpp index fc45347d0b..65aaca999e 100644 --- a/apps/opencs/view/world/scenesubview.hpp +++ b/apps/opencs/view/world/scenesubview.hpp @@ -83,14 +83,6 @@ namespace CSVWorld void cellSelectionChanged (const CSMWorld::UniversalId& id); void handleDrop(const std::vector& data); - - public slots: - - void updateUserSetting (const QString &, const QStringList &); - - signals: - - void updateSceneUserSetting (const QString &, const QStringList &); }; } From 14708e181c82c1abe4625317f2e50b9ca1f5890b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 17 Sep 2015 11:31:25 +0200 Subject: [PATCH 53/81] more cleanup (cherry picked from commit 659b87b25faec71089ae5f8b96b4283d58abaab7) Conflicts: apps/opencs/view/doc/view.hpp --- apps/opencs/view/doc/view.hpp | 3 --- apps/opencs/view/world/scenesubview.cpp | 5 ----- apps/opencs/view/world/scenesubview.hpp | 2 -- 3 files changed, 10 deletions(-) diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 04d31dea56..f83e496277 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -118,9 +118,6 @@ namespace CSVDoc Operations *getOperations() const; - /// Function called by view manager when user preferences are updated - void updateEditorSetting (const QString &, const QString &); - protected: virtual void moveEvent(QMoveEvent * event); diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index b698d9034a..c2f3442f89 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -132,11 +132,6 @@ void CSVWorld::SceneSubView::setEditLock (bool locked) } -void CSVWorld::SceneSubView::updateEditorSetting(const QString &settingName, const QString &settingValue) -{ - -} - void CSVWorld::SceneSubView::setStatusBar (bool show) { mBottom->setStatusBar (show); diff --git a/apps/opencs/view/world/scenesubview.hpp b/apps/opencs/view/world/scenesubview.hpp index 65aaca999e..a34d719013 100644 --- a/apps/opencs/view/world/scenesubview.hpp +++ b/apps/opencs/view/world/scenesubview.hpp @@ -52,8 +52,6 @@ namespace CSVWorld virtual void setEditLock (bool locked); - virtual void updateEditorSetting (const QString& key, const QString& value); - virtual void setStatusBar (bool show); virtual void useHint (const std::string& hint); From 69e63285078a5bc4c202a4ad16b795a936b48f5e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 22 Sep 2015 15:36:00 +0200 Subject: [PATCH 54/81] fixed local variable caching issue in automatic error checking (Fixes #2927) (cherry picked from commit 7bef97bf3331dbdf9544c2caad17ecf68b3be96b) --- apps/opencs/model/world/scriptcontext.cpp | 17 +++++++++++-- apps/opencs/model/world/scriptcontext.hpp | 3 +++ apps/opencs/view/world/scripterrortable.cpp | 5 ++++ apps/opencs/view/world/scripterrortable.hpp | 5 ++++ apps/opencs/view/world/scriptsubview.cpp | 27 ++++++++++++++++++++- apps/opencs/view/world/scriptsubview.hpp | 1 + 6 files changed, 55 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/world/scriptcontext.cpp b/apps/opencs/model/world/scriptcontext.cpp index bcbca4b28d..f644ad37ad 100644 --- a/apps/opencs/model/world/scriptcontext.cpp +++ b/apps/opencs/model/world/scriptcontext.cpp @@ -39,8 +39,6 @@ char CSMWorld::ScriptContext::getGlobalType (const std::string& name) const std::pair CSMWorld::ScriptContext::getMemberType (const std::string& name, const std::string& id) const { - /// \todo invalidate locals cache on change to scripts - std::string id2 = Misc::StringUtils::lowerCase (id); int index = mData.getScripts().searchId (id2); @@ -120,3 +118,18 @@ void CSMWorld::ScriptContext::clear() mIdsUpdated = false; mLocals.clear(); } + +bool CSMWorld::ScriptContext::clearLocals (const std::string& script) +{ + std::map::iterator iter = + mLocals.find (Misc::StringUtils::lowerCase (script)); + + if (iter!=mLocals.end()) + { + mLocals.erase (iter); + mIdsUpdated = false; + return true; + } + + return false; +} diff --git a/apps/opencs/model/world/scriptcontext.hpp b/apps/opencs/model/world/scriptcontext.hpp index 29ee42645a..2cd59f070f 100644 --- a/apps/opencs/model/world/scriptcontext.hpp +++ b/apps/opencs/model/world/scriptcontext.hpp @@ -46,6 +46,9 @@ namespace CSMWorld void clear(); ///< Remove all cached data. + + /// \return Were there any locals that needed clearing? + bool clearLocals (const std::string& script); }; } diff --git a/apps/opencs/view/world/scripterrortable.cpp b/apps/opencs/view/world/scripterrortable.cpp index b44e1c0bde..a9e315c73c 100644 --- a/apps/opencs/view/world/scripterrortable.cpp +++ b/apps/opencs/view/world/scripterrortable.cpp @@ -131,6 +131,11 @@ void CSVWorld::ScriptErrorTable::clear() setRowCount (0); } +bool CSVWorld::ScriptErrorTable::clearLocals (const std::string& script) +{ + return mContext.clearLocals (script); +} + void CSVWorld::ScriptErrorTable::cellClicked (int row, int column) { if (item (row, 1)) diff --git a/apps/opencs/view/world/scripterrortable.hpp b/apps/opencs/view/world/scripterrortable.hpp index 98db425cfd..33af7c8643 100644 --- a/apps/opencs/view/world/scripterrortable.hpp +++ b/apps/opencs/view/world/scripterrortable.hpp @@ -44,6 +44,11 @@ namespace CSVWorld void clear(); + /// Clear local variable cache for \a script. + /// + /// \return Were there any locals that needed clearing? + bool clearLocals (const std::string& script); + private slots: void cellClicked (int row, int column); diff --git a/apps/opencs/view/world/scriptsubview.cpp b/apps/opencs/view/world/scriptsubview.cpp index d405d17652..d99f789b3a 100644 --- a/apps/opencs/view/world/scriptsubview.cpp +++ b/apps/opencs/view/world/scriptsubview.cpp @@ -89,6 +89,7 @@ CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc: *document.getData().getTableModel (CSMWorld::UniversalId::Type_Scripts)); mColumn = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_ScriptText); + mIdColumn = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id); mStateColumn = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Modification); QString source = mModel->data (mModel->getModelIndex (id.getId(), mColumn)).toString(); @@ -241,6 +242,15 @@ void CSVWorld::ScriptSubView::dataChanged (const QModelIndex& topLeft, const QMo ScriptEdit::ChangeLock lock (*mEditor); + bool updateRequired = false; + + for (int i=topLeft.row(); i<=bottomRight.row(); ++i) + { + std::string id = mModel->data (mModel->index (i, mIdColumn)).toString().toUtf8().constData(); + if (mErrors->clearLocals (id)) + updateRequired = true; + } + QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn); if (index.row()>=topLeft.row() && index.row()<=bottomRight.row()) @@ -256,13 +266,28 @@ void CSVWorld::ScriptSubView::dataChanged (const QModelIndex& topLeft, const QMo mEditor->setPlainText (source); mEditor->setTextCursor (cursor); - recompile(); + updateRequired = true; } } + + if (updateRequired) + recompile(); } void CSVWorld::ScriptSubView::rowsAboutToBeRemoved (const QModelIndex& parent, int start, int end) { + bool updateRequired = false; + + for (int i=start; i<=end; ++i) + { + std::string id = mModel->data (mModel->index (i, mIdColumn)).toString().toUtf8().constData(); + if (mErrors->clearLocals (id)) + updateRequired = true; + } + + if (updateRequired) + recompile(); + QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn); if (!parent.isValid() && index.row()>=start && index.row()<=end) diff --git a/apps/opencs/view/world/scriptsubview.hpp b/apps/opencs/view/world/scriptsubview.hpp index 6125dd259d..907dc7958b 100644 --- a/apps/opencs/view/world/scriptsubview.hpp +++ b/apps/opencs/view/world/scriptsubview.hpp @@ -38,6 +38,7 @@ namespace CSVWorld CSMDoc::Document& mDocument; CSMWorld::IdTable *mModel; int mColumn; + int mIdColumn; int mStateColumn; TableBottomBox *mBottom; RecordButtonBar *mButtons; From 890405bdb154f689e61d490e654fcf8083ebf992 Mon Sep 17 00:00:00 2001 From: Emmanuel Anne Date: Fri, 25 Sep 2015 14:18:08 +0200 Subject: [PATCH 55/81] scripts: recognize '+' also as a unary operator it fixes the armor sorter in "Blades safe house.esp" (cherry picked from commit dace7ab7060c47155d70170a091b465c8b3b2688) --- components/compiler/exprparser.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index b588b6196b..53b24eab69 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 c5235ea7942c1466a951364f7009d5d00bc44600 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 26 Sep 2015 11:30:35 +0200 Subject: [PATCH 56/81] removed a redundant else and made unary + work also in the console (cherry picked from commit ae54f34f25ce08a2abc5ee9a162292940d256c84) --- 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 53b24eab69..c0375b4366 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 032af7d650..c1622c3e04 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 46775608595f24ed140e08f0944d5f264ed889ae Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 26 Sep 2015 11:34:46 +0200 Subject: [PATCH 57/81] adjusted a workaround for names starting with digits that interfered with some numerical expressions written without spaces (cherry picked from commit 435e52306a0b1a7ef4cf7059bbc388b3262d2631) --- 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 f25e69e399..3c5bb77475 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 cb6198a843d01a1e45210bc39b98af9ca34a2c9f Mon Sep 17 00:00:00 2001 From: "artemutin@yandex.ru" Date: Tue, 29 Sep 2015 10:46:03 +1000 Subject: [PATCH 58/81] Added StartScriptCreator class with redefined getErrors method. (cherry picked from commit 3f27c856300671083123d3027cf7b6299bc01438) --- 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 0000000000..5812cd9312 --- /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 0000000000..4c91ad96a2 --- /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 b0018aa7913d162b5af018f04799baf04dcbe746 Mon Sep 17 00:00:00 2001 From: "artemutin@yandex.ru" Date: Tue, 29 Sep 2015 22:43:20 +1000 Subject: [PATCH 59/81] Fix namespace, add file to CMakeLists.txt (cherry picked from commit e672880f644066716452d363b61eff1c56010b0f) --- 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 3b756495df..cd75db705e 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 5812cd9312..69b1b3ff12 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 4c91ad96a2..07fe8ff3d3 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 7f46bc155a9899f4c784003f4599c2d5238b1104 Mon Sep 17 00:00:00 2001 From: "artemutin@yandex.ru" Date: Tue, 29 Sep 2015 22:44:25 +1000 Subject: [PATCH 60/81] add getIdValidatorResult method to GenericCreator, for use in subclass StartScriptCreator (cherry picked from commit 903cd3322b2a24e4d0a757ede8e429583f34f2b4) --- 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 8ed52bf803..df77399417 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 471d0622eb..f63c451092 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 c34d8c2a0dfaba38b1a340c146ecab2f2cc582de Mon Sep 17 00:00:00 2001 From: "artemutin@yandex.ru" Date: Tue, 29 Sep 2015 23:52:35 +1000 Subject: [PATCH 61/81] Add StartScriptCreator to a factory manager. (cherry picked from commit ecce3a197550cd8b689e7d2bf697461325a7c6b9) Conflicts: apps/opencs/view/world/subviews.cpp --- apps/opencs/view/world/subviews.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index 47a1093354..cffe283d4d 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" @@ -53,6 +54,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 >); @@ -125,7 +129,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 }; @@ -135,6 +138,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 8fffbb3f9b153220fc2ce7751dccf0a1df918f02 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 30 Sep 2015 09:44:05 +0200 Subject: [PATCH 62/81] updated credits file (cherry picked from commit 64902bf22112d0b44464f7657b12db86627cdd38) --- AUTHORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.md b/AUTHORS.md index a5d4d4ea87..565d5a7039 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 9cc046ce4e69d3a5d36d40217850d0996aa19eb4 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Thu, 8 Oct 2015 12:35:09 +1100 Subject: [PATCH 63/81] Further rationalise the use of ColumnIds - Address Zini's review comments as per https://github.com/OpenMW/openmw/pull/755 (cherry picked from commit 998348e606182eb171dd82b99b647e3dff798b26) --- 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 2143ec730e..39232d4423 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 400e31333f..e2871d4d85 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 28e6fd050c..6adc66951f 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" }, @@ -294,8 +294,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" }, @@ -577,7 +576,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 ea50822b96..1992f225ad 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 fee1cf2b40..10297df5b6 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -212,15 +212,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)); @@ -282,7 +282,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( @@ -398,7 +398,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 588cdcd911..b775d8156b 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -84,7 +84,7 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data) 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( @@ -501,7 +501,7 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data) skillsMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcSkillsRefIdAdapter(data))); 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 4590a2dd05..51755c7e23 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 b3daa7d95681800091b5e7173afd6c917d04297a Mon Sep 17 00:00:00 2001 From: cc9cii Date: Thu, 8 Oct 2015 12:47:23 +1100 Subject: [PATCH 64/81] Fix AiWander sub-table editing. Should resolve bugs #2888 and #2930. (cherry picked from commit 3bbcf6a9169dc24d47c4d10e24f3818681fc34c0) Conflicts: apps/opencs/model/world/columns.cpp apps/opencs/model/world/columns.hpp --- apps/opencs/model/world/columns.cpp | 11 +- apps/opencs/model/world/columns.hpp | 11 +- apps/opencs/model/world/refidadapterimp.hpp | 146 ++++++++++++-------- apps/opencs/model/world/refidcollection.cpp | 18 ++- 4 files changed, 123 insertions(+), 63 deletions(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 6adc66951f..c06cc26180 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" }, @@ -317,6 +317,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_SpellSrc, "From Race" }, { ColumnId_SpellCost, "Cast Cost" }, { ColumnId_SpellChance, "Cast Chance" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 1992f225ad..d30b939e08 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, + ColumnId_SpellSrc = 90, ColumnId_SpellCost = 177, ColumnId_SpellChance = 254, diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 3da273c890..03da88ddc5 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -1435,6 +1435,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 { @@ -1518,6 +1520,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; @@ -1545,47 +1548,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) @@ -1615,11 +1623,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 @@ -1628,6 +1637,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) @@ -1639,62 +1650,77 @@ namespace CSMWorld content.mWander.mTimeOfDay = static_cast(value.toInt()); else return; // return without saving + + break; // always save case 4: - if (content.mType == ESM::AI_Wander) - break; // FIXME: idle - else - return; // return without saving case 5: - if (content.mType == ESM::AI_Wander) - { - content.mWander.mShouldRepeat = static_cast(value.toInt()); - break; - } - case 6: // NAME32 - if (content.mType == ESM::AI_Activate) - { - content.mActivate.mName.assign(value.toString().toUtf8().constData()); - break; - } - else - return; // return without saving - case 7: // 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 6: + case 7: case 8: - 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: - 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: - 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: + if (content.mType == ESM::AI_Wander) + content.mWander.mIdle[subColIndex-4] = static_cast(value.toInt()); + else + return; // return without saving + + break; // always save + case 12: + if (content.mType == ESM::AI_Wander) + content.mWander.mShouldRepeat = static_cast(value.toInt()); + 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()); + else + return; // return without saving + + 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()); + else + return; // return without saving + + break; // always save + case 15: + if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort) + content.mCellName = std::string(value.toString().toUtf8().constData()); + else + return; // return without saving + + 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 + + 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 + + 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!"); } @@ -1704,7 +1730,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 b775d8156b..9ad980dad0 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -203,8 +203,24 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data) 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_AiWanderIdle, CSMWorld::ColumnBase::Display_Integer)); + 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_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 71077fda6a91f484e8e178b99d647c3cfc33c78f Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 9 Oct 2015 06:29:50 +1100 Subject: [PATCH 65/81] Disable toolbar context menu. Should resolve bug #2953. (cherry picked from commit 64821b0785a306f90e4f2f3be9c6a8fa61d440eb) --- 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 47a2ffd51b..1f9762b318 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -474,6 +474,8 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to mOperations = new Operations; addDockWidget (Qt::BottomDockWidgetArea, mOperations); + setContextMenuPolicy(Qt::NoContextMenu); + updateTitle(); setupUi(); From aa31704d5d21fcb32b6e268e2aa1699280b15855 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 9 Oct 2015 12:14:22 +0200 Subject: [PATCH 66/81] deal with script execution from within a script (Fixes #2964) (cherry picked from commit 8eb6d337d556dce2f64698ac30ad0df881bf84e0) --- components/interpreter/interpreter.cpp | 59 +++++++++++++++++++++----- components/interpreter/interpreter.hpp | 7 +++ 2 files changed, 55 insertions(+), 11 deletions(-) diff --git a/components/interpreter/interpreter.cpp b/components/interpreter/interpreter.cpp index 4fd3a8d8c9..e6e06370ff 100644 --- a/components/interpreter/interpreter.cpp +++ b/components/interpreter/interpreter.cpp @@ -133,7 +133,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() @@ -203,19 +230,29 @@ namespace Interpreter { assert (codeSize>=4); - mRuntime.configure (code, codeSize, context); + begin(); - int opcodes = static_cast (code[0]); - - const Type_Code *codeBlock = code + 4; - - while (mRuntime.getPC()>=0 && mRuntime.getPC() (code[0]); + + const Type_Code *codeBlock = code + 4; + + while (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 ba9190ed5eef6324459a63768ea5f8a73c15c6bc Mon Sep 17 00:00:00 2001 From: "artemutin@yandex.ru" Date: Wed, 7 Oct 2015 12:39:19 +1000 Subject: [PATCH 67/81] Implemented line and col calculations in scriptsubview (cherry picked from commit e7a3f059aafb643238d95de8d34554747d7e74f2) --- apps/opencs/view/world/scriptsubview.cpp | 44 +++++++++++++++--------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/apps/opencs/view/world/scriptsubview.cpp b/apps/opencs/view/world/scriptsubview.cpp index d99f789b3a..35b9ccf0c3 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(); + QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn); + QString source = mModel->data (index).toString(); + size_t pos; + stream >> pos >> pos; - cursor.movePosition (QTextCursor::Start); - if (cursor.movePosition (QTextCursor::Down, QTextCursor::MoveAnchor, line)) - cursor.movePosition (QTextCursor::Right, QTextCursor::MoveAnchor, column); - - mEditor->setFocus(); - mEditor->setTextCursor (cursor); + 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 f44d7e97b05cf58c0949138b0b9bd9fbb61f85d2 Mon Sep 17 00:00:00 2001 From: "artemutin@yandex.ru" Date: Fri, 9 Oct 2015 21:52:12 +1000 Subject: [PATCH 68/81] Stream error handling, and other minor changes. (cherry picked from commit 4ca7b2660932efb06535f148a643a7e814f3a72d) --- 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 35b9ccf0c3..eb0c706564 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 437cabf778bfed1a83bdb4758883a45ff86f2e7e Mon Sep 17 00:00:00 2001 From: "artemutin@yandex.ru" Date: Sun, 11 Oct 2015 21:49:10 +1000 Subject: [PATCH 69/81] If table dont use any filter, filter update now dont cause a reapply of empty filter (cherry picked from commit 33e12a99fad15ced87a9996c42ffeb84983be2a4) --- 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 657a47750d..5fbc66464c 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 a0f9f8919a..5c3f1b09eb 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 91c4afe78c3893e5d5a848fc6ed2d73aaba8a69f Mon Sep 17 00:00:00 2001 From: "artemutin@yandex.ru" Date: Tue, 13 Oct 2015 23:44:23 +1000 Subject: [PATCH 70/81] 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. (cherry picked from commit eae36f800585a9347e778b36a1010b2a05f576c4) --- 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 5fbc66464c..600fa4f3bf 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 5c3f1b09eb..f672877d94 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 30de5c1c595c75aea4347217e41d6473ec7ae506 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 28 Oct 2015 11:18:48 +1100 Subject: [PATCH 71/81] Fix editing ingredient effects sub-table. Should resolve bug #2978. (cherry picked from commit 9f0e059a15106eb5fa8f1174eadd91076623e7d3) --- apps/opencs/model/world/refidadapterimp.cpp | 127 ++++++++++++++++++++ apps/opencs/model/world/refidadapterimp.hpp | 60 +++++++++ apps/opencs/model/world/refidcollection.cpp | 17 ++- 3 files changed, 203 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index 64c18a99be..653b60ea24 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -57,6 +57,133 @@ void CSMWorld::PotionRefIdAdapter::setData (const RefIdColumn *column, RefIdData } +CSMWorld::IngredientColumns::IngredientColumns (const InventoryColumns& columns) +: InventoryColumns (columns) {} + +CSMWorld::IngredientRefIdAdapter::IngredientRefIdAdapter (const IngredientColumns& columns) +: InventoryRefIdAdapter (UniversalId::Type_Ingredient, columns), + mColumns(columns) +{} + +QVariant CSMWorld::IngredientRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data, + int index) const +{ + const Record& record = static_cast&> ( + data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Ingredient))); + + if (column==mColumns.mEffects) + return true; // to show nested tables in dialogue subview, see IdTree::hasChildren() + + return InventoryRefIdAdapter::getData (column, data, index); +} + +void CSMWorld::IngredientRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const +{ + InventoryRefIdAdapter::setData (column, data, index, value); + + return; +} + + +CSMWorld::IngredEffectRefIdAdapter::IngredEffectRefIdAdapter() +: mType(UniversalId::Type_Ingredient) +{} + +CSMWorld::IngredEffectRefIdAdapter::~IngredEffectRefIdAdapter() +{} + +void CSMWorld::IngredEffectRefIdAdapter::addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const +{ + // Do nothing, this table cannot be changed by the user +} + +void CSMWorld::IngredEffectRefIdAdapter::removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const +{ + // Do nothing, this table cannot be changed by the user +} + +void CSMWorld::IngredEffectRefIdAdapter::setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const +{ + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); + ESM::Ingredient ingredient = record.get(); + + ingredient.mData = + static_cast >&>(nestedTable).mNestedTable.at(0); + + record.setModified (ingredient); +} + +CSMWorld::NestedTableWrapperBase* CSMWorld::IngredEffectRefIdAdapter::nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const +{ + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); + + // return the whole struct + std::vector wrap; + wrap.push_back(record.get().mData); + + // deleted by dtor of NestedTableStoring + return new NestedTableWrapper >(wrap); +} + +QVariant CSMWorld::IngredEffectRefIdAdapter::getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const +{ + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); + + if (subRowIndex < 0 || subRowIndex >= 4) + throw std::runtime_error ("index out of range"); + + switch (subColIndex) + { + case 0: return record.get().mData.mEffectID[subRowIndex]; + case 1: return record.get().mData.mSkills[subRowIndex]; + case 2: return record.get().mData.mAttributes[subRowIndex]; + default: + throw std::runtime_error("Trying to access non-existing column in the nested table!"); + } +} + +void CSMWorld::IngredEffectRefIdAdapter::setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const +{ + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (row, mType))); + ESM::Ingredient ingredient = record.get(); + + if (subRowIndex < 0 || subRowIndex >= 4) + throw std::runtime_error ("index out of range"); + + switch(subColIndex) + { + case 0: ingredient.mData.mEffectID[subRowIndex] = value.toInt(); break; + case 1: ingredient.mData.mSkills[subRowIndex] = value.toInt(); break; + case 2: ingredient.mData.mAttributes[subRowIndex] = value.toInt(); break; + default: + throw std::runtime_error("Trying to access non-existing column in the nested table!"); + } + + record.setModified (ingredient); +} + +int CSMWorld::IngredEffectRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const +{ + return 3; // effect, skill, attribute +} + +int CSMWorld::IngredEffectRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const +{ + return 4; // up to 4 effects +} + + CSMWorld::ApparatusRefIdAdapter::ApparatusRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *type, const RefIdColumn *quality) : InventoryRefIdAdapter (UniversalId::Type_Apparatus, columns), diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 03da88ddc5..ad9c762643 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -346,6 +346,66 @@ namespace CSMWorld ///< If the data type does not match an exception is thrown. }; + struct IngredientColumns : public InventoryColumns + { + const RefIdColumn *mEffects; + + IngredientColumns (const InventoryColumns& columns); + }; + + class IngredientRefIdAdapter : public InventoryRefIdAdapter + { + IngredientColumns mColumns; + + public: + + IngredientRefIdAdapter (const IngredientColumns& columns); + + virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) + const; + + virtual void setData (const RefIdColumn *column, RefIdData& data, int index, + const QVariant& value) const; + ///< If the data type does not match an exception is thrown. + }; + + class IngredEffectRefIdAdapter : public NestedRefIdAdapterBase + { + UniversalId::Type mType; + + // not implemented + IngredEffectRefIdAdapter (const IngredEffectRefIdAdapter&); + IngredEffectRefIdAdapter& operator= (const IngredEffectRefIdAdapter&); + + public: + + IngredEffectRefIdAdapter(); + + virtual ~IngredEffectRefIdAdapter(); + + virtual void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const; + + virtual void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const; + + virtual void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const; + + virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const; + + virtual QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const; + + virtual void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const; + + virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const; + + virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const; + }; + struct EnchantableColumns : public InventoryColumns { const RefIdColumn *mEnchantment; diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index 9ad980dad0..355075c47c 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -72,6 +72,21 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data) mColumns.push_back (RefIdColumn (Columns::ColumnId_CoinValue, ColumnBase::Display_Integer)); inventoryColumns.mValue = &mColumns.back(); + IngredientColumns ingredientColumns (inventoryColumns); + mColumns.push_back (RefIdColumn (Columns::ColumnId_EffectList, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + ingredientColumns.mEffects = &mColumns.back(); + std::map ingredientEffectsMap; + ingredientEffectsMap.insert(std::make_pair(UniversalId::Type_Ingredient, + new IngredEffectRefIdAdapter ())); + mNestedAdapters.push_back (std::make_pair(&mColumns.back(), ingredientEffectsMap)); + mColumns.back().addColumn( + new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_EffectId)); + mColumns.back().addColumn( + new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_SkillId)); + mColumns.back().addColumn( + new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute)); + // nested table PotionColumns potionColumns (inventoryColumns); mColumns.push_back (RefIdColumn (Columns::ColumnId_EffectList, @@ -662,7 +677,7 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data) mAdapters.insert (std::make_pair (UniversalId::Type_Door, new DoorRefIdAdapter (nameColumns, openSound, closeSound))); mAdapters.insert (std::make_pair (UniversalId::Type_Ingredient, - new InventoryRefIdAdapter (UniversalId::Type_Ingredient, inventoryColumns))); + new IngredientRefIdAdapter (ingredientColumns))); mAdapters.insert (std::make_pair (UniversalId::Type_CreatureLevelledList, new LevelledListRefIdAdapter ( UniversalId::Type_CreatureLevelledList, levListColumns))); From bb1a959c888a66e086ea1926421e3d679e2b63bf Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 28 Oct 2015 11:30:36 +1100 Subject: [PATCH 72/81] Fix skills and attributes being possible to add to irrelevant effects. Should resolve bug #2980. (cherry picked from commit 1a64b4072570e09a75e2ac250576589244ed8a3e) --- .../model/world/nestedcoladapterimp.hpp | 30 +++++++++++++++++-- apps/opencs/model/world/refidadapterimp.cpp | 30 +++++++++++++++++-- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/nestedcoladapterimp.hpp b/apps/opencs/model/world/nestedcoladapterimp.hpp index 81c52588bb..2fd569bd0d 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.hpp +++ b/apps/opencs/model/world/nestedcoladapterimp.hpp @@ -317,8 +317,34 @@ namespace CSMWorld else throw std::runtime_error("Magic effects ID unexpected value"); } - case 1: return effect.mSkill; - case 2: return effect.mAttribute; + case 1: + { + switch (effect.mEffectID) + { + case ESM::MagicEffect::DrainSkill: + case ESM::MagicEffect::DamageSkill: + case ESM::MagicEffect::RestoreSkill: + case ESM::MagicEffect::FortifySkill: + case ESM::MagicEffect::AbsorbSkill: + return effect.mSkill; + default: + return QVariant(); + } + } + case 2: + { + switch (effect.mEffectID) + { + case ESM::MagicEffect::DrainAttribute: + case ESM::MagicEffect::DamageAttribute: + case ESM::MagicEffect::RestoreAttribute: + case ESM::MagicEffect::FortifyAttribute: + case ESM::MagicEffect::AbsorbAttribute: + return effect.mAttribute; + default: + return QVariant(); + } + } case 3: { if (effect.mRange >=0 && effect.mRange <=2) diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index 653b60ea24..77836d79a5 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -144,8 +144,34 @@ QVariant CSMWorld::IngredEffectRefIdAdapter::getNestedData (const RefIdColumn *c switch (subColIndex) { case 0: return record.get().mData.mEffectID[subRowIndex]; - case 1: return record.get().mData.mSkills[subRowIndex]; - case 2: return record.get().mData.mAttributes[subRowIndex]; + case 1: + { + switch (record.get().mData.mEffectID[subRowIndex]) + { + case ESM::MagicEffect::DrainSkill: + case ESM::MagicEffect::DamageSkill: + case ESM::MagicEffect::RestoreSkill: + case ESM::MagicEffect::FortifySkill: + case ESM::MagicEffect::AbsorbSkill: + return record.get().mData.mSkills[subRowIndex]; + default: + return QVariant(); + } + } + case 2: + { + switch (record.get().mData.mEffectID[subRowIndex]) + { + case ESM::MagicEffect::DrainAttribute: + case ESM::MagicEffect::DamageAttribute: + case ESM::MagicEffect::RestoreAttribute: + case ESM::MagicEffect::FortifyAttribute: + case ESM::MagicEffect::AbsorbAttribute: + return record.get().mData.mAttributes[subRowIndex]; + default: + return QVariant(); + } + } default: throw std::runtime_error("Trying to access non-existing column in the nested table!"); } From b595f2641ca557a38d02801fbeea0edbebf5b82f Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 28 Oct 2015 11:49:24 +1100 Subject: [PATCH 73/81] Fix issue where mandatory effects field was allowed to be empty (and vice versa) (cherry picked from commit 972193c7ebcb597dfdd5b38e72965efa1bb4e70f) --- apps/opencs/model/world/columnbase.cpp | 4 ++++ apps/opencs/model/world/columnbase.hpp | 4 ++++ apps/opencs/model/world/data.cpp | 8 ++++---- apps/opencs/model/world/refidcollection.cpp | 10 +++++----- apps/opencs/view/doc/viewmanager.cpp | 3 +++ 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/apps/opencs/model/world/columnbase.cpp b/apps/opencs/model/world/columnbase.cpp index 39232d4423..1f16c9695b 100644 --- a/apps/opencs/model/world/columnbase.cpp +++ b/apps/opencs/model/world/columnbase.cpp @@ -86,6 +86,10 @@ bool CSMWorld::ColumnBase::isId (Display display) Display_InfoCondVar, Display_InfoCondComp, + Display_EffectSkill, + Display_EffectAttribute, + Display_IngredEffectId, + Display_None }; diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index e2871d4d85..67d79fdbee 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -124,6 +124,10 @@ namespace CSMWorld Display_String32, Display_LongString256, + Display_EffectSkill, // must display at least one, unlike Display_Skill + Display_EffectAttribute, // must display at least one, unlike Display_Attribute + Display_IngredEffectId, // display none allowed, unlike Display_EffectId + //top level columns that nest other columns Display_NestedHeader }; diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 10297df5b6..0b33632da8 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -282,9 +282,9 @@ 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_Skill, ColumnBase::Display_SkillId)); + new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_EffectSkill)); mSpells.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute)); + new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_EffectAttribute)); mSpells.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_EffectRange, ColumnBase::Display_EffectRange)); mSpells.getNestableColumn(index)->addColumn( @@ -398,9 +398,9 @@ 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_Skill, ColumnBase::Display_SkillId)); + new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_EffectSkill)); mEnchantments.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute)); + new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_EffectAttribute)); mEnchantments.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_EffectRange, ColumnBase::Display_EffectRange)); mEnchantments.getNestableColumn(index)->addColumn( diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index 355075c47c..a5e8133386 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -81,11 +81,11 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data) new IngredEffectRefIdAdapter ())); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), ingredientEffectsMap)); mColumns.back().addColumn( - new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_EffectId)); + new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_IngredEffectId)); mColumns.back().addColumn( - new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_SkillId)); + new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_EffectSkill)); mColumns.back().addColumn( - new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute)); + new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_EffectAttribute)); // nested table PotionColumns potionColumns (inventoryColumns); @@ -99,9 +99,9 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data) mColumns.back().addColumn( new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_EffectId)); mColumns.back().addColumn( - new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_SkillId)); + new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_EffectSkill)); mColumns.back().addColumn( - new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute)); + new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_EffectAttribute)); mColumns.back().addColumn( new NestedChildColumn (Columns::ColumnId_EffectRange, ColumnBase::Display_EffectRange)); mColumns.back().addColumn( diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 51755c7e23..766051bcae 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -104,6 +104,9 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) { CSMWorld::ColumnBase::Display_AiPackageType, CSMWorld::Columns::ColumnId_AiPackageType, false }, { CSMWorld::ColumnBase::Display_InfoCondFunc, CSMWorld::Columns::ColumnId_InfoCondFunc, false }, { CSMWorld::ColumnBase::Display_InfoCondComp, CSMWorld::Columns::ColumnId_InfoCondComp, false }, + { CSMWorld::ColumnBase::Display_IngredEffectId, CSMWorld::Columns::ColumnId_EffectId, true }, + { CSMWorld::ColumnBase::Display_EffectSkill, CSMWorld::Columns::ColumnId_Skill, false }, + { CSMWorld::ColumnBase::Display_EffectAttribute, CSMWorld::Columns::ColumnId_Attribute, false }, }; for (std::size_t i=0; i Date: Wed, 28 Oct 2015 20:30:30 +1100 Subject: [PATCH 74/81] Disable context menu for fixed size sub-tables. Should resolve bug #2932. (cherry picked from commit 80869d9bae8c472ec7d1dca38eb668cc32850352) Conflicts: apps/opencs/view/world/dialoguesubview.cpp apps/opencs/view/world/nestedtable.cpp apps/opencs/view/world/nestedtable.hpp --- apps/opencs/model/world/columnbase.hpp | 22 +++++++++-- apps/opencs/model/world/data.cpp | 6 ++- apps/opencs/model/world/refidadapterimp.cpp | 41 +++++++++++---------- apps/opencs/view/world/dialoguesubview.cpp | 18 +++++++-- apps/opencs/view/world/nestedtable.cpp | 31 ++++++++++------ apps/opencs/view/world/nestedtable.hpp | 3 +- 6 files changed, 81 insertions(+), 40 deletions(-) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index 67d79fdbee..c40bd9663d 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -12,6 +12,13 @@ namespace CSMWorld { + enum TableEditModes + { + TableEdit_None, // no editing + TableEdit_Full, // edit cells and add/remove rows + TableEdit_FixedRows // edit cells only + }; + struct ColumnBase { enum Roles @@ -190,8 +197,8 @@ namespace CSMWorld template struct NestedParentColumn : public Column { - NestedParentColumn (int id, int flags = ColumnBase::Flag_Dialogue) : Column (id, - ColumnBase::Display_NestedHeader, flags) + NestedParentColumn (int id, int flags = ColumnBase::Flag_Dialogue, bool fixedRows = false) + : Column (id, ColumnBase::Display_NestedHeader, flags), mFixedRows(fixedRows) {} virtual void set (Record& record, const QVariant& data) @@ -202,13 +209,20 @@ namespace CSMWorld virtual QVariant get (const Record& record) const { - return true; // required by IdTree::hasChildren() + // by default editable; also see IdTree::hasChildren() + if (mFixedRows) + return QVariant::fromValue(TableEditModes::TableEdit_FixedRows); + else + return QVariant::fromValue(TableEditModes::TableEdit_Full); } virtual bool isEditable() const { return true; } + + Private: + bool mFixedRows; }; struct NestedChildColumn : public NestableColumn @@ -223,4 +237,6 @@ namespace CSMWorld }; } +Q_DECLARE_METATYPE(CSMWorld::TableEditModes) + #endif diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 0b33632da8..dfb2d99d32 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -205,7 +205,8 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mRaces.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_Spell)); // Race attributes - mRaces.addColumn (new NestedParentColumn (Columns::ColumnId_RaceAttributes)); + mRaces.addColumn (new NestedParentColumn (Columns::ColumnId_RaceAttributes, + ColumnBase::Flag_Dialogue, true)); // fixed rows table index = mRaces.getColumns()-1; mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceAttributeAdapter())); mRaces.getNestableColumn(index)->addColumn( @@ -216,7 +217,8 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mRaces.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_Female, ColumnBase::Display_Integer)); // Race skill bonus - mRaces.addColumn (new NestedParentColumn (Columns::ColumnId_RaceSkillBonus)); + mRaces.addColumn (new NestedParentColumn (Columns::ColumnId_RaceSkillBonus, + ColumnBase::Flag_Dialogue, true)); // fixed rows table index = mRaces.getColumns()-1; mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceSkillsBonusAdapter())); mRaces.getNestableColumn(index)->addColumn( diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index 77836d79a5..ed288ee982 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -30,8 +30,9 @@ QVariant CSMWorld::PotionRefIdAdapter::getData (const RefIdColumn *column, const if (column==mAutoCalc) return record.get().mData.mAutoCalc!=0; + // to show nested tables in dialogue subview, see IdTree::hasChildren() if (column==mColumns.mEffects) - return true; // to show nested tables in dialogue subview, see IdTree::hasChildren() + return QVariant::fromValue(TableEditModes::TableEdit_Full); return InventoryRefIdAdapter::getData (column, data, index); } @@ -72,7 +73,7 @@ QVariant CSMWorld::IngredientRefIdAdapter::getData (const RefIdColumn *column, c data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Ingredient))); if (column==mColumns.mEffects) - return true; // to show nested tables in dialogue subview, see IdTree::hasChildren() + return QVariant::fromValue(TableEditModes::TableEdit_FixedRows); return InventoryRefIdAdapter::getData (column, data, index); } @@ -276,7 +277,7 @@ QVariant CSMWorld::ArmorRefIdAdapter::getData (const RefIdColumn *column, return record.get().mData.mArmor; if (column==mPartRef) - return true; // to show nested tables in dialogue subview, see IdTree::hasChildren() + return QVariant::fromValue(TableEditModes::TableEdit_Full); return EnchantableRefIdAdapter::getData (column, data, index); } @@ -364,7 +365,7 @@ QVariant CSMWorld::ClothingRefIdAdapter::getData (const RefIdColumn *column, return record.get().mData.mType; if (column==mPartRef) - return true; // to show nested tables in dialogue subview, see IdTree::hasChildren() + return QVariant::fromValue(TableEditModes::TableEdit_Full); return EnchantableRefIdAdapter::getData (column, data, index); } @@ -412,7 +413,7 @@ QVariant CSMWorld::ContainerRefIdAdapter::getData (const RefIdColumn *column, return (record.get().mFlags & ESM::Container::Respawn)!=0; if (column==mContent) - return true; // Required to show nested tables in dialogue subview + return QVariant::fromValue(TableEditModes::TableEdit_Full); return NameRefIdAdapter::getData (column, data, index); } @@ -481,13 +482,13 @@ QVariant CSMWorld::CreatureRefIdAdapter::getData (const RefIdColumn *column, con return QString::fromUtf8 (record.get().mOriginal.c_str()); if (column==mColumns.mAttributes) - return true; // Required to show nested tables in dialogue subview + return QVariant::fromValue(TableEditModes::TableEdit_FixedRows); if (column==mColumns.mAttacks) - return true; // Required to show nested tables in dialogue subview + return QVariant::fromValue(TableEditModes::TableEdit_FixedRows); if (column==mColumns.mMisc) - return true; // Required to show nested items in dialogue subview + return QVariant::fromValue(TableEditModes::TableEdit_Full); std::map::const_iterator iter = mColumns.mFlags.find (column); @@ -727,13 +728,13 @@ QVariant CSMWorld::NpcRefIdAdapter::getData (const RefIdColumn *column, const Re if (column==mColumns.mAttributes || column==mColumns.mSkills) { if ((record.get().mFlags & ESM::NPC::Autocalc) != 0) - return QVariant(QVariant::UserType); + return QVariant::fromValue(TableEditModes::TableEdit_None); else - return true; + return QVariant::fromValue(TableEditModes::TableEdit_FixedRows); } if (column==mColumns.mMisc) - return true; + return QVariant::fromValue(TableEditModes::TableEdit_Full); std::map::const_iterator iter = mColumns.mFlags.find (column); @@ -1613,21 +1614,21 @@ QVariant ActorRefIdAdapter::getData (const RefIdColumn *column, const return record.get().mAiData.mAlarm; if (column==mActors.mInventory) - return true; // to show nested tables in dialogue subview, see IdTree::hasChildren() + return QVariant::fromValue(TableEditModes::TableEdit_Full); if (column==mActors.mSpells) { if ((record.get().mFlags & ESM::NPC::Autocalc) != 0) - return QVariant(QVariant::UserType); + return QVariant::fromValue(TableEditModes::TableEdit_None); else - return true; + return QVariant::fromValue(TableEditModes::TableEdit_Full); } if (column==mActors.mDestinations) - return true; // to show nested tables in dialogue subview, see IdTree::hasChildren() + return QVariant::fromValue(TableEditModes::TableEdit_Full); if (column==mActors.mAiPackages) - return true; // to show nested tables in dialogue subview, see IdTree::hasChildren() + return QVariant::fromValue(TableEditModes::TableEdit_Full); std::map::const_iterator iter = mActors.mServices.find (column); @@ -1794,16 +1795,16 @@ QVariant ActorRefIdAdapter::getData (const RefIdColumn *column, c return record.get().mAiData.mAlarm; if (column==mActors.mInventory) - return true; // to show nested tables in dialogue subview, see IdTree::hasChildren() + return QVariant::fromValue(TableEditModes::TableEdit_Full); if (column==mActors.mSpells) - return true; // to show nested tables in dialogue subview, see IdTree::hasChildren() + return QVariant::fromValue(TableEditModes::TableEdit_Full); if (column==mActors.mDestinations) - return true; // to show nested tables in dialogue subview, see IdTree::hasChildren() + return QVariant::fromValue(TableEditModes::TableEdit_Full); if (column==mActors.mAiPackages) - return true; // to show nested tables in dialogue subview, see IdTree::hasChildren() + return QVariant::fromValue(TableEditModes::TableEdit_Full); std::map::const_iterator iter = mActors.mServices.find (column); diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index b8683d2fee..ed023ff7c1 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -564,8 +564,20 @@ void CSVWorld::EditWidget::remake(int row) static_cast (mTable->data (mTable->index (row, typeColumn)).toInt()), mTable->data (mTable->index (row, idColumn)).toString().toUtf8().constData()); - bool editable = mTable->index(row, i).data().type() != QVariant::UserType; - NestedTable* table = new NestedTable(mDocument, id, mNestedModels.back(), this, editable); + bool editable = true; + bool fixedRows = false; + QVariant v = mTable->index(row, i).data(); + if (v.canConvert()) + { + assert (QString(v.typeName()) == "CSMWorld::TableEditModes"); + + if (v.value() == CSMWorld::TableEditModes::TableEdit_None) + editable = false; + else if (v.value() == CSMWorld::TableEditModes::TableEdit_FixedRows) + fixedRows = true; + } + + NestedTable* table = new NestedTable(mDocument, id, mNestedModels.back(), this, editable, fixedRows); if (!editable) { table->setEditTriggers(QAbstractItemView::NoEditTriggers); @@ -588,7 +600,7 @@ void CSVWorld::EditWidget::remake(int row) new QLabel (mTable->headerData (i, Qt::Horizontal, Qt::DisplayRole).toString(), mMainWidget); label->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed); - if(mTable->index(row, i).data().type() == QVariant::UserType) + if(!editable) label->setEnabled(false); tablesLayout->addWidget(label); diff --git a/apps/opencs/view/world/nestedtable.cpp b/apps/opencs/view/world/nestedtable.cpp index 89b1718918..23d5664396 100644 --- a/apps/opencs/view/world/nestedtable.cpp +++ b/apps/opencs/view/world/nestedtable.cpp @@ -17,9 +17,12 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document, CSMWorld::UniversalId id, CSMWorld::NestedTableProxyModel* model, QWidget* parent, - bool editable) + bool editable, + bool fixedRows) : DragRecordTable(document, parent), - mEditIdAction(0), + mAddNewRowAction(NULL), + mRemoveRowAction(NULL), + mEditIdAction(NULL), mModel(model) { mDispatcher = new CSMWorld::CommandDispatcher (document, id, this); @@ -53,15 +56,18 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document, if (editable) { - mAddNewRowAction = new QAction (tr ("Add new row"), this); + if (!fixedRows) + { + mAddNewRowAction = new QAction (tr ("Add new row"), this); - connect(mAddNewRowAction, SIGNAL(triggered()), - this, SLOT(addNewRowActionTriggered())); + connect(mAddNewRowAction, SIGNAL(triggered()), + this, SLOT(addNewRowActionTriggered())); - mRemoveRowAction = new QAction (tr ("Remove row"), this); + mRemoveRowAction = new QAction (tr ("Remove row"), this); - connect(mRemoveRowAction, SIGNAL(triggered()), - this, SLOT(removeRowActionTriggered())); + connect(mRemoveRowAction, SIGNAL(triggered()), + this, SLOT(removeRowActionTriggered())); + } mEditIdAction = new TableEditIdAction(*this, this); connect(mEditIdAction, SIGNAL(triggered()), this, SLOT(editCell())); @@ -92,10 +98,13 @@ void CSVWorld::NestedTable::contextMenuEvent (QContextMenuEvent *event) menu.addSeparator(); } - if (selectionModel()->selectedRows().size() == 1) - menu.addAction(mRemoveRowAction); + if (mAddNewRowAction && mRemoveRowAction) + { + if (selectionModel()->selectedRows().size() == 1) + menu.addAction(mRemoveRowAction); - menu.addAction(mAddNewRowAction); + menu.addAction(mAddNewRowAction); + } menu.exec (event->globalPos()); } diff --git a/apps/opencs/view/world/nestedtable.hpp b/apps/opencs/view/world/nestedtable.hpp index 23a925dcaf..765060ea5b 100644 --- a/apps/opencs/view/world/nestedtable.hpp +++ b/apps/opencs/view/world/nestedtable.hpp @@ -39,7 +39,8 @@ namespace CSVWorld CSMWorld::UniversalId id, CSMWorld::NestedTableProxyModel* model, QWidget* parent = NULL, - bool editable = true); + bool editable = true, + bool fixedRows = false); virtual std::vector getDraggedRecords() const; From 0ec4af42100739d6823cb5927d7d0613445f11f3 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 28 Oct 2015 20:52:07 +1100 Subject: [PATCH 75/81] Re-add mistakenly removed line and fix a silly typo. (cherry picked from commit 77471d1592611fe08b65e6b34b7e656d78753944) --- apps/opencs/model/world/columnbase.hpp | 2 +- apps/opencs/view/world/dialoguesubview.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index c40bd9663d..8a0a706448 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -221,7 +221,7 @@ namespace CSMWorld return true; } - Private: + private: bool mFixedRows; }; diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index ed023ff7c1..67b4863630 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -577,7 +577,9 @@ void CSVWorld::EditWidget::remake(int row) fixedRows = true; } - NestedTable* table = new NestedTable(mDocument, id, mNestedModels.back(), this, editable, fixedRows); + NestedTable* table = + new NestedTable(mDocument, id, mNestedModels.back(), this, editable, fixedRows); + table->resizeColumnsToContents(); if (!editable) { table->setEditTriggers(QAbstractItemView::NoEditTriggers); From 245357c9b2d18ad170951a956a6cc51c82b003fa Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 28 Oct 2015 23:33:24 +1100 Subject: [PATCH 76/81] Move TableEditModes enum inside a class scope. (cherry picked from commit 107ccd84d4f411a825c2f095bae7f84e65f8609d) Conflicts: apps/opencs/model/world/refidadapterimp.cpp --- apps/opencs/model/world/columnbase.hpp | 20 ++++----- apps/opencs/model/world/refidadapterimp.cpp | 45 ++++++++++----------- apps/opencs/view/world/dialoguesubview.cpp | 8 ++-- 3 files changed, 36 insertions(+), 37 deletions(-) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index 8a0a706448..c75a3c2a12 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -12,15 +12,15 @@ namespace CSMWorld { - enum TableEditModes - { - TableEdit_None, // no editing - TableEdit_Full, // edit cells and add/remove rows - TableEdit_FixedRows // edit cells only - }; - struct ColumnBase { + enum TableEditModes + { + TableEdit_None, // no editing + TableEdit_Full, // edit cells and add/remove rows + TableEdit_FixedRows // edit cells only + }; + enum Roles { Role_Flags = Qt::UserRole, @@ -211,9 +211,9 @@ namespace CSMWorld { // by default editable; also see IdTree::hasChildren() if (mFixedRows) - return QVariant::fromValue(TableEditModes::TableEdit_FixedRows); + return QVariant::fromValue(ColumnBase::TableEdit_FixedRows); else - return QVariant::fromValue(TableEditModes::TableEdit_Full); + return QVariant::fromValue(ColumnBase::TableEdit_Full); } virtual bool isEditable() const @@ -237,6 +237,6 @@ namespace CSMWorld }; } -Q_DECLARE_METATYPE(CSMWorld::TableEditModes) +Q_DECLARE_METATYPE(CSMWorld::ColumnBase::TableEditModes) #endif diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index ed288ee982..3e7dc3acae 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -6,7 +6,9 @@ #include #include +#include +#include "columnbase.hpp" #include "nestedtablewrapper.hpp" #include "usertype.hpp" #include "idtree.hpp" @@ -32,7 +34,7 @@ QVariant CSMWorld::PotionRefIdAdapter::getData (const RefIdColumn *column, const // to show nested tables in dialogue subview, see IdTree::hasChildren() if (column==mColumns.mEffects) - return QVariant::fromValue(TableEditModes::TableEdit_Full); + return QVariant::fromValue(ColumnBase::TableEdit_Full); return InventoryRefIdAdapter::getData (column, data, index); } @@ -69,11 +71,8 @@ CSMWorld::IngredientRefIdAdapter::IngredientRefIdAdapter (const IngredientColumn QVariant CSMWorld::IngredientRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data, int index) const { - const Record& record = static_cast&> ( - data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Ingredient))); - if (column==mColumns.mEffects) - return QVariant::fromValue(TableEditModes::TableEdit_FixedRows); + return QVariant::fromValue(ColumnBase::TableEdit_FixedRows); return InventoryRefIdAdapter::getData (column, data, index); } @@ -277,7 +276,7 @@ QVariant CSMWorld::ArmorRefIdAdapter::getData (const RefIdColumn *column, return record.get().mData.mArmor; if (column==mPartRef) - return QVariant::fromValue(TableEditModes::TableEdit_Full); + return QVariant::fromValue(ColumnBase::TableEdit_Full); return EnchantableRefIdAdapter::getData (column, data, index); } @@ -365,7 +364,7 @@ QVariant CSMWorld::ClothingRefIdAdapter::getData (const RefIdColumn *column, return record.get().mData.mType; if (column==mPartRef) - return QVariant::fromValue(TableEditModes::TableEdit_Full); + return QVariant::fromValue(ColumnBase::TableEdit_Full); return EnchantableRefIdAdapter::getData (column, data, index); } @@ -413,7 +412,7 @@ QVariant CSMWorld::ContainerRefIdAdapter::getData (const RefIdColumn *column, return (record.get().mFlags & ESM::Container::Respawn)!=0; if (column==mContent) - return QVariant::fromValue(TableEditModes::TableEdit_Full); + return QVariant::fromValue(ColumnBase::TableEdit_Full); return NameRefIdAdapter::getData (column, data, index); } @@ -482,13 +481,13 @@ QVariant CSMWorld::CreatureRefIdAdapter::getData (const RefIdColumn *column, con return QString::fromUtf8 (record.get().mOriginal.c_str()); if (column==mColumns.mAttributes) - return QVariant::fromValue(TableEditModes::TableEdit_FixedRows); + return QVariant::fromValue(ColumnBase::TableEdit_FixedRows); if (column==mColumns.mAttacks) - return QVariant::fromValue(TableEditModes::TableEdit_FixedRows); + return QVariant::fromValue(ColumnBase::TableEdit_FixedRows); if (column==mColumns.mMisc) - return QVariant::fromValue(TableEditModes::TableEdit_Full); + return QVariant::fromValue(ColumnBase::TableEdit_Full); std::map::const_iterator iter = mColumns.mFlags.find (column); @@ -728,13 +727,13 @@ QVariant CSMWorld::NpcRefIdAdapter::getData (const RefIdColumn *column, const Re if (column==mColumns.mAttributes || column==mColumns.mSkills) { if ((record.get().mFlags & ESM::NPC::Autocalc) != 0) - return QVariant::fromValue(TableEditModes::TableEdit_None); + return QVariant::fromValue(ColumnBase::TableEdit_None); else - return QVariant::fromValue(TableEditModes::TableEdit_FixedRows); + return QVariant::fromValue(ColumnBase::TableEdit_FixedRows); } if (column==mColumns.mMisc) - return QVariant::fromValue(TableEditModes::TableEdit_Full); + return QVariant::fromValue(ColumnBase::TableEdit_Full); std::map::const_iterator iter = mColumns.mFlags.find (column); @@ -1614,21 +1613,21 @@ QVariant ActorRefIdAdapter::getData (const RefIdColumn *column, const return record.get().mAiData.mAlarm; if (column==mActors.mInventory) - return QVariant::fromValue(TableEditModes::TableEdit_Full); + return QVariant::fromValue(ColumnBase::TableEdit_Full); if (column==mActors.mSpells) { if ((record.get().mFlags & ESM::NPC::Autocalc) != 0) - return QVariant::fromValue(TableEditModes::TableEdit_None); + return QVariant::fromValue(ColumnBase::TableEdit_None); else - return QVariant::fromValue(TableEditModes::TableEdit_Full); + return QVariant::fromValue(ColumnBase::TableEdit_Full); } if (column==mActors.mDestinations) - return QVariant::fromValue(TableEditModes::TableEdit_Full); + return QVariant::fromValue(ColumnBase::TableEdit_Full); if (column==mActors.mAiPackages) - return QVariant::fromValue(TableEditModes::TableEdit_Full); + return QVariant::fromValue(ColumnBase::TableEdit_Full); std::map::const_iterator iter = mActors.mServices.find (column); @@ -1795,16 +1794,16 @@ QVariant ActorRefIdAdapter::getData (const RefIdColumn *column, c return record.get().mAiData.mAlarm; if (column==mActors.mInventory) - return QVariant::fromValue(TableEditModes::TableEdit_Full); + return QVariant::fromValue(ColumnBase::TableEdit_Full); if (column==mActors.mSpells) - return QVariant::fromValue(TableEditModes::TableEdit_Full); + return QVariant::fromValue(ColumnBase::TableEdit_Full); if (column==mActors.mDestinations) - return QVariant::fromValue(TableEditModes::TableEdit_Full); + return QVariant::fromValue(ColumnBase::TableEdit_Full); if (column==mActors.mAiPackages) - return QVariant::fromValue(TableEditModes::TableEdit_Full); + return QVariant::fromValue(ColumnBase::TableEdit_Full); std::map::const_iterator iter = mActors.mServices.find (column); diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 67b4863630..14b7fcac3d 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -567,13 +567,13 @@ void CSVWorld::EditWidget::remake(int row) bool editable = true; bool fixedRows = false; QVariant v = mTable->index(row, i).data(); - if (v.canConvert()) + if (v.canConvert()) { - assert (QString(v.typeName()) == "CSMWorld::TableEditModes"); + assert (QString(v.typeName()) == "CSMWorld::ColumnBase::TableEditModes"); - if (v.value() == CSMWorld::TableEditModes::TableEdit_None) + if (v.value() == CSMWorld::ColumnBase::TableEdit_None) editable = false; - else if (v.value() == CSMWorld::TableEditModes::TableEdit_FixedRows) + else if (v.value() == CSMWorld::ColumnBase::TableEdit_FixedRows) fixedRows = true; } From 894f3a9418ed70d8a111ce7b5c2fb276ce7a12e1 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 31 Oct 2015 20:42:42 +1100 Subject: [PATCH 77/81] Fix saving when only topic info was modified (topic itself unchanged) (cherry picked from commit 78c735adc609dda06954746b31cea4289a7060ad) --- apps/opencs/model/doc/savingstages.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index c6d8a8cb34..138e84b9a4 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -134,10 +134,21 @@ void CSMDoc::WriteDialogueCollectionStage::perform (int stage, Messages& message state==CSMWorld::RecordBase::State_ModifiedOnly || infoModified) { - mState.getWriter().startRecord (topic.mModified.sRecordId); - mState.getWriter().writeHNCString ("NAME", topic.mModified.mId); - topic.mModified.save (mState.getWriter()); - mState.getWriter().endRecord (topic.mModified.sRecordId); + if (infoModified && state != CSMWorld::RecordBase::State_Modified + && state != CSMWorld::RecordBase::State_ModifiedOnly) + { + mState.getWriter().startRecord (topic.mBase.sRecordId); + mState.getWriter().writeHNCString ("NAME", topic.mBase.mId); + topic.mBase.save (mState.getWriter()); + mState.getWriter().endRecord (topic.mBase.sRecordId); + } + else + { + mState.getWriter().startRecord (topic.mModified.sRecordId); + mState.getWriter().writeHNCString ("NAME", topic.mModified.mId); + topic.mModified.save (mState.getWriter()); + mState.getWriter().endRecord (topic.mModified.sRecordId); + } // write modified selected info records for (CSMWorld::InfoCollection::RecordConstIterator iter (range.first); iter!=range.second; From 26195dc5fe9e5edb01bfbba88dedf287ca323dba Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 31 Oct 2015 20:45:16 +1100 Subject: [PATCH 78/81] Rename a variable to make it less confusing. (cherry picked from commit 7c007d9c6d530126075165766a8c497bd3de7d62) --- apps/opencs/model/doc/savingstages.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 138e84b9a4..3fba2cd85c 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -154,14 +154,14 @@ void CSMDoc::WriteDialogueCollectionStage::perform (int stage, Messages& message for (CSMWorld::InfoCollection::RecordConstIterator iter (range.first); iter!=range.second; ++iter) { - CSMWorld::RecordBase::State state = iter->mState; + CSMWorld::RecordBase::State infoState = iter->mState; - if (state==CSMWorld::RecordBase::State_Deleted) + if (infoState==CSMWorld::RecordBase::State_Deleted) { /// \todo wrote record with delete flag } - else if (state==CSMWorld::RecordBase::State_Modified || - state==CSMWorld::RecordBase::State_ModifiedOnly) + else if (infoState==CSMWorld::RecordBase::State_Modified || + infoState==CSMWorld::RecordBase::State_ModifiedOnly) { ESM::DialInfo info = iter->get(); info.mId = info.mId.substr (info.mId.find_last_of ('#')+1); From a19a1dabe2ebcbf19d8cc69b5230c67474795e6d Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 1 Nov 2015 11:23:28 +1100 Subject: [PATCH 79/81] Add a check for scale value of 0. Should resolve bug #2880. (cherry picked from commit 819fecd08ec163e3f6b94ca40330f68214d54579) --- apps/opencs/model/tools/referenceablecheck.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/opencs/model/tools/referenceablecheck.cpp b/apps/opencs/model/tools/referenceablecheck.cpp index 6b323547f0..336a5e7132 100644 --- a/apps/opencs/model/tools/referenceablecheck.cpp +++ b/apps/opencs/model/tools/referenceablecheck.cpp @@ -468,6 +468,9 @@ void CSMTools::ReferenceableCheckStage::creatureCheck ( if (creature.mData.mGold < 0) //It seems that this is for gold in merchant creatures messages.push_back (std::make_pair (id, creature.mId + " has negative gold ")); + if (creature.mScale == 0) + messages.push_back (std::make_pair (id, creature.mId + " has zero scale value")); + // Check that mentioned scripts exist scriptCheck(creature, messages, id.toString()); } From 6d38d974708271fec3076f9766c52abb1de43d60 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Mon, 2 Nov 2015 06:43:20 +1100 Subject: [PATCH 80/81] Fix some sub-tables becoming uneditable since commit 80869d (cherry picked from commit 4af469511da373c48d7b3eaa0b4e1eb37971558c) Conflicts: apps/opencs/model/world/refidadapterimp.hpp --- apps/opencs/model/world/refidadapterimp.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index ad9c762643..170b5ebc03 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -1983,7 +1983,7 @@ namespace CSMWorld int index) const { if (column==mLevList.mLevList || column == mLevList.mNestedListLevList) - return true; // to show nested tables in dialogue subview, see IdTree::hasChildren() + return QVariant::fromValue(ColumnBase::TableEdit_Full); return BaseRefIdAdapter::getData (column, data, index); } From 12a8692cdbb3b3dfed428bd1df130f5ce7d149b6 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Mon, 2 Nov 2015 06:57:24 +1100 Subject: [PATCH 81/81] Fix include file issue. (cherry picked from commit 7f477e2fae47bdfe78ac17b2622ed2fdd844fd98) --- apps/opencs/model/world/refidadapterimp.cpp | 1 - apps/opencs/model/world/refidadapterimp.hpp | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index 3e7dc3acae..a268cb5f08 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -8,7 +8,6 @@ #include #include -#include "columnbase.hpp" #include "nestedtablewrapper.hpp" #include "usertype.hpp" #include "idtree.hpp" diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 170b5ebc03..a2b4df3c4b 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -15,6 +15,7 @@ #include #include +#include "columnbase.hpp" #include "record.hpp" #include "refiddata.hpp" #include "universalid.hpp"