From c3cd6e8a8aaccf74a8e62d6460a938584be4fc4c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 21 Nov 2012 17:31:18 +0100 Subject: [PATCH 001/136] new attempt at the editor --- CMakeLists.txt | 7 +++- apps/opencs/CMakeLists.txt | 44 +++++++++++++++++++++++ apps/opencs/main.cpp | 5 +++ apps/opencs/model/doc/document.cpp | 4 +++ apps/opencs/model/doc/document.hpp | 17 +++++++++ apps/opencs/model/doc/documentmanager.cpp | 37 +++++++++++++++++++ apps/opencs/model/doc/documentmanager.hpp | 31 ++++++++++++++++ 7 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/CMakeLists.txt create mode 100644 apps/opencs/main.cpp create mode 100644 apps/opencs/model/doc/document.cpp create mode 100644 apps/opencs/model/doc/document.hpp create mode 100644 apps/opencs/model/doc/documentmanager.cpp create mode 100644 apps/opencs/model/doc/documentmanager.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 78388e20f..d657de6ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ option(OGRE_STATIC "Link static build of Ogre and Ogre Plugins into the binaries option(BUILD_ESMTOOL "build ESM inspector" ON) option(BUILD_LAUNCHER "build Launcher" ON) option(BUILD_MWINIIMPORTER "build MWiniImporter" ON) +option(BUILD_OPENCS "build OpenMW Construction Set" ON) option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF) option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest ang GMock frameworks" OFF) @@ -244,7 +245,7 @@ if (APPLE) else () set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_DBG}) endif () - + #set(OGRE_PLUGIN_DIR "${OGRE_PLUGIN_DIR}/") configure_file(${OpenMW_SOURCE_DIR}/files/mac/Info.plist @@ -462,6 +463,10 @@ if (BUILD_MWINIIMPORTER) add_subdirectory( apps/mwiniimporter ) endif() +if (BUILD_OPENCS) + add_subdirectory (apps/opencs) +endif() + # UnitTests if (BUILD_UNITTESTS) add_subdirectory( apps/openmw_test_suite ) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt new file mode 100644 index 000000000..d213f68f9 --- /dev/null +++ b/apps/opencs/CMakeLists.txt @@ -0,0 +1,44 @@ + +set (OPENCS_SRC + main.cpp + + model/doc/documentmanager.cpp model/doc/document.cpp + ) + +set (OPENCS_HDR + model/doc/documentmanager.hpp model/doc/document.hpp + ) + +set (OPENCS_US + ) + +set (OPENCS_RES + ) + +source_group (opencs FILES ${OPENCS_SRC} ${OPENCS_HDR}) + +if(WIN32) + set(QT_USE_QTMAIN TRUE) +endif(WIN32) + +find_package(Qt4 COMPONENTS QtCore QtGui QtXml QtXmlPatterns REQUIRED) +include(${QT_USE_FILE}) + +qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI}) +qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR}) +qt4_add_resources(OPENCS_RES_SRC ${OPENCS_RES}) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +add_executable(opencs + ${OPENCS_SRC} + ${OPENCS_UI_HDR} + ${OPENCS_MOC_SRC} + ${OPENCS_RES_SRC} +) + +target_link_libraries(opencs + ${Boost_LIBRARIES} + ${QT_LIBRARIES} + components +) \ No newline at end of file diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp new file mode 100644 index 000000000..cd443603b --- /dev/null +++ b/apps/opencs/main.cpp @@ -0,0 +1,5 @@ + +int main(int argc, char *argv[]) +{ + +} \ No newline at end of file diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp new file mode 100644 index 000000000..7154c484b --- /dev/null +++ b/apps/opencs/model/doc/document.cpp @@ -0,0 +1,4 @@ + +#include "document.hpp" + +CSMDoc::Document::Document() {} \ No newline at end of file diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp new file mode 100644 index 000000000..7badf8fd7 --- /dev/null +++ b/apps/opencs/model/doc/document.hpp @@ -0,0 +1,17 @@ +#ifndef CSM_DOCUMENT_H +#define CSM_DOCUMENT_H + +namespace CSMDoc +{ + class Document + { + Document (const Document&); + Document& operator= (const Document&); + + public: + + Document(); + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp new file mode 100644 index 000000000..68595f2d4 --- /dev/null +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -0,0 +1,37 @@ + +#include "documentmanager.hpp" + +#include +#include + +#include "document.hpp" + +CSMDoc::DocumentManager::DocumentManager() {} + +CSMDoc::DocumentManager::~DocumentManager() +{ + for (std::vector::iterator iter (mDocuments.begin()); iter!=mDocuments.end(); ++iter) + delete *iter; +} + +CSMDoc::Document *CSMDoc::DocumentManager::addDocument() +{ + Document *document = new Document; + + mDocuments.push_back (document); + + return document; +} + +bool CSMDoc::DocumentManager::removeDocument (Document *document) +{ + std::vector::iterator iter = std::find (mDocuments.begin(), mDocuments.end(), document); + + if (iter==mDocuments.end()) + throw std::runtime_error ("removing invalid document"); + + mDocuments.erase (iter); + delete document; + + return mDocuments.empty(); +} \ No newline at end of file diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp new file mode 100644 index 000000000..7f0d388bc --- /dev/null +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -0,0 +1,31 @@ +#ifndef CSM_DOCUMENTMGR_H +#define CSM_DOCUMENTMGR_H + +#include + +namespace CSMDoc +{ + class Document; + + class DocumentManager + { + std::vector mDocuments; + + DocumentManager (const DocumentManager&); + DocumentManager& operator= (const DocumentManager&); + + public: + + DocumentManager(); + + ~DocumentManager(); + + Document *addDocument(); + ///< The ownership of the returned document is not transferred to the caller. + + bool removeDocument (Document *document); + ///< \return last document removed? + }; +} + +#endif \ No newline at end of file From 9834bb3ad52db108a11d6afe1a26d31f6833d925 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 22 Nov 2012 13:30:02 +0100 Subject: [PATCH 002/136] basic document handling --- apps/opencs/CMakeLists.txt | 8 ++++- apps/opencs/editor.cpp | 21 +++++++++++++ apps/opencs/editor.hpp | 29 +++++++++++++++++ apps/opencs/main.cpp | 8 +++++ apps/opencs/model/doc/document.hpp | 5 +-- apps/opencs/model/doc/documentmanager.hpp | 4 +-- apps/opencs/view/doc/view.cpp | 8 +++++ apps/opencs/view/doc/view.hpp | 30 ++++++++++++++++++ apps/opencs/view/doc/viewmanager.cpp | 26 ++++++++++++++++ apps/opencs/view/doc/viewmanager.hpp | 38 +++++++++++++++++++++++ 10 files changed, 172 insertions(+), 5 deletions(-) create mode 100644 apps/opencs/editor.cpp create mode 100644 apps/opencs/editor.hpp create mode 100644 apps/opencs/view/doc/view.cpp create mode 100644 apps/opencs/view/doc/view.hpp create mode 100644 apps/opencs/view/doc/viewmanager.cpp create mode 100644 apps/opencs/view/doc/viewmanager.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index d213f68f9..d7f113447 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -1,12 +1,18 @@ set (OPENCS_SRC - main.cpp + main.cpp editor.cpp model/doc/documentmanager.cpp model/doc/document.cpp + + view/doc/viewmanager.cpp view/doc/view.cpp ) set (OPENCS_HDR + editor.hpp + model/doc/documentmanager.hpp model/doc/document.hpp + + view/doc/viewmanager.hpp view/doc/view.hpp ) set (OPENCS_US diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp new file mode 100644 index 000000000..0a8a137f6 --- /dev/null +++ b/apps/opencs/editor.cpp @@ -0,0 +1,21 @@ + +#include "editor.hpp" + +#include + +CS::Editor::Editor() +{ +} + +void CS::Editor::createDocument() +{ + CSMDoc::Document *document = mDocumentManager.addDocument(); + mViewManager.addView (document); +} + +int CS::Editor::run() +{ + createDocument(); + + return QApplication::exec(); +} \ No newline at end of file diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp new file mode 100644 index 000000000..6e183b843 --- /dev/null +++ b/apps/opencs/editor.hpp @@ -0,0 +1,29 @@ +#ifndef CS_EDITOR_H +#define CS_EDITOR_H + +#include "model/doc/documentmanager.hpp" +#include "view/doc/viewmanager.hpp" + +namespace CS +{ + class Editor + { + CSMDoc::DocumentManager mDocumentManager; + CSVDoc::ViewManager mViewManager; + + // not implemented + Editor (const Editor&); + Editor& operator= (const Editor&); + + public: + + Editor(); + + void createDocument(); + + int run(); + ///< \return error status + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index cd443603b..15772eba0 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -1,5 +1,13 @@ +#include "editor.hpp" + +#include + int main(int argc, char *argv[]) { + QApplication mApplication (argc, argv); + + CS::Editor editor; + return editor.run(); } \ No newline at end of file diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 7badf8fd7..e44085962 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -1,10 +1,11 @@ -#ifndef CSM_DOCUMENT_H -#define CSM_DOCUMENT_H +#ifndef CSM_DOC_DOCUMENT_H +#define CSM_DOC_DOCUMENT_H namespace CSMDoc { class Document { + // not implemented Document (const Document&); Document& operator= (const Document&); diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index 7f0d388bc..f20f3101d 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -1,5 +1,5 @@ -#ifndef CSM_DOCUMENTMGR_H -#define CSM_DOCUMENTMGR_H +#ifndef CSM_DOC_DOCUMENTMGR_H +#define CSM_DOC_DOCUMENTMGR_H #include diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp new file mode 100644 index 000000000..2bad69bad --- /dev/null +++ b/apps/opencs/view/doc/view.cpp @@ -0,0 +1,8 @@ + +#include "view.hpp" + +CSVDoc::View::View (CSMDoc::Document *document) : mDocument (document) +{ + resize (200, 200); + setWindowTitle ("New Document"); +} \ No newline at end of file diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp new file mode 100644 index 000000000..797eef083 --- /dev/null +++ b/apps/opencs/view/doc/view.hpp @@ -0,0 +1,30 @@ +#ifndef CSV_DOC_VIEW_H +#define CSV_DOC_VIEW_H + +#include + +namespace CSMDoc +{ + class Document; +} + +namespace CSVDoc +{ + class View : public QWidget + { + Q_OBJECT + + CSMDoc::Document *mDocument; + + // not implemented + View (const View&); + View& operator= (const View&); + + public: + + View (CSMDoc::Document *document); + ///< The ownership of \a document is not transferred to *this. + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp new file mode 100644 index 000000000..59b79be47 --- /dev/null +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -0,0 +1,26 @@ + +#include "viewmanager.hpp" + +#include "view.hpp" + +CSVDoc::ViewManager::ViewManager() +{ + +} + +CSVDoc::ViewManager::~ViewManager() +{ + for (std::vector::iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) + delete *iter; +} + +CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) +{ + View *view = new View (document); + + mViews.push_back (view); + + view->show(); + + return view; +} \ No newline at end of file diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp new file mode 100644 index 000000000..dc6a07bce --- /dev/null +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -0,0 +1,38 @@ +#ifndef CSV_DOC_VIEWMANAGER_H +#define CSV_DOC_VIEWMANAGER_H + +#include + +namespace CSMDoc +{ + class Document; +} + +namespace CSVDoc +{ + class View; + + class ViewManager + { + std::vector mViews; + + // not implemented + ViewManager (const ViewManager&); + ViewManager& operator= (const ViewManager&); + + public: + + ViewManager(); + + ~ViewManager(); + + View *addView (CSMDoc::Document *document); + ///< The ownership of the returned view is not transferred. + + + + }; + +} + +#endif \ No newline at end of file From 758371d7e4c346f92b715bb3cb26ec9dfbd58e55 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 22 Nov 2012 14:10:23 +0100 Subject: [PATCH 003/136] implemented view/document closing --- apps/opencs/editor.cpp | 2 +- apps/opencs/view/doc/view.cpp | 25 ++++++++++++++++- apps/opencs/view/doc/view.hpp | 13 ++++++++- apps/opencs/view/doc/viewmanager.cpp | 41 ++++++++++++++++++++++++++-- apps/opencs/view/doc/viewmanager.hpp | 10 ++++++- 5 files changed, 85 insertions(+), 6 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 0a8a137f6..264ae7543 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -3,7 +3,7 @@ #include -CS::Editor::Editor() +CS::Editor::Editor() : mViewManager (mDocumentManager) { } diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 2bad69bad..51078d448 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -1,8 +1,31 @@ #include "view.hpp" -CSVDoc::View::View (CSMDoc::Document *document) : mDocument (document) +#include + +#include + +#include "viewmanager.hpp" + +void CSVDoc::View::closeEvent (QCloseEvent *event) +{ + if (!mViewManager.closeRequest (this)) + event->ignore(); +} + +CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document) +: mViewManager (viewManager), mDocument (document) { resize (200, 200); setWindowTitle ("New Document"); +} + +const CSMDoc::Document *CSVDoc::View::getDocument() const +{ + return mDocument; +} + +CSMDoc::Document *CSVDoc::View::getDocument() +{ + return mDocument; } \ No newline at end of file diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 797eef083..b12bb7e41 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -10,20 +10,31 @@ namespace CSMDoc namespace CSVDoc { + class ViewManager; + class View : public QWidget { Q_OBJECT + ViewManager& mViewManager; CSMDoc::Document *mDocument; // not implemented View (const View&); View& operator= (const View&); + private: + + void closeEvent (QCloseEvent *event); + public: - View (CSMDoc::Document *document); + View (ViewManager& viewManager, CSMDoc::Document *document); ///< The ownership of \a document is not transferred to *this. + + const CSMDoc::Document *getDocument() const; + + CSMDoc::Document *getDocument(); }; } diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 59b79be47..da73213f7 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -1,9 +1,12 @@ #include "viewmanager.hpp" +#include "../../model/doc/documentmanager.hpp" + #include "view.hpp" -CSVDoc::ViewManager::ViewManager() +CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) +: mDocumentManager (documentManager) { } @@ -12,15 +15,49 @@ CSVDoc::ViewManager::~ViewManager() { for (std::vector::iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) delete *iter; + + for (std::vector::iterator iter (mClosed.begin()); iter!=mClosed.end(); ++iter) + delete *iter; } CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) { - View *view = new View (document); + View *view = new View (*this, document); mViews.push_back (view); view->show(); return view; +} + +int CSVDoc::ViewManager::countViews (const CSMDoc::Document *document) const +{ + int count = 0; + + for (std::vector::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) + if ((*iter)->getDocument()==document) + ++count; + + return count; +} + +bool CSVDoc::ViewManager::closeRequest (View *view) +{ + std::vector::iterator iter = std::find (mViews.begin(), mViews.end(), view); + + if (iter!=mViews.end()) + { + bool last = countViews (view->getDocument())<=1; + + /// \todo check if document has not been saved -> return false and start close dialogue + + mViews.erase (iter); + mClosed.push_back (view); + + if (last) + mDocumentManager.removeDocument (view->getDocument()); + } + + return true; } \ No newline at end of file diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index dc6a07bce..6901590ed 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -6,6 +6,7 @@ namespace CSMDoc { class Document; + class DocumentManager; } namespace CSVDoc @@ -14,7 +15,9 @@ namespace CSVDoc class ViewManager { + CSMDoc::DocumentManager& mDocumentManager; std::vector mViews; + std::vector mClosed; // not implemented ViewManager (const ViewManager&); @@ -22,13 +25,18 @@ namespace CSVDoc public: - ViewManager(); + ViewManager (CSMDoc::DocumentManager& documentManager); ~ViewManager(); View *addView (CSMDoc::Document *document); ///< The ownership of the returned view is not transferred. + int countViews (const CSMDoc::Document *document) const; + ///< Return number of views for \a document. + + bool closeRequest (View *view); + }; From 789cecb9df5616fd49717ec006b3c7962a73b408 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 22 Nov 2012 14:49:58 +0100 Subject: [PATCH 004/136] added main menu and implemented new view function --- apps/opencs/view/doc/view.cpp | 20 ++++++++++++++++++++ apps/opencs/view/doc/view.hpp | 12 ++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 51078d448..847462964 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "viewmanager.hpp" @@ -13,11 +14,25 @@ void CSVDoc::View::closeEvent (QCloseEvent *event) event->ignore(); } +void CSVDoc::View::setupUi() +{ + // window menu + QMenu *view = menuBar()->addMenu (tr ("&View")); + + QAction *newWindow = new QAction (tr ("&New View"), this); + connect (newWindow, SIGNAL (triggered()), this, SLOT (newView())); + + view->addAction (newWindow); +} + CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document) : mViewManager (viewManager), mDocument (document) { + setCentralWidget (new QWidget); resize (200, 200); setWindowTitle ("New Document"); + + setupUi(); } const CSMDoc::Document *CSVDoc::View::getDocument() const @@ -28,4 +43,9 @@ const CSMDoc::Document *CSVDoc::View::getDocument() const CSMDoc::Document *CSVDoc::View::getDocument() { return mDocument; +} + +void CSVDoc::View::newView() +{ + mViewManager.addView (mDocument); } \ No newline at end of file diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index b12bb7e41..df88ff2cc 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -1,7 +1,9 @@ #ifndef CSV_DOC_VIEW_H #define CSV_DOC_VIEW_H -#include +#include + +class QAction; namespace CSMDoc { @@ -12,7 +14,7 @@ namespace CSVDoc { class ViewManager; - class View : public QWidget + class View : public QMainWindow { Q_OBJECT @@ -27,6 +29,8 @@ namespace CSVDoc void closeEvent (QCloseEvent *event); + void setupUi(); + public: View (ViewManager& viewManager, CSMDoc::Document *document); @@ -35,6 +39,10 @@ namespace CSVDoc const CSMDoc::Document *getDocument() const; CSMDoc::Document *getDocument(); + + private slots: + + void newView(); }; } From 1ddcea1f072e5cd727f5066c911f0a1015cfd983 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 22 Nov 2012 15:09:04 +0100 Subject: [PATCH 005/136] display view indices in title bar --- apps/opencs/view/doc/view.cpp | 30 +++++++++++++++++++++++----- apps/opencs/view/doc/view.hpp | 8 +++++++- apps/opencs/view/doc/viewmanager.cpp | 26 +++++++++++++++++++++++- apps/opencs/view/doc/viewmanager.hpp | 2 ++ 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 847462964..406ce7dc7 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -1,7 +1,7 @@ #include "view.hpp" -#include +#include #include #include @@ -16,7 +16,7 @@ void CSVDoc::View::closeEvent (QCloseEvent *event) void CSVDoc::View::setupUi() { - // window menu + // view menu QMenu *view = menuBar()->addMenu (tr ("&View")); QAction *newWindow = new QAction (tr ("&New View"), this); @@ -25,12 +25,25 @@ void CSVDoc::View::setupUi() view->addAction (newWindow); } -CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document) -: mViewManager (viewManager), mDocument (document) +void CSVDoc::View::updateTitle() +{ + std::ostringstream stream; + + stream << "New Document "; + + if (mViewTotal>1) + stream << " [" << (mViewIndex+1) << "/" << mViewTotal << "]"; + + setWindowTitle (stream.str().c_str()); +} + +CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) +: mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), mViewTotal (totalViews) { setCentralWidget (new QWidget); resize (200, 200); - setWindowTitle ("New Document"); + + updateTitle(); setupUi(); } @@ -45,6 +58,13 @@ CSMDoc::Document *CSVDoc::View::getDocument() return mDocument; } +void CSVDoc::View::setIndex (int viewIndex, int totalViews) +{ + mViewIndex = viewIndex; + mViewTotal = totalViews; + updateTitle(); +} + void CSVDoc::View::newView() { mViewManager.addView (mDocument); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index df88ff2cc..78ec45a5d 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -20,6 +20,8 @@ namespace CSVDoc ViewManager& mViewManager; CSMDoc::Document *mDocument; + int mViewIndex; + int mViewTotal; // not implemented View (const View&); @@ -31,15 +33,19 @@ namespace CSVDoc void setupUi(); + void updateTitle(); + public: - View (ViewManager& viewManager, CSMDoc::Document *document); + View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews); ///< The ownership of \a document is not transferred to *this. const CSMDoc::Document *getDocument() const; CSMDoc::Document *getDocument(); + void setIndex (int viewIndex, int totalViews); + private slots: void newView(); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index da73213f7..f6ac6e43d 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -1,10 +1,30 @@ #include "viewmanager.hpp" +#include + #include "../../model/doc/documentmanager.hpp" #include "view.hpp" +void CSVDoc::ViewManager::updateIndices() +{ + std::map > documents; + + for (std::vector::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) + { + std::map >::iterator document = documents.find ((*iter)->getDocument()); + + if (document==documents.end()) + document = + documents.insert ( + std::make_pair ((*iter)->getDocument(), std::make_pair (0, countViews ((*iter)->getDocument())))). + first; + + (*iter)->setIndex (document->second.first++, document->second.second); + } +} + CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) : mDocumentManager (documentManager) { @@ -22,12 +42,14 @@ CSVDoc::ViewManager::~ViewManager() CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) { - View *view = new View (*this, document); + View *view = new View (*this, document, countViews (document)+1); mViews.push_back (view); view->show(); + updateIndices(); + return view; } @@ -57,6 +79,8 @@ bool CSVDoc::ViewManager::closeRequest (View *view) if (last) mDocumentManager.removeDocument (view->getDocument()); + else + updateIndices(); } return true; diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index 6901590ed..765fafbea 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -23,6 +23,8 @@ namespace CSVDoc ViewManager (const ViewManager&); ViewManager& operator= (const ViewManager&); + void updateIndices(); + public: ViewManager (CSMDoc::DocumentManager& documentManager); From ed3d8b8ca2a4cd5dea2870f5bbbcf3f7de6abb0c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 22 Nov 2012 15:54:31 +0100 Subject: [PATCH 006/136] added undo stack and undo/redo actions --- apps/opencs/model/doc/document.cpp | 7 ++++++- apps/opencs/model/doc/document.hpp | 6 ++++++ apps/opencs/view/doc/view.cpp | 25 ++++++++++++++++++++++--- apps/opencs/view/doc/view.hpp | 4 ++++ 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 7154c484b..448598a4e 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -1,4 +1,9 @@ #include "document.hpp" -CSMDoc::Document::Document() {} \ No newline at end of file +CSMDoc::Document::Document() {} + +QUndoStack& CSMDoc::Document::getUndoStack() +{ + return mUndoStack; +} \ No newline at end of file diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index e44085962..1dea7afc2 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -1,10 +1,14 @@ #ifndef CSM_DOC_DOCUMENT_H #define CSM_DOC_DOCUMENT_H +#include + namespace CSMDoc { class Document { + QUndoStack mUndoStack; + // not implemented Document (const Document&); Document& operator= (const Document&); @@ -12,6 +16,8 @@ namespace CSMDoc public: Document(); + + QUndoStack& getUndoStack(); }; } diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 406ce7dc7..7a2296fed 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -6,6 +6,8 @@ #include #include +#include "../../model/doc/document.hpp" + #include "viewmanager.hpp" void CSVDoc::View::closeEvent (QCloseEvent *event) @@ -14,17 +16,34 @@ void CSVDoc::View::closeEvent (QCloseEvent *event) event->ignore(); } -void CSVDoc::View::setupUi() +void CSVDoc::View::setupEditMenu() +{ + QMenu *edit = menuBar()->addMenu (tr ("&Edit")); + + QAction *undo = mDocument->getUndoStack().createUndoAction (this, tr("&Undo")); + undo->setShortcuts (QKeySequence::Undo); + edit->addAction (undo); + + QAction *redo = mDocument->getUndoStack().createRedoAction (this, tr("&Redo")); + redo->setShortcuts (QKeySequence::Redo); + edit->addAction (redo); +} + +void CSVDoc::View::setupViewMenu() { - // view menu QMenu *view = menuBar()->addMenu (tr ("&View")); QAction *newWindow = new QAction (tr ("&New View"), this); connect (newWindow, SIGNAL (triggered()), this, SLOT (newView())); - view->addAction (newWindow); } +void CSVDoc::View::setupUi() +{ + setupEditMenu(); + setupViewMenu(); +} + void CSVDoc::View::updateTitle() { std::ostringstream stream; diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 78ec45a5d..457cc84fa 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -31,6 +31,10 @@ namespace CSVDoc void closeEvent (QCloseEvent *event); + void setupEditMenu(); + + void setupViewMenu(); + void setupUi(); void updateTitle(); From 8e546ebd30a6fb8c983bf11ccd9ce22f073b31ed Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 22 Nov 2012 16:00:23 +0100 Subject: [PATCH 007/136] added test command --- apps/opencs/view/doc/view.cpp | 10 ++++++++++ apps/opencs/view/doc/view.hpp | 2 ++ 2 files changed, 12 insertions(+) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 7a2296fed..c5792b27a 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -27,6 +27,11 @@ void CSVDoc::View::setupEditMenu() QAction *redo = mDocument->getUndoStack().createRedoAction (this, tr("&Redo")); redo->setShortcuts (QKeySequence::Redo); edit->addAction (redo); + + // test + QAction *test = new QAction (tr ("&Test Command"), this); + connect (test, SIGNAL (triggered()), this, SLOT (test())); + edit->addAction (test); } void CSVDoc::View::setupViewMenu() @@ -87,4 +92,9 @@ void CSVDoc::View::setIndex (int viewIndex, int totalViews) void CSVDoc::View::newView() { mViewManager.addView (mDocument); +} + +void CSVDoc::View::test() +{ + mDocument->getUndoStack().push (new QUndoCommand()); } \ No newline at end of file diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 457cc84fa..2c312715a 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -53,6 +53,8 @@ namespace CSVDoc private slots: void newView(); + + void test(); }; } From d7c63d4c74472e7bffd47531319c94343feb646f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 22 Nov 2012 23:42:17 +0100 Subject: [PATCH 008/136] track document modification state and display it in the top level window title bar --- apps/opencs/model/doc/document.cpp | 20 +++++++++++++++++++- apps/opencs/model/doc/document.hpp | 22 +++++++++++++++++++++- apps/opencs/view/doc/view.cpp | 8 ++++++++ apps/opencs/view/doc/view.hpp | 2 ++ apps/opencs/view/doc/viewmanager.cpp | 15 +++++++++++++++ apps/opencs/view/doc/viewmanager.hpp | 11 ++++++++--- 6 files changed, 73 insertions(+), 5 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 448598a4e..8770b3b90 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -1,9 +1,27 @@ #include "document.hpp" -CSMDoc::Document::Document() {} +CSMDoc::Document::Document() +{ + connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool))); +} QUndoStack& CSMDoc::Document::getUndoStack() { return mUndoStack; +} + +int CSMDoc::Document::getState() const +{ + int state = 0; + + if (!mUndoStack.isClean()) + state |= State_Modified; + + return state; +} + +void CSMDoc::Document::modificationStateChanged (bool clean) +{ + emit stateChanged (getState(), this); } \ No newline at end of file diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 1dea7afc2..0499aaf9f 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -2,11 +2,21 @@ #define CSM_DOC_DOCUMENT_H #include +#include namespace CSMDoc { - class Document + class Document : public QObject { + Q_OBJECT + + public: + + enum State + { + State_Modified = 1 + }; + QUndoStack mUndoStack; // not implemented @@ -18,6 +28,16 @@ namespace CSMDoc Document(); QUndoStack& getUndoStack(); + + int getState() const; + + signals: + + void stateChanged (int state, CSMDoc::Document *document); + + private slots: + + void modificationStateChanged (bool clean); }; } diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index c5792b27a..be753e216 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -55,6 +55,9 @@ void CSVDoc::View::updateTitle() stream << "New Document "; + if (mDocument->getState() & CSMDoc::Document::State_Modified) + stream << " *"; + if (mViewTotal>1) stream << " [" << (mViewIndex+1) << "/" << mViewTotal << "]"; @@ -89,6 +92,11 @@ void CSVDoc::View::setIndex (int viewIndex, int totalViews) updateTitle(); } +void CSVDoc::View::updateDocumentState() +{ + updateTitle(); +} + void CSVDoc::View::newView() { mViewManager.addView (mDocument); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 2c312715a..67eafe2d5 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -50,6 +50,8 @@ namespace CSVDoc void setIndex (int viewIndex, int totalViews); + void updateDocumentState(); + private slots: void newView(); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index f6ac6e43d..ad391dabe 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -4,6 +4,7 @@ #include #include "../../model/doc/documentmanager.hpp" +#include "../../model/doc/document.hpp" #include "view.hpp" @@ -42,6 +43,13 @@ CSVDoc::ViewManager::~ViewManager() CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) { + if (countViews (document)==0) + { + // new document + connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), + this, SLOT (documentStateChanged (int, CSMDoc::Document *))); + } + View *view = new View (*this, document, countViews (document)+1); mViews.push_back (view); @@ -84,4 +92,11 @@ bool CSVDoc::ViewManager::closeRequest (View *view) } return true; +} + +void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *document) +{ + for (std::vector::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) + if ((*iter)->getDocument()==document) + (*iter)->updateDocumentState(); } \ No newline at end of file diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index 765fafbea..1565b7c37 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -3,6 +3,8 @@ #include +#include + namespace CSMDoc { class Document; @@ -13,8 +15,10 @@ namespace CSVDoc { class View; - class ViewManager + class ViewManager : public QObject { + Q_OBJECT + CSMDoc::DocumentManager& mDocumentManager; std::vector mViews; std::vector mClosed; @@ -29,7 +33,7 @@ namespace CSVDoc ViewManager (CSMDoc::DocumentManager& documentManager); - ~ViewManager(); + virtual ~ViewManager(); View *addView (CSMDoc::Document *document); ///< The ownership of the returned view is not transferred. @@ -39,8 +43,9 @@ namespace CSVDoc bool closeRequest (View *view); + private slots: - + void documentStateChanged (int state, CSMDoc::Document *document); }; } From 5838929371d37b2f4b8771d3c1a8fb17b3989b06 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 23 Nov 2012 00:36:01 +0100 Subject: [PATCH 009/136] implemented a dummy save function (does not actually save anything) --- apps/opencs/model/doc/document.cpp | 30 ++++++++++++++++++++++++++++ apps/opencs/model/doc/document.hpp | 15 +++++++++++++- apps/opencs/view/doc/view.cpp | 15 ++++++++++++++ apps/opencs/view/doc/view.hpp | 4 ++++ apps/opencs/view/doc/viewmanager.cpp | 2 +- 5 files changed, 64 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 8770b3b90..8788ecb9f 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -4,6 +4,10 @@ CSMDoc::Document::Document() { connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool))); + + // dummy implementation -> remove when proper save is implemented. + mSaveCount = 0; + connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving())); } QUndoStack& CSMDoc::Document::getUndoStack() @@ -18,10 +22,36 @@ int CSMDoc::Document::getState() const if (!mUndoStack.isClean()) state |= State_Modified; + if (mSaveCount) + state |= State_Locked | State_Saving; + return state; } +void CSMDoc::Document::save() +{ + mSaveCount = 1; + mSaveTimer.start (500); +} + +void CSMDoc::Document::abortSave() +{ + mSaveTimer.stop(); +} + void CSMDoc::Document::modificationStateChanged (bool clean) { emit stateChanged (getState(), this); +} + +void CSMDoc::Document::saving() +{ + ++mSaveCount; + + if (mSaveCount>15) + { + mSaveCount = 0; + mSaveTimer.stop(); + mUndoStack.setClean(); + } } \ No newline at end of file diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 0499aaf9f..90589b09c 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace CSMDoc { @@ -14,11 +15,16 @@ namespace CSMDoc enum State { - State_Modified = 1 + State_Modified = 1, + State_Locked = 2, + State_Saving = 4 }; QUndoStack mUndoStack; + int mSaveCount; ///< dummy implementation -> remove when proper save is implemented. + QTimer mSaveTimer; ///< dummy implementation -> remove when proper save is implemented. + // not implemented Document (const Document&); Document& operator= (const Document&); @@ -31,6 +37,10 @@ namespace CSMDoc int getState() const; + void save(); + + void abortSave(); + signals: void stateChanged (int state, CSMDoc::Document *document); @@ -38,6 +48,9 @@ namespace CSMDoc private slots: void modificationStateChanged (bool clean); + + void saving(); + ///< dummy implementation -> remove when proper save is implemented. }; } diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index be753e216..59852bef0 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -16,6 +16,15 @@ void CSVDoc::View::closeEvent (QCloseEvent *event) event->ignore(); } +void CSVDoc::View::setupFileMenu() +{ + QMenu *file = menuBar()->addMenu (tr ("&File")); + + QAction *save = new QAction (tr ("&Save"), this); + connect (save, SIGNAL (triggered()), this, SLOT (save())); + file->addAction (save); +} + void CSVDoc::View::setupEditMenu() { QMenu *edit = menuBar()->addMenu (tr ("&Edit")); @@ -45,6 +54,7 @@ void CSVDoc::View::setupViewMenu() void CSVDoc::View::setupUi() { + setupFileMenu(); setupEditMenu(); setupViewMenu(); } @@ -105,4 +115,9 @@ void CSVDoc::View::newView() void CSVDoc::View::test() { mDocument->getUndoStack().push (new QUndoCommand()); +} + +void CSVDoc::View::save() +{ + mDocument->save(); } \ No newline at end of file diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 67eafe2d5..be7d23fd0 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -31,6 +31,8 @@ namespace CSVDoc void closeEvent (QCloseEvent *event); + void setupFileMenu(); + void setupEditMenu(); void setupViewMenu(); @@ -57,6 +59,8 @@ namespace CSVDoc void newView(); void test(); + + void save(); }; } diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index ad391dabe..c7f147660 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -99,4 +99,4 @@ void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *doc for (std::vector::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) if ((*iter)->getDocument()==document) (*iter)->updateDocumentState(); -} \ No newline at end of file +} From 931eb08114184442f856239f1f32f1da25ddde6d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 23 Nov 2012 00:51:04 +0100 Subject: [PATCH 010/136] implemented edit locking (used during saves) --- apps/opencs/model/doc/document.cpp | 3 +++ apps/opencs/view/doc/view.cpp | 26 ++++++++++++++++++++------ apps/opencs/view/doc/view.hpp | 7 +++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 8788ecb9f..16af492a9 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -32,11 +32,13 @@ void CSMDoc::Document::save() { mSaveCount = 1; mSaveTimer.start (500); + emit stateChanged (getState(), this); } void CSMDoc::Document::abortSave() { mSaveTimer.stop(); + emit stateChanged (getState(), this); } void CSMDoc::Document::modificationStateChanged (bool clean) @@ -53,5 +55,6 @@ void CSMDoc::Document::saving() mSaveCount = 0; mSaveTimer.stop(); mUndoStack.setClean(); + emit stateChanged (getState(), this); } } \ No newline at end of file diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 59852bef0..85db5e51f 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -23,24 +23,26 @@ void CSVDoc::View::setupFileMenu() QAction *save = new QAction (tr ("&Save"), this); connect (save, SIGNAL (triggered()), this, SLOT (save())); file->addAction (save); + mEditingActions.push_back (save); } void CSVDoc::View::setupEditMenu() { QMenu *edit = menuBar()->addMenu (tr ("&Edit")); - QAction *undo = mDocument->getUndoStack().createUndoAction (this, tr("&Undo")); - undo->setShortcuts (QKeySequence::Undo); - edit->addAction (undo); + mUndo = mDocument->getUndoStack().createUndoAction (this, tr("&Undo")); + mUndo->setShortcuts (QKeySequence::Undo); + edit->addAction (mUndo); - QAction *redo = mDocument->getUndoStack().createRedoAction (this, tr("&Redo")); - redo->setShortcuts (QKeySequence::Redo); - edit->addAction (redo); + mRedo= mDocument->getUndoStack().createRedoAction (this, tr("&Redo")); + mRedo->setShortcuts (QKeySequence::Redo); + edit->addAction (mRedo); // test QAction *test = new QAction (tr ("&Test Command"), this); connect (test, SIGNAL (triggered()), this, SLOT (test())); edit->addAction (test); + mEditingActions.push_back (test); } void CSVDoc::View::setupViewMenu() @@ -74,6 +76,17 @@ void CSVDoc::View::updateTitle() setWindowTitle (stream.str().c_str()); } +void CSVDoc::View::updateActions() +{ + bool editing = !(mDocument->getState() & CSMDoc::Document::State_Locked); + + for (std::vector::iterator iter (mEditingActions.begin()); iter!=mEditingActions.end(); ++iter) + (*iter)->setEnabled (editing); + + mUndo->setEnabled (editing & mDocument->getUndoStack().canUndo()); + mRedo->setEnabled (editing & mDocument->getUndoStack().canRedo()); +} + CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) : mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), mViewTotal (totalViews) { @@ -105,6 +118,7 @@ void CSVDoc::View::setIndex (int viewIndex, int totalViews) void CSVDoc::View::updateDocumentState() { updateTitle(); + updateActions(); } void CSVDoc::View::newView() diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index be7d23fd0..bab142959 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -1,6 +1,8 @@ #ifndef CSV_DOC_VIEW_H #define CSV_DOC_VIEW_H +#include + #include class QAction; @@ -22,6 +24,9 @@ namespace CSVDoc CSMDoc::Document *mDocument; int mViewIndex; int mViewTotal; + QAction *mUndo; + QAction *mRedo; + std::vector mEditingActions; // not implemented View (const View&); @@ -41,6 +46,8 @@ namespace CSVDoc void updateTitle(); + void updateActions(); + public: View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews); From 03aacd326395c8548d5091bf5b83b92e6b969d69 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 23 Nov 2012 10:25:34 +0100 Subject: [PATCH 011/136] added progress tracking --- apps/opencs/model/doc/document.cpp | 5 ++++- apps/opencs/model/doc/document.hpp | 5 ++++- apps/opencs/view/doc/view.cpp | 5 +++++ apps/opencs/view/doc/view.hpp | 2 ++ apps/opencs/view/doc/viewmanager.cpp | 11 +++++++++++ apps/opencs/view/doc/viewmanager.hpp | 2 ++ 6 files changed, 28 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 16af492a9..3c2c5cd8a 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -23,7 +23,7 @@ int CSMDoc::Document::getState() const state |= State_Modified; if (mSaveCount) - state |= State_Locked | State_Saving; + state |= State_Locked | State_Saving | State_Progress; return state; } @@ -33,6 +33,7 @@ void CSMDoc::Document::save() mSaveCount = 1; mSaveTimer.start (500); emit stateChanged (getState(), this); + emit progress (1, 16, this); } void CSMDoc::Document::abortSave() @@ -50,6 +51,8 @@ void CSMDoc::Document::saving() { ++mSaveCount; + emit progress (mSaveCount, 16, this); + if (mSaveCount>15) { mSaveCount = 0; diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 90589b09c..b1c9ead86 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -17,7 +17,8 @@ namespace CSMDoc { State_Modified = 1, State_Locked = 2, - State_Saving = 4 + State_Saving = 4, + State_Progress = 8 }; QUndoStack mUndoStack; @@ -45,6 +46,8 @@ namespace CSMDoc void stateChanged (int state, CSMDoc::Document *document); + void progress (int current, int max, CSMDoc::Document *document); + private slots: void modificationStateChanged (bool clean); diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 85db5e51f..8f3efc673 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -121,6 +121,11 @@ void CSVDoc::View::updateDocumentState() updateActions(); } +void CSVDoc::View::updateProgress (int current, int max) +{ + +} + void CSVDoc::View::newView() { mViewManager.addView (mDocument); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index bab142959..ab945188f 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -61,6 +61,8 @@ namespace CSVDoc void updateDocumentState(); + void updateProgress (int current, int max); + private slots: void newView(); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index c7f147660..752501b19 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -48,6 +48,9 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) // new document connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (documentStateChanged (int, CSMDoc::Document *))); + + connect (document, SIGNAL (progress (int, int, CSMDoc::Document *)), + this, SLOT (progress (int, int, CSMDoc::Document *))); } View *view = new View (*this, document, countViews (document)+1); @@ -80,6 +83,7 @@ bool CSVDoc::ViewManager::closeRequest (View *view) { bool last = countViews (view->getDocument())<=1; + /// \todo check if save is in progress -> warn user about possible data loss /// \todo check if document has not been saved -> return false and start close dialogue mViews.erase (iter); @@ -100,3 +104,10 @@ void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *doc if ((*iter)->getDocument()==document) (*iter)->updateDocumentState(); } + +void CSVDoc::ViewManager::progress (int current, int max, CSMDoc::Document *document) +{ + for (std::vector::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) + if ((*iter)->getDocument()==document) + (*iter)->updateProgress (current, max); +} \ No newline at end of file diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index 1565b7c37..8cfc36f3f 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -46,6 +46,8 @@ namespace CSVDoc private slots: void documentStateChanged (int state, CSMDoc::Document *document); + + void progress (int current, int max, CSMDoc::Document *document); }; } From 04158d03b05cc63ba238835821a4125ea0ba8869 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 23 Nov 2012 10:30:14 +0100 Subject: [PATCH 012/136] clean up properly after closing a top level window --- apps/opencs/view/doc/viewmanager.cpp | 5 +---- apps/opencs/view/doc/viewmanager.hpp | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 752501b19..7f94f52a2 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -36,9 +36,6 @@ CSVDoc::ViewManager::~ViewManager() { for (std::vector::iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) delete *iter; - - for (std::vector::iterator iter (mClosed.begin()); iter!=mClosed.end(); ++iter) - delete *iter; } CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) @@ -87,7 +84,7 @@ bool CSVDoc::ViewManager::closeRequest (View *view) /// \todo check if document has not been saved -> return false and start close dialogue mViews.erase (iter); - mClosed.push_back (view); + view->deleteLater(); if (last) mDocumentManager.removeDocument (view->getDocument()); diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index 8cfc36f3f..bcf6dc59e 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -21,7 +21,6 @@ namespace CSVDoc CSMDoc::DocumentManager& mDocumentManager; std::vector mViews; - std::vector mClosed; // not implemented ViewManager (const ViewManager&); From eaa58e0530c3624ee186f5f43ef02f63203354a3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 23 Nov 2012 10:52:46 +0100 Subject: [PATCH 013/136] preparations for multiple parallel progress-type operations --- apps/opencs/model/doc/document.cpp | 6 +++--- apps/opencs/model/doc/document.hpp | 5 ++--- apps/opencs/view/doc/view.cpp | 11 ++++++----- apps/opencs/view/doc/view.hpp | 3 ++- apps/opencs/view/doc/viewmanager.cpp | 8 ++++---- apps/opencs/view/doc/viewmanager.hpp | 2 +- 6 files changed, 18 insertions(+), 17 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 3c2c5cd8a..c4f830531 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -23,7 +23,7 @@ int CSMDoc::Document::getState() const state |= State_Modified; if (mSaveCount) - state |= State_Locked | State_Saving | State_Progress; + state |= State_Locked | State_Saving; return state; } @@ -33,7 +33,7 @@ void CSMDoc::Document::save() mSaveCount = 1; mSaveTimer.start (500); emit stateChanged (getState(), this); - emit progress (1, 16, this); + emit progress (1, 16, State_Saving, this); } void CSMDoc::Document::abortSave() @@ -51,7 +51,7 @@ void CSMDoc::Document::saving() { ++mSaveCount; - emit progress (mSaveCount, 16, this); + emit progress (mSaveCount, 16, State_Saving, this); if (mSaveCount>15) { diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index b1c9ead86..8553427a1 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -17,8 +17,7 @@ namespace CSMDoc { State_Modified = 1, State_Locked = 2, - State_Saving = 4, - State_Progress = 8 + State_Saving = 4 }; QUndoStack mUndoStack; @@ -46,7 +45,7 @@ namespace CSMDoc void stateChanged (int state, CSMDoc::Document *document); - void progress (int current, int max, CSMDoc::Document *document); + void progress (int current, int max, int type, CSMDoc::Document *document); private slots: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 8f3efc673..3e9701669 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -20,10 +20,9 @@ void CSVDoc::View::setupFileMenu() { QMenu *file = menuBar()->addMenu (tr ("&File")); - QAction *save = new QAction (tr ("&Save"), this); - connect (save, SIGNAL (triggered()), this, SLOT (save())); - file->addAction (save); - mEditingActions.push_back (save); + mSave = new QAction (tr ("&Save"), this); + connect (mSave, SIGNAL (triggered()), this, SLOT (save())); + file->addAction (mSave); } void CSVDoc::View::setupEditMenu() @@ -85,6 +84,8 @@ void CSVDoc::View::updateActions() mUndo->setEnabled (editing & mDocument->getUndoStack().canUndo()); mRedo->setEnabled (editing & mDocument->getUndoStack().canRedo()); + + mSave->setEnabled (!(mDocument->getState() & CSMDoc::Document::State_Saving)); } CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) @@ -121,7 +122,7 @@ void CSVDoc::View::updateDocumentState() updateActions(); } -void CSVDoc::View::updateProgress (int current, int max) +void CSVDoc::View::updateProgress (int current, int max, int type) { } diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index ab945188f..1836ced8b 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -26,6 +26,7 @@ namespace CSVDoc int mViewTotal; QAction *mUndo; QAction *mRedo; + QAction *mSave; std::vector mEditingActions; // not implemented @@ -61,7 +62,7 @@ namespace CSVDoc void updateDocumentState(); - void updateProgress (int current, int max); + void updateProgress (int current, int max, int type); private slots: diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 7f94f52a2..ed31fdb75 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -46,8 +46,8 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (documentStateChanged (int, CSMDoc::Document *))); - connect (document, SIGNAL (progress (int, int, CSMDoc::Document *)), - this, SLOT (progress (int, int, CSMDoc::Document *))); + connect (document, SIGNAL (progress (int, int, int, CSMDoc::Document *)), + this, SLOT (progress (int, int, int, CSMDoc::Document *))); } View *view = new View (*this, document, countViews (document)+1); @@ -102,9 +102,9 @@ void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *doc (*iter)->updateDocumentState(); } -void CSVDoc::ViewManager::progress (int current, int max, CSMDoc::Document *document) +void CSVDoc::ViewManager::progress (int current, int max, int type, CSMDoc::Document *document) { for (std::vector::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) if ((*iter)->getDocument()==document) - (*iter)->updateProgress (current, max); + (*iter)->updateProgress (current, max, type); } \ No newline at end of file diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index bcf6dc59e..eac490250 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -46,7 +46,7 @@ namespace CSVDoc void documentStateChanged (int state, CSMDoc::Document *document); - void progress (int current, int max, CSMDoc::Document *document); + void progress (int current, int max, int type, CSMDoc::Document *document); }; } From 2fc183d595a59ff9d84b67dc32448234ebe4d6ff Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 23 Nov 2012 12:20:35 +0100 Subject: [PATCH 014/136] added operations progress bar --- apps/opencs/CMakeLists.txt | 4 +-- apps/opencs/model/doc/document.cpp | 13 +++++--- apps/opencs/model/doc/document.hpp | 4 +-- apps/opencs/view/doc/operation.cpp | 49 ++++++++++++++++++++++++++++ apps/opencs/view/doc/operation.hpp | 31 ++++++++++++++++++ apps/opencs/view/doc/operations.cpp | 47 ++++++++++++++++++++++++++ apps/opencs/view/doc/operations.hpp | 37 +++++++++++++++++++++ apps/opencs/view/doc/view.cpp | 20 ++++++++++-- apps/opencs/view/doc/view.hpp | 4 ++- apps/opencs/view/doc/viewmanager.cpp | 8 ++--- apps/opencs/view/doc/viewmanager.hpp | 2 +- 11 files changed, 202 insertions(+), 17 deletions(-) create mode 100644 apps/opencs/view/doc/operation.cpp create mode 100644 apps/opencs/view/doc/operation.hpp create mode 100644 apps/opencs/view/doc/operations.cpp create mode 100644 apps/opencs/view/doc/operations.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index d7f113447..66b9f4942 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -4,7 +4,7 @@ set (OPENCS_SRC model/doc/documentmanager.cpp model/doc/document.cpp - view/doc/viewmanager.cpp view/doc/view.cpp + view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp ) set (OPENCS_HDR @@ -12,7 +12,7 @@ set (OPENCS_HDR model/doc/documentmanager.hpp model/doc/document.hpp - view/doc/viewmanager.hpp view/doc/view.hpp + view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp ) set (OPENCS_US diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index c4f830531..473d72375 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -33,13 +33,16 @@ void CSMDoc::Document::save() mSaveCount = 1; mSaveTimer.start (500); emit stateChanged (getState(), this); - emit progress (1, 16, State_Saving, this); + emit progress (1, 16, State_Saving, 1, this); } -void CSMDoc::Document::abortSave() +void CSMDoc::Document::abortOperation (int type) { - mSaveTimer.stop(); - emit stateChanged (getState(), this); + if (type==State_Saving) + { + mSaveTimer.stop(); + emit stateChanged (getState(), this); + } } void CSMDoc::Document::modificationStateChanged (bool clean) @@ -51,7 +54,7 @@ void CSMDoc::Document::saving() { ++mSaveCount; - emit progress (mSaveCount, 16, State_Saving, this); + emit progress (mSaveCount, 16, State_Saving, 1, this); if (mSaveCount>15) { diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 8553427a1..3bed0151d 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -39,13 +39,13 @@ namespace CSMDoc void save(); - void abortSave(); + void abortOperation (int type); signals: void stateChanged (int state, CSMDoc::Document *document); - void progress (int current, int max, int type, CSMDoc::Document *document); + void progress (int current, int max, int type, int threads, CSMDoc::Document *document); private slots: diff --git a/apps/opencs/view/doc/operation.cpp b/apps/opencs/view/doc/operation.cpp new file mode 100644 index 000000000..cd9477557 --- /dev/null +++ b/apps/opencs/view/doc/operation.cpp @@ -0,0 +1,49 @@ + +#include "operation.hpp" + +#include + +#include "../../model/doc/document.hpp" + +void CSVDoc::Operation::updateLabel (int threads) +{ + if (threads==-1 || ((threads==0)!=mStalling)) + { + std::string name ("unknown operation"); + + switch (mType) + { + case CSMDoc::Document::State_Saving: name = "saving"; break; + } + + std::ostringstream stream; + + if ((mStalling = (threads<=0))) + { + stream << name << " (waiting for a free worker thread)"; + } + else + { + stream << name << " (%p%)"; + } + + setFormat (stream.str().c_str()); + } +} + +CSVDoc::Operation::Operation (int type) : mType (type), mStalling (false) +{ + updateLabel(); +} + +void CSVDoc::Operation::setProgress (int current, int max, int threads) +{ + updateLabel (threads); + setRange (0, max); + setValue (current); +} + +int CSVDoc::Operation::getType() const +{ + return mType; +} \ No newline at end of file diff --git a/apps/opencs/view/doc/operation.hpp b/apps/opencs/view/doc/operation.hpp new file mode 100644 index 000000000..362725b6f --- /dev/null +++ b/apps/opencs/view/doc/operation.hpp @@ -0,0 +1,31 @@ +#ifndef CSV_DOC_OPERATION_H +#define CSV_DOC_OPERATION_H + +#include + +namespace CSVDoc +{ + class Operation : public QProgressBar + { + Q_OBJECT + + int mType; + bool mStalling; + + // not implemented + Operation (const Operation&); + Operation& operator= (const Operation&); + + void updateLabel (int threads = -1); + + public: + + Operation (int type); + + void setProgress (int current, int max, int threads); + + int getType() const; + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/doc/operations.cpp b/apps/opencs/view/doc/operations.cpp new file mode 100644 index 000000000..ba444a119 --- /dev/null +++ b/apps/opencs/view/doc/operations.cpp @@ -0,0 +1,47 @@ + +#include "operations.hpp" + +#include + +#include "operation.hpp" + +CSVDoc::Operations::Operations() +{ + /// \todo make widget height fixed (exactly the height required to display all operations) + + setFeatures (QDockWidget::NoDockWidgetFeatures); + + QWidget *widget = new QWidget; + setWidget (widget); + + mLayout = new QVBoxLayout; + + widget->setLayout (mLayout); +} + +void CSVDoc::Operations::setProgress (int current, int max, int type, int threads) +{ + for (std::vector::iterator iter (mOperations.begin()); iter!=mOperations.end(); ++iter) + if ((*iter)->getType()==type) + { + (*iter)->setProgress (current, max, threads); + return; + } + + Operation *operation = new Operation (type); + + mLayout->addWidget (operation); + mOperations.push_back (operation); + operation->setProgress (current, max, threads); +} + +void CSVDoc::Operations::quitOperation (int type) +{ + for (std::vector::iterator iter (mOperations.begin()); iter!=mOperations.end(); ++iter) + if ((*iter)->getType()==type) + { + delete *iter; + mOperations.erase (iter); + break; + } +} \ No newline at end of file diff --git a/apps/opencs/view/doc/operations.hpp b/apps/opencs/view/doc/operations.hpp new file mode 100644 index 000000000..b96677450 --- /dev/null +++ b/apps/opencs/view/doc/operations.hpp @@ -0,0 +1,37 @@ +#ifndef CSV_DOC_OPERATIONS_H +#define CSV_DOC_OPERATIONS_H + +#include + +#include + +class QVBoxLayout; + +namespace CSVDoc +{ + class Operation; + + class Operations : public QDockWidget + { + Q_OBJECT + + QVBoxLayout *mLayout; + std::vector mOperations; + + // not implemented + Operations (const Operations&); + Operations& operator= (const Operations&); + + public: + + Operations(); + + void setProgress (int current, int max, int type, int threads); + ///< Implicitly starts the operation, if it is not running already. + + void quitOperation (int type); + ///< Calling this function for an operation that is not running is a no-op. + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 3e9701669..fe018ab3b 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -9,6 +9,7 @@ #include "../../model/doc/document.hpp" #include "viewmanager.hpp" +#include "operations.hpp" void CSVDoc::View::closeEvent (QCloseEvent *event) { @@ -94,6 +95,9 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to setCentralWidget (new QWidget); resize (200, 200); + mOperations = new Operations; + addDockWidget (Qt::BottomDockWidgetArea, mOperations); + updateTitle(); setupUi(); @@ -120,11 +124,23 @@ void CSVDoc::View::updateDocumentState() { updateTitle(); updateActions(); + + static const int operations[] = + { + CSMDoc::Document::State_Saving, + -1 // end marker + }; + + int state = mDocument->getState() ; + + for (int i=0; operations[i]!=-1; ++i) + if (!(state & operations[i])) + mOperations->quitOperation (operations[i]); } -void CSVDoc::View::updateProgress (int current, int max, int type) +void CSVDoc::View::updateProgress (int current, int max, int type, int threads) { - + mOperations->setProgress (current, max, type, threads); } void CSVDoc::View::newView() diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 1836ced8b..191af36b5 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -15,6 +15,7 @@ namespace CSMDoc namespace CSVDoc { class ViewManager; + class Operations; class View : public QMainWindow { @@ -28,6 +29,7 @@ namespace CSVDoc QAction *mRedo; QAction *mSave; std::vector mEditingActions; + Operations *mOperations; // not implemented View (const View&); @@ -62,7 +64,7 @@ namespace CSVDoc void updateDocumentState(); - void updateProgress (int current, int max, int type); + void updateProgress (int current, int max, int type, int threads); private slots: diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index ed31fdb75..673afbad8 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -46,8 +46,8 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (documentStateChanged (int, CSMDoc::Document *))); - connect (document, SIGNAL (progress (int, int, int, CSMDoc::Document *)), - this, SLOT (progress (int, int, int, CSMDoc::Document *))); + connect (document, SIGNAL (progress (int, int, int, int, CSMDoc::Document *)), + this, SLOT (progress (int, int, int, int, CSMDoc::Document *))); } View *view = new View (*this, document, countViews (document)+1); @@ -102,9 +102,9 @@ void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *doc (*iter)->updateDocumentState(); } -void CSVDoc::ViewManager::progress (int current, int max, int type, CSMDoc::Document *document) +void CSVDoc::ViewManager::progress (int current, int max, int type, int threads, CSMDoc::Document *document) { for (std::vector::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) if ((*iter)->getDocument()==document) - (*iter)->updateProgress (current, max, type); + (*iter)->updateProgress (current, max, type, threads); } \ No newline at end of file diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index eac490250..caf75a0cd 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -46,7 +46,7 @@ namespace CSVDoc void documentStateChanged (int state, CSMDoc::Document *document); - void progress (int current, int max, int type, CSMDoc::Document *document); + void progress (int current, int max, int type, int threads, CSMDoc::Document *document); }; } From 997386d8736b036bdb3dd1a7a38e904d4793a755 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 23 Nov 2012 13:15:45 +0100 Subject: [PATCH 015/136] implemented world verify function (doesn't do anything yet; mostly meant as a test for multi-operation interface) --- apps/opencs/model/doc/document.cpp | 34 ++++++++++++++++++++++++++++++ apps/opencs/model/doc/document.hpp | 11 +++++++++- apps/opencs/view/doc/operation.cpp | 3 +++ apps/opencs/view/doc/view.cpp | 18 +++++++++++++++- apps/opencs/view/doc/view.hpp | 5 +++++ 5 files changed, 69 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 473d72375..5c39e16c0 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -8,6 +8,10 @@ CSMDoc::Document::Document() // dummy implementation -> remove when proper save is implemented. mSaveCount = 0; connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving())); + + // dummy implementation -> remove when proper verify is implemented. + mVerifyCount = 0; + connect (&mVerifyTimer, SIGNAL(timeout()), this, SLOT (verifying())); } QUndoStack& CSMDoc::Document::getUndoStack() @@ -25,6 +29,9 @@ int CSMDoc::Document::getState() const if (mSaveCount) state |= State_Locked | State_Saving; + if (mVerifyCount) + state |= State_Locked | State_Verifying; + return state; } @@ -36,6 +43,14 @@ void CSMDoc::Document::save() emit progress (1, 16, State_Saving, 1, this); } +void CSMDoc::Document::verify() +{ + mVerifyCount = 1; + mVerifyTimer.start (500); + emit stateChanged (getState(), this); + emit progress (1, 20, State_Verifying, 1, this); +} + void CSMDoc::Document::abortOperation (int type) { if (type==State_Saving) @@ -43,6 +58,11 @@ void CSMDoc::Document::abortOperation (int type) mSaveTimer.stop(); emit stateChanged (getState(), this); } + else if (type==State_Verifying) + { + mVerifyTimer.stop(); + emit stateChanged (getState(), this); + } } void CSMDoc::Document::modificationStateChanged (bool clean) @@ -63,4 +83,18 @@ void CSMDoc::Document::saving() mUndoStack.setClean(); emit stateChanged (getState(), this); } +} + +void CSMDoc::Document::verifying() +{ + ++mVerifyCount; + + emit progress (mVerifyCount, 20, State_Verifying, 1, this); + + if (mVerifyCount>19) + { + mVerifyCount = 0; + mVerifyTimer.stop(); + emit stateChanged (getState(), this); + } } \ No newline at end of file diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 3bed0151d..e691bb38f 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -17,7 +17,8 @@ namespace CSMDoc { State_Modified = 1, State_Locked = 2, - State_Saving = 4 + State_Saving = 4, + State_Verifying = 8 }; QUndoStack mUndoStack; @@ -25,6 +26,9 @@ namespace CSMDoc int mSaveCount; ///< dummy implementation -> remove when proper save is implemented. QTimer mSaveTimer; ///< dummy implementation -> remove when proper save is implemented. + int mVerifyCount; ///< dummy implementation -> remove when proper verify is implemented. + QTimer mVerifyTimer; ///< dummy implementation -> remove when proper verify is implemented. + // not implemented Document (const Document&); Document& operator= (const Document&); @@ -39,6 +43,8 @@ namespace CSMDoc void save(); + void verify(); + void abortOperation (int type); signals: @@ -53,6 +59,9 @@ namespace CSMDoc void saving(); ///< dummy implementation -> remove when proper save is implemented. + + void verifying(); + ///< dummy implementation -> remove when proper verify is implemented. }; } diff --git a/apps/opencs/view/doc/operation.cpp b/apps/opencs/view/doc/operation.cpp index cd9477557..02a93f9c5 100644 --- a/apps/opencs/view/doc/operation.cpp +++ b/apps/opencs/view/doc/operation.cpp @@ -14,6 +14,7 @@ void CSVDoc::Operation::updateLabel (int threads) switch (mType) { case CSMDoc::Document::State_Saving: name = "saving"; break; + case CSMDoc::Document::State_Verifying: name = "verifying"; break; } std::ostringstream stream; @@ -34,6 +35,8 @@ void CSVDoc::Operation::updateLabel (int threads) CSVDoc::Operation::Operation (int type) : mType (type), mStalling (false) { updateLabel(); + + /// \todo assign different progress bar colours to allow the user to distinguish easily between operation types } void CSVDoc::Operation::setProgress (int current, int max, int threads) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index fe018ab3b..8ed1f83b8 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -54,11 +54,21 @@ void CSVDoc::View::setupViewMenu() view->addAction (newWindow); } +void CSVDoc::View::setupWorldMenu() +{ + QMenu *world = menuBar()->addMenu (tr ("&World")); + + mVerify = new QAction (tr ("&Verify"), this); + connect (mVerify, SIGNAL (triggered()), this, SLOT (verify())); + world->addAction (mVerify); +} + void CSVDoc::View::setupUi() { setupFileMenu(); setupEditMenu(); setupViewMenu(); + setupWorldMenu(); } void CSVDoc::View::updateTitle() @@ -87,6 +97,7 @@ void CSVDoc::View::updateActions() mRedo->setEnabled (editing & mDocument->getUndoStack().canRedo()); mSave->setEnabled (!(mDocument->getState() & CSMDoc::Document::State_Saving)); + mVerify->setEnabled (!(mDocument->getState() & CSMDoc::Document::State_Verifying)); } CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) @@ -127,7 +138,7 @@ void CSVDoc::View::updateDocumentState() static const int operations[] = { - CSMDoc::Document::State_Saving, + CSMDoc::Document::State_Saving, CSMDoc::Document::State_Verifying, -1 // end marker }; @@ -156,4 +167,9 @@ void CSVDoc::View::test() void CSVDoc::View::save() { mDocument->save(); +} + +void CSVDoc::View::verify() +{ + mDocument->verify(); } \ No newline at end of file diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 191af36b5..15394a7d8 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -28,6 +28,7 @@ namespace CSVDoc QAction *mUndo; QAction *mRedo; QAction *mSave; + QAction *mVerify; std::vector mEditingActions; Operations *mOperations; @@ -45,6 +46,8 @@ namespace CSVDoc void setupViewMenu(); + void setupWorldMenu(); + void setupUi(); void updateTitle(); @@ -73,6 +76,8 @@ namespace CSVDoc void test(); void save(); + + void verify(); }; } From 303506d24b00a0bbcbb7f796fa071b5f750c3be9 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 23 Nov 2012 14:05:49 +0100 Subject: [PATCH 016/136] added new document function --- apps/opencs/editor.cpp | 12 ++++++++++-- apps/opencs/editor.hpp | 14 +++++++++++--- apps/opencs/model/doc/document.cpp | 9 ++++++++- apps/opencs/model/doc/document.hpp | 9 ++++++++- apps/opencs/model/doc/documentmanager.cpp | 4 ++-- apps/opencs/model/doc/documentmanager.hpp | 3 ++- apps/opencs/view/doc/view.cpp | 8 ++++++-- apps/opencs/view/doc/view.hpp | 4 ++++ apps/opencs/view/doc/viewmanager.cpp | 2 ++ apps/opencs/view/doc/viewmanager.hpp | 4 ++++ 10 files changed, 57 insertions(+), 12 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 264ae7543..c03a1dc5d 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -1,20 +1,28 @@ #include "editor.hpp" +#include + #include -CS::Editor::Editor() : mViewManager (mDocumentManager) +CS::Editor::Editor() : mViewManager (mDocumentManager), mNewDocumentIndex (0) { + connect (&mViewManager, SIGNAL (newDocumentRequest ()), this, SLOT (createDocument ())); } void CS::Editor::createDocument() { - CSMDoc::Document *document = mDocumentManager.addDocument(); + std::ostringstream stream; + + stream << "NewDocument" << (++mNewDocumentIndex); + + CSMDoc::Document *document = mDocumentManager.addDocument (stream.str()); mViewManager.addView (document); } int CS::Editor::run() { + /// \todo Instead of creating an empty document, open a small welcome dialogue window with buttons for new/load/recent projects createDocument(); return QApplication::exec(); diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index 6e183b843..60f7beaf1 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -1,13 +1,19 @@ #ifndef CS_EDITOR_H #define CS_EDITOR_H +#include + #include "model/doc/documentmanager.hpp" #include "view/doc/viewmanager.hpp" namespace CS { - class Editor + class Editor : public QObject { + Q_OBJECT + + int mNewDocumentIndex; ///< \todo remove when the proper new document dialogue is implemented. + CSMDoc::DocumentManager mDocumentManager; CSVDoc::ViewManager mViewManager; @@ -19,10 +25,12 @@ namespace CS Editor(); - void createDocument(); - int run(); ///< \return error status + + public slots: + + void createDocument(); }; } diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 5c39e16c0..cd65e83ae 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -1,8 +1,10 @@ #include "document.hpp" -CSMDoc::Document::Document() +CSMDoc::Document::Document (const std::string& name) { + mName = name; ///< \todo replace with ESX list + connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool))); // dummy implementation -> remove when proper save is implemented. @@ -35,6 +37,11 @@ int CSMDoc::Document::getState() const return state; } +const std::string& CSMDoc::Document::getName() const +{ + return mName; +} + void CSMDoc::Document::save() { mSaveCount = 1; diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index e691bb38f..0249d8e5c 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -1,6 +1,8 @@ #ifndef CSM_DOC_DOCUMENT_H #define CSM_DOC_DOCUMENT_H +#include + #include #include #include @@ -21,6 +23,7 @@ namespace CSMDoc State_Verifying = 8 }; + std::string mName; ///< \todo replace name with ESX list QUndoStack mUndoStack; int mSaveCount; ///< dummy implementation -> remove when proper save is implemented. @@ -35,12 +38,16 @@ namespace CSMDoc public: - Document(); + Document (const std::string& name); + ///< \todo replace name with ESX list QUndoStack& getUndoStack(); int getState() const; + const std::string& getName() const; + ///< \todo replace with ESX list + void save(); void verify(); diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index 68595f2d4..8ae2764f2 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -14,9 +14,9 @@ CSMDoc::DocumentManager::~DocumentManager() delete *iter; } -CSMDoc::Document *CSMDoc::DocumentManager::addDocument() +CSMDoc::Document *CSMDoc::DocumentManager::addDocument (const std::string& name) { - Document *document = new Document; + Document *document = new Document (name); mDocuments.push_back (document); diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index f20f3101d..730c7fae1 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -2,6 +2,7 @@ #define CSM_DOC_DOCUMENTMGR_H #include +#include namespace CSMDoc { @@ -20,7 +21,7 @@ namespace CSMDoc ~DocumentManager(); - Document *addDocument(); + Document *addDocument (const std::string& name); ///< The ownership of the returned document is not transferred to the caller. bool removeDocument (Document *document); diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 8ed1f83b8..5c7199aa4 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -21,6 +21,10 @@ void CSVDoc::View::setupFileMenu() { QMenu *file = menuBar()->addMenu (tr ("&File")); + QAction *new_ = new QAction (tr ("New"), this); + connect (new_, SIGNAL (triggered()), this, SIGNAL (newDocumentRequest())); + file->addAction (new_); + mSave = new QAction (tr ("&Save"), this); connect (mSave, SIGNAL (triggered()), this, SLOT (save())); file->addAction (mSave); @@ -75,7 +79,7 @@ void CSVDoc::View::updateTitle() { std::ostringstream stream; - stream << "New Document "; + stream << mDocument->getName(); if (mDocument->getState() & CSMDoc::Document::State_Modified) stream << " *"; @@ -104,7 +108,7 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to : mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), mViewTotal (totalViews) { setCentralWidget (new QWidget); - resize (200, 200); + resize (200, 200); /// \todo get default size from settings and set reasonable minimal size mOperations = new Operations; addDockWidget (Qt::BottomDockWidgetArea, mOperations); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 15394a7d8..d15d942fc 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -69,6 +69,10 @@ namespace CSVDoc void updateProgress (int current, int max, int type, int threads); + signals: + + void newDocumentRequest(); + private slots: void newView(); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 673afbad8..22847c78b 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -56,6 +56,8 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) view->show(); + connect (view, SIGNAL (newDocumentRequest ()), this, SIGNAL (newDocumentRequest())); + updateIndices(); return view; diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index caf75a0cd..5e4b1be07 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -42,6 +42,10 @@ namespace CSVDoc bool closeRequest (View *view); + signals: + + void newDocumentRequest(); + private slots: void documentStateChanged (int state, CSMDoc::Document *document); From 019146756fc0d91ab46b54c696fc33770c0d2f1a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 24 Nov 2012 10:14:43 +0100 Subject: [PATCH 017/136] minor documentation changes regarding future improvements and additions --- apps/opencs/model/doc/document.hpp | 4 +++- apps/opencs/view/doc/operation.cpp | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 0249d8e5c..1f73b5437 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -20,7 +20,9 @@ namespace CSMDoc State_Modified = 1, State_Locked = 2, State_Saving = 4, - State_Verifying = 8 + State_Verifying = 8, + State_Compiling = 16, // not implemented yet + State_Searching = 32 // not implemented yet }; std::string mName; ///< \todo replace name with ESX list diff --git a/apps/opencs/view/doc/operation.cpp b/apps/opencs/view/doc/operation.cpp index 02a93f9c5..62f006be5 100644 --- a/apps/opencs/view/doc/operation.cpp +++ b/apps/opencs/view/doc/operation.cpp @@ -34,6 +34,8 @@ void CSVDoc::Operation::updateLabel (int threads) CSVDoc::Operation::Operation (int type) : mType (type), mStalling (false) { + /// \todo Add a cancel button or a pop up menu with a cancel item + updateLabel(); /// \todo assign different progress bar colours to allow the user to distinguish easily between operation types From 4c0dcd46a19fea65c1c8bd31f82fbbe9103b7429 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 24 Nov 2012 11:01:53 +0100 Subject: [PATCH 018/136] added UniversalId class --- apps/opencs/CMakeLists.txt | 4 + apps/opencs/model/world/universalid.cpp | 161 ++++++++++++++++++++++++ apps/opencs/model/world/universalid.hpp | 80 ++++++++++++ 3 files changed, 245 insertions(+) create mode 100644 apps/opencs/model/world/universalid.cpp create mode 100644 apps/opencs/model/world/universalid.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 66b9f4942..cb721ac54 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -4,6 +4,8 @@ set (OPENCS_SRC model/doc/documentmanager.cpp model/doc/document.cpp + model/world/universalid.cpp + view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp ) @@ -12,6 +14,8 @@ set (OPENCS_HDR model/doc/documentmanager.hpp model/doc/document.hpp + model/world/universalid.hpp + view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp ) diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp new file mode 100644 index 000000000..b56a336a6 --- /dev/null +++ b/apps/opencs/model/world/universalid.cpp @@ -0,0 +1,161 @@ + +#include "universalid.hpp" + +#include +#include +#include + +namespace +{ + struct TypeData + { + CSMWorld::UniversalId::Class mClass; + CSMWorld::UniversalId::Type mType; + const char *mName; + }; + + static const TypeData sNoArg[] = + { + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty" }, + + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker + }; + + static const TypeData sIdArg[] = + { + + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker + }; + + static const TypeData sIndexArg[] = + { + + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker + }; +} + +CSMWorld::UniversalId::UniversalId (Type type) : mArgumentType (ArgumentType_None), mType (type), mIndex (0) +{ + for (int i=0; sNoArg[i].mName; ++i) + if (type==sNoArg[i].mType) + { + mClass = sNoArg[i].mClass; + return; + } + + throw std::logic_error ("invalid argument-less UniversalId type"); +} + +CSMWorld::UniversalId::UniversalId (Type type, const std::string& id) +: mArgumentType (ArgumentType_Id), mType (type), mId (id), mIndex (0) +{ + for (int i=0; sIdArg[i].mName; ++i) + if (type==sIdArg[i].mType) + { + mClass = sIdArg[i].mClass; + return; + } + + throw std::logic_error ("invalid ID argument UniversalId type"); +} + +CSMWorld::UniversalId::UniversalId (Type type, int index) +: mArgumentType (ArgumentType_Index), mType (type), mIndex (index) +{ + for (int i=0; sIndexArg[i].mName; ++i) + if (type==sIndexArg[i].mType) + { + mClass = sIndexArg[i].mClass; + return; + } + + throw std::logic_error ("invalid index argument UniversalId type"); +} + +CSMWorld::UniversalId::Class CSMWorld::UniversalId::getClass() const +{ + return mClass; +} + +CSMWorld::UniversalId::ArgumentType CSMWorld::UniversalId::getArgumentType() const +{ + return mArgumentType; +} + +CSMWorld::UniversalId::Type CSMWorld::UniversalId::getType() const +{ + return mType; +} + +const std::string& CSMWorld::UniversalId::getId() const +{ + if (mArgumentType!=ArgumentType_Id) + throw std::logic_error ("invalid access to ID of non-ID UniversalId"); + + return mId; +} + +int CSMWorld::UniversalId::getIndex() const +{ + if (mArgumentType!=ArgumentType_Index) + throw std::logic_error ("invalid access to index of non-index UniversalId"); + + return mIndex; +} + +bool CSMWorld::UniversalId::isEqual (const UniversalId& universalId) const +{ + if (mClass!=universalId.mClass || mArgumentType!=universalId.mArgumentType || mType!=universalId.mType) + return false; + + switch (mArgumentType) + { + case ArgumentType_Id: return mId==universalId.mId; + case ArgumentType_Index: return mIndex==universalId.mIndex; + + default: return true; + } +} + +std::string CSMWorld::UniversalId::getTypeName() const +{ + const TypeData *typeData = mArgumentType==ArgumentType_None ? sNoArg : + (mArgumentType==ArgumentType_Id ? sIdArg : sIndexArg); + + for (int i=0; typeData[i].mName; ++i) + if (typeData[i].mType==mType) + return typeData[i].mName; + + throw std::logic_error ("failed to retrieve UniversalId type name"); +} + +std::string CSMWorld::UniversalId::toString() const +{ + std::ostringstream stream; + + stream << getTypeName(); + + switch (mArgumentType) + { + case ArgumentType_None: break; + case ArgumentType_Id: stream << " " << mId; + case ArgumentType_Index: stream << " " << mIndex; + } + + return stream.str(); +} + +bool operator== (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right) +{ + return left.isEqual (right); +} + +bool operator!= (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right) +{ + return !left.isEqual (right); +} + +std::ostream& operator< (std::ostream& stream, const CSMWorld::UniversalId& universalId) +{ + return stream << universalId.toString(); +} \ No newline at end of file diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp new file mode 100644 index 000000000..6f085cfc2 --- /dev/null +++ b/apps/opencs/model/world/universalid.hpp @@ -0,0 +1,80 @@ +#ifndef CSM_WOLRD_UNIVERSALID_H +#define CSM_WOLRD_UNIVERSALID_H + +#include +#include + +namespace CSMWorld +{ + class UniversalId + { + public: + + enum Class + { + Class_None = 0, + Class_Record, + Class_SubRecord, + Class_RecordList, + Class_Collection, // multiple types of records combined + Class_Transient, // not part of the world data or the project data + Class_NonRecord // record like data that is not part of the world + }; + + enum ArgumentType + { + ArgumentType_None, + ArgumentType_Id, + ArgumentType_Index + }; + + enum Type + { + Type_None + }; + + private: + + Class mClass; + ArgumentType mArgumentType; + Type mType; + std::string mId; + int mIndex; + + public: + + UniversalId (Type type = Type_None); + ///< Using a type for a non-argument-less UniversalId will throw an exception. + + UniversalId (Type type, const std::string& id); + ///< Using a type for a non-ID-argument UniversalId will throw an exception. + + UniversalId (Type type, int index); + ///< Using a type for a non-index-argument UniversalId will throw an exception. + + Class getClass() const; + + ArgumentType getArgumentType() const; + + Type getType() const; + + const std::string& getId() const; + ///< Calling this function for a non-ID type will throw an exception. + + int getIndex() const; + ///< Calling this function for a non-index type will throw an exception. + + bool isEqual (const UniversalId& universalId) const; + + std::string getTypeName() const; + + std::string toString() const; + }; + + bool operator== (const UniversalId& left, const UniversalId& right); + bool operator!= (const UniversalId& left, const UniversalId& right); + + std::ostream& operator< (std::ostream& stream, const UniversalId& universalId); +} + +#endif From eece4226c0427ac2cd7ca5e7b621e6bc8799e8e7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 24 Nov 2012 13:17:21 +0100 Subject: [PATCH 019/136] basic sub view system (very incomplete) --- apps/opencs/CMakeLists.txt | 4 ++++ apps/opencs/view/doc/view.cpp | 32 ++++++++++++++++++++++++++++-- apps/opencs/view/doc/view.hpp | 9 +++++++++ apps/opencs/view/world/subview.cpp | 18 +++++++++++++++++ apps/opencs/view/world/subview.hpp | 28 ++++++++++++++++++++++++++ 5 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 apps/opencs/view/world/subview.cpp create mode 100644 apps/opencs/view/world/subview.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index cb721ac54..a56e77d08 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -7,6 +7,8 @@ set (OPENCS_SRC model/world/universalid.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp + + view/world/subview.cpp ) set (OPENCS_HDR @@ -17,6 +19,8 @@ set (OPENCS_HDR model/world/universalid.hpp view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp + + view/world/subview.hpp ) set (OPENCS_US diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 5c7199aa4..9bcb8fc5a 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -5,9 +5,12 @@ #include #include +#include #include "../../model/doc/document.hpp" +#include "../world/subview.hpp" + #include "viewmanager.hpp" #include "operations.hpp" @@ -56,6 +59,10 @@ void CSVDoc::View::setupViewMenu() QAction *newWindow = new QAction (tr ("&New View"), this); connect (newWindow, SIGNAL (triggered()), this, SLOT (newView())); view->addAction (newWindow); + + QAction *test = new QAction (tr ("Add test Subview"), this); + connect (test, SIGNAL (triggered()), this, SLOT (addTestSubView())); + view->addAction (test); } void CSVDoc::View::setupWorldMenu() @@ -107,8 +114,9 @@ void CSVDoc::View::updateActions() CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) : mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), mViewTotal (totalViews) { - setCentralWidget (new QWidget); - resize (200, 200); /// \todo get default size from settings and set reasonable minimal size + setDockOptions (QMainWindow::AllowNestedDocks); + + resize (300, 300); /// \todo get default size from settings and set reasonable minimal size mOperations = new Operations; addDockWidget (Qt::BottomDockWidgetArea, mOperations); @@ -158,6 +166,21 @@ void CSVDoc::View::updateProgress (int current, int max, int type, int threads) mOperations->setProgress (current, max, type, threads); } +void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id) +{ + /// \todo add an user setting for limiting the number of sub views per top level view. Automatically open a new top level view if this + /// number is exceeded + + /// \todo if the sub view limit setting is one, the sub view title bar should be hidden and the text in the main title bar adjusted + /// accordingly + + /// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis) + + CSVWorld::SubView *view = new CSVWorld::SubView (id); + addDockWidget (Qt::RightDockWidgetArea, view); + view->show(); +} + void CSVDoc::View::newView() { mViewManager.addView (mDocument); @@ -176,4 +199,9 @@ void CSVDoc::View::save() void CSVDoc::View::verify() { mDocument->verify(); +} + +void CSVDoc::View::addTestSubView() +{ + addSubView (CSMWorld::UniversalId::Type_None); } \ No newline at end of file diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index d15d942fc..7a9164e12 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -12,6 +12,11 @@ namespace CSMDoc class Document; } +namespace CSMWorld +{ + class UniversalId; +} + namespace CSVDoc { class ViewManager; @@ -69,6 +74,8 @@ namespace CSVDoc void updateProgress (int current, int max, int type, int threads); + void addSubView (const CSMWorld::UniversalId& id); + signals: void newDocumentRequest(); @@ -82,6 +89,8 @@ namespace CSVDoc void save(); void verify(); + + void addTestSubView(); ///< \todo remove }; } diff --git a/apps/opencs/view/world/subview.cpp b/apps/opencs/view/world/subview.cpp new file mode 100644 index 000000000..23f075980 --- /dev/null +++ b/apps/opencs/view/world/subview.cpp @@ -0,0 +1,18 @@ + +#include "subview.hpp" + +CSVWorld::SubView::SubView (const CSMWorld::UniversalId& id) : mUniversalId (id) +{ + /// \todo add a button to the title bar that clones this sub view + + setWindowTitle (mUniversalId.toString().c_str()); + + /// \todo remove (for testing only) + setMinimumWidth (100); + setMinimumHeight (60); +} + +CSMWorld::UniversalId CSVWorld::SubView::getUniversalId() const +{ + return mUniversalId; +} diff --git a/apps/opencs/view/world/subview.hpp b/apps/opencs/view/world/subview.hpp new file mode 100644 index 000000000..8488690c8 --- /dev/null +++ b/apps/opencs/view/world/subview.hpp @@ -0,0 +1,28 @@ +#ifndef CSV_WORLD_SUBVIEW_H +#define CSV_WORLD_SUBVIEW_H + +#include "../../model/world/universalid.hpp" + +#include + +namespace CSVWorld +{ + class SubView : public QDockWidget + { + Q_OBJECT + + CSMWorld::UniversalId mUniversalId; + + // not implemented + SubView (const SubView&); + SubView& operator= (SubView&); + + public: + + SubView (const CSMWorld::UniversalId& id); + + CSMWorld::UniversalId getUniversalId() const; + }; +} + +#endif \ No newline at end of file From ef9575498f231e50a99a7beadc048e21ce74486d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 26 Nov 2012 12:29:22 +0100 Subject: [PATCH 020/136] basic (non-editable) subview for global variables --- apps/opencs/CMakeLists.txt | 9 +- apps/opencs/editor.cpp | 18 +++ apps/opencs/model/doc/document.cpp | 10 ++ apps/opencs/model/doc/document.hpp | 9 ++ apps/opencs/model/world/columns.hpp | 21 +++ apps/opencs/model/world/data.cpp | 47 +++++++ apps/opencs/model/world/data.hpp | 39 ++++++ apps/opencs/model/world/idcollection.cpp | 6 + apps/opencs/model/world/idcollection.hpp | 158 +++++++++++++++++++++++ apps/opencs/model/world/idtable.cpp | 55 ++++++++ apps/opencs/model/world/idtable.hpp | 37 ++++++ apps/opencs/model/world/record.hpp | 76 +++++++++++ apps/opencs/model/world/universalid.cpp | 29 ++++- apps/opencs/model/world/universalid.hpp | 7 +- apps/opencs/view/doc/view.cpp | 33 +++-- apps/opencs/view/doc/view.hpp | 11 +- apps/opencs/view/world/globals.cpp | 26 ++++ apps/opencs/view/world/globals.hpp | 17 +++ apps/opencs/view/world/subview.hpp | 22 ++++ components/esm/loadglob.hpp | 2 +- 20 files changed, 614 insertions(+), 18 deletions(-) create mode 100644 apps/opencs/model/world/columns.hpp create mode 100644 apps/opencs/model/world/data.cpp create mode 100644 apps/opencs/model/world/data.hpp create mode 100644 apps/opencs/model/world/idcollection.cpp create mode 100644 apps/opencs/model/world/idcollection.hpp create mode 100644 apps/opencs/model/world/idtable.cpp create mode 100644 apps/opencs/model/world/idtable.hpp create mode 100644 apps/opencs/model/world/record.hpp create mode 100644 apps/opencs/view/world/globals.cpp create mode 100644 apps/opencs/view/world/globals.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index a56e77d08..92fd859be 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -4,11 +4,11 @@ set (OPENCS_SRC model/doc/documentmanager.cpp model/doc/document.cpp - model/world/universalid.cpp + model/world/universalid.cpp model/world/idcollection.cpp model/world/data.cpp model/world/idtable.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp - view/world/subview.cpp + view/world/subview.cpp view/world/globals.cpp ) set (OPENCS_HDR @@ -16,11 +16,12 @@ set (OPENCS_HDR model/doc/documentmanager.hpp model/doc/document.hpp - model/world/universalid.hpp + model/world/universalid.hpp model/world/record.hpp model/world/idcollection.hpp model/world/data.hpp + model/world/idtable.hpp model/world/columns.hpp view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp - view/world/subview.hpp + view/world/subview.hpp view/world/globals.hpp ) set (OPENCS_US diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index c03a1dc5d..6977a22f0 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -5,6 +5,9 @@ #include +#include "model/doc/document.hpp" +#include "model/world/data.hpp" + CS::Editor::Editor() : mViewManager (mDocumentManager), mNewDocumentIndex (0) { connect (&mViewManager, SIGNAL (newDocumentRequest ()), this, SLOT (createDocument ())); @@ -17,6 +20,21 @@ void CS::Editor::createDocument() stream << "NewDocument" << (++mNewDocumentIndex); CSMDoc::Document *document = mDocumentManager.addDocument (stream.str()); + + static const char *sGlobals[] = + { + "Day", "DaysPassed", "GameHour", "Month", "PCRace", "PCVampire", "PCWerewolf", "PCYear", 0 + }; + + for (int i=0; sGlobals[i]; ++i) + { + ESM::Global record; + record.mId = sGlobals[i]; + record.mValue = i==0 ? 1 : 0; + record.mType = ESM::VT_Float; + document->getData().getGlobals().add (record); + } + mViewManager.addView (document); } diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index cd65e83ae..e8091b3e0 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -104,4 +104,14 @@ void CSMDoc::Document::verifying() mVerifyTimer.stop(); emit stateChanged (getState(), this); } +} + +const CSMWorld::Data& CSMDoc::Document::getData() const +{ + return mData; +} + +CSMWorld::Data& CSMDoc::Document::getData() +{ + return mData; } \ No newline at end of file diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 1f73b5437..b414bf04d 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -7,6 +7,8 @@ #include #include +#include "../world/data.hpp" + namespace CSMDoc { class Document : public QObject @@ -25,8 +27,11 @@ namespace CSMDoc State_Searching = 32 // not implemented yet }; + private: + std::string mName; ///< \todo replace name with ESX list QUndoStack mUndoStack; + CSMWorld::Data mData; int mSaveCount; ///< dummy implementation -> remove when proper save is implemented. QTimer mSaveTimer; ///< dummy implementation -> remove when proper save is implemented. @@ -56,6 +61,10 @@ namespace CSMDoc void abortOperation (int type); + const CSMWorld::Data& getData() const; + + CSMWorld::Data& getData(); + signals: void stateChanged (int state, CSMDoc::Document *document); diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp new file mode 100644 index 000000000..56362e4cd --- /dev/null +++ b/apps/opencs/model/world/columns.hpp @@ -0,0 +1,21 @@ +#ifndef CSM_WOLRD_COLUMNS_H +#define CSM_WOLRD_COLUMNS_H + +#include "idcollection.hpp" + +namespace CSMWorld +{ + template + struct FloatValueColumn : public Column + { + FloatValueColumn() : Column ("Value") {} + + virtual QVariant get (const Record& record) const + { + return record.get().mValue; + } + }; + +} + +#endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp new file mode 100644 index 000000000..7fdb149b3 --- /dev/null +++ b/apps/opencs/model/world/data.cpp @@ -0,0 +1,47 @@ + +#include "data.hpp" + +#include + +#include + +#include + +#include "idtable.hpp" +#include "columns.hpp" + +CSMWorld::Data::Data() +{ + mGlobals.addColumn (new FloatValueColumn); + + mModels.insert (std::make_pair ( + UniversalId (UniversalId::Type_Globals), + new IdTable (&mGlobals) + )); +} + +CSMWorld::Data::~Data() +{ + for (std::map::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter) + delete iter->second; +} + +const CSMWorld::IdCollection& CSMWorld::Data::getGlobals() const +{ + return mGlobals; +} + +CSMWorld::IdCollection& CSMWorld::Data::getGlobals() +{ + return mGlobals; +} + +QAbstractTableModel *CSMWorld::Data::getTableModel (const UniversalId& id) +{ + std::map::iterator iter = mModels.find (id); + + if (iter==mModels.end()) + throw std::logic_error ("No table model available for " + id.toString()); + + return iter->second; +} \ No newline at end of file diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp new file mode 100644 index 000000000..11073c5e3 --- /dev/null +++ b/apps/opencs/model/world/data.hpp @@ -0,0 +1,39 @@ +#ifndef CSM_WOLRD_IDLIST_H +#define CSM_WOLRD_IDLIST_H + +#include + +#include + +#include "idcollection.hpp" +#include "universalid.hpp" + +class QAbstractTableModel; + +namespace CSMWorld +{ + class Data + { + IdCollection mGlobals; + std::map mModels; + + // not implemented + Data (const Data&); + Data& operator= (const Data&); + + public: + + Data(); + + ~Data(); + + const IdCollection& getGlobals() const; + + IdCollection& getGlobals(); + + QAbstractTableModel *getTableModel (const UniversalId& id); + ///< If no table model is available for \æ id, an exception is thrown. + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/model/world/idcollection.cpp b/apps/opencs/model/world/idcollection.cpp new file mode 100644 index 000000000..fc4bb1ef6 --- /dev/null +++ b/apps/opencs/model/world/idcollection.cpp @@ -0,0 +1,6 @@ + +#include "idcollection.hpp" + +CSMWorld::IdCollectionBase::IdCollectionBase() {} + +CSMWorld::IdCollectionBase::~IdCollectionBase() {} \ No newline at end of file diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp new file mode 100644 index 000000000..0bddda1ac --- /dev/null +++ b/apps/opencs/model/world/idcollection.hpp @@ -0,0 +1,158 @@ +#ifndef CSM_WOLRD_IDCOLLECTION_H +#define CSM_WOLRD_IDCOLLECTION_H + +#include +#include +#include +#include +#include + +#include + +#include "record.hpp" + +namespace CSMWorld +{ + template + struct Column + { + std::string mTitle; + + Column (const std::string& title) : mTitle (title) {} + + virtual ~Column() {} + + virtual QVariant get (const Record& record) const = 0; + }; + + class IdCollectionBase + { + // not implemented + IdCollectionBase (const IdCollectionBase&); + IdCollectionBase& operator= (const IdCollectionBase&); + + public: + + IdCollectionBase(); + + virtual ~IdCollectionBase(); + + virtual int getSize() const = 0; + + virtual std::string getId (int index) const = 0; + + virtual int getColumns() const = 0; + + virtual std::string getTitle (int column) const = 0; + + virtual QVariant getData (int index, int column) const = 0; + }; + + ///< \brief Collection of ID-based records + template + class IdCollection : public IdCollectionBase + { + std::vector > mRecords; + std::map mIndex; + std::vector *> mColumns; + + // not implemented + IdCollection (const IdCollection&); + IdCollection& operator= (const IdCollection&); + + public: + + IdCollection(); + + virtual ~IdCollection(); + + void add (const ESXRecordT& record); + ///< Add a new record (modified) + + virtual int getSize() const; + + virtual std::string getId (int index) const; + + virtual int getColumns() const; + + virtual QVariant getData (int index, int column) const; + + virtual std::string getTitle (int column) const; + + virtual void addColumn (Column *column); + }; + + template + IdCollection::IdCollection() + {} + + template + IdCollection::~IdCollection() + { + for (typename std::vector *>::iterator iter (mColumns.begin()); iter!=mColumns.end(); ++iter) + delete *iter; + } + + template + void IdCollection::add (const ESXRecordT& record) + { + std::string id; + + std::transform (record.mId.begin(), record.mId.end(), std::back_inserter (id), + (int(*)(int)) std::tolower); + + std::map::iterator iter = mIndex.find (id); + + if (iter==mIndex.end()) + { + Record record2; + record2.mState = Record::State_ModifiedOnly; + record2.mModified = record; + + mRecords.push_back (record2); + mIndex.insert (std::make_pair (id, mRecords.size()-1)); + } + else + { + mRecords[iter->second].setModified (record); + } + } + + template + int IdCollection::getSize() const + { + return mRecords.size(); + } + + template + std::string IdCollection::getId (int index) const + { + return mRecords.at (index).get().mId; + } + + template + int IdCollection::getColumns() const + { + return mColumns.size(); + } + + template + QVariant IdCollection::getData (int index, int column) const + { + return mColumns.at (column)->get (mRecords.at (index)); + } + + template + std::string IdCollection::getTitle (int column) const + { + return mColumns.at (column)->mTitle; + } + + template + void IdCollection::addColumn (Column *column) + { + mColumns.push_back (column); + } +} + +#endif diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp new file mode 100644 index 000000000..f8acd4f9f --- /dev/null +++ b/apps/opencs/model/world/idtable.cpp @@ -0,0 +1,55 @@ + +#include "idtable.hpp" + +#include "idcollection.hpp" + +CSMWorld::IdTable::IdTable (IdCollectionBase *idCollection) : mIdCollection (idCollection) +{ + +} + +CSMWorld::IdTable::~IdTable() +{ + +} + +int CSMWorld::IdTable::rowCount (const QModelIndex & parent) const +{ + if (parent.isValid()) + return 0; + + return mIdCollection->getSize(); +} + +int CSMWorld::IdTable::columnCount (const QModelIndex & parent) const +{ + if (parent.isValid()) + return 0; + + return 1+mIdCollection->getColumns(); +} + +QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const +{ + if (role!=Qt::DisplayRole) + return QVariant(); + + if (index.column()==0) + return QVariant (tr (mIdCollection->getId (index.row()).c_str())); + + return mIdCollection->getData (index.row(), index.column()-1); +} + +QVariant CSMWorld::IdTable::headerData (int section, Qt::Orientation orientation, int role) const +{ + if (role!=Qt::DisplayRole) + return QVariant(); + + if (orientation==Qt::Vertical) + return QVariant(); + + if (section==0) + return QVariant (tr ("ID")); + + return tr (mIdCollection->getTitle (section-1).c_str()); +} \ No newline at end of file diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp new file mode 100644 index 000000000..4fb939fa3 --- /dev/null +++ b/apps/opencs/model/world/idtable.hpp @@ -0,0 +1,37 @@ +#ifndef CSM_WOLRD_IDTABLE_H +#define CSM_WOLRD_IDTABLE_H + +#include + +namespace CSMWorld +{ + class IdCollectionBase; + + class IdTable : public QAbstractTableModel + { + Q_OBJECT + + IdCollectionBase *mIdCollection; + + // not implemented + IdTable (const IdTable&); + IdTable& operator= (const IdTable&); + + public: + + IdTable (IdCollectionBase *idCollection); + ///< The ownership of \a idCollection is not transferred. + + virtual ~IdTable(); + + int rowCount (const QModelIndex & parent = QModelIndex()) const; + + int columnCount (const QModelIndex & parent = QModelIndex()) const; + + QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + + QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + }; +} + +#endif diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp new file mode 100644 index 000000000..230d39eb0 --- /dev/null +++ b/apps/opencs/model/world/record.hpp @@ -0,0 +1,76 @@ +#ifndef CSM_WOLRD_RECORD_H +#define CSM_WOLRD_RECORD_H + +#include + +namespace CSMWorld +{ + template + struct Record + { + enum state + { + State_BaseOnly, // defined in base only + State_Modified, // exists in base, but has been modified + State_ModifiedOnly, // newly created in modified + State_Deleted // exists in base, but has been deleted + }; + + ESXRecordT mBase; + ESXRecordT mModified; + state mState; + + bool isDeleted() const; + + bool isModified() const; + + const ESXRecordT& get() const; + ///< Throws an exception, if the record is deleted. + + ESXRecordT& get(); + ///< Throws an exception, if the record is deleted. + + void setModified (const ESXRecordT& modified); + }; + + template + bool Record::isDeleted() const + { + return mState==State_Deleted; + } + + template + bool Record::isModified() const + { + return mState==State_Modified || mState==State_ModifiedOnly; + } + + template + const ESXRecordT& Record::get() const + { + if (isDeleted()) + throw std::logic_error ("attempt to access a deleted record"); + + return mState==State_BaseOnly ? mBase : mModified; + } + + template + ESXRecordT& Record::get() + { + if (isDeleted()) + throw std::logic_error ("attempt to access a deleted record"); + + return mState==State_BaseOnly ? mBase : mModified; + } + + template + void Record::setModified (const ESXRecordT& modified) + { + mModified = modified; + + if (mState!=State_ModifiedOnly) + mState = State_Modified; + } +} + +#endif diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index b56a336a6..e2d8d1ffb 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -17,6 +17,7 @@ namespace static const TypeData sNoArg[] = { { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; @@ -117,6 +118,23 @@ bool CSMWorld::UniversalId::isEqual (const UniversalId& universalId) const } } +bool CSMWorld::UniversalId::isLess (const UniversalId& universalId) const +{ + if (mTypeuniversalId.mType) + return false; + + switch (mArgumentType) + { + case ArgumentType_Id: return mId +#include #include #include @@ -10,6 +11,7 @@ #include "../../model/doc/document.hpp" #include "../world/subview.hpp" +#include "../world/globals.hpp" #include "viewmanager.hpp" #include "operations.hpp" @@ -59,16 +61,16 @@ void CSVDoc::View::setupViewMenu() QAction *newWindow = new QAction (tr ("&New View"), this); connect (newWindow, SIGNAL (triggered()), this, SLOT (newView())); view->addAction (newWindow); - - QAction *test = new QAction (tr ("Add test Subview"), this); - connect (test, SIGNAL (triggered()), this, SLOT (addTestSubView())); - view->addAction (test); } void CSVDoc::View::setupWorldMenu() { QMenu *world = menuBar()->addMenu (tr ("&World")); + QAction *globals = new QAction (tr ("Globals"), this); + connect (globals, SIGNAL (triggered()), this, SLOT (addGlobalsSubView())); + world->addAction (globals); + mVerify = new QAction (tr ("&Verify"), this); connect (mVerify, SIGNAL (triggered()), this, SLOT (verify())); world->addAction (mVerify); @@ -124,6 +126,16 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to updateTitle(); setupUi(); + + mSubViewFactories.insert (std::make_pair (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), + new CSVWorld::SubViewFactory())); +} + +CSVDoc::View::~View() +{ + for (std::map::iterator iter (mSubViewFactories.begin()); + iter!=mSubViewFactories.end(); ++iter) + delete iter->second; } const CSMDoc::Document *CSVDoc::View::getDocument() const @@ -176,8 +188,13 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id) /// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis) - CSVWorld::SubView *view = new CSVWorld::SubView (id); - addDockWidget (Qt::RightDockWidgetArea, view); + std::map::iterator iter = mSubViewFactories.find (id); + + if (iter==mSubViewFactories.end()) + throw std::logic_error ("can't create subview for " + id.toString()); + + CSVWorld::SubView *view = iter->second->makeSubView (id, mDocument->getData()); + addDockWidget (Qt::TopDockWidgetArea, view); view->show(); } @@ -201,7 +218,7 @@ void CSVDoc::View::verify() mDocument->verify(); } -void CSVDoc::View::addTestSubView() +void CSVDoc::View::addGlobalsSubView() { - addSubView (CSMWorld::UniversalId::Type_None); + addSubView (CSMWorld::UniversalId::Type_Globals); } \ No newline at end of file diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 7a9164e12..8e2b27293 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -2,6 +2,7 @@ #define CSV_DOC_VIEW_H #include +#include #include @@ -17,6 +18,11 @@ namespace CSMWorld class UniversalId; } +namespace CSVWorld +{ + struct SubViewFactoryBase; +} + namespace CSVDoc { class ViewManager; @@ -36,6 +42,7 @@ namespace CSVDoc QAction *mVerify; std::vector mEditingActions; Operations *mOperations; + std::map mSubViewFactories; // not implemented View (const View&); @@ -64,6 +71,8 @@ namespace CSVDoc View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews); ///< The ownership of \a document is not transferred to *this. + virtual ~View(); + const CSMDoc::Document *getDocument() const; CSMDoc::Document *getDocument(); @@ -90,7 +99,7 @@ namespace CSVDoc void verify(); - void addTestSubView(); ///< \todo remove + void addGlobalsSubView(); }; } diff --git a/apps/opencs/view/world/globals.cpp b/apps/opencs/view/world/globals.cpp new file mode 100644 index 000000000..1c0faa029 --- /dev/null +++ b/apps/opencs/view/world/globals.cpp @@ -0,0 +1,26 @@ + +#include "globals.hpp" + +#include +#include +#include + +#include "../../model/world/data.hpp" + +CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data) +: SubView (id) +{ + QTableView *table = new QTableView(); + + setWidget (table); + + QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel (this); + proxyModel->setSourceModel (data.getTableModel (id)); + + table->setModel (proxyModel); + table->horizontalHeader()->setResizeMode (QHeaderView::Interactive); + table->verticalHeader()->hide(); + table->setSortingEnabled (true); + + /// \todo make initial layout fill the whole width of the table +} \ No newline at end of file diff --git a/apps/opencs/view/world/globals.hpp b/apps/opencs/view/world/globals.hpp new file mode 100644 index 000000000..c54716255 --- /dev/null +++ b/apps/opencs/view/world/globals.hpp @@ -0,0 +1,17 @@ +#ifndef CSV_WORLD_GLOBALS_H +#define CSV_WORLD_GLOBALS_H + +#include "subview.hpp" + +namespace CSVWorld +{ + class Globals : public SubView + { + + public: + + Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data); + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/world/subview.hpp b/apps/opencs/view/world/subview.hpp index 8488690c8..95cbe4243 100644 --- a/apps/opencs/view/world/subview.hpp +++ b/apps/opencs/view/world/subview.hpp @@ -5,6 +5,11 @@ #include +namespace CSMWorld +{ + class Data; +} + namespace CSVWorld { class SubView : public QDockWidget @@ -23,6 +28,23 @@ namespace CSVWorld CSMWorld::UniversalId getUniversalId() const; }; + + struct SubViewFactoryBase + { + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data) = 0; + }; + + template + struct SubViewFactory : public SubViewFactoryBase + { + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data); + }; + + template + SubView *SubViewFactory::makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data) + { + return new SubViewT (id, data); + } } #endif \ No newline at end of file diff --git a/components/esm/loadglob.hpp b/components/esm/loadglob.hpp index 302729d2e..5cfb3c87b 100644 --- a/components/esm/loadglob.hpp +++ b/components/esm/loadglob.hpp @@ -18,7 +18,7 @@ class ESMWriter; struct Global { std::string mId; - unsigned mValue; + float mValue; VarType mType; void load(ESMReader &esm); From 92f70635a2bb7d26ffecd3582cfd6c18ae01516b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 27 Nov 2012 10:42:46 +0100 Subject: [PATCH 021/136] improved selection behaviour --- apps/opencs/view/world/globals.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/opencs/view/world/globals.cpp b/apps/opencs/view/world/globals.cpp index 1c0faa029..1f68a57fe 100644 --- a/apps/opencs/view/world/globals.cpp +++ b/apps/opencs/view/world/globals.cpp @@ -21,6 +21,8 @@ CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& dat table->horizontalHeader()->setResizeMode (QHeaderView::Interactive); table->verticalHeader()->hide(); table->setSortingEnabled (true); + table->setSelectionBehavior (QAbstractItemView::SelectRows); + table->setSelectionMode (QAbstractItemView::ExtendedSelection); /// \todo make initial layout fill the whole width of the table } \ No newline at end of file From 8a09e03d5c6b369bffcac7dbb16916151eb2c548 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 29 Nov 2012 14:45:34 +0100 Subject: [PATCH 022/136] global variable editing (no undo support yet) --- apps/opencs/model/world/columns.hpp | 12 +++++++++ apps/opencs/model/world/idcollection.hpp | 26 ++++++++++++++++++- apps/opencs/model/world/idtable.cpp | 33 +++++++++++++++++++++++- apps/opencs/model/world/idtable.hpp | 4 +++ apps/opencs/model/world/record.hpp | 18 ++++++++----- components/esm/loadglob.cpp | 4 +++ components/esm/loadglob.hpp | 3 +++ 7 files changed, 91 insertions(+), 9 deletions(-) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 56362e4cd..4d0ecb58e 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -14,6 +14,18 @@ namespace CSMWorld { return record.get().mValue; } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT base = record.getBase(); + base.mValue = data.toFloat(); + record.setModified (base); + } + + virtual bool isEditable() const + { + return true; + } }; } diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index 0bddda1ac..ee6a4b2ce 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -23,6 +23,10 @@ namespace CSMWorld virtual ~Column() {} virtual QVariant get (const Record& record) const = 0; + + virtual void set (Record& record, const QVariant& data) = 0; + + virtual bool isEditable() const = 0; }; class IdCollectionBase @@ -46,6 +50,10 @@ namespace CSMWorld virtual std::string getTitle (int column) const = 0; virtual QVariant getData (int index, int column) const = 0; + + virtual void setData (int index, int column, const QVariant& data) = 0; + + virtual bool isEditable (int column) const = 0; }; ///< \brief Collection of ID-based records @@ -77,9 +85,13 @@ namespace CSMWorld virtual QVariant getData (int index, int column) const; + virtual void setData (int index, int column, const QVariant& data); + virtual std::string getTitle (int column) const; - virtual void addColumn (Column *column); + virtual bool isEditable (int column) const; + + void addColumn (Column *column); }; template @@ -142,12 +154,24 @@ namespace CSMWorld return mColumns.at (column)->get (mRecords.at (index)); } + template + void IdCollection::setData (int index, int column, const QVariant& data) + { + return mColumns.at (column)->set (mRecords.at (index), data); + } + template std::string IdCollection::getTitle (int column) const { return mColumns.at (column)->mTitle; } + template + bool IdCollection::isEditable (int column) const + { + return mColumns.at (column)->isEditable(); + } + template void IdCollection::addColumn (Column *column) { diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index f8acd4f9f..8fdc4fb8f 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -31,9 +31,18 @@ int CSMWorld::IdTable::columnCount (const QModelIndex & parent) const QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const { - if (role!=Qt::DisplayRole) + if (role!=Qt::DisplayRole && role!=Qt::EditRole) return QVariant(); + if (role==Qt::EditRole) + { + if (index.column()==0) + return QVariant(); + + if (!mIdCollection->isEditable (index.column()-1)) + return QVariant(); + } + if (index.column()==0) return QVariant (tr (mIdCollection->getId (index.row()).c_str())); @@ -52,4 +61,26 @@ QVariant CSMWorld::IdTable::headerData (int section, Qt::Orientation orientation return QVariant (tr ("ID")); return tr (mIdCollection->getTitle (section-1).c_str()); +} + +bool CSMWorld::IdTable::setData ( const QModelIndex &index, const QVariant &value, int role) +{ + if (index.column()>0 && role==Qt::EditRole) + { + mIdCollection->setData (index.row(), index.column()-1, value); + emit dataChanged (index, index); + return true; + } + + return false; +} + +Qt::ItemFlags CSMWorld::IdTable::flags (const QModelIndex & index) const +{ + Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; + + if (index.column()>0) + flags |= Qt::ItemIsEditable; + + return flags; } \ No newline at end of file diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index 4fb939fa3..30af3aaf7 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -31,6 +31,10 @@ namespace CSMWorld QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + bool setData ( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + + Qt::ItemFlags flags (const QModelIndex & index) const; }; } diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index 230d39eb0..950d7f176 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -8,7 +8,7 @@ namespace CSMWorld template struct Record { - enum state + enum State { State_BaseOnly, // defined in base only State_Modified, // exists in base, but has been modified @@ -18,7 +18,7 @@ namespace CSMWorld ESXRecordT mBase; ESXRecordT mModified; - state mState; + State mState; bool isDeleted() const; @@ -27,10 +27,11 @@ namespace CSMWorld const ESXRecordT& get() const; ///< Throws an exception, if the record is deleted. - ESXRecordT& get(); - ///< Throws an exception, if the record is deleted. + const ESXRecordT& getBase() const; + ///< Throws an exception, if the record is deleted. Returns modified, if there is no base. void setModified (const ESXRecordT& modified); + ///< Throws an exception, if the record is deleted. }; template @@ -55,21 +56,24 @@ namespace CSMWorld } template - ESXRecordT& Record::get() + const ESXRecordT& Record::getBase() const { if (isDeleted()) throw std::logic_error ("attempt to access a deleted record"); - return mState==State_BaseOnly ? mBase : mModified; + return mState==State_ModifiedOnly ? mModified : mBase; } template void Record::setModified (const ESXRecordT& modified) { + if (isDeleted()) + throw std::logic_error ("attempt to modify a deleted record"); + mModified = modified; if (mState!=State_ModifiedOnly) - mState = State_Modified; + mState = mBase==mModified ? State_BaseOnly : State_Modified; } } diff --git a/components/esm/loadglob.cpp b/components/esm/loadglob.cpp index 39c07fb31..0335da0df 100644 --- a/components/esm/loadglob.cpp +++ b/components/esm/loadglob.cpp @@ -44,4 +44,8 @@ void Global::save(ESMWriter &esm) esm.writeHNT("FLTV", mValue); } + bool operator== (const Global& left, const Global& right) + { + return left.mId==right.mId && left.mValue==right.mValue && left.mType==right.mType; + } } diff --git a/components/esm/loadglob.hpp b/components/esm/loadglob.hpp index 5cfb3c87b..5c5dafaec 100644 --- a/components/esm/loadglob.hpp +++ b/components/esm/loadglob.hpp @@ -24,5 +24,8 @@ struct Global void load(ESMReader &esm); void save(ESMWriter &esm); }; + +bool operator== (const Global& left, const Global& right); + } #endif From 4086b556d242280d7ad2e8bd030e7118dab5d57d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 29 Nov 2012 16:05:28 +0100 Subject: [PATCH 023/136] use commands for modifying globals --- apps/opencs/CMakeLists.txt | 2 + apps/opencs/model/world/commands.cpp | 23 +++++++++++ apps/opencs/model/world/commands.hpp | 33 ++++++++++++++++ apps/opencs/view/doc/view.cpp | 2 +- apps/opencs/view/world/globals.cpp | 59 +++++++++++++++++++++++++++- apps/opencs/view/world/globals.hpp | 42 +++++++++++++++++++- apps/opencs/view/world/subview.hpp | 12 ++++-- 7 files changed, 164 insertions(+), 9 deletions(-) create mode 100644 apps/opencs/model/world/commands.cpp create mode 100644 apps/opencs/model/world/commands.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 92fd859be..61580461f 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -5,6 +5,7 @@ set (OPENCS_SRC model/doc/documentmanager.cpp model/doc/document.cpp model/world/universalid.cpp model/world/idcollection.cpp model/world/data.cpp model/world/idtable.cpp + model/world/commands.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp @@ -20,6 +21,7 @@ set (OPENCS_HDR model/world/idtable.hpp model/world/columns.hpp view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp + model/world/commands.hpp view/world/subview.hpp view/world/globals.hpp ) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp new file mode 100644 index 000000000..a15d00619 --- /dev/null +++ b/apps/opencs/model/world/commands.cpp @@ -0,0 +1,23 @@ + +#include "commands.hpp" + +#include + +CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelIndex& index, + const QVariant& new_, QUndoCommand *parent) +: QUndoCommand (parent), mModel (model), mIndex (index), mNew (new_) +{ + mOld = mModel.data (mIndex, Qt::EditRole); + + setText ("Modify " + mModel.headerData (mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString()); +} + +void CSMWorld::ModifyCommand::redo() +{ + mModel.setData (mIndex, mNew); +} + +void CSMWorld::ModifyCommand::undo() +{ + mModel.setData (mIndex, mOld); +} \ No newline at end of file diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp new file mode 100644 index 000000000..ffaee59ef --- /dev/null +++ b/apps/opencs/model/world/commands.hpp @@ -0,0 +1,33 @@ +#ifndef CSM_WOLRD_COMMANDS_H +#define CSM_WOLRD_COMMANDS_H + +#include "record.hpp" + +#include +#include +#include + +class QModelIndex; +class QAbstractItemModel; + +namespace CSMWorld +{ + class ModifyCommand : public QUndoCommand + { + QAbstractItemModel& mModel; + QModelIndex mIndex; + QVariant mNew; + QVariant mOld; + + public: + + ModifyCommand (QAbstractItemModel& model, const QModelIndex& index, const QVariant& new_, + QUndoCommand *parent = 0); + + virtual void redo(); + + virtual void undo(); + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 18d58bbf5..c81ba2ba1 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -193,7 +193,7 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id) if (iter==mSubViewFactories.end()) throw std::logic_error ("can't create subview for " + id.toString()); - CSVWorld::SubView *view = iter->second->makeSubView (id, mDocument->getData()); + CSVWorld::SubView *view = iter->second->makeSubView (id, mDocument->getData(), mDocument->getUndoStack()); addDockWidget (Qt::TopDockWidgetArea, view); view->show(); } diff --git a/apps/opencs/view/world/globals.cpp b/apps/opencs/view/world/globals.cpp index 1f68a57fe..a57f63dff 100644 --- a/apps/opencs/view/world/globals.cpp +++ b/apps/opencs/view/world/globals.cpp @@ -4,18 +4,73 @@ #include #include #include +#include #include "../../model/world/data.hpp" -CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data) +#include "../../model/world/commands.hpp" + +CSVWorld::NastyTableModelHack::NastyTableModelHack (QAbstractItemModel& model) +: mModel (model) +{} + +int CSVWorld::NastyTableModelHack::rowCount (const QModelIndex & parent) const +{ + return mModel.rowCount (parent); +} + +int CSVWorld::NastyTableModelHack::columnCount (const QModelIndex & parent) const +{ + return mModel.columnCount (parent); +} + +QVariant CSVWorld::NastyTableModelHack::data (const QModelIndex & index, int role) const +{ + return mModel.data (index, role); +} + +bool CSVWorld::NastyTableModelHack::setData ( const QModelIndex &index, const QVariant &value, int role) +{ + mData = value; + return true; +} + +QVariant CSVWorld::NastyTableModelHack::getData() const +{ + return mData; +} + +CSVWorld::CommandDelegate::CommandDelegate (QUndoStack& undoStack, QObject *parent) +: QStyledItemDelegate (parent), mUndoStack (undoStack) +{} + +void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemModel *model, + const QModelIndex& index) const +{ + NastyTableModelHack hack (*model); + QStyledItemDelegate::setModelData (editor, &hack, index); + mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData())); +} + +CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) : SubView (id) { QTableView *table = new QTableView(); setWidget (table); + QAbstractTableModel *model = data.getTableModel (id); + + int columns = model->columnCount(); + + for (int i=1; isetItemDelegateForColumn (i, delegate); + } + QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel (this); - proxyModel->setSourceModel (data.getTableModel (id)); + proxyModel->setSourceModel (model); table->setModel (proxyModel); table->horizontalHeader()->setResizeMode (QHeaderView::Interactive); diff --git a/apps/opencs/view/world/globals.hpp b/apps/opencs/view/world/globals.hpp index c54716255..11ab7b6aa 100644 --- a/apps/opencs/view/world/globals.hpp +++ b/apps/opencs/view/world/globals.hpp @@ -3,14 +3,52 @@ #include "subview.hpp" +#include + +class QUndoStack; + namespace CSVWorld { - class Globals : public SubView + ///< \brief Getting the data out of an editor widget + /// + /// Really, Qt? Really? + class NastyTableModelHack : public QAbstractTableModel { + QAbstractItemModel& mModel; + QVariant mData; + + public: + + NastyTableModelHack (QAbstractItemModel& model); + int rowCount (const QModelIndex & parent = QModelIndex()) const; + + int columnCount (const QModelIndex & parent = QModelIndex()) const; + + QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + + bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + + QVariant getData() const; + }; + + ///< \brief Use commands instead of manipulating the model directly + class CommandDelegate : public QStyledItemDelegate + { + QUndoStack& mUndoStack; + + public: + + CommandDelegate (QUndoStack& undoStack, QObject *parent); + + void setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const; + }; + + class Globals : public SubView + { public: - Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data); + Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); }; } diff --git a/apps/opencs/view/world/subview.hpp b/apps/opencs/view/world/subview.hpp index 95cbe4243..fd7a51631 100644 --- a/apps/opencs/view/world/subview.hpp +++ b/apps/opencs/view/world/subview.hpp @@ -5,6 +5,8 @@ #include +class QUndoStack; + namespace CSMWorld { class Data; @@ -31,19 +33,21 @@ namespace CSVWorld struct SubViewFactoryBase { - virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data) = 0; + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) + = 0; }; template struct SubViewFactory : public SubViewFactoryBase { - virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data); + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); }; template - SubView *SubViewFactory::makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data) + SubView *SubViewFactory::makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, + QUndoStack& undoStack) { - return new SubViewT (id, data); + return new SubViewT (id, data, undoStack); } } From fd55c0cae2603562c7a648bf62c70bbbd33976a3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 29 Nov 2012 18:56:28 +0100 Subject: [PATCH 024/136] record IDs are no longer handled as a special case --- apps/opencs/model/world/columns.hpp | 16 +++++++++++++++ apps/opencs/model/world/data.cpp | 1 + apps/opencs/model/world/idcollection.hpp | 6 +++++- apps/opencs/model/world/idtable.cpp | 26 +++++++----------------- apps/opencs/view/world/globals.cpp | 2 +- 5 files changed, 30 insertions(+), 21 deletions(-) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 4d0ecb58e..3220b3bba 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -28,6 +28,22 @@ namespace CSMWorld } }; + template + struct StringIdColumn : public Column + { + StringIdColumn() : Column ("ID") {} + + virtual QVariant get (const Record& record) const + { + return record.get().mId.c_str(); + } + + virtual bool isEditable() const + { + return false; + } + }; + } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 7fdb149b3..aeafc1676 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -12,6 +12,7 @@ CSMWorld::Data::Data() { + mGlobals.addColumn (new StringIdColumn); mGlobals.addColumn (new FloatValueColumn); mModels.insert (std::make_pair ( diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index ee6a4b2ce..41cd352ce 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -24,7 +25,10 @@ namespace CSMWorld virtual QVariant get (const Record& record) const = 0; - virtual void set (Record& record, const QVariant& data) = 0; + virtual void set (Record& record, const QVariant& data) + { + throw std::logic_error ("Column " + mTitle + " is not editable"); + } virtual bool isEditable() const = 0; }; diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 8fdc4fb8f..1fc2bfedb 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -26,7 +26,7 @@ int CSMWorld::IdTable::columnCount (const QModelIndex & parent) const if (parent.isValid()) return 0; - return 1+mIdCollection->getColumns(); + return mIdCollection->getColumns(); } QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const @@ -34,19 +34,10 @@ QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const if (role!=Qt::DisplayRole && role!=Qt::EditRole) return QVariant(); - if (role==Qt::EditRole) - { - if (index.column()==0) - return QVariant(); - - if (!mIdCollection->isEditable (index.column()-1)) + if (role==Qt::EditRole && !mIdCollection->isEditable (index.column())) return QVariant(); - } - - if (index.column()==0) - return QVariant (tr (mIdCollection->getId (index.row()).c_str())); - return mIdCollection->getData (index.row(), index.column()-1); + return mIdCollection->getData (index.row(), index.column()); } QVariant CSMWorld::IdTable::headerData (int section, Qt::Orientation orientation, int role) const @@ -57,17 +48,14 @@ QVariant CSMWorld::IdTable::headerData (int section, Qt::Orientation orientation if (orientation==Qt::Vertical) return QVariant(); - if (section==0) - return QVariant (tr ("ID")); - - return tr (mIdCollection->getTitle (section-1).c_str()); + return tr (mIdCollection->getTitle (section).c_str()); } bool CSMWorld::IdTable::setData ( const QModelIndex &index, const QVariant &value, int role) { - if (index.column()>0 && role==Qt::EditRole) + if (mIdCollection->isEditable (index.column()) && role==Qt::EditRole) { - mIdCollection->setData (index.row(), index.column()-1, value); + mIdCollection->setData (index.row(), index.column(), value); emit dataChanged (index, index); return true; } @@ -79,7 +67,7 @@ Qt::ItemFlags CSMWorld::IdTable::flags (const QModelIndex & index) const { Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; - if (index.column()>0) + if (mIdCollection->isEditable (index.column())) flags |= Qt::ItemIsEditable; return flags; diff --git a/apps/opencs/view/world/globals.cpp b/apps/opencs/view/world/globals.cpp index a57f63dff..459b8c357 100644 --- a/apps/opencs/view/world/globals.cpp +++ b/apps/opencs/view/world/globals.cpp @@ -63,7 +63,7 @@ CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& dat int columns = model->columnCount(); - for (int i=1; isetItemDelegateForColumn (i, delegate); From 8dd76b49af58ee7822fd11145cf0694a11ca51b1 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 29 Nov 2012 19:09:06 +0100 Subject: [PATCH 025/136] factored out table widget from globals sub view --- apps/opencs/CMakeLists.txt | 4 +- apps/opencs/view/doc/view.cpp | 11 --- apps/opencs/view/doc/view.hpp | 2 - apps/opencs/view/world/globals.cpp | 75 +----------------- apps/opencs/view/world/globals.hpp | 37 --------- apps/opencs/view/world/table.cpp | 118 +++++++++++++++++++++++++++++ apps/opencs/view/world/table.hpp | 25 ++++++ 7 files changed, 147 insertions(+), 125 deletions(-) create mode 100644 apps/opencs/view/world/table.cpp create mode 100644 apps/opencs/view/world/table.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 61580461f..dfd987345 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -9,7 +9,7 @@ set (OPENCS_SRC view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp - view/world/subview.cpp view/world/globals.cpp + view/world/subview.cpp view/world/table.cpp view/world/globals.cpp ) set (OPENCS_HDR @@ -23,7 +23,7 @@ set (OPENCS_HDR view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp model/world/commands.hpp - view/world/subview.hpp view/world/globals.hpp + view/world/subview.hpp view/world/table.hpp view/world/globals.hpp ) set (OPENCS_US diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index c81ba2ba1..0c336376b 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -46,12 +46,6 @@ void CSVDoc::View::setupEditMenu() mRedo= mDocument->getUndoStack().createRedoAction (this, tr("&Redo")); mRedo->setShortcuts (QKeySequence::Redo); edit->addAction (mRedo); - - // test - QAction *test = new QAction (tr ("&Test Command"), this); - connect (test, SIGNAL (triggered()), this, SLOT (test())); - edit->addAction (test); - mEditingActions.push_back (test); } void CSVDoc::View::setupViewMenu() @@ -203,11 +197,6 @@ void CSVDoc::View::newView() mViewManager.addView (mDocument); } -void CSVDoc::View::test() -{ - mDocument->getUndoStack().push (new QUndoCommand()); -} - void CSVDoc::View::save() { mDocument->save(); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 8e2b27293..c86c3b362 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -93,8 +93,6 @@ namespace CSVDoc void newView(); - void test(); - void save(); void verify(); diff --git a/apps/opencs/view/world/globals.cpp b/apps/opencs/view/world/globals.cpp index 459b8c357..a8b6497db 100644 --- a/apps/opencs/view/world/globals.cpp +++ b/apps/opencs/view/world/globals.cpp @@ -1,83 +1,12 @@ #include "globals.hpp" -#include -#include -#include -#include - -#include "../../model/world/data.hpp" - -#include "../../model/world/commands.hpp" - -CSVWorld::NastyTableModelHack::NastyTableModelHack (QAbstractItemModel& model) -: mModel (model) -{} - -int CSVWorld::NastyTableModelHack::rowCount (const QModelIndex & parent) const -{ - return mModel.rowCount (parent); -} - -int CSVWorld::NastyTableModelHack::columnCount (const QModelIndex & parent) const -{ - return mModel.columnCount (parent); -} - -QVariant CSVWorld::NastyTableModelHack::data (const QModelIndex & index, int role) const -{ - return mModel.data (index, role); -} - -bool CSVWorld::NastyTableModelHack::setData ( const QModelIndex &index, const QVariant &value, int role) -{ - mData = value; - return true; -} - -QVariant CSVWorld::NastyTableModelHack::getData() const -{ - return mData; -} - -CSVWorld::CommandDelegate::CommandDelegate (QUndoStack& undoStack, QObject *parent) -: QStyledItemDelegate (parent), mUndoStack (undoStack) -{} - -void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemModel *model, - const QModelIndex& index) const -{ - NastyTableModelHack hack (*model); - QStyledItemDelegate::setModelData (editor, &hack, index); - mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData())); -} +#include "table.hpp" CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) : SubView (id) { - QTableView *table = new QTableView(); + QTableView *table = new Table (id, data, undoStack); setWidget (table); - - QAbstractTableModel *model = data.getTableModel (id); - - int columns = model->columnCount(); - - for (int i=0; isetItemDelegateForColumn (i, delegate); - } - - QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel (this); - proxyModel->setSourceModel (model); - - table->setModel (proxyModel); - table->horizontalHeader()->setResizeMode (QHeaderView::Interactive); - table->verticalHeader()->hide(); - table->setSortingEnabled (true); - table->setSelectionBehavior (QAbstractItemView::SelectRows); - table->setSelectionMode (QAbstractItemView::ExtendedSelection); - - /// \todo make initial layout fill the whole width of the table } \ No newline at end of file diff --git a/apps/opencs/view/world/globals.hpp b/apps/opencs/view/world/globals.hpp index 11ab7b6aa..c4a9fd402 100644 --- a/apps/opencs/view/world/globals.hpp +++ b/apps/opencs/view/world/globals.hpp @@ -3,47 +3,10 @@ #include "subview.hpp" -#include - class QUndoStack; namespace CSVWorld { - ///< \brief Getting the data out of an editor widget - /// - /// Really, Qt? Really? - class NastyTableModelHack : public QAbstractTableModel - { - QAbstractItemModel& mModel; - QVariant mData; - - public: - - NastyTableModelHack (QAbstractItemModel& model); - - int rowCount (const QModelIndex & parent = QModelIndex()) const; - - int columnCount (const QModelIndex & parent = QModelIndex()) const; - - QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; - - bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); - - QVariant getData() const; - }; - - ///< \brief Use commands instead of manipulating the model directly - class CommandDelegate : public QStyledItemDelegate - { - QUndoStack& mUndoStack; - - public: - - CommandDelegate (QUndoStack& undoStack, QObject *parent); - - void setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const; - }; - class Globals : public SubView { public: diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp new file mode 100644 index 000000000..2c9aa431f --- /dev/null +++ b/apps/opencs/view/world/table.cpp @@ -0,0 +1,118 @@ + +#include "table.hpp" + +#include +#include +#include +#include + +#include "../../model/world/data.hpp" + +#include "../../model/world/commands.hpp" + +namespace CSVWorld +{ + ///< \brief Getting the data out of an editor widget + /// + /// Really, Qt? Really? + class NastyTableModelHack : public QAbstractTableModel + { + QAbstractItemModel& mModel; + QVariant mData; + + public: + + NastyTableModelHack (QAbstractItemModel& model); + + int rowCount (const QModelIndex & parent = QModelIndex()) const; + + int columnCount (const QModelIndex & parent = QModelIndex()) const; + + QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + + bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + + QVariant getData() const; + }; + + ///< \brief Use commands instead of manipulating the model directly + class CommandDelegate : public QStyledItemDelegate + { + QUndoStack& mUndoStack; + + public: + + CommandDelegate (QUndoStack& undoStack, QObject *parent); + + void setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const; + }; + +} + +CSVWorld::NastyTableModelHack::NastyTableModelHack (QAbstractItemModel& model) +: mModel (model) +{} + +int CSVWorld::NastyTableModelHack::rowCount (const QModelIndex & parent) const +{ + return mModel.rowCount (parent); +} + +int CSVWorld::NastyTableModelHack::columnCount (const QModelIndex & parent) const +{ + return mModel.columnCount (parent); +} + +QVariant CSVWorld::NastyTableModelHack::data (const QModelIndex & index, int role) const +{ + return mModel.data (index, role); +} + +bool CSVWorld::NastyTableModelHack::setData ( const QModelIndex &index, const QVariant &value, int role) +{ + mData = value; + return true; +} + +QVariant CSVWorld::NastyTableModelHack::getData() const +{ + return mData; +} + +CSVWorld::CommandDelegate::CommandDelegate (QUndoStack& undoStack, QObject *parent) +: QStyledItemDelegate (parent), mUndoStack (undoStack) +{} + +void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemModel *model, + const QModelIndex& index) const +{ + NastyTableModelHack hack (*model); + QStyledItemDelegate::setModelData (editor, &hack, index); + mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData())); +} + + +CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) +{ + QAbstractTableModel *model = data.getTableModel (id); + + int columns = model->columnCount(); + + for (int i=0; isetSourceModel (model); + + setModel (proxyModel); + horizontalHeader()->setResizeMode (QHeaderView::Interactive); + verticalHeader()->hide(); + setSortingEnabled (true); + setSelectionBehavior (QAbstractItemView::SelectRows); + setSelectionMode (QAbstractItemView::ExtendedSelection); + + /// \todo make initial layout fill the whole width of the table +} \ No newline at end of file diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp new file mode 100644 index 000000000..dbb3c3443 --- /dev/null +++ b/apps/opencs/view/world/table.hpp @@ -0,0 +1,25 @@ +#ifndef CSV_WORLD_TABLE_H +#define CSV_WORLD_TABLE_H + +#include + +class QUndoStack; + +namespace CSMWorld +{ + class Data; + class UniversalId; +} + +namespace CSVWorld +{ + ///< Table widget + class Table : public QTableView + { + public: + + Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); + }; +} + +#endif From 7079b9062f66250fa9b0790c75bfd76533cbd814 Mon Sep 17 00:00:00 2001 From: rpopovici Date: Fri, 30 Nov 2012 02:16:16 +0200 Subject: [PATCH 026/136] add AI script functions --- apps/openmw/mwmechanics/aiescort.cpp | 6 + apps/openmw/mwmechanics/aiescort.hpp | 5 + apps/openmw/mwmechanics/aifollow.cpp | 5 + apps/openmw/mwmechanics/aifollow.hpp | 4 +- apps/openmw/mwscript/aiextensions.cpp | 239 +++++++++++++++++++++++-- apps/openmw/mwscript/docs/vmformat.txt | 16 +- 6 files changed, 262 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index 27cd9095d..ebbea55b0 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -5,6 +5,12 @@ MWMechanics::AiEscort::AiEscort(const std::string &actorId,int duration, float x : mActorId(actorId), mX(x), mY(y), mZ(z), mDuration(duration) { } + +MWMechanics::AiEscort::AiEscort(const std::string &actorId,const std::string &cellId,int duration, float x, float y, float z) +: mActorId(actorId), mCellId(cellId), mX(x), mY(y), mZ(z), mDuration(duration) +{ +} + MWMechanics::AiEscort *MWMechanics::AiEscort::clone() const { diff --git a/apps/openmw/mwmechanics/aiescort.hpp b/apps/openmw/mwmechanics/aiescort.hpp index fef70f508..d89a9586c 100644 --- a/apps/openmw/mwmechanics/aiescort.hpp +++ b/apps/openmw/mwmechanics/aiescort.hpp @@ -10,6 +10,10 @@ namespace MWMechanics { public: AiEscort(const std::string &actorId,int duration, float x, float y, float z); + ///< \implement AiEscort + AiEscort(const std::string &actorId,const std::string &cellId,int duration, float x, float y, float z); + ///< \implement AiEscortCell + virtual AiEscort *clone() const; virtual bool execute (const MWWorld::Ptr& actor); @@ -19,6 +23,7 @@ namespace MWMechanics private: std::string mActorId; + std::string mCellId; float mX; float mY; float mZ; diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 3fee6d98c..dab9e0283 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -5,6 +5,11 @@ MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float : mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId) { } +MWMechanics::AiFollow::AiFollow(const std::string &actorId,const std::string &cellId,float duration, float x, float y, float z) +: mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(cellId) +{ +} + MWMechanics::AiFollow *MWMechanics::AiFollow::clone() const { return new AiFollow(*this); diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index ded13d780..0b37b0a2d 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -11,6 +11,7 @@ namespace MWMechanics { public: AiFollow(const std::string &ActorId,float duration, float X, float Y, float Z); + AiFollow(const std::string &ActorId,const std::string &CellId,float duration, float X, float Y, float Z); virtual AiFollow *clone() const; virtual bool execute (const MWWorld::Ptr& actor); ///< \return Package completed? @@ -21,7 +22,8 @@ namespace MWMechanics float mX; float mY; float mZ; - std::string mActorId; + std::string mActorId; + std::string mCellId; }; } #endif diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index 787962ad1..a4108c17e 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -10,6 +10,11 @@ #include "../mwworld/class.hpp" #include "../mwmechanics/creaturestats.hpp" +#include "../mwmechanics/aiactivate.hpp" +#include "../mwmechanics/aiescort.hpp" +#include "../mwmechanics/aifollow.hpp" +#include "../mwmechanics/aitravel.hpp" +#include "../mwmechanics/aiwander.hpp" #include "interpretercontext.hpp" #include "ref.hpp" @@ -20,6 +25,27 @@ namespace MWScript { namespace Ai { + template + class OpAiActivate : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + MWWorld::Ptr ptr = R()(runtime); + + std::string objectID = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + // discard additional arguments (reset), because we have no idea what they mean. + for (unsigned int i=0; i class OpAiTravel : public Interpreter::Opcode1 { @@ -41,6 +67,9 @@ namespace MWScript // discard additional arguments (reset), because we have no idea what they mean. for (unsigned int i=0; i + class OpAiEscortCell : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + MWWorld::Ptr ptr = R()(runtime); + + std::string actorID = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + std::string cellID = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); Interpreter::Type_Float duration = runtime[0].mFloat; @@ -72,6 +139,9 @@ namespace MWScript // discard additional arguments (reset), because we have no idea what they mean. for (unsigned int i=0; i idleList; + for (unsigned int i=0; i + class OpAiFollow : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + MWWorld::Ptr ptr = R()(runtime); + + std::string actorID = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Float duration = runtime[0].mFloat; + runtime.pop(); + + Interpreter::Type_Float x = runtime[0].mFloat; + runtime.pop(); + + Interpreter::Type_Float y = runtime[0].mFloat; + runtime.pop(); + + Interpreter::Type_Float z = runtime[0].mFloat; + runtime.pop(); + + // discard additional arguments (reset), because we have no idea what they mean. + for (unsigned int i=0; i + class OpAiFollowCell : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + MWWorld::Ptr ptr = R()(runtime); + + std::string actorID = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + std::string cellID = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Float duration = runtime[0].mFloat; + runtime.pop(); + + Interpreter::Type_Float x = runtime[0].mFloat; + runtime.pop(); + + Interpreter::Type_Float y = runtime[0].mFloat; + runtime.pop(); + + Interpreter::Type_Float z = runtime[0].mFloat; + runtime.pop(); + + // discard additional arguments (reset), because we have no idea what they mean. + for (unsigned int i=0; i + class OpGetCurrentAIPackage : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + Interpreter::Type_Integer value = MWWorld::Class::get (ptr).getCreatureStats (ptr).getAiSequence().getTypeId (); + + runtime.push (value); + } + }; + + template + class OpGetDetected : public Interpreter::Opcode1 + { + public: + + virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0) + { + MWWorld::Ptr ptr = R()(runtime); + + std::string actorID = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Integer value = false; // TODO replace with implementation + + std::cout << "AiGetDetected: " << actorID << ", " << value << std::endl; + + runtime.push (value); + } + }; + const int opcodeAiTravel = 0x20000; const int opcodeAiTravelExplicit = 0x20001; @@ -189,8 +375,20 @@ namespace MWScript const int opcodeAiEscortExplicit = 0x20003; const int opcodeGetAiPackageDone = 0x200007c; const int opcodeGetAiPackageDoneExplicit = 0x200007d; + const int opcodeGetCurrentAiPackage = 0x20001b1; + const int opcodeGetCurrentAiPackageExplicit = 0x20001b2; + const int opcodeGetDetected = 0x20001b3; + const int opcodeGetDetectedExplicit = 0x20001b4; const int opcodeAiWander = 0x20010; const int opcodeAiWanderExplicit = 0x20011; + const int opcodeAIActivate = 0x20018; + const int opcodeAIActivateExplicit = 0x20019; + const int opcodeAiEscortCell = 0x2001a; + const int opcodeAiEscortCellExplicit = 0x2001b; + const int opcodeAiFollow = 0x2001c; + const int opcodeAiFollowExplicit = 0x2001d; + const int opcodeAiFollowCell = 0x2001e; + const int opcodeAiFollowCellExplicit = 0x2001f; const int opcodeSetHello = 0x200015e; const int opcodeSetHelloExplicit = 0x200015d; const int opcodeSetFight = 0x200015e; @@ -202,16 +400,26 @@ namespace MWScript void registerExtensions (Compiler::Extensions& extensions) { + extensions.registerInstruction ("aiactivate", "c/l", opcodeAIActivate, + opcodeAIActivateExplicit); extensions.registerInstruction ("aitravel", "fff/l", opcodeAiTravel, opcodeAiTravelExplicit); extensions.registerInstruction ("aiescort", "cffff/l", opcodeAiEscort, opcodeAiEscortExplicit); + extensions.registerInstruction ("aiescortcell", "ccffff/l", opcodeAiEscortCell, + opcodeAiEscortCellExplicit); extensions.registerInstruction ("aiwander", "fff/llllllllll", opcodeAiWander, opcodeAiWanderExplicit); - + extensions.registerInstruction ("aifollow", "cffff/l", opcodeAiFollow, + opcodeAiFollowExplicit); + extensions.registerInstruction ("aifollowcell", "ccffff/l", opcodeAiFollowCell, + opcodeAiFollowCellExplicit); extensions.registerFunction ("getaipackagedone", 'l', "", opcodeGetAiPackageDone, opcodeGetAiPackageDoneExplicit); - + extensions.registerFunction ("getcurrentaipackage", 'l', "", opcodeGetCurrentAiPackage, + opcodeGetAiPackageDoneExplicit); + extensions.registerFunction ("getdetected", 'l', "c", opcodeGetDetected, + opcodeGetDetectedExplicit); extensions.registerInstruction ("sethello", "l", opcodeSetHello, opcodeSetHelloExplicit); extensions.registerInstruction ("setfight", "l", opcodeSetFight, opcodeSetFightExplicit); extensions.registerInstruction ("setflee", "l", opcodeSetFlee, opcodeSetFleeExplicit); @@ -220,15 +428,26 @@ namespace MWScript void installOpcodes (Interpreter::Interpreter& interpreter) { + interpreter.installSegment3 (opcodeAIActivate, new OpAiActivate); + interpreter.installSegment3 (opcodeAIActivateExplicit, new OpAiActivate); interpreter.installSegment3 (opcodeAiTravel, new OpAiTravel); interpreter.installSegment3 (opcodeAiTravelExplicit, new OpAiTravel); interpreter.installSegment3 (opcodeAiEscort, new OpAiEscort); interpreter.installSegment3 (opcodeAiEscortExplicit, new OpAiEscort); + interpreter.installSegment3 (opcodeAiEscortCell, new OpAiEscortCell); + interpreter.installSegment3 (opcodeAiEscortCellExplicit, new OpAiEscortCell); interpreter.installSegment3 (opcodeAiWander, new OpAiWander); interpreter.installSegment3 (opcodeAiWanderExplicit, new OpAiWander); + interpreter.installSegment3 (opcodeAiFollow, new OpAiFollow); + interpreter.installSegment3 (opcodeAiFollowExplicit, new OpAiFollow); + interpreter.installSegment3 (opcodeAiFollowCell, new OpAiFollowCell); + interpreter.installSegment3 (opcodeAiFollowCellExplicit, new OpAiFollowCell); interpreter.installSegment5 (opcodeGetAiPackageDone, new OpGetAiPackageDone); - interpreter.installSegment5 (opcodeGetAiPackageDoneExplicit, - new OpGetAiPackageDone); + interpreter.installSegment5 (opcodeGetAiPackageDoneExplicit, new OpGetAiPackageDone); + interpreter.installSegment5 (opcodeGetCurrentAiPackage, new OpGetCurrentAIPackage); + interpreter.installSegment5 (opcodeGetCurrentAiPackageExplicit, new OpGetCurrentAIPackage); + interpreter.installSegment3 (opcodeGetDetected, new OpGetDetected); + interpreter.installSegment3 (opcodeGetDetectedExplicit, new OpGetDetected); interpreter.installSegment5 (opcodeSetHello, new OpSetHello); interpreter.installSegment5 (opcodeSetHelloExplicit, new OpSetHello); interpreter.installSegment5 (opcodeSetFight, new OpSetFight); diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index b130aa954..19517ac8d 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -37,7 +37,15 @@ op 0x20014: SetPCFacRep op 0x20015: SetPCFacRep, explicit reference op 0x20016: ModPCFacRep op 0x20017: ModPCFacRep, explicit reference -op s 0x20018-0x3ffff unused +op 0x20018: AIActivate +op 0x20019: AIActivate, explicit reference +op 0x2001a: AiEscortCell +op 0x2001b: AiEscortCell, explicit reference +op 0x2001c: AiFollow +op 0x2001d: AiFollow, explicit reference +op 0x2001e: AiFollowCell +op 0x2001f: AiFollowCell, explicit reference +op s 0x20020-0x3ffff unused Segment 4: (not implemented yet) @@ -226,5 +234,9 @@ op 0x20001ad: SetReputation op 0x20001ae: ModReputation op 0x20001af: SetReputation, explicit op 0x20001b0: ModReputation, explicit -opcodes 0x20001b1-0x3ffffff unused +op 0x20001b1: GetCurrentAIPackage +op 0x20001b2: GetCurrentAIPackage, explicit reference +op 0x20001b3: GetDetected +op 0x20001b4: GetDetected, explicit reference +opcodes 0x20001b5-0x3ffffff unused From ec1f957e54887dcb153d4ab07c51348373f65bb7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 30 Nov 2012 13:58:10 +0100 Subject: [PATCH 027/136] edit lock for sub views --- apps/opencs/view/doc/view.cpp | 5 +++++ apps/opencs/view/world/globals.cpp | 7 +++++-- apps/opencs/view/world/globals.hpp | 6 ++++++ apps/opencs/view/world/subview.hpp | 2 ++ apps/opencs/view/world/table.cpp | 27 +++++++++++++++++++++++---- apps/opencs/view/world/table.hpp | 8 ++++++++ 6 files changed, 49 insertions(+), 6 deletions(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 0c336376b..3d5ebc84b 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -165,6 +165,11 @@ void CSVDoc::View::updateDocumentState() for (int i=0; operations[i]!=-1; ++i) if (!(state & operations[i])) mOperations->quitOperation (operations[i]); + + QList subViews = findChildren(); + + for (QList::iterator iter (subViews.begin()); iter!=subViews.end(); ++iter) + (*iter)->setEditLock (state && CSMDoc::Document::State_Locked); } void CSVDoc::View::updateProgress (int current, int max, int type, int threads) diff --git a/apps/opencs/view/world/globals.cpp b/apps/opencs/view/world/globals.cpp index a8b6497db..68c9012aa 100644 --- a/apps/opencs/view/world/globals.cpp +++ b/apps/opencs/view/world/globals.cpp @@ -6,7 +6,10 @@ CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) : SubView (id) { - QTableView *table = new Table (id, data, undoStack); + setWidget (mTable = new Table (id, data, undoStack)); +} - setWidget (table); +void CSVWorld::Globals::setEditLock (bool locked) +{ + mTable->setEditLock (locked); } \ No newline at end of file diff --git a/apps/opencs/view/world/globals.hpp b/apps/opencs/view/world/globals.hpp index c4a9fd402..33cbce47f 100644 --- a/apps/opencs/view/world/globals.hpp +++ b/apps/opencs/view/world/globals.hpp @@ -7,11 +7,17 @@ class QUndoStack; namespace CSVWorld { + class Table; + class Globals : public SubView { + Table *mTable; + public: Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); + + virtual void setEditLock (bool locked); }; } diff --git a/apps/opencs/view/world/subview.hpp b/apps/opencs/view/world/subview.hpp index fd7a51631..543a9b2a1 100644 --- a/apps/opencs/view/world/subview.hpp +++ b/apps/opencs/view/world/subview.hpp @@ -29,6 +29,8 @@ namespace CSVWorld SubView (const CSMWorld::UniversalId& id); CSMWorld::UniversalId getUniversalId() const; + + virtual void setEditLock (bool locked) = 0; }; struct SubViewFactoryBase diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 2c9aa431f..590f7ea98 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -39,12 +39,15 @@ namespace CSVWorld class CommandDelegate : public QStyledItemDelegate { QUndoStack& mUndoStack; + bool mEditLock; public: CommandDelegate (QUndoStack& undoStack, QObject *parent); void setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const; + + void setEditLock (bool locked); }; } @@ -80,15 +83,24 @@ QVariant CSVWorld::NastyTableModelHack::getData() const } CSVWorld::CommandDelegate::CommandDelegate (QUndoStack& undoStack, QObject *parent) -: QStyledItemDelegate (parent), mUndoStack (undoStack) +: QStyledItemDelegate (parent), mUndoStack (undoStack), mEditLock (false) {} void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const { - NastyTableModelHack hack (*model); - QStyledItemDelegate::setModelData (editor, &hack, index); - mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData())); + if (!mEditLock) + { + NastyTableModelHack hack (*model); + QStyledItemDelegate::setModelData (editor, &hack, index); + mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData())); + } + ///< \todo provide some kind of feedback to the user, indicating that editing is currently not possible. +} + +void CSVWorld::CommandDelegate::setEditLock (bool locked) +{ + mEditLock = locked; } @@ -101,6 +113,7 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q for (int i=0; i::iterator iter (mDelegates.begin()); iter!=mDelegates.end(); ++iter) + (*iter)->setEditLock (locked); } \ No newline at end of file diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index dbb3c3443..ae203f516 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -1,6 +1,8 @@ #ifndef CSV_WORLD_TABLE_H #define CSV_WORLD_TABLE_H +#include + #include class QUndoStack; @@ -13,12 +15,18 @@ namespace CSMWorld namespace CSVWorld { + class CommandDelegate; + ///< Table widget class Table : public QTableView { + std::vector mDelegates; + public: Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); + + void setEditLock (bool locked); }; } From bd5e364ac1e29667e789d026360170f8a66734dc Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 1 Dec 2012 13:42:12 +0100 Subject: [PATCH 028/136] display record state in table --- apps/opencs/model/world/columns.hpp | 15 +++++++++++++++ apps/opencs/model/world/data.cpp | 1 + 2 files changed, 16 insertions(+) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 3220b3bba..e81780cee 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -44,6 +44,21 @@ namespace CSMWorld } }; + template + struct RecordStateColumn : public Column + { + RecordStateColumn() : Column ("*") {} + + virtual QVariant get (const Record& record) const + { + return static_cast (record.mState); + } + + virtual bool isEditable() const + { + return false; + } + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index aeafc1676..c0df54c10 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -13,6 +13,7 @@ CSMWorld::Data::Data() { mGlobals.addColumn (new StringIdColumn); + mGlobals.addColumn (new RecordStateColumn); mGlobals.addColumn (new FloatValueColumn); mModels.insert (std::make_pair ( From db29e411c4a28805611ce7d90e0ee8294af09cb8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 3 Dec 2012 13:56:02 +0100 Subject: [PATCH 029/136] added merge functions; temporarily merge on document creation --- apps/opencs/editor.cpp | 2 ++ apps/opencs/model/world/columns.hpp | 3 +++ apps/opencs/model/world/data.cpp | 5 ++++ apps/opencs/model/world/data.hpp | 3 +++ apps/opencs/model/world/idcollection.hpp | 30 ++++++++++++++++++++++++ apps/opencs/model/world/record.hpp | 30 ++++++++++++++++++++++-- 6 files changed, 71 insertions(+), 2 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 6977a22f0..1632ed220 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -35,6 +35,8 @@ void CS::Editor::createDocument() document->getData().getGlobals().add (record); } + document->getData().merge(); /// \todo remove once proper ESX loading is implemented + mViewManager.addView (document); } diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index e81780cee..483ce929d 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -51,6 +51,9 @@ namespace CSMWorld virtual QVariant get (const Record& record) const { + if (record.mState==Record::State_Erased) + return static_cast (Record::State_Deleted); + return static_cast (record.mState); } diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index c0df54c10..f350299ec 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -46,4 +46,9 @@ QAbstractTableModel *CSMWorld::Data::getTableModel (const UniversalId& id) throw std::logic_error ("No table model available for " + id.toString()); return iter->second; +} + +void CSMWorld::Data::merge() +{ + mGlobals.merge(); } \ No newline at end of file diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 11073c5e3..a8a21e205 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -33,6 +33,9 @@ namespace CSMWorld QAbstractTableModel *getTableModel (const UniversalId& id); ///< If no table model is available for \æ id, an exception is thrown. + + void merge(); + ///< Merge modified into base. }; } diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index 41cd352ce..d9ab16747 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -58,6 +59,12 @@ namespace CSMWorld virtual void setData (int index, int column, const QVariant& data) = 0; virtual bool isEditable (int column) const = 0; + + virtual void merge() = 0; + ///< Merge modified into base. + + virtual void purge() = 0; + ///< Remove records that are flagged as erased. }; ///< \brief Collection of ID-based records @@ -95,6 +102,12 @@ namespace CSMWorld virtual bool isEditable (int column) const; + virtual void merge(); + ///< Merge modified into base. + + virtual void purge(); + ///< Remove records that are flagged as erased. + void addColumn (Column *column); }; @@ -181,6 +194,23 @@ namespace CSMWorld { mColumns.push_back (column); } + + template + void IdCollection::merge() + { + for (typename std::vector >::iterator iter (mRecords.begin()); iter!=mRecords.end(); ++iter) + iter->merge(); + + purge(); + } + + template + void IdCollection::purge() + { + mRecords.erase (std::remove_if (mRecords.begin(), mRecords.end(), + std::mem_fun_ref (&Record::isErased) // I want lambda :( + ), mRecords.end()); + } } #endif diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index 950d7f176..c08d2e0d1 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -13,7 +13,8 @@ namespace CSMWorld State_BaseOnly, // defined in base only State_Modified, // exists in base, but has been modified State_ModifiedOnly, // newly created in modified - State_Deleted // exists in base, but has been deleted + State_Deleted, // exists in base, but has been deleted + State_Erased // does not exist at all (we mostly treat that the same way as deleted) }; ESXRecordT mBase; @@ -22,6 +23,8 @@ namespace CSMWorld bool isDeleted() const; + bool isErased() const; + bool isModified() const; const ESXRecordT& get() const; @@ -32,12 +35,21 @@ namespace CSMWorld void setModified (const ESXRecordT& modified); ///< Throws an exception, if the record is deleted. + + void merge(); + ///< Merge modified into base. }; template bool Record::isDeleted() const { - return mState==State_Deleted; + return mState==State_Deleted || mState==State_Erased; + } + + template + bool Record::isErased() const + { + return mState==State_Erased; } template @@ -75,6 +87,20 @@ namespace CSMWorld if (mState!=State_ModifiedOnly) mState = mBase==mModified ? State_BaseOnly : State_Modified; } + + template + void Record::merge() + { + if (isModified()) + { + mBase = mModified; + mState = State_BaseOnly; + } + else if (mState==State_Deleted) + { + mState = State_Erased; + } + } } #endif From 49d62390045bfc3794f98da72fee9ce0351415fd Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 3 Dec 2012 21:44:16 +0100 Subject: [PATCH 030/136] added pop-up menu with create record action --- apps/opencs/CMakeLists.txt | 6 +- apps/opencs/model/world/commands.cpp | 18 ++++++ apps/opencs/model/world/commands.hpp | 18 ++++++ apps/opencs/model/world/idcollection.hpp | 56 +++++++++++++++++++ apps/opencs/model/world/idtable.cpp | 30 ++++++++++ apps/opencs/model/world/idtable.hpp | 18 ++++-- apps/opencs/model/world/idtableproxymodel.cpp | 18 ++++++ apps/opencs/model/world/idtableproxymodel.hpp | 24 ++++++++ apps/opencs/model/world/record.hpp | 17 +++--- apps/opencs/view/world/globals.cpp | 2 +- apps/opencs/view/world/table.cpp | 45 +++++++++++++-- apps/opencs/view/world/table.hpp | 18 +++++- 12 files changed, 246 insertions(+), 24 deletions(-) create mode 100644 apps/opencs/model/world/idtableproxymodel.cpp create mode 100644 apps/opencs/model/world/idtableproxymodel.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index dfd987345..6d18a1811 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -5,7 +5,7 @@ set (OPENCS_SRC model/doc/documentmanager.cpp model/doc/document.cpp model/world/universalid.cpp model/world/idcollection.cpp model/world/data.cpp model/world/idtable.cpp - model/world/commands.cpp + model/world/commands.cpp model/world/idtableproxymodel.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp @@ -18,10 +18,10 @@ set (OPENCS_HDR model/doc/documentmanager.hpp model/doc/document.hpp model/world/universalid.hpp model/world/record.hpp model/world/idcollection.hpp model/world/data.hpp - model/world/idtable.hpp model/world/columns.hpp + model/world/idtable.hpp model/world/columns.hpp model/world/idtableproxymodel.hpp + model/world/commands.hpp view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp - model/world/commands.hpp view/world/subview.hpp view/world/table.hpp view/world/globals.hpp ) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index a15d00619..7bb76acd0 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -3,6 +3,8 @@ #include +#include "idtableproxymodel.hpp" + CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelIndex& index, const QVariant& new_, QUndoCommand *parent) : QUndoCommand (parent), mModel (model), mIndex (index), mNew (new_) @@ -20,4 +22,20 @@ void CSMWorld::ModifyCommand::redo() void CSMWorld::ModifyCommand::undo() { mModel.setData (mIndex, mOld); +} + +CSMWorld::CreateCommand::CreateCommand (IdTableProxyModel& model, const std::string& id, QUndoCommand *parent) +: QUndoCommand (parent), mModel (model), mId (id) +{ + setText (("Create record " + id).c_str()); +} + +void CSMWorld::CreateCommand::redo() +{ + mModel.addRecord (mId); +} + +void CSMWorld::CreateCommand::undo() +{ + mModel.removeRow (mModel.getModelIndex (mId, 0).row()); } \ No newline at end of file diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index ffaee59ef..50b9045c6 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -3,6 +3,8 @@ #include "record.hpp" +#include + #include #include #include @@ -12,6 +14,8 @@ class QAbstractItemModel; namespace CSMWorld { + class IdTableProxyModel; + class ModifyCommand : public QUndoCommand { QAbstractItemModel& mModel; @@ -28,6 +32,20 @@ namespace CSMWorld virtual void undo(); }; + + class CreateCommand : public QUndoCommand + { + IdTableProxyModel& mModel; + std::string mId; + + public: + + CreateCommand (IdTableProxyModel& model, const std::string& id, QUndoCommand *parent = 0); + + virtual void redo(); + + virtual void undo(); + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index d9ab16747..be7891bd2 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -50,6 +50,8 @@ namespace CSMWorld virtual std::string getId (int index) const = 0; + virtual int getIndex (const std::string& id) const = 0; + virtual int getColumns() const = 0; virtual std::string getTitle (int column) const = 0; @@ -65,6 +67,10 @@ namespace CSMWorld virtual void purge() = 0; ///< Remove records that are flagged as erased. + + virtual void removeRows (int index, int count) = 0; + + virtual void appendBlankRecord (const std::string& id) = 0; }; ///< \brief Collection of ID-based records @@ -92,6 +98,8 @@ namespace CSMWorld virtual std::string getId (int index) const; + virtual int getIndex (const std::string& id) const; + virtual int getColumns() const; virtual QVariant getData (int index, int column) const; @@ -108,6 +116,10 @@ namespace CSMWorld virtual void purge(); ///< Remove records that are flagged as erased. + virtual void removeRows (int index, int count) ; + + virtual void appendBlankRecord (const std::string& id); + void addColumn (Column *column); }; @@ -159,6 +171,17 @@ namespace CSMWorld return mRecords.at (index).get().mId; } + template + int IdCollection::getIndex (const std::string& id) const + { + std::map::const_iterator iter = mIndex.find (id); + + if (iter==mIndex.end()) + throw std::runtime_error ("invalid ID: " + id); + + return iter->second; + } + template int IdCollection::getColumns() const { @@ -211,6 +234,39 @@ namespace CSMWorld std::mem_fun_ref (&Record::isErased) // I want lambda :( ), mRecords.end()); } + + template + void IdCollection::removeRows (int index, int count) + { + mRecords.erase (mRecords.begin()+index, mRecords.begin()+index+count); + + typename std::map::iterator iter = mIndex.begin(); + + while (iter!=mIndex.end()) + { + if (iter->second>=index) + { + if (iter->second>=index+count) + { + iter->second -= count; + } + else + { + mIndex.erase (iter++); + } + } + + ++iter; + } + } + + template + void IdCollection::appendBlankRecord (const std::string& id) + { + ESXRecordT record; + record.mId = id; + add (record); + } } #endif diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 1fc2bfedb..50a6953d6 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -71,4 +71,34 @@ Qt::ItemFlags CSMWorld::IdTable::flags (const QModelIndex & index) const flags |= Qt::ItemIsEditable; return flags; +} + +bool CSMWorld::IdTable::removeRows (int row, int count, const QModelIndex& parent) +{ + if (parent.isValid()) + return false; + + beginRemoveRows (parent, row, row+count-1); + + mIdCollection->removeRows (row, count); + + endRemoveRows(); + + return true; +} + +void CSMWorld::IdTable::addRecord (const std::string& id) +{ + int index = mIdCollection->getSize(); + + beginInsertRows (QModelIndex(), index, index); + + mIdCollection->appendBlankRecord (id); + + endInsertRows(); +} + +QModelIndex CSMWorld::IdTable::getModelIndex (const std::string& id, int column) const +{ + return index (mIdCollection->getIndex (id), column); } \ No newline at end of file diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index 30af3aaf7..f95873c7a 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -24,17 +24,23 @@ namespace CSMWorld virtual ~IdTable(); - int rowCount (const QModelIndex & parent = QModelIndex()) const; + virtual int rowCount (const QModelIndex & parent = QModelIndex()) const; - int columnCount (const QModelIndex & parent = QModelIndex()) const; + virtual int columnCount (const QModelIndex & parent = QModelIndex()) const; - QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + virtual QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; - QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + virtual QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - bool setData ( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + virtual bool setData ( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); - Qt::ItemFlags flags (const QModelIndex & index) const; + virtual Qt::ItemFlags flags (const QModelIndex & index) const; + + virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); + + void addRecord (const std::string& id); + + QModelIndex getModelIndex (const std::string& id, int column) const; }; } diff --git a/apps/opencs/model/world/idtableproxymodel.cpp b/apps/opencs/model/world/idtableproxymodel.cpp new file mode 100644 index 000000000..78995f60b --- /dev/null +++ b/apps/opencs/model/world/idtableproxymodel.cpp @@ -0,0 +1,18 @@ + +#include "idtableproxymodel.hpp" + +#include "idtable.hpp" + +CSMWorld::IdTableProxyModel::IdTableProxyModel (QObject *parent) +: QSortFilterProxyModel (parent) +{} + +void CSMWorld::IdTableProxyModel::addRecord (const std::string& id) +{ + dynamic_cast (*sourceModel()).addRecord (id); +} + +QModelIndex CSMWorld::IdTableProxyModel::getModelIndex (const std::string& id, int column) const +{ + return mapFromSource (dynamic_cast (*sourceModel()).getModelIndex (id, column)); +} \ No newline at end of file diff --git a/apps/opencs/model/world/idtableproxymodel.hpp b/apps/opencs/model/world/idtableproxymodel.hpp new file mode 100644 index 000000000..3f1537cce --- /dev/null +++ b/apps/opencs/model/world/idtableproxymodel.hpp @@ -0,0 +1,24 @@ +#ifndef CSM_WOLRD_IDTABLEPROXYMODEL_H +#define CSM_WOLRD_IDTABLEPROXYMODEL_H + +#include + +#include + +namespace CSMWorld +{ + class IdTableProxyModel : public QSortFilterProxyModel + { + Q_OBJECT + + public: + + IdTableProxyModel (QObject *parent = 0); + + virtual void addRecord (const std::string& id); + + virtual QModelIndex getModelIndex (const std::string& id, int column) const; + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index c08d2e0d1..df93501f3 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -5,18 +5,21 @@ namespace CSMWorld { - template - struct Record + struct RecordBase { enum State { - State_BaseOnly, // defined in base only - State_Modified, // exists in base, but has been modified - State_ModifiedOnly, // newly created in modified - State_Deleted, // exists in base, but has been deleted - State_Erased // does not exist at all (we mostly treat that the same way as deleted) + State_BaseOnly = 0, // defined in base only + State_Modified = 1, // exists in base, but has been modified + State_ModifiedOnly = 2, // newly created in modified + State_Deleted = 3, // exists in base, but has been deleted + State_Erased = 4 // does not exist at all (we mostly treat that the same way as deleted) }; + }; + template + struct Record : public RecordBase + { ESXRecordT mBase; ESXRecordT mModified; State mState; diff --git a/apps/opencs/view/world/globals.cpp b/apps/opencs/view/world/globals.cpp index 68c9012aa..20cdb80f4 100644 --- a/apps/opencs/view/world/globals.cpp +++ b/apps/opencs/view/world/globals.cpp @@ -6,7 +6,7 @@ CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) : SubView (id) { - setWidget (mTable = new Table (id, data, undoStack)); + setWidget (mTable = new Table (id, data, undoStack, true)); } void CSVWorld::Globals::setEditLock (bool locked) diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 590f7ea98..862ebdc79 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -3,12 +3,14 @@ #include #include -#include #include +#include +#include +#include #include "../../model/world/data.hpp" - #include "../../model/world/commands.hpp" +#include "../../model/world/idtableproxymodel.hpp" namespace CSVWorld { @@ -104,7 +106,19 @@ void CSVWorld::CommandDelegate::setEditLock (bool locked) } -CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) + void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) +{ + QMenu menu (this); + + if (mCreateAction) + menu.addAction (mCreateAction); + + menu.exec (event->globalPos()); +} + +CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, + bool createAndDelete) +: mUndoStack (undoStack), mCreateAction (0) { QAbstractTableModel *model = data.getTableModel (id); @@ -117,10 +131,10 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q setItemDelegateForColumn (i, delegate); } - QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel (this); - proxyModel->setSourceModel (model); + mModel = new CSMWorld::IdTableProxyModel (this); + mModel->setSourceModel (model); - setModel (proxyModel); + setModel (mModel); horizontalHeader()->setResizeMode (QHeaderView::Interactive); verticalHeader()->hide(); setSortingEnabled (true); @@ -128,10 +142,29 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q setSelectionMode (QAbstractItemView::ExtendedSelection); /// \todo make initial layout fill the whole width of the table + + if (createAndDelete) + { + mCreateAction = new QAction (tr ("CreateRecord"), this); + connect (mCreateAction, SIGNAL (triggered()), this, SLOT (createRecord())); + addAction (mCreateAction); + } } void CSVWorld::Table::setEditLock (bool locked) { for (std::vector::iterator iter (mDelegates.begin()); iter!=mDelegates.end(); ++iter) (*iter)->setEditLock (locked); +} + +#include /// \todo remove +void CSVWorld::Table::createRecord() +{ + /// \todo ask the user for an ID instead. + static int index = 0; + + std::ostringstream stream; + stream << "id" << index++; + + mUndoStack.push (new CSMWorld::CreateCommand (*mModel, stream.str())); } \ No newline at end of file diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index ae203f516..f07f3ff24 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -6,11 +6,13 @@ #include class QUndoStack; +class QAction; namespace CSMWorld { class Data; class UniversalId; + class IdTableProxyModel; } namespace CSVWorld @@ -20,13 +22,27 @@ namespace CSVWorld ///< Table widget class Table : public QTableView { + Q_OBJECT + std::vector mDelegates; + QUndoStack& mUndoStack; + QAction *mCreateAction; + CSMWorld::IdTableProxyModel *mModel; + + private: + + void contextMenuEvent (QContextMenuEvent *event); public: - Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); + Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, bool createAndDelete); + ///< \param createAndDelete Allow creation and deletion of records. void setEditLock (bool locked); + + private slots: + + void createRecord(); }; } From 0a8b7602d316c63d2909270be035d2137a6551a3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 3 Dec 2012 21:51:42 +0100 Subject: [PATCH 031/136] fixed edit lock --- apps/opencs/view/doc/view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 3d5ebc84b..1a8d56878 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -169,7 +169,7 @@ void CSVDoc::View::updateDocumentState() QList subViews = findChildren(); for (QList::iterator iter (subViews.begin()); iter!=subViews.end(); ++iter) - (*iter)->setEditLock (state && CSMDoc::Document::State_Locked); + (*iter)->setEditLock (state & CSMDoc::Document::State_Locked); } void CSVDoc::View::updateProgress (int current, int max, int type, int threads) From 8e93bfa607ba7e38a507e7ffe346df0f5c9ecaec Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 3 Dec 2012 22:03:02 +0100 Subject: [PATCH 032/136] turned the global class into a general purpose table subview class --- apps/opencs/CMakeLists.txt | 4 ++-- apps/opencs/view/doc/view.cpp | 5 ++--- apps/opencs/view/world/globals.cpp | 15 --------------- apps/opencs/view/world/globals.hpp | 24 ------------------------ apps/opencs/view/world/subview.hpp | 23 +++++++++++++++++++++++ apps/opencs/view/world/table.cpp | 2 +- apps/opencs/view/world/tablesubview.cpp | 16 ++++++++++++++++ apps/opencs/view/world/tablesubview.hpp | 25 +++++++++++++++++++++++++ 8 files changed, 69 insertions(+), 45 deletions(-) delete mode 100644 apps/opencs/view/world/globals.cpp delete mode 100644 apps/opencs/view/world/globals.hpp create mode 100644 apps/opencs/view/world/tablesubview.cpp create mode 100644 apps/opencs/view/world/tablesubview.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 6d18a1811..4ef4f93c7 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -9,7 +9,7 @@ set (OPENCS_SRC view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp - view/world/subview.cpp view/world/table.cpp view/world/globals.cpp + view/world/subview.cpp view/world/table.cpp view/world/tablesubview.cpp ) set (OPENCS_HDR @@ -23,7 +23,7 @@ set (OPENCS_HDR view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp - view/world/subview.hpp view/world/table.hpp view/world/globals.hpp + view/world/subview.hpp view/world/table.hpp view/world/tablesubview.hpp ) set (OPENCS_US diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 1a8d56878..65ec103a2 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -10,8 +10,7 @@ #include "../../model/doc/document.hpp" -#include "../world/subview.hpp" -#include "../world/globals.hpp" +#include "../world/tablesubview.hpp" #include "viewmanager.hpp" #include "operations.hpp" @@ -122,7 +121,7 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to setupUi(); mSubViewFactories.insert (std::make_pair (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), - new CSVWorld::SubViewFactory())); + new CSVWorld::SubViewFactoryWithCreateFlag (true))); } CSVDoc::View::~View() diff --git a/apps/opencs/view/world/globals.cpp b/apps/opencs/view/world/globals.cpp deleted file mode 100644 index 20cdb80f4..000000000 --- a/apps/opencs/view/world/globals.cpp +++ /dev/null @@ -1,15 +0,0 @@ - -#include "globals.hpp" - -#include "table.hpp" - -CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) -: SubView (id) -{ - setWidget (mTable = new Table (id, data, undoStack, true)); -} - -void CSVWorld::Globals::setEditLock (bool locked) -{ - mTable->setEditLock (locked); -} \ No newline at end of file diff --git a/apps/opencs/view/world/globals.hpp b/apps/opencs/view/world/globals.hpp deleted file mode 100644 index 33cbce47f..000000000 --- a/apps/opencs/view/world/globals.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef CSV_WORLD_GLOBALS_H -#define CSV_WORLD_GLOBALS_H - -#include "subview.hpp" - -class QUndoStack; - -namespace CSVWorld -{ - class Table; - - class Globals : public SubView - { - Table *mTable; - - public: - - Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); - - virtual void setEditLock (bool locked); - }; -} - -#endif \ No newline at end of file diff --git a/apps/opencs/view/world/subview.hpp b/apps/opencs/view/world/subview.hpp index 543a9b2a1..95448cb47 100644 --- a/apps/opencs/view/world/subview.hpp +++ b/apps/opencs/view/world/subview.hpp @@ -51,6 +51,29 @@ namespace CSVWorld { return new SubViewT (id, data, undoStack); } + + template + struct SubViewFactoryWithCreateFlag : public SubViewFactoryBase + { + bool mCreateAndDelete; + + SubViewFactoryWithCreateFlag (bool createAndDelete); + + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); + }; + + template + SubViewFactoryWithCreateFlag::SubViewFactoryWithCreateFlag (bool createAndDelete) + : mCreateAndDelete (createAndDelete) + {} + + template + SubView *SubViewFactoryWithCreateFlag::makeSubView (const CSMWorld::UniversalId& id, + CSMWorld::Data& data, + QUndoStack& undoStack) + { + return new SubViewT (id, data, undoStack, mCreateAndDelete); + } } #endif \ No newline at end of file diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 862ebdc79..4f20d9fd2 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -145,7 +145,7 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q if (createAndDelete) { - mCreateAction = new QAction (tr ("CreateRecord"), this); + mCreateAction = new QAction (tr ("Add Record"), this); connect (mCreateAction, SIGNAL (triggered()), this, SLOT (createRecord())); addAction (mCreateAction); } diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp new file mode 100644 index 000000000..3bc555a2d --- /dev/null +++ b/apps/opencs/view/world/tablesubview.cpp @@ -0,0 +1,16 @@ + +#include "tablesubview.hpp" + +#include "table.hpp" + +CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, + bool createAndDelete) +: SubView (id) +{ + setWidget (mTable = new Table (id, data, undoStack, createAndDelete)); +} + +void CSVWorld::TableSubView::setEditLock (bool locked) +{ + mTable->setEditLock (locked); +} \ No newline at end of file diff --git a/apps/opencs/view/world/tablesubview.hpp b/apps/opencs/view/world/tablesubview.hpp new file mode 100644 index 000000000..b45b3c279 --- /dev/null +++ b/apps/opencs/view/world/tablesubview.hpp @@ -0,0 +1,25 @@ +#ifndef CSV_WORLD_TABLESUBVIEW_H +#define CSV_WORLD_TABLESUBVIEW_H + +#include "subview.hpp" + +class QUndoStack; + +namespace CSVWorld +{ + class Table; + + class TableSubView : public SubView + { + Table *mTable; + + public: + + TableSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, + bool createAndDelete); + + virtual void setEditLock (bool locked); + }; +} + +#endif \ No newline at end of file From 5cd2fe00ab41eaef4618e017061fd86630987338 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 3 Dec 2012 22:16:02 +0100 Subject: [PATCH 033/136] initialise blank global records --- apps/opencs/model/world/idcollection.hpp | 1 + components/esm/loadglob.cpp | 6 ++++++ components/esm/loadglob.hpp | 3 +++ 3 files changed, 10 insertions(+) diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index be7891bd2..e4bb31dbe 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -265,6 +265,7 @@ namespace CSMWorld { ESXRecordT record; record.mId = id; + record.blank(); add (record); } } diff --git a/components/esm/loadglob.cpp b/components/esm/loadglob.cpp index 0335da0df..ceaa86948 100644 --- a/components/esm/loadglob.cpp +++ b/components/esm/loadglob.cpp @@ -44,6 +44,12 @@ void Global::save(ESMWriter &esm) esm.writeHNT("FLTV", mValue); } + void Global::blank() + { + mValue = 0; + mType = VT_Float; + } + bool operator== (const Global& left, const Global& right) { return left.mId==right.mId && left.mValue==right.mValue && left.mType==right.mType; diff --git a/components/esm/loadglob.hpp b/components/esm/loadglob.hpp index 5c5dafaec..6111648a6 100644 --- a/components/esm/loadglob.hpp +++ b/components/esm/loadglob.hpp @@ -23,6 +23,9 @@ struct Global void load(ESMReader &esm); void save(ESMWriter &esm); + + void blank(); + ///< Set record to default state (does not touch the ID). }; bool operator== (const Global& left, const Global& right); From f07b7d17cdb1e07d907fe1518bd7249b695e64f3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 4 Dec 2012 20:43:47 +0100 Subject: [PATCH 034/136] improved exception handling --- apps/opencs/main.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index 15772eba0..4b1a688c2 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -1,11 +1,37 @@ #include "editor.hpp" +#include +#include + #include +class Application : public QApplication +{ + private: + + bool notify (QObject *receiver, QEvent *event) + { + try + { + return QApplication::notify (receiver, event); + } + catch (const std::exception& exception) + { + std::cerr << "An exception has been caught: " << exception.what() << std::endl; + } + + return false; + } + + public: + + Application (int& argc, char *argv[]) : QApplication (argc, argv) {} +}; + int main(int argc, char *argv[]) { - QApplication mApplication (argc, argv); + Application mApplication (argc, argv); CS::Editor editor; From b41cc5e9e943580281b7be67262de633c41f8404 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 6 Dec 2012 14:56:04 +0100 Subject: [PATCH 035/136] added revert command --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/world/columns.hpp | 7 +- apps/opencs/model/world/commands.cpp | 34 +++++++++ apps/opencs/model/world/commands.hpp | 23 +++++++ apps/opencs/model/world/idcollection.hpp | 87 +++++++++++++++++++++++- apps/opencs/model/world/idtable.cpp | 32 ++++++++- apps/opencs/model/world/idtable.hpp | 6 ++ apps/opencs/model/world/record.cpp | 21 ++++++ apps/opencs/model/world/record.hpp | 35 ++++------ apps/opencs/view/world/table.cpp | 55 +++++++++++++-- apps/opencs/view/world/table.hpp | 7 +- 11 files changed, 275 insertions(+), 34 deletions(-) create mode 100644 apps/opencs/model/world/record.cpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 4ef4f93c7..5a9e1e99c 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -5,7 +5,7 @@ set (OPENCS_SRC model/doc/documentmanager.cpp model/doc/document.cpp model/world/universalid.cpp model/world/idcollection.cpp model/world/data.cpp model/world/idtable.cpp - model/world/commands.cpp model/world/idtableproxymodel.cpp + model/world/commands.cpp model/world/idtableproxymodel.cpp model/world/record.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 483ce929d..188d3a2ac 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -57,9 +57,14 @@ namespace CSMWorld return static_cast (record.mState); } + virtual void set (Record& record, const QVariant& data) + { + record.mState = static_cast (data.toInt()); + } + virtual bool isEditable() const { - return false; + return true; } }; } diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index 7bb76acd0..96a1b639c 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -4,6 +4,7 @@ #include #include "idtableproxymodel.hpp" +#include "idtable.hpp" CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelIndex& index, const QVariant& new_, QUndoCommand *parent) @@ -38,4 +39,37 @@ void CSMWorld::CreateCommand::redo() void CSMWorld::CreateCommand::undo() { mModel.removeRow (mModel.getModelIndex (mId, 0).row()); +} + +CSMWorld::RevertCommand::RevertCommand (IdTable& model, const std::string& id, QUndoCommand *parent) +: QUndoCommand (parent), mModel (model), mId (id), mOld (0) +{ + setText (("Revert record " + id).c_str()); + + mOld = model.getRecord (id).clone(); +} + +CSMWorld::RevertCommand::~RevertCommand() +{ + delete mOld; +} + +void CSMWorld::RevertCommand::redo() +{ + QModelIndex index = mModel.getModelIndex (mId, 1); + RecordBase::State state = static_cast (mModel.data (index).toInt()); + + if (state==RecordBase::State_ModifiedOnly) + { + mModel.removeRows (index.row(), 1); + } + else + { + mModel.setData (index, static_cast (RecordBase::State_BaseOnly)); + } +} + +void CSMWorld::RevertCommand::undo() +{ + mModel.setRecord (*mOld); } \ No newline at end of file diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index 50b9045c6..e916d05c9 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -15,6 +15,8 @@ class QAbstractItemModel; namespace CSMWorld { class IdTableProxyModel; + class IdTable; + class RecordBase; class ModifyCommand : public QUndoCommand { @@ -46,6 +48,27 @@ namespace CSMWorld virtual void undo(); }; + + class RevertCommand : public QUndoCommand + { + IdTable& mModel; + std::string mId; + RecordBase *mOld; + + // not implemented + RevertCommand (const RevertCommand&); + RevertCommand& operator= (const RevertCommand&); + + public: + + RevertCommand (IdTable& model, const std::string& id, QUndoCommand *parent = 0); + + virtual ~RevertCommand(); + + virtual void redo(); + + virtual void undo(); + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index e4bb31dbe..50afa715e 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -71,6 +71,25 @@ namespace CSMWorld virtual void removeRows (int index, int count) = 0; virtual void appendBlankRecord (const std::string& id) = 0; + + virtual int searchId (const std::string& id) const = 0; + ////< Search record with \a id. + /// \return index of record (if found) or -1 (not found) + + virtual void replace (int index, const RecordBase& record) = 0; + ///< If the record type does not match, an exception is thrown. + /// + /// \attention \a record must not change the ID. + + virtual void appendRecord (const RecordBase& record) = 0; + ///< If the record type does not match, an exception is thrown. + + virtual std::string getId (const RecordBase& record) const = 0; + ///< Return ID for \a record. + /// + /// \attention Throw san exception, if the type of \a record does not match. + + virtual const RecordBase& getRecord (const std::string& id) const = 0; }; ///< \brief Collection of ID-based records @@ -120,6 +139,25 @@ namespace CSMWorld virtual void appendBlankRecord (const std::string& id); + virtual int searchId (const std::string& id) const; + ////< Search record with \a id. + /// \return index of record (if found) or -1 (not found) + + virtual void replace (int index, const RecordBase& record); + ///< If the record type does not match, an exception is thrown. + /// + /// \attention \a record must not change the ID. + + virtual void appendRecord (const RecordBase& record); + ///< If the record type does not match, an exception is thrown. + + virtual std::string getId (const RecordBase& record) const; + ///< Return ID for \a record. + /// + /// \attention Throw san exception, if the type of \a record does not match. + + virtual const RecordBase& getRecord (const std::string& id) const; + void addColumn (Column *column); }; @@ -174,12 +212,12 @@ namespace CSMWorld template int IdCollection::getIndex (const std::string& id) const { - std::map::const_iterator iter = mIndex.find (id); + int index = searchId (id); - if (iter==mIndex.end()) + if (index==-1) throw std::runtime_error ("invalid ID: " + id); - return iter->second; + return index; } template @@ -268,6 +306,49 @@ namespace CSMWorld record.blank(); add (record); } + + template + int IdCollection::searchId (const std::string& id) const + { + std::string id2; + + std::transform (id.begin(), id.end(), std::back_inserter (id2), + (int(*)(int)) std::tolower); + + std::map::const_iterator iter = mIndex.find (id2); + + if (iter==mIndex.end()) + return -1; + + return iter->second; + } + + template + void IdCollection::replace (int index, const RecordBase& record) + { + mRecords.at (index) = dynamic_cast&> (record); + } + + template + void IdCollection::appendRecord (const RecordBase& record) + { + mRecords.push_back (dynamic_cast&> (record)); + mIndex.insert (std::make_pair (getId (record), mRecords.size()-1)); + } + + template + std::string IdCollection::getId (const RecordBase& record) const + { + const Record& record2 = dynamic_cast&> (record); + return (record2.isModified() ? record2.mModified : record2.mBase).mId; + } + + template + const RecordBase& IdCollection::getRecord (const std::string& id) const + { + int index = getIndex (id); + return mRecords.at (index); + } } #endif diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 50a6953d6..a2b0a3c1f 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -56,7 +56,10 @@ bool CSMWorld::IdTable::setData ( const QModelIndex &index, const QVariant &valu if (mIdCollection->isEditable (index.column()) && role==Qt::EditRole) { mIdCollection->setData (index.row(), index.column(), value); - emit dataChanged (index, index); + + emit dataChanged (CSMWorld::IdTable::index (index.row(), 0), + CSMWorld::IdTable::index (index.row(), mIdCollection->getColumns()-1)); + return true; } @@ -101,4 +104,31 @@ void CSMWorld::IdTable::addRecord (const std::string& id) QModelIndex CSMWorld::IdTable::getModelIndex (const std::string& id, int column) const { return index (mIdCollection->getIndex (id), column); +} + +void CSMWorld::IdTable::setRecord (const RecordBase& record) +{ + int index = mIdCollection->searchId (mIdCollection->getId (record)); + + if (index==-1) + { + int index = mIdCollection->getSize(); + + beginInsertRows (QModelIndex(), index, index); + + mIdCollection->appendRecord (record); + + endInsertRows(); + } + else + { + mIdCollection->replace (index, record); + emit dataChanged (CSMWorld::IdTable::index (index, 0), + CSMWorld::IdTable::index (index, mIdCollection->getColumns()-1)); + } +} + +const CSMWorld::RecordBase& CSMWorld::IdTable::getRecord (const std::string& id) const +{ + return mIdCollection->getRecord (id); } \ No newline at end of file diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index f95873c7a..deaebaa38 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -6,6 +6,7 @@ namespace CSMWorld { class IdCollectionBase; + class RecordBase; class IdTable : public QAbstractTableModel { @@ -41,6 +42,11 @@ namespace CSMWorld void addRecord (const std::string& id); QModelIndex getModelIndex (const std::string& id, int column) const; + + void setRecord (const RecordBase& record); + ///< Add record or overwrite existing recrod. + + const RecordBase& getRecord (const std::string& id) const; }; } diff --git a/apps/opencs/model/world/record.cpp b/apps/opencs/model/world/record.cpp new file mode 100644 index 000000000..229985a8a --- /dev/null +++ b/apps/opencs/model/world/record.cpp @@ -0,0 +1,21 @@ + +#include "record.hpp" + +CSMWorld::RecordBase::~RecordBase() {} + +bool CSMWorld::RecordBase::RecordBase::isDeleted() const +{ + return mState==State_Deleted || mState==State_Erased; +} + + +bool CSMWorld::RecordBase::RecordBase::isErased() const +{ + return mState==State_Erased; +} + + +bool CSMWorld::RecordBase::RecordBase::isModified() const +{ + return mState==State_Modified || mState==State_ModifiedOnly; +} \ No newline at end of file diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index df93501f3..3b83836ab 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -15,20 +15,27 @@ namespace CSMWorld State_Deleted = 3, // exists in base, but has been deleted State_Erased = 4 // does not exist at all (we mostly treat that the same way as deleted) }; - }; - template - struct Record : public RecordBase - { - ESXRecordT mBase; - ESXRecordT mModified; State mState; + virtual ~RecordBase(); + + virtual RecordBase *clone() const = 0; + bool isDeleted() const; bool isErased() const; bool isModified() const; + }; + + template + struct Record : public RecordBase + { + ESXRecordT mBase; + ESXRecordT mModified; + + virtual RecordBase *clone() const; const ESXRecordT& get() const; ///< Throws an exception, if the record is deleted. @@ -44,21 +51,9 @@ namespace CSMWorld }; template - bool Record::isDeleted() const - { - return mState==State_Deleted || mState==State_Erased; - } - - template - bool Record::isErased() const - { - return mState==State_Erased; - } - - template - bool Record::isModified() const + RecordBase *Record::clone() const { - return mState==State_Modified || mState==State_ModifiedOnly; + return new Record (*this); } template diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 4f20d9fd2..dafcb95c0 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -11,6 +11,8 @@ #include "../../model/world/data.hpp" #include "../../model/world/commands.hpp" #include "../../model/world/idtableproxymodel.hpp" +#include "../../model/world/idtable.hpp" +#include "../../model/world/record.hpp" namespace CSVWorld { @@ -108,11 +110,16 @@ void CSVWorld::CommandDelegate::setEditLock (bool locked) void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) { - QMenu menu (this); + QModelIndexList selectedRows = selectionModel()->selectedRows(); + + QMenu menu (this); if (mCreateAction) menu.addAction (mCreateAction); + if (selectedRows.size()>0) + menu.addAction (mRevertAction); + menu.exec (event->globalPos()); } @@ -120,9 +127,9 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q bool createAndDelete) : mUndoStack (undoStack), mCreateAction (0) { - QAbstractTableModel *model = data.getTableModel (id); + mModel = &dynamic_cast (*data.getTableModel (id)); - int columns = model->columnCount(); + int columns = mModel->columnCount(); for (int i=0; isetSourceModel (model); + mProxyModel = new CSMWorld::IdTableProxyModel (this); + mProxyModel->setSourceModel (mModel); - setModel (mModel); + setModel (mProxyModel); horizontalHeader()->setResizeMode (QHeaderView::Interactive); verticalHeader()->hide(); setSortingEnabled (true); @@ -149,6 +156,10 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q connect (mCreateAction, SIGNAL (triggered()), this, SLOT (createRecord())); addAction (mCreateAction); } + + mRevertAction = new QAction (tr ("Revert Record"), this); + connect (mRevertAction, SIGNAL (triggered()), this, SLOT (revertRecord())); + addAction (mRevertAction); } void CSVWorld::Table::setEditLock (bool locked) @@ -166,5 +177,35 @@ void CSVWorld::Table::createRecord() std::ostringstream stream; stream << "id" << index++; - mUndoStack.push (new CSMWorld::CreateCommand (*mModel, stream.str())); + mUndoStack.push (new CSMWorld::CreateCommand (*mProxyModel, stream.str())); +} + +void CSVWorld::Table::revertRecord() +{ + QModelIndexList selectedRows = selectionModel()->selectedRows(); + + std::vector revertableIds; + + for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter) + { + std::string id = mProxyModel->data (*iter).toString().toStdString(); + + CSMWorld::RecordBase::State state = + static_cast (mModel->data (mModel->getModelIndex (id, 1)).toInt()); + + if (state!=CSMWorld::RecordBase::State_BaseOnly) + revertableIds.push_back (id); + } + + if (revertableIds.size()>0) + { + if (revertableIds.size()>1) + mUndoStack.beginMacro (tr ("Revert multiple records")); + + for (std::vector::const_iterator iter (revertableIds.begin()); iter!=revertableIds.end(); ++iter) + mUndoStack.push (new CSMWorld::RevertCommand (*mModel, *iter)); + + if (revertableIds.size()>1) + mUndoStack.endMacro(); + } } \ No newline at end of file diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index f07f3ff24..022d4f12a 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -13,6 +13,7 @@ namespace CSMWorld class Data; class UniversalId; class IdTableProxyModel; + class IdTable; } namespace CSVWorld @@ -27,7 +28,9 @@ namespace CSVWorld std::vector mDelegates; QUndoStack& mUndoStack; QAction *mCreateAction; - CSMWorld::IdTableProxyModel *mModel; + QAction *mRevertAction; + CSMWorld::IdTableProxyModel *mProxyModel; + CSMWorld::IdTable *mModel; private: @@ -43,6 +46,8 @@ namespace CSVWorld private slots: void createRecord(); + + void revertRecord(); }; } From c12ee129f7019f5664f3a25b28e8f8961b5121bb Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 6 Dec 2012 15:18:41 +0100 Subject: [PATCH 036/136] added delete command --- apps/opencs/model/world/commands.cpp | 33 +++++++++++++++++++++++++ apps/opencs/model/world/commands.hpp | 21 ++++++++++++++++ apps/opencs/model/world/record.hpp | 6 ++--- apps/opencs/view/world/table.cpp | 37 ++++++++++++++++++++++++++++ apps/opencs/view/world/table.hpp | 3 +++ 5 files changed, 97 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index 96a1b639c..e22ecf992 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -70,6 +70,39 @@ void CSMWorld::RevertCommand::redo() } void CSMWorld::RevertCommand::undo() +{ + mModel.setRecord (*mOld); +} + +CSMWorld::DeleteCommand::DeleteCommand (IdTable& model, const std::string& id, QUndoCommand *parent) +: QUndoCommand (parent), mModel (model), mId (id), mOld (0) +{ + setText (("Delete record " + id).c_str()); + + mOld = model.getRecord (id).clone(); +} + +CSMWorld::DeleteCommand::~DeleteCommand() +{ + delete mOld; +} + +void CSMWorld::DeleteCommand::redo() +{ + QModelIndex index = mModel.getModelIndex (mId, 1); + RecordBase::State state = static_cast (mModel.data (index).toInt()); + + if (state==RecordBase::State_ModifiedOnly) + { + mModel.removeRows (index.row(), 1); + } + else + { + mModel.setData (index, static_cast (RecordBase::State_Deleted)); + } +} + +void CSMWorld::DeleteCommand::undo() { mModel.setRecord (*mOld); } \ No newline at end of file diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index e916d05c9..af419215d 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -69,6 +69,27 @@ namespace CSMWorld virtual void undo(); }; + + class DeleteCommand : public QUndoCommand + { + IdTable& mModel; + std::string mId; + RecordBase *mOld; + + // not implemented + DeleteCommand (const DeleteCommand&); + DeleteCommand& operator= (const DeleteCommand&); + + public: + + DeleteCommand (IdTable& model, const std::string& id, QUndoCommand *parent = 0); + + virtual ~DeleteCommand(); + + virtual void redo(); + + virtual void undo(); + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index 3b83836ab..53bb7ea2c 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -59,7 +59,7 @@ namespace CSMWorld template const ESXRecordT& Record::get() const { - if (isDeleted()) + if (mState==State_Erased) throw std::logic_error ("attempt to access a deleted record"); return mState==State_BaseOnly ? mBase : mModified; @@ -68,7 +68,7 @@ namespace CSMWorld template const ESXRecordT& Record::getBase() const { - if (isDeleted()) + if (mState==State_Erased) throw std::logic_error ("attempt to access a deleted record"); return mState==State_ModifiedOnly ? mModified : mBase; @@ -77,7 +77,7 @@ namespace CSMWorld template void Record::setModified (const ESXRecordT& modified) { - if (isDeleted()) + if (mState==State_Erased) throw std::logic_error ("attempt to modify a deleted record"); mModified = modified; diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index dafcb95c0..1595b6926 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -120,6 +120,9 @@ void CSVWorld::CommandDelegate::setEditLock (bool locked) if (selectedRows.size()>0) menu.addAction (mRevertAction); + if (selectedRows.size()>0) + menu.addAction (mDeleteAction); + menu.exec (event->globalPos()); } @@ -160,6 +163,10 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q mRevertAction = new QAction (tr ("Revert Record"), this); connect (mRevertAction, SIGNAL (triggered()), this, SLOT (revertRecord())); addAction (mRevertAction); + + mDeleteAction = new QAction (tr ("Delete Record"), this); + connect (mDeleteAction, SIGNAL (triggered()), this, SLOT (deleteRecord())); + addAction (mDeleteAction); } void CSVWorld::Table::setEditLock (bool locked) @@ -205,6 +212,36 @@ void CSVWorld::Table::revertRecord() for (std::vector::const_iterator iter (revertableIds.begin()); iter!=revertableIds.end(); ++iter) mUndoStack.push (new CSMWorld::RevertCommand (*mModel, *iter)); + if (revertableIds.size()>1) + mUndoStack.endMacro(); + } +} + +void CSVWorld::Table::deleteRecord() +{ + QModelIndexList selectedRows = selectionModel()->selectedRows(); + + std::vector revertableIds; + + for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter) + { + std::string id = mProxyModel->data (*iter).toString().toStdString(); + + CSMWorld::RecordBase::State state = + static_cast (mModel->data (mModel->getModelIndex (id, 1)).toInt()); + + if (state!=CSMWorld::RecordBase::State_Deleted) + revertableIds.push_back (id); + } + + if (revertableIds.size()>0) + { + if (revertableIds.size()>1) + mUndoStack.beginMacro (tr ("Delete multiple records")); + + for (std::vector::const_iterator iter (revertableIds.begin()); iter!=revertableIds.end(); ++iter) + mUndoStack.push (new CSMWorld::DeleteCommand (*mModel, *iter)); + if (revertableIds.size()>1) mUndoStack.endMacro(); } diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 022d4f12a..555dc8e1f 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -29,6 +29,7 @@ namespace CSVWorld QUndoStack& mUndoStack; QAction *mCreateAction; QAction *mRevertAction; + QAction *mDeleteAction; CSMWorld::IdTableProxyModel *mProxyModel; CSMWorld::IdTable *mModel; @@ -48,6 +49,8 @@ namespace CSVWorld void createRecord(); void revertRecord(); + + void deleteRecord(); }; } From 2b53cf6547f9611be8e4c6508865437a331f373c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 6 Dec 2012 15:25:31 +0100 Subject: [PATCH 037/136] do not list actions in the pop up menu that do not apply to any of the selected records --- apps/opencs/view/world/table.cpp | 85 ++++++++++++++++++-------------- apps/opencs/view/world/table.hpp | 5 ++ 2 files changed, 54 insertions(+), 36 deletions(-) diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 1595b6926..31f7d22ed 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -107,8 +107,7 @@ void CSVWorld::CommandDelegate::setEditLock (bool locked) mEditLock = locked; } - - void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) +void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) { QModelIndexList selectedRows = selectionModel()->selectedRows(); @@ -117,15 +116,55 @@ void CSVWorld::CommandDelegate::setEditLock (bool locked) if (mCreateAction) menu.addAction (mCreateAction); - if (selectedRows.size()>0) + if (listRevertableSelectedIds().size()>0) menu.addAction (mRevertAction); - if (selectedRows.size()>0) + if (listDeletableSelectedIds().size()>0) menu.addAction (mDeleteAction); menu.exec (event->globalPos()); } +std::vector CSVWorld::Table::listRevertableSelectedIds() const +{ + QModelIndexList selectedRows = selectionModel()->selectedRows(); + + std::vector revertableIds; + + for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter) + { + std::string id = mProxyModel->data (*iter).toString().toStdString(); + + CSMWorld::RecordBase::State state = + static_cast (mModel->data (mModel->getModelIndex (id, 1)).toInt()); + + if (state!=CSMWorld::RecordBase::State_BaseOnly) + revertableIds.push_back (id); + } + + return revertableIds; +} + +std::vector CSVWorld::Table::listDeletableSelectedIds() const +{ + QModelIndexList selectedRows = selectionModel()->selectedRows(); + + std::vector deletableIds; + + for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter) + { + std::string id = mProxyModel->data (*iter).toString().toStdString(); + + CSMWorld::RecordBase::State state = + static_cast (mModel->data (mModel->getModelIndex (id, 1)).toInt()); + + if (state!=CSMWorld::RecordBase::State_Deleted) + deletableIds.push_back (id); + } + + return deletableIds; +} + CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, bool createAndDelete) : mUndoStack (undoStack), mCreateAction (0) @@ -189,20 +228,7 @@ void CSVWorld::Table::createRecord() void CSVWorld::Table::revertRecord() { - QModelIndexList selectedRows = selectionModel()->selectedRows(); - - std::vector revertableIds; - - for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter) - { - std::string id = mProxyModel->data (*iter).toString().toStdString(); - - CSMWorld::RecordBase::State state = - static_cast (mModel->data (mModel->getModelIndex (id, 1)).toInt()); - - if (state!=CSMWorld::RecordBase::State_BaseOnly) - revertableIds.push_back (id); - } + std::vector revertableIds = listRevertableSelectedIds(); if (revertableIds.size()>0) { @@ -219,30 +245,17 @@ void CSVWorld::Table::revertRecord() void CSVWorld::Table::deleteRecord() { - QModelIndexList selectedRows = selectionModel()->selectedRows(); + std::vector deletableIds = listDeletableSelectedIds(); - std::vector revertableIds; - - for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter) - { - std::string id = mProxyModel->data (*iter).toString().toStdString(); - - CSMWorld::RecordBase::State state = - static_cast (mModel->data (mModel->getModelIndex (id, 1)).toInt()); - - if (state!=CSMWorld::RecordBase::State_Deleted) - revertableIds.push_back (id); - } - - if (revertableIds.size()>0) + if (deletableIds.size()>0) { - if (revertableIds.size()>1) + if (deletableIds.size()>1) mUndoStack.beginMacro (tr ("Delete multiple records")); - for (std::vector::const_iterator iter (revertableIds.begin()); iter!=revertableIds.end(); ++iter) + for (std::vector::const_iterator iter (deletableIds.begin()); iter!=deletableIds.end(); ++iter) mUndoStack.push (new CSMWorld::DeleteCommand (*mModel, *iter)); - if (revertableIds.size()>1) + if (deletableIds.size()>1) mUndoStack.endMacro(); } } \ No newline at end of file diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 555dc8e1f..264d2bc5c 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -2,6 +2,7 @@ #define CSV_WORLD_TABLE_H #include +#include #include @@ -37,6 +38,10 @@ namespace CSVWorld void contextMenuEvent (QContextMenuEvent *event); + std::vector listRevertableSelectedIds() const; + + std::vector listDeletableSelectedIds() const; + public: Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, bool createAndDelete); From fdc7e93835defe57d5fca0e47515ec3aba01fda6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 8 Dec 2012 11:59:13 +0100 Subject: [PATCH 038/136] preliminary multi-threaded verify implementation (does not actually perfom any document verification yet) --- apps/opencs/CMakeLists.txt | 4 +++ apps/opencs/model/doc/document.cpp | 42 ++++++++++++------------- apps/opencs/model/doc/document.hpp | 11 +++++-- apps/opencs/model/tools/tools.cpp | 46 ++++++++++++++++++++++++++++ apps/opencs/model/tools/tools.hpp | 45 +++++++++++++++++++++++++++ apps/opencs/model/tools/verifier.cpp | 33 ++++++++++++++++++++ apps/opencs/model/tools/verifier.hpp | 33 ++++++++++++++++++++ 7 files changed, 189 insertions(+), 25 deletions(-) create mode 100644 apps/opencs/model/tools/tools.cpp create mode 100644 apps/opencs/model/tools/tools.hpp create mode 100644 apps/opencs/model/tools/verifier.cpp create mode 100644 apps/opencs/model/tools/verifier.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 5a9e1e99c..ca235042a 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -7,6 +7,8 @@ set (OPENCS_SRC model/world/universalid.cpp model/world/idcollection.cpp model/world/data.cpp model/world/idtable.cpp model/world/commands.cpp model/world/idtableproxymodel.cpp model/world/record.cpp + model/tools/tools.cpp model/tools/verifier.cpp + view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp view/world/subview.cpp view/world/table.cpp view/world/tablesubview.cpp @@ -21,6 +23,8 @@ set (OPENCS_HDR model/world/idtable.hpp model/world/columns.hpp model/world/idtableproxymodel.hpp model/world/commands.hpp + model/tools/tools.hpp model/tools/verifier.hpp + view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp view/world/subview.hpp view/world/table.hpp view/world/tablesubview.hpp diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index e8091b3e0..f85fde038 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -7,13 +7,16 @@ CSMDoc::Document::Document (const std::string& name) connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool))); + connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int))); + connect (&mTools, SIGNAL (done (int)), this, SLOT (operationDone (int))); + // dummy implementation -> remove when proper save is implemented. mSaveCount = 0; connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving())); // dummy implementation -> remove when proper verify is implemented. mVerifyCount = 0; - connect (&mVerifyTimer, SIGNAL(timeout()), this, SLOT (verifying())); + } QUndoStack& CSMDoc::Document::getUndoStack() @@ -53,23 +56,19 @@ void CSMDoc::Document::save() void CSMDoc::Document::verify() { mVerifyCount = 1; - mVerifyTimer.start (500); emit stateChanged (getState(), this); - emit progress (1, 20, State_Verifying, 1, this); + mTools.runVerifier(); } void CSMDoc::Document::abortOperation (int type) { + mTools.abortOperation (type); + if (type==State_Saving) { mSaveTimer.stop(); emit stateChanged (getState(), this); } - else if (type==State_Verifying) - { - mVerifyTimer.stop(); - emit stateChanged (getState(), this); - } } void CSMDoc::Document::modificationStateChanged (bool clean) @@ -77,6 +76,14 @@ void CSMDoc::Document::modificationStateChanged (bool clean) emit stateChanged (getState(), this); } +void CSMDoc::Document::operationDone (int type) +{ + if (type==State_Verifying) + mVerifyCount = 0; + + emit stateChanged (getState(), this); +} + void CSMDoc::Document::saving() { ++mSaveCount; @@ -92,20 +99,6 @@ void CSMDoc::Document::saving() } } -void CSMDoc::Document::verifying() -{ - ++mVerifyCount; - - emit progress (mVerifyCount, 20, State_Verifying, 1, this); - - if (mVerifyCount>19) - { - mVerifyCount = 0; - mVerifyTimer.stop(); - emit stateChanged (getState(), this); - } -} - const CSMWorld::Data& CSMDoc::Document::getData() const { return mData; @@ -114,4 +107,9 @@ const CSMWorld::Data& CSMDoc::Document::getData() const CSMWorld::Data& CSMDoc::Document::getData() { return mData; +} + +void CSMDoc::Document::progress (int current, int max, int type) +{ + emit progress (current, max, type, 1, this); } \ No newline at end of file diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index b414bf04d..3fe20bc80 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -9,6 +9,8 @@ #include "../world/data.hpp" +#include "../tools/tools.hpp" + namespace CSMDoc { class Document : public QObject @@ -32,12 +34,12 @@ namespace CSMDoc std::string mName; ///< \todo replace name with ESX list QUndoStack mUndoStack; CSMWorld::Data mData; + CSMTools::Tools mTools; int mSaveCount; ///< dummy implementation -> remove when proper save is implemented. QTimer mSaveTimer; ///< dummy implementation -> remove when proper save is implemented. int mVerifyCount; ///< dummy implementation -> remove when proper verify is implemented. - QTimer mVerifyTimer; ///< dummy implementation -> remove when proper verify is implemented. // not implemented Document (const Document&); @@ -75,11 +77,14 @@ namespace CSMDoc void modificationStateChanged (bool clean); + void operationDone (int type); + void saving(); ///< dummy implementation -> remove when proper save is implemented. - void verifying(); - ///< dummy implementation -> remove when proper verify is implemented. + public slots: + + void progress (int current, int max, int type); }; } diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp new file mode 100644 index 000000000..941a22cff --- /dev/null +++ b/apps/opencs/model/tools/tools.cpp @@ -0,0 +1,46 @@ + +#include "tools.hpp" + +#include + +#include "verifier.hpp" + +#include "../doc/document.hpp" + +CSMTools::Verifier *CSMTools::Tools::getVerifier() +{ + if (!mVerifier) + { + mVerifier = new Verifier; + + connect (mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); + connect (mVerifier, SIGNAL (finished()), this, SLOT (verifierDone())); + } + + return mVerifier; +} + +CSMTools::Tools::Tools() : mVerifier (0) +{ + +} + +CSMTools::Tools::~Tools() +{ + delete mVerifier; +} + +void CSMTools::Tools::runVerifier() +{ + getVerifier()->start(); +} + +void CSMTools::Tools::abortOperation (int type) +{ + +} + +void CSMTools::Tools::verifierDone() +{ + emit done (CSMDoc::Document::State_Verifying); +} \ No newline at end of file diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp new file mode 100644 index 000000000..65b1d1684 --- /dev/null +++ b/apps/opencs/model/tools/tools.hpp @@ -0,0 +1,45 @@ +#ifndef CSM_TOOLS_TOOLS_H +#define CSM_TOOLS_TOOLS_H + +#include + +namespace CSMTools +{ + class Verifier; + + class Tools : public QObject + { + Q_OBJECT + + Verifier *mVerifier; + + // not implemented + Tools (const Tools&); + Tools& operator= (const Tools&); + + Verifier *getVerifier(); + + public: + + Tools(); + + virtual ~Tools(); + + void runVerifier(); + + void abortOperation (int type); + ///< \attention The operation is not aborted immediately. + + private slots: + + void verifierDone(); + + signals: + + void progress (int current, int max, int type); + + void done (int type); + }; +} + +#endif diff --git a/apps/opencs/model/tools/verifier.cpp b/apps/opencs/model/tools/verifier.cpp new file mode 100644 index 000000000..43a864289 --- /dev/null +++ b/apps/opencs/model/tools/verifier.cpp @@ -0,0 +1,33 @@ + +#include "verifier.hpp" + +#include + +#include "../doc/document.hpp" + +void CSMTools::Verifier::run() +{ + mStep = 0; + + QTimer timer; + + timer.connect (&timer, SIGNAL (timeout()), this, SLOT (verify())); + + timer.start (0); + + exec(); +} + +void CSMTools::Verifier::abort() +{ + exit(); +} + +void CSMTools::Verifier::verify() +{ + ++mStep; + emit progress (mStep, 1000, CSMDoc::Document::State_Verifying); + + if (mStep>=1000) + exit(); +} \ No newline at end of file diff --git a/apps/opencs/model/tools/verifier.hpp b/apps/opencs/model/tools/verifier.hpp new file mode 100644 index 000000000..0e7fae19c --- /dev/null +++ b/apps/opencs/model/tools/verifier.hpp @@ -0,0 +1,33 @@ +#ifndef CSM_TOOLS_VERIFIER_H +#define CSM_TOOLS_VERIFIER_H + +#include + +namespace CSMTools +{ + class Verifier : public QThread + { + Q_OBJECT + + int mStep; + + public: + + virtual void run(); + + signals: + + void progress (int current, int max, int type); + + public slots: + + void abort(); + + private slots: + + void verify(); + }; + +} + +#endif From a2b4f431760d0fcae95c1774ae7f6913acb1b0af Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 8 Dec 2012 14:44:03 +0100 Subject: [PATCH 039/136] moved document state enum to a separate file --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/doc/document.cpp | 5 ++--- apps/opencs/model/doc/document.hpp | 14 ++------------ apps/opencs/model/doc/state.hpp | 19 +++++++++++++++++++ apps/opencs/model/tools/tools.cpp | 4 ++-- apps/opencs/model/tools/verifier.cpp | 4 ++-- apps/opencs/view/doc/operation.cpp | 4 ++-- apps/opencs/view/doc/view.cpp | 12 ++++++------ 8 files changed, 36 insertions(+), 28 deletions(-) create mode 100644 apps/opencs/model/doc/state.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index ca235042a..ce83e4ea6 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -17,7 +17,7 @@ set (OPENCS_SRC set (OPENCS_HDR editor.hpp - model/doc/documentmanager.hpp model/doc/document.hpp + model/doc/documentmanager.hpp model/doc/document.hpp model/doc/state.hpp model/world/universalid.hpp model/world/record.hpp model/world/idcollection.hpp model/world/data.hpp model/world/idtable.hpp model/world/columns.hpp model/world/idtableproxymodel.hpp diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index f85fde038..2bd0f2e3e 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -16,7 +16,6 @@ CSMDoc::Document::Document (const std::string& name) // dummy implementation -> remove when proper verify is implemented. mVerifyCount = 0; - } QUndoStack& CSMDoc::Document::getUndoStack() @@ -32,10 +31,10 @@ int CSMDoc::Document::getState() const state |= State_Modified; if (mSaveCount) - state |= State_Locked | State_Saving; + state |= State_Locked | State_Saving | State_Operation; if (mVerifyCount) - state |= State_Locked | State_Verifying; + state |= State_Locked | State_Verifying | State_Operation; return state; } diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 3fe20bc80..6226e3165 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -11,24 +11,14 @@ #include "../tools/tools.hpp" +#include "state.hpp" + namespace CSMDoc { class Document : public QObject { Q_OBJECT - public: - - enum State - { - State_Modified = 1, - State_Locked = 2, - State_Saving = 4, - State_Verifying = 8, - State_Compiling = 16, // not implemented yet - State_Searching = 32 // not implemented yet - }; - private: std::string mName; ///< \todo replace name with ESX list diff --git a/apps/opencs/model/doc/state.hpp b/apps/opencs/model/doc/state.hpp new file mode 100644 index 000000000..04e6fae89 --- /dev/null +++ b/apps/opencs/model/doc/state.hpp @@ -0,0 +1,19 @@ +#ifndef CSM_DOC_STATE_H +#define CSM_DOC_STATE_H + +namespace CSMDoc +{ + enum State + { + State_Modified = 1, + State_Locked = 2, + State_Operation = 4, + + State_Saving = 8, + State_Verifying = 16, + State_Compiling = 32, // not implemented yet + State_Searching = 64 // not implemented yet + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 941a22cff..95375332c 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -5,7 +5,7 @@ #include "verifier.hpp" -#include "../doc/document.hpp" +#include "../doc/state.hpp" CSMTools::Verifier *CSMTools::Tools::getVerifier() { @@ -42,5 +42,5 @@ void CSMTools::Tools::abortOperation (int type) void CSMTools::Tools::verifierDone() { - emit done (CSMDoc::Document::State_Verifying); + emit done (CSMDoc::State_Verifying); } \ No newline at end of file diff --git a/apps/opencs/model/tools/verifier.cpp b/apps/opencs/model/tools/verifier.cpp index 43a864289..14cb692e9 100644 --- a/apps/opencs/model/tools/verifier.cpp +++ b/apps/opencs/model/tools/verifier.cpp @@ -3,7 +3,7 @@ #include -#include "../doc/document.hpp" +#include "../doc/state.hpp" void CSMTools::Verifier::run() { @@ -26,7 +26,7 @@ void CSMTools::Verifier::abort() void CSMTools::Verifier::verify() { ++mStep; - emit progress (mStep, 1000, CSMDoc::Document::State_Verifying); + emit progress (mStep, 1000, CSMDoc::State_Verifying); if (mStep>=1000) exit(); diff --git a/apps/opencs/view/doc/operation.cpp b/apps/opencs/view/doc/operation.cpp index 62f006be5..3f415da03 100644 --- a/apps/opencs/view/doc/operation.cpp +++ b/apps/opencs/view/doc/operation.cpp @@ -13,8 +13,8 @@ void CSVDoc::Operation::updateLabel (int threads) switch (mType) { - case CSMDoc::Document::State_Saving: name = "saving"; break; - case CSMDoc::Document::State_Verifying: name = "verifying"; break; + case CSMDoc::State_Saving: name = "saving"; break; + case CSMDoc::State_Verifying: name = "verifying"; break; } std::ostringstream stream; diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 65ec103a2..539b149cb 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -83,7 +83,7 @@ void CSVDoc::View::updateTitle() stream << mDocument->getName(); - if (mDocument->getState() & CSMDoc::Document::State_Modified) + if (mDocument->getState() & CSMDoc::State_Modified) stream << " *"; if (mViewTotal>1) @@ -94,7 +94,7 @@ void CSVDoc::View::updateTitle() void CSVDoc::View::updateActions() { - bool editing = !(mDocument->getState() & CSMDoc::Document::State_Locked); + bool editing = !(mDocument->getState() & CSMDoc::State_Locked); for (std::vector::iterator iter (mEditingActions.begin()); iter!=mEditingActions.end(); ++iter) (*iter)->setEnabled (editing); @@ -102,8 +102,8 @@ void CSVDoc::View::updateActions() mUndo->setEnabled (editing & mDocument->getUndoStack().canUndo()); mRedo->setEnabled (editing & mDocument->getUndoStack().canRedo()); - mSave->setEnabled (!(mDocument->getState() & CSMDoc::Document::State_Saving)); - mVerify->setEnabled (!(mDocument->getState() & CSMDoc::Document::State_Verifying)); + mSave->setEnabled (!(mDocument->getState() & CSMDoc::State_Saving)); + mVerify->setEnabled (!(mDocument->getState() & CSMDoc::State_Verifying)); } CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) @@ -155,7 +155,7 @@ void CSVDoc::View::updateDocumentState() static const int operations[] = { - CSMDoc::Document::State_Saving, CSMDoc::Document::State_Verifying, + CSMDoc::State_Saving, CSMDoc::State_Verifying, -1 // end marker }; @@ -168,7 +168,7 @@ void CSVDoc::View::updateDocumentState() QList subViews = findChildren(); for (QList::iterator iter (subViews.begin()); iter!=subViews.end(); ++iter) - (*iter)->setEditLock (state & CSMDoc::Document::State_Locked); + (*iter)->setEditLock (state & CSMDoc::State_Locked); } void CSVDoc::View::updateProgress (int current, int max, int type, int threads) From af9b48f4d333839a66b96cf23e9faa62cbfaa7c8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 8 Dec 2012 15:25:50 +0100 Subject: [PATCH 040/136] added operations base class --- apps/opencs/CMakeLists.txt | 4 +-- apps/opencs/model/tools/operation.cpp | 35 +++++++++++++++++++++++++++ apps/opencs/model/tools/operation.hpp | 35 +++++++++++++++++++++++++++ apps/opencs/model/tools/verifier.cpp | 30 ++--------------------- apps/opencs/model/tools/verifier.hpp | 22 +++-------------- 5 files changed, 77 insertions(+), 49 deletions(-) create mode 100644 apps/opencs/model/tools/operation.cpp create mode 100644 apps/opencs/model/tools/operation.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index ce83e4ea6..d2b87be51 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -7,7 +7,7 @@ set (OPENCS_SRC model/world/universalid.cpp model/world/idcollection.cpp model/world/data.cpp model/world/idtable.cpp model/world/commands.cpp model/world/idtableproxymodel.cpp model/world/record.cpp - model/tools/tools.cpp model/tools/verifier.cpp + model/tools/tools.cpp model/tools/operation.cpp model/tools/verifier.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp @@ -23,7 +23,7 @@ set (OPENCS_HDR model/world/idtable.hpp model/world/columns.hpp model/world/idtableproxymodel.hpp model/world/commands.hpp - model/tools/tools.hpp model/tools/verifier.hpp + model/tools/tools.hpp model/tools/operation.hpp model/tools/verifier.hpp view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp diff --git a/apps/opencs/model/tools/operation.cpp b/apps/opencs/model/tools/operation.cpp new file mode 100644 index 000000000..ba5866168 --- /dev/null +++ b/apps/opencs/model/tools/operation.cpp @@ -0,0 +1,35 @@ + +#include "operation.hpp" + +#include + +#include "../doc/state.hpp" + +CSMTools::Operation::Operation (int type) : mType (type) {} + +void CSMTools::Operation::run() +{ + mStep = 0; + + QTimer timer; + + timer.connect (&timer, SIGNAL (timeout()), this, SLOT (verify())); + + timer.start (0); + + exec(); +} + +void CSMTools::Operation::abort() +{ + exit(); +} + +void CSMTools::Operation::verify() +{ + ++mStep; + emit progress (mStep, 1000, mType); + + if (mStep>=1000) + exit(); +} \ No newline at end of file diff --git a/apps/opencs/model/tools/operation.hpp b/apps/opencs/model/tools/operation.hpp new file mode 100644 index 000000000..b75e2898f --- /dev/null +++ b/apps/opencs/model/tools/operation.hpp @@ -0,0 +1,35 @@ +#ifndef CSM_TOOLS_OPERATION_H +#define CSM_TOOLS_OPERATION_H + +#include + +namespace CSMTools +{ + class Operation : public QThread + { + Q_OBJECT + + int mType; + int mStep; + + public: + + Operation (int type); + + virtual void run(); + + signals: + + void progress (int current, int max, int type); + + public slots: + + void abort(); + + private slots: + + void verify(); + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/model/tools/verifier.cpp b/apps/opencs/model/tools/verifier.cpp index 14cb692e9..9c00d4ea7 100644 --- a/apps/opencs/model/tools/verifier.cpp +++ b/apps/opencs/model/tools/verifier.cpp @@ -1,33 +1,7 @@ #include "verifier.hpp" -#include - #include "../doc/state.hpp" -void CSMTools::Verifier::run() -{ - mStep = 0; - - QTimer timer; - - timer.connect (&timer, SIGNAL (timeout()), this, SLOT (verify())); - - timer.start (0); - - exec(); -} - -void CSMTools::Verifier::abort() -{ - exit(); -} - -void CSMTools::Verifier::verify() -{ - ++mStep; - emit progress (mStep, 1000, CSMDoc::State_Verifying); - - if (mStep>=1000) - exit(); -} \ No newline at end of file +CSMTools::Verifier::Verifier() : Operation (CSMDoc::State_Verifying) +{} diff --git a/apps/opencs/model/tools/verifier.hpp b/apps/opencs/model/tools/verifier.hpp index 0e7fae19c..054f87169 100644 --- a/apps/opencs/model/tools/verifier.hpp +++ b/apps/opencs/model/tools/verifier.hpp @@ -1,33 +1,17 @@ #ifndef CSM_TOOLS_VERIFIER_H #define CSM_TOOLS_VERIFIER_H -#include +#include "operation.hpp" namespace CSMTools { - class Verifier : public QThread + class Verifier : public Operation { - Q_OBJECT - - int mStep; - public: - virtual void run(); - - signals: - - void progress (int current, int max, int type); + Verifier(); - public slots: - - void abort(); - - private slots: - - void verify(); }; - } #endif From 8b7f342641b38c740cb78bc0f137b22f2f94ba6e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 8 Dec 2012 17:00:58 +0100 Subject: [PATCH 041/136] removed last remains of old verify implementation --- apps/opencs/model/doc/document.cpp | 13 +++--------- apps/opencs/model/doc/document.hpp | 2 -- apps/opencs/model/tools/tools.cpp | 34 ++++++++++++++++++++++++++++++ apps/opencs/model/tools/tools.hpp | 9 ++++++++ 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 2bd0f2e3e..d8ad5ff01 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -13,9 +13,6 @@ CSMDoc::Document::Document (const std::string& name) // dummy implementation -> remove when proper save is implemented. mSaveCount = 0; connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving())); - - // dummy implementation -> remove when proper verify is implemented. - mVerifyCount = 0; } QUndoStack& CSMDoc::Document::getUndoStack() @@ -33,8 +30,8 @@ int CSMDoc::Document::getState() const if (mSaveCount) state |= State_Locked | State_Saving | State_Operation; - if (mVerifyCount) - state |= State_Locked | State_Verifying | State_Operation; + if (int operations = mTools.getRunningOperations()) + state |= State_Locked | State_Operation | operations; return state; } @@ -54,9 +51,8 @@ void CSMDoc::Document::save() void CSMDoc::Document::verify() { - mVerifyCount = 1; - emit stateChanged (getState(), this); mTools.runVerifier(); + emit stateChanged (getState(), this); } void CSMDoc::Document::abortOperation (int type) @@ -77,9 +73,6 @@ void CSMDoc::Document::modificationStateChanged (bool clean) void CSMDoc::Document::operationDone (int type) { - if (type==State_Verifying) - mVerifyCount = 0; - emit stateChanged (getState(), this); } diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 6226e3165..40f8c0ea1 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -29,8 +29,6 @@ namespace CSMDoc int mSaveCount; ///< dummy implementation -> remove when proper save is implemented. QTimer mSaveTimer; ///< dummy implementation -> remove when proper save is implemented. - int mVerifyCount; ///< dummy implementation -> remove when proper verify is implemented. - // not implemented Document (const Document&); Document& operator= (const Document&); diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 95375332c..608244a3c 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -7,6 +7,21 @@ #include "../doc/state.hpp" +CSMTools::Operation *CSMTools::Tools::get (int type) +{ + switch (type) + { + case CSMDoc::State_Verifying: return mVerifier; + } + + return 0; +} + +const CSMTools::Operation *CSMTools::Tools::get (int type) const +{ + return const_cast (this)->get (type); +} + CSMTools::Verifier *CSMTools::Tools::getVerifier() { if (!mVerifier) @@ -37,7 +52,26 @@ void CSMTools::Tools::runVerifier() void CSMTools::Tools::abortOperation (int type) { + if (Operation *operation = get (type)) + operation->abort(); +} + +int CSMTools::Tools::getRunningOperations() const +{ + static const int sOperations[] = + { + CSMDoc::State_Verifying, + -1 + }; + + int result = 0; + + for (int i=0; sOperations[i]!=-1; ++i) + if (const Operation *operation = get (sOperations[i])) + if (operation->isRunning()) + result |= sOperations[i]; + return result; } void CSMTools::Tools::verifierDone() diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index 65b1d1684..ab1863738 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -6,6 +6,7 @@ namespace CSMTools { class Verifier; + class Operation; class Tools : public QObject { @@ -19,6 +20,12 @@ namespace CSMTools Verifier *getVerifier(); + Operation *get (int type); + ///< Returns a 0-pointer, if operation hasn't been used yet. + + const Operation *get (int type) const; + ///< Returns a 0-pointer, if operation hasn't been used yet. + public: Tools(); @@ -30,6 +37,8 @@ namespace CSMTools void abortOperation (int type); ///< \attention The operation is not aborted immediately. + int getRunningOperations() const; + private slots: void verifierDone(); From 6c18be39f0e10b43163de194fe93d0714df40eef Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 8 Dec 2012 17:53:45 +0100 Subject: [PATCH 042/136] added stage class --- apps/opencs/CMakeLists.txt | 4 +-- apps/opencs/model/tools/operation.cpp | 49 ++++++++++++++++++++++++--- apps/opencs/model/tools/operation.hpp | 19 ++++++++++- apps/opencs/model/tools/stage.cpp | 4 +++ apps/opencs/model/tools/stage.hpp | 20 +++++++++++ 5 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 apps/opencs/model/tools/stage.cpp create mode 100644 apps/opencs/model/tools/stage.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index d2b87be51..381ce51cf 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -7,7 +7,7 @@ set (OPENCS_SRC model/world/universalid.cpp model/world/idcollection.cpp model/world/data.cpp model/world/idtable.cpp model/world/commands.cpp model/world/idtableproxymodel.cpp model/world/record.cpp - model/tools/tools.cpp model/tools/operation.cpp model/tools/verifier.cpp + model/tools/tools.cpp model/tools/operation.cpp model/tools/stage.cpp model/tools/verifier.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp @@ -23,7 +23,7 @@ set (OPENCS_HDR model/world/idtable.hpp model/world/columns.hpp model/world/idtableproxymodel.hpp model/world/commands.hpp - model/tools/tools.hpp model/tools/operation.hpp model/tools/verifier.hpp + model/tools/tools.hpp model/tools/operation.hpp model/tools/stage.hpp model/tools/verifier.hpp view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp diff --git a/apps/opencs/model/tools/operation.cpp b/apps/opencs/model/tools/operation.cpp index ba5866168..12c4a8108 100644 --- a/apps/opencs/model/tools/operation.cpp +++ b/apps/opencs/model/tools/operation.cpp @@ -5,11 +5,33 @@ #include "../doc/state.hpp" +#include "stage.hpp" + +void CSMTools::Operation::prepareStages() +{ + mCurrentStage = mStages.begin(); + mCurrentStep = 0; + mCurrentStepTotal = 0; + mTotalSteps = 0; + + for (std::vector >::iterator iter (mStages.begin()); iter!=mStages.end(); ++iter) + { + iter->second = mTotalSteps; + mTotalSteps += iter->first->setup(); + } +} + CSMTools::Operation::Operation (int type) : mType (type) {} +CSMTools::Operation::~Operation() +{ + for (std::vector >::iterator iter (mStages.begin()); iter!=mStages.end(); ++iter) + delete iter->first; +} + void CSMTools::Operation::run() { - mStep = 0; + prepareStages(); QTimer timer; @@ -20,6 +42,11 @@ void CSMTools::Operation::run() exec(); } +void CSMTools::Operation::appendStage (Stage *stage) +{ + mStages.push_back (std::make_pair (stage, 0)); +} + void CSMTools::Operation::abort() { exit(); @@ -27,9 +54,23 @@ void CSMTools::Operation::abort() void CSMTools::Operation::verify() { - ++mStep; - emit progress (mStep, 1000, mType); + while (mCurrentStage!=mStages.end()) + { + if (mCurrentStep>=mCurrentStage->second) + { + mCurrentStep = 0; + ++mCurrentStage; + } + else + { + mCurrentStage->first->perform (mCurrentStep++); + ++mCurrentStepTotal; + break; + } + } + + emit progress (mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType); - if (mStep>=1000) + if (mCurrentStage==mStages.end()) exit(); } \ No newline at end of file diff --git a/apps/opencs/model/tools/operation.hpp b/apps/opencs/model/tools/operation.hpp index b75e2898f..72419e00a 100644 --- a/apps/opencs/model/tools/operation.hpp +++ b/apps/opencs/model/tools/operation.hpp @@ -1,23 +1,40 @@ #ifndef CSM_TOOLS_OPERATION_H #define CSM_TOOLS_OPERATION_H +#include + #include namespace CSMTools { + class Stage; + class Operation : public QThread { Q_OBJECT int mType; - int mStep; + std::vector > mStages; // stage, number of steps + std::vector >::iterator mCurrentStage; + int mCurrentStep; + int mCurrentStepTotal; + int mTotalSteps; + + void prepareStages(); public: Operation (int type); + virtual ~Operation(); + virtual void run(); + void appendStage (Stage *stage); + ///< The ownership of \a stage is transferred to *this. + /// + /// \attention Do no call this function while this Operation is running. + signals: void progress (int current, int max, int type); diff --git a/apps/opencs/model/tools/stage.cpp b/apps/opencs/model/tools/stage.cpp new file mode 100644 index 000000000..6f4567e57 --- /dev/null +++ b/apps/opencs/model/tools/stage.cpp @@ -0,0 +1,4 @@ + +#include "stage.hpp" + +CSMTools::Stage::~Stage() {} \ No newline at end of file diff --git a/apps/opencs/model/tools/stage.hpp b/apps/opencs/model/tools/stage.hpp new file mode 100644 index 000000000..912559410 --- /dev/null +++ b/apps/opencs/model/tools/stage.hpp @@ -0,0 +1,20 @@ +#ifndef CSM_TOOLS_STAGE_H +#define CSM_TOOLS_STAGE_H + +namespace CSMTools +{ + class Stage + { + public: + + virtual ~Stage(); + + virtual int setup() = 0; + ///< \return number of steps + + virtual void perform (int stage) = 0; + }; +} + +#endif + From 89b449733128f2967cecfe47c7c15d1890e023de Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 8 Dec 2012 18:15:00 +0100 Subject: [PATCH 043/136] added missing edit locks for create/revert/delete --- apps/opencs/view/world/table.cpp | 76 +++++++++++++++++++------------- apps/opencs/view/world/table.hpp | 1 + 2 files changed, 47 insertions(+), 30 deletions(-) diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 31f7d22ed..593dc8563 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -113,14 +113,19 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) QMenu menu (this); - if (mCreateAction) - menu.addAction (mCreateAction); + /// \todo add menu items for select all and clear selection - if (listRevertableSelectedIds().size()>0) - menu.addAction (mRevertAction); + if (!mEditLock) + { + if (mCreateAction) + menu.addAction (mCreateAction); - if (listDeletableSelectedIds().size()>0) - menu.addAction (mDeleteAction); + if (listRevertableSelectedIds().size()>0) + menu.addAction (mRevertAction); + + if (listDeletableSelectedIds().size()>0) + menu.addAction (mDeleteAction); + } menu.exec (event->globalPos()); } @@ -167,7 +172,7 @@ std::vector CSVWorld::Table::listDeletableSelectedIds() const CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, bool createAndDelete) -: mUndoStack (undoStack), mCreateAction (0) +: mUndoStack (undoStack), mCreateAction (0), mEditLock (false) { mModel = &dynamic_cast (*data.getTableModel (id)); @@ -212,50 +217,61 @@ void CSVWorld::Table::setEditLock (bool locked) { for (std::vector::iterator iter (mDelegates.begin()); iter!=mDelegates.end(); ++iter) (*iter)->setEditLock (locked); + + mEditLock = locked; } #include /// \todo remove void CSVWorld::Table::createRecord() { - /// \todo ask the user for an ID instead. - static int index = 0; + if (!mEditLock) + { + /// \todo ask the user for an ID instead. + static int index = 0; - std::ostringstream stream; - stream << "id" << index++; + std::ostringstream stream; + stream << "id" << index++; - mUndoStack.push (new CSMWorld::CreateCommand (*mProxyModel, stream.str())); + mUndoStack.push (new CSMWorld::CreateCommand (*mProxyModel, stream.str())); + } } void CSVWorld::Table::revertRecord() { - std::vector revertableIds = listRevertableSelectedIds(); - - if (revertableIds.size()>0) + if (!mEditLock) { - if (revertableIds.size()>1) - mUndoStack.beginMacro (tr ("Revert multiple records")); + std::vector revertableIds = listRevertableSelectedIds(); + + if (revertableIds.size()>0) + { + if (revertableIds.size()>1) + mUndoStack.beginMacro (tr ("Revert multiple records")); - for (std::vector::const_iterator iter (revertableIds.begin()); iter!=revertableIds.end(); ++iter) - mUndoStack.push (new CSMWorld::RevertCommand (*mModel, *iter)); + for (std::vector::const_iterator iter (revertableIds.begin()); iter!=revertableIds.end(); ++iter) + mUndoStack.push (new CSMWorld::RevertCommand (*mModel, *iter)); - if (revertableIds.size()>1) - mUndoStack.endMacro(); + if (revertableIds.size()>1) + mUndoStack.endMacro(); + } } } void CSVWorld::Table::deleteRecord() { - std::vector deletableIds = listDeletableSelectedIds(); - - if (deletableIds.size()>0) + if (!mEditLock) { - if (deletableIds.size()>1) - mUndoStack.beginMacro (tr ("Delete multiple records")); + std::vector deletableIds = listDeletableSelectedIds(); + + if (deletableIds.size()>0) + { + if (deletableIds.size()>1) + mUndoStack.beginMacro (tr ("Delete multiple records")); - for (std::vector::const_iterator iter (deletableIds.begin()); iter!=deletableIds.end(); ++iter) - mUndoStack.push (new CSMWorld::DeleteCommand (*mModel, *iter)); + for (std::vector::const_iterator iter (deletableIds.begin()); iter!=deletableIds.end(); ++iter) + mUndoStack.push (new CSMWorld::DeleteCommand (*mModel, *iter)); - if (deletableIds.size()>1) - mUndoStack.endMacro(); + if (deletableIds.size()>1) + mUndoStack.endMacro(); + } } } \ No newline at end of file diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 264d2bc5c..b58ba8328 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -33,6 +33,7 @@ namespace CSVWorld QAction *mDeleteAction; CSMWorld::IdTableProxyModel *mProxyModel; CSMWorld::IdTable *mModel; + bool mEditLock; private: From 72623652e46dd5ce94b4e1b4f2593cb889db23b1 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 8 Dec 2012 18:38:36 +0100 Subject: [PATCH 044/136] addded messages interface for operations/stages --- apps/opencs/model/tools/operation.cpp | 10 +++++++++- apps/opencs/model/tools/operation.hpp | 2 ++ apps/opencs/model/tools/stage.hpp | 6 +++++- apps/opencs/model/tools/tools.cpp | 10 ++++++++++ apps/opencs/model/tools/tools.hpp | 2 ++ 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/tools/operation.cpp b/apps/opencs/model/tools/operation.cpp index 12c4a8108..b68f79ca4 100644 --- a/apps/opencs/model/tools/operation.cpp +++ b/apps/opencs/model/tools/operation.cpp @@ -1,6 +1,9 @@ #include "operation.hpp" +#include +#include + #include #include "../doc/state.hpp" @@ -54,6 +57,8 @@ void CSMTools::Operation::abort() void CSMTools::Operation::verify() { + std::vector messages; + while (mCurrentStage!=mStages.end()) { if (mCurrentStep>=mCurrentStage->second) @@ -63,7 +68,7 @@ void CSMTools::Operation::verify() } else { - mCurrentStage->first->perform (mCurrentStep++); + mCurrentStage->first->perform (mCurrentStep++, messages); ++mCurrentStepTotal; break; } @@ -71,6 +76,9 @@ void CSMTools::Operation::verify() emit progress (mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType); + for (std::vector::const_iterator iter (messages.begin()); iter!=messages.end(); ++iter) + emit reportMessage (iter->c_str(), mType); + if (mCurrentStage==mStages.end()) exit(); } \ No newline at end of file diff --git a/apps/opencs/model/tools/operation.hpp b/apps/opencs/model/tools/operation.hpp index 72419e00a..4731c58fa 100644 --- a/apps/opencs/model/tools/operation.hpp +++ b/apps/opencs/model/tools/operation.hpp @@ -39,6 +39,8 @@ namespace CSMTools void progress (int current, int max, int type); + void reportMessage (const QString& message, int type); + public slots: void abort(); diff --git a/apps/opencs/model/tools/stage.hpp b/apps/opencs/model/tools/stage.hpp index 912559410..1ad61960a 100644 --- a/apps/opencs/model/tools/stage.hpp +++ b/apps/opencs/model/tools/stage.hpp @@ -1,6 +1,9 @@ #ifndef CSM_TOOLS_STAGE_H #define CSM_TOOLS_STAGE_H +#include +#include + namespace CSMTools { class Stage @@ -12,7 +15,8 @@ namespace CSMTools virtual int setup() = 0; ///< \return number of steps - virtual void perform (int stage) = 0; + virtual void perform (int stage, std::vector& messages) = 0; + ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 608244a3c..8293b7291 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -30,6 +30,8 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier() connect (mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); connect (mVerifier, SIGNAL (finished()), this, SLOT (verifierDone())); + connect (mVerifier, SIGNAL (reportMessage (const QString&, int)), + this, SLOT (verifierMessage (const QString&, int))); } return mVerifier; @@ -77,4 +79,12 @@ int CSMTools::Tools::getRunningOperations() const void CSMTools::Tools::verifierDone() { emit done (CSMDoc::State_Verifying); +} + +#include +void CSMTools::Tools::verifierMessage (const QString& message, int type) +{ + /// \todo store it in a result model instead + + std::cout << message.toStdString() << std::endl; } \ No newline at end of file diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index ab1863738..04140bb91 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -43,6 +43,8 @@ namespace CSMTools void verifierDone(); + void verifierMessage (const QString& message, int type); + signals: void progress (int current, int max, int type); From 9fe7ff969047df565bae6b39045b6fb52fcf8b50 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 8 Dec 2012 23:27:59 +0100 Subject: [PATCH 045/136] added mandatory ID check stage --- apps/opencs/CMakeLists.txt | 2 ++ apps/opencs/model/doc/document.cpp | 1 + apps/opencs/model/doc/document.hpp | 5 ++- apps/opencs/model/tools/mandatoryid.cpp | 21 +++++++++++ apps/opencs/model/tools/mandatoryid.hpp | 38 ++++++++++++++++++++ apps/opencs/model/tools/operation.cpp | 4 +-- apps/opencs/model/tools/stage.hpp | 12 +++---- apps/opencs/model/tools/tools.cpp | 19 +++++++++- apps/opencs/model/tools/tools.hpp | 8 ++++- apps/opencs/model/world/universalid.cpp | 48 ++++++++++++++++++++++++- apps/opencs/model/world/universalid.hpp | 2 ++ 11 files changed, 148 insertions(+), 12 deletions(-) create mode 100644 apps/opencs/model/tools/mandatoryid.cpp create mode 100644 apps/opencs/model/tools/mandatoryid.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 381ce51cf..bad1e1376 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -8,6 +8,7 @@ set (OPENCS_SRC model/world/commands.cpp model/world/idtableproxymodel.cpp model/world/record.cpp model/tools/tools.cpp model/tools/operation.cpp model/tools/stage.cpp model/tools/verifier.cpp + model/tools/mandatoryid.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp @@ -24,6 +25,7 @@ set (OPENCS_HDR model/world/commands.hpp model/tools/tools.hpp model/tools/operation.hpp model/tools/stage.hpp model/tools/verifier.hpp + model/tools/mandatoryid.hpp view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index d8ad5ff01..f03344e08 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2,6 +2,7 @@ #include "document.hpp" CSMDoc::Document::Document (const std::string& name) +: mTools (mData) { mName = name; ///< \todo replace with ESX list diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 40f8c0ea1..f9d0a232c 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -22,10 +22,13 @@ namespace CSMDoc private: std::string mName; ///< \todo replace name with ESX list - QUndoStack mUndoStack; CSMWorld::Data mData; CSMTools::Tools mTools; + // 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 + // using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late. + QUndoStack mUndoStack; + int mSaveCount; ///< dummy implementation -> remove when proper save is implemented. QTimer mSaveTimer; ///< dummy implementation -> remove when proper save is implemented. diff --git a/apps/opencs/model/tools/mandatoryid.cpp b/apps/opencs/model/tools/mandatoryid.cpp new file mode 100644 index 000000000..87ac77e67 --- /dev/null +++ b/apps/opencs/model/tools/mandatoryid.cpp @@ -0,0 +1,21 @@ + +#include "mandatoryid.hpp" + +#include "../world/idcollection.hpp" + +CSMTools::MandatoryIdStage::MandatoryIdStage (const CSMWorld::IdCollectionBase& idCollection, + const CSMWorld::UniversalId& collectionId, const std::vector& ids) +: mIdCollection (idCollection), mCollectionId (collectionId), mIds (ids) +{} + +int CSMTools::MandatoryIdStage::setup() +{ + return mIds.size(); +} + +void CSMTools::MandatoryIdStage::perform (int stage, std::vector& messages) +{ + if (mIdCollection.searchId (mIds.at (stage))==-1 || + mIdCollection.getRecord (mIds.at (stage)).isDeleted()) + messages.push_back (mCollectionId.toString() + " Missing mandatory record: " + mIds.at (stage)); +} \ No newline at end of file diff --git a/apps/opencs/model/tools/mandatoryid.hpp b/apps/opencs/model/tools/mandatoryid.hpp new file mode 100644 index 000000000..14fcec204 --- /dev/null +++ b/apps/opencs/model/tools/mandatoryid.hpp @@ -0,0 +1,38 @@ +#ifndef CSM_TOOLS_MANDATORYID_H +#define CSM_TOOLS_MANDATORYID_H + +#include +#include + +#include "../world/universalid.hpp" + +#include "stage.hpp" + +namespace CSMWorld +{ + class IdCollectionBase; +} + +namespace CSMTools +{ + /// \brief Verify stage: make sure that records with specific IDs exist. + class MandatoryIdStage : public Stage + { + const CSMWorld::IdCollectionBase& mIdCollection; + CSMWorld::UniversalId mCollectionId; + std::vector mIds; + + public: + + MandatoryIdStage (const CSMWorld::IdCollectionBase& idCollection, const CSMWorld::UniversalId& collectionId, + const std::vector& ids); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, std::vector& messages); + ///< Messages resulting from this tage will be appended to \a messages. + }; +} + +#endif diff --git a/apps/opencs/model/tools/operation.cpp b/apps/opencs/model/tools/operation.cpp index b68f79ca4..71761cdae 100644 --- a/apps/opencs/model/tools/operation.cpp +++ b/apps/opencs/model/tools/operation.cpp @@ -19,8 +19,8 @@ void CSMTools::Operation::prepareStages() for (std::vector >::iterator iter (mStages.begin()); iter!=mStages.end(); ++iter) { - iter->second = mTotalSteps; - mTotalSteps += iter->first->setup(); + iter->second = iter->first->setup(); + mTotalSteps += iter->second; } } diff --git a/apps/opencs/model/tools/stage.hpp b/apps/opencs/model/tools/stage.hpp index 1ad61960a..3020936f3 100644 --- a/apps/opencs/model/tools/stage.hpp +++ b/apps/opencs/model/tools/stage.hpp @@ -8,15 +8,15 @@ namespace CSMTools { class Stage { - public: + public: - virtual ~Stage(); + virtual ~Stage(); - virtual int setup() = 0; - ///< \return number of steps + virtual int setup() = 0; + ///< \return number of steps - virtual void perform (int stage, std::vector& messages) = 0; - ///< Messages resulting from this tage will be appended to \a messages. + virtual void perform (int stage, std::vector& messages) = 0; + ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 8293b7291..a3cdb7822 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -7,6 +7,10 @@ #include "../doc/state.hpp" +#include "../world/data.hpp" + +#include "mandatoryid.hpp" + CSMTools::Operation *CSMTools::Tools::get (int type) { switch (type) @@ -32,12 +36,25 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier() connect (mVerifier, SIGNAL (finished()), this, SLOT (verifierDone())); connect (mVerifier, SIGNAL (reportMessage (const QString&, int)), this, SLOT (verifierMessage (const QString&, int))); + + std::vector mandatoryIds; // I want C++11, damn it! + mandatoryIds.push_back ("Day"); + mandatoryIds.push_back ("DaysPassed"); + mandatoryIds.push_back ("GameHour"); + mandatoryIds.push_back ("Month"); + mandatoryIds.push_back ("PCRace"); + mandatoryIds.push_back ("PCVampire"); + mandatoryIds.push_back ("PCWerewolf"); + mandatoryIds.push_back ("PCYear"); + + mVerifier->appendStage (new MandatoryIdStage (mData.getGlobals(), + CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds)); } return mVerifier; } -CSMTools::Tools::Tools() : mVerifier (0) +CSMTools::Tools::Tools (CSMWorld::Data& data) : mData (data), mVerifier (0) { } diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index 04140bb91..da49fd8b8 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -3,6 +3,11 @@ #include +namespace CSMWorld +{ + class Data; +} + namespace CSMTools { class Verifier; @@ -12,6 +17,7 @@ namespace CSMTools { Q_OBJECT + CSMWorld::Data& mData; Verifier *mVerifier; // not implemented @@ -28,7 +34,7 @@ namespace CSMTools public: - Tools(); + Tools (CSMWorld::Data& data); virtual ~Tools(); diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index e2d8d1ffb..229779f5a 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -35,6 +35,52 @@ namespace }; } +CSMWorld::UniversalId::UniversalId (const std::string& universalId) +{ + std::string::size_type index = universalId.find (':'); + + if (index!=std::string::npos) + { + std::string type = universalId.substr (0, index); + + for (int i=0; sNoArg[i].mName; ++i) + if (type==sNoArg[i].mName) + { + mArgumentType = ArgumentType_None; + mType = sNoArg[i].mType; + mClass = sNoArg[i].mClass; + return; + } + + for (int i=0; sIdArg[i].mName; ++i) + if (type==sIdArg[i].mName) + { + mArgumentType = ArgumentType_Id; + mType = sIdArg[i].mType; + mClass = sIdArg[i].mClass; + mId = universalId.substr (0, index); + return; + } + + for (int i=0; sIndexArg[i].mName; ++i) + if (type==sIndexArg[i].mName) + { + mArgumentType = ArgumentType_Index; + mType = sIndexArg[i].mType; + mClass = sIndexArg[i].mClass; + + std::istringstream stream (universalId.substr (0, index)); + + if (stream >> mIndex) + return; + + break; + } + } + + throw std::runtime_error ("invalid UniversalId: " + universalId); +} + CSMWorld::UniversalId::UniversalId (Type type) : mArgumentType (ArgumentType_None), mType (type), mIndex (0) { for (int i=0; sNoArg[i].mName; ++i) @@ -151,7 +197,7 @@ std::string CSMWorld::UniversalId::toString() const { std::ostringstream stream; - stream << getTypeName(); + stream << getTypeName() << ":"; switch (mArgumentType) { diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 6dc0eda1e..7b630ebc7 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -44,6 +44,8 @@ namespace CSMWorld public: + UniversalId (const std::string& universalId); + UniversalId (Type type = Type_None); ///< Using a type for a non-argument-less UniversalId will throw an exception. From 832fc56d34d06092bd6fc4344ca6fe71399b2205 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 9 Dec 2012 11:10:35 +0100 Subject: [PATCH 046/136] changed UniversalId to string conversion --- apps/opencs/model/tools/mandatoryid.cpp | 2 +- apps/opencs/model/world/universalid.cpp | 73 +++++++++++++------------ 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/apps/opencs/model/tools/mandatoryid.cpp b/apps/opencs/model/tools/mandatoryid.cpp index 87ac77e67..f9f2ca378 100644 --- a/apps/opencs/model/tools/mandatoryid.cpp +++ b/apps/opencs/model/tools/mandatoryid.cpp @@ -17,5 +17,5 @@ void CSMTools::MandatoryIdStage::perform (int stage, std::vector& m { if (mIdCollection.searchId (mIds.at (stage))==-1 || mIdCollection.getRecord (mIds.at (stage)).isDeleted()) - messages.push_back (mCollectionId.toString() + " Missing mandatory record: " + mIds.at (stage)); + messages.push_back (mCollectionId.toString() + "|Missing mandatory record: " + mIds.at (stage)); } \ No newline at end of file diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 229779f5a..98fb1d0b9 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -43,39 +43,44 @@ CSMWorld::UniversalId::UniversalId (const std::string& universalId) { std::string type = universalId.substr (0, index); - for (int i=0; sNoArg[i].mName; ++i) - if (type==sNoArg[i].mName) - { - mArgumentType = ArgumentType_None; - mType = sNoArg[i].mType; - mClass = sNoArg[i].mClass; - return; - } - - for (int i=0; sIdArg[i].mName; ++i) - if (type==sIdArg[i].mName) - { - mArgumentType = ArgumentType_Id; - mType = sIdArg[i].mType; - mClass = sIdArg[i].mClass; - mId = universalId.substr (0, index); - return; - } - - for (int i=0; sIndexArg[i].mName; ++i) - if (type==sIndexArg[i].mName) - { - mArgumentType = ArgumentType_Index; - mType = sIndexArg[i].mType; - mClass = sIndexArg[i].mClass; - - std::istringstream stream (universalId.substr (0, index)); - - if (stream >> mIndex) + if (index==std::string::npos) + { + for (int i=0; sNoArg[i].mName; ++i) + if (type==sNoArg[i].mName) + { + mArgumentType = ArgumentType_None; + mType = sNoArg[i].mType; + mClass = sNoArg[i].mClass; + return; + } + } + else + { + for (int i=0; sIdArg[i].mName; ++i) + if (type==sIdArg[i].mName) + { + mArgumentType = ArgumentType_Id; + mType = sIdArg[i].mType; + mClass = sIdArg[i].mClass; + mId = universalId.substr (0, index); return; + } - break; - } + for (int i=0; sIndexArg[i].mName; ++i) + if (type==sIndexArg[i].mName) + { + mArgumentType = ArgumentType_Index; + mType = sIndexArg[i].mType; + mClass = sIndexArg[i].mClass; + + std::istringstream stream (universalId.substr (0, index)); + + if (stream >> mIndex) + return; + + break; + } + } } throw std::runtime_error ("invalid UniversalId: " + universalId); @@ -197,13 +202,13 @@ std::string CSMWorld::UniversalId::toString() const { std::ostringstream stream; - stream << getTypeName() << ":"; + stream << getTypeName(); switch (mArgumentType) { case ArgumentType_None: break; - case ArgumentType_Id: stream << " " << mId; - case ArgumentType_Index: stream << " " << mIndex; + case ArgumentType_Id: stream << ": " << mId; + case ArgumentType_Index: stream << ": " << mIndex; } return stream.str(); From 0ed378dfb21fd3796f44a5ee0cd5542ca88e7af6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 11 Dec 2012 11:24:30 +0100 Subject: [PATCH 047/136] changed sub view factory method signature --- apps/opencs/view/doc/view.cpp | 2 +- apps/opencs/view/world/subview.hpp | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 539b149cb..c1659b388 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -191,7 +191,7 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id) if (iter==mSubViewFactories.end()) throw std::logic_error ("can't create subview for " + id.toString()); - CSVWorld::SubView *view = iter->second->makeSubView (id, mDocument->getData(), mDocument->getUndoStack()); + CSVWorld::SubView *view = iter->second->makeSubView (id, *mDocument); addDockWidget (Qt::TopDockWidgetArea, view); view->show(); } diff --git a/apps/opencs/view/world/subview.hpp b/apps/opencs/view/world/subview.hpp index 95448cb47..ff130828b 100644 --- a/apps/opencs/view/world/subview.hpp +++ b/apps/opencs/view/world/subview.hpp @@ -1,6 +1,8 @@ #ifndef CSV_WORLD_SUBVIEW_H #define CSV_WORLD_SUBVIEW_H +#include "../../model/doc/document.hpp" + #include "../../model/world/universalid.hpp" #include @@ -35,21 +37,20 @@ namespace CSVWorld struct SubViewFactoryBase { - virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) = 0; }; template struct SubViewFactory : public SubViewFactoryBase { - virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); }; template - SubView *SubViewFactory::makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, - QUndoStack& undoStack) + SubView *SubViewFactory::makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) { - return new SubViewT (id, data, undoStack); + return new SubViewT (id, document.getData(), document.getUndoStack()); } template @@ -59,7 +60,7 @@ namespace CSVWorld SubViewFactoryWithCreateFlag (bool createAndDelete); - virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); }; template @@ -69,10 +70,9 @@ namespace CSVWorld template SubView *SubViewFactoryWithCreateFlag::makeSubView (const CSMWorld::UniversalId& id, - CSMWorld::Data& data, - QUndoStack& undoStack) + CSMDoc::Document& document) { - return new SubViewT (id, data, undoStack, mCreateAndDelete); + return new SubViewT (id, document.getData(), document.getUndoStack(), mCreateAndDelete); } } From 2db930a5cf36f19b174b8a1c8e1cdb6789ba6a14 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 11 Dec 2012 13:22:43 +0100 Subject: [PATCH 048/136] rewrote subview factory system --- apps/opencs/CMakeLists.txt | 10 +-- apps/opencs/view/{world => doc}/subview.cpp | 4 +- apps/opencs/view/doc/subview.hpp | 41 +++++++++++ apps/opencs/view/doc/subviewfactory.cpp | 38 ++++++++++ apps/opencs/view/doc/subviewfactory.hpp | 55 ++++++++++++++ apps/opencs/view/doc/subviewfactoryimp.hpp | 50 +++++++++++++ apps/opencs/view/doc/view.cpp | 20 ++---- apps/opencs/view/doc/view.hpp | 9 +-- apps/opencs/view/world/subview.hpp | 79 --------------------- apps/opencs/view/world/subviews.cpp | 12 ++++ apps/opencs/view/world/subviews.hpp | 14 ++++ apps/opencs/view/world/tablesubview.cpp | 6 +- apps/opencs/view/world/tablesubview.hpp | 12 ++-- 13 files changed, 239 insertions(+), 111 deletions(-) rename apps/opencs/view/{world => doc}/subview.cpp (65%) create mode 100644 apps/opencs/view/doc/subview.hpp create mode 100644 apps/opencs/view/doc/subviewfactory.cpp create mode 100644 apps/opencs/view/doc/subviewfactory.hpp create mode 100644 apps/opencs/view/doc/subviewfactoryimp.hpp delete mode 100644 apps/opencs/view/world/subview.hpp create mode 100644 apps/opencs/view/world/subviews.cpp create mode 100644 apps/opencs/view/world/subviews.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index bad1e1376..67cbcc772 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -10,9 +10,10 @@ set (OPENCS_SRC model/tools/tools.cpp model/tools/operation.cpp model/tools/stage.cpp model/tools/verifier.cpp model/tools/mandatoryid.cpp - view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp + view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp view/doc/subviewfactory.cpp + view/doc/subview.cpp - view/world/subview.cpp view/world/table.cpp view/world/tablesubview.cpp + view/world/table.cpp view/world/tablesubview.cpp view/world/subviews.cpp ) set (OPENCS_HDR @@ -27,9 +28,10 @@ set (OPENCS_HDR model/tools/tools.hpp model/tools/operation.hpp model/tools/stage.hpp model/tools/verifier.hpp model/tools/mandatoryid.hpp - view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp + view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp view/doc/subviewfactory.hpp + view/doc/subview.hpp view/doc/subviewfactoryimp.hpp - view/world/subview.hpp view/world/table.hpp view/world/tablesubview.hpp + view/world/table.hpp view/world/tablesubview.hpp view/world/subviews.hpp ) set (OPENCS_US diff --git a/apps/opencs/view/world/subview.cpp b/apps/opencs/view/doc/subview.cpp similarity index 65% rename from apps/opencs/view/world/subview.cpp rename to apps/opencs/view/doc/subview.cpp index 23f075980..1c356fa73 100644 --- a/apps/opencs/view/world/subview.cpp +++ b/apps/opencs/view/doc/subview.cpp @@ -1,7 +1,7 @@ #include "subview.hpp" -CSVWorld::SubView::SubView (const CSMWorld::UniversalId& id) : mUniversalId (id) +CSVDoc::SubView::SubView (const CSMWorld::UniversalId& id) : mUniversalId (id) { /// \todo add a button to the title bar that clones this sub view @@ -12,7 +12,7 @@ CSVWorld::SubView::SubView (const CSMWorld::UniversalId& id) : mUniversalId (id) setMinimumHeight (60); } -CSMWorld::UniversalId CSVWorld::SubView::getUniversalId() const +CSMWorld::UniversalId CSVDoc::SubView::getUniversalId() const { return mUniversalId; } diff --git a/apps/opencs/view/doc/subview.hpp b/apps/opencs/view/doc/subview.hpp new file mode 100644 index 000000000..50ec511ab --- /dev/null +++ b/apps/opencs/view/doc/subview.hpp @@ -0,0 +1,41 @@ +#ifndef CSV_DOC_SUBVIEW_H +#define CSV_DOC_SUBVIEW_H + +#include "../../model/doc/document.hpp" + +#include "../../model/world/universalid.hpp" + +#include "subviewfactory.hpp" + +#include + +class QUndoStack; + +namespace CSMWorld +{ + class Data; +} + +namespace CSVDoc +{ + class SubView : public QDockWidget + { + Q_OBJECT + + CSMWorld::UniversalId mUniversalId; + + // not implemented + SubView (const SubView&); + SubView& operator= (SubView&); + + public: + + SubView (const CSMWorld::UniversalId& id); + + CSMWorld::UniversalId getUniversalId() const; + + virtual void setEditLock (bool locked) = 0; + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/doc/subviewfactory.cpp b/apps/opencs/view/doc/subviewfactory.cpp new file mode 100644 index 000000000..8576f6b1d --- /dev/null +++ b/apps/opencs/view/doc/subviewfactory.cpp @@ -0,0 +1,38 @@ + +#include "subviewfactory.hpp" + +#include + +#include + +CSVDoc::SubViewFactoryBase::SubViewFactoryBase() {} + +CSVDoc::SubViewFactoryBase::~SubViewFactoryBase() {} + + +CSVDoc::SubViewFactoryManager::SubViewFactoryManager() {} + +CSVDoc::SubViewFactoryManager::~SubViewFactoryManager() +{ + for (std::map::iterator iter (mSubViewFactories.begin()); + iter!=mSubViewFactories.end(); ++iter) + delete iter->second; +} + +void CSVDoc::SubViewFactoryManager::add (const CSMWorld::UniversalId::Type& id, SubViewFactoryBase *factory) +{ + assert (mSubViewFactories.find (id)==mSubViewFactories.end()); + + mSubViewFactories.insert (std::make_pair (id, factory)); +} + +CSVDoc::SubView *CSVDoc::SubViewFactoryManager::makeSubView (const CSMWorld::UniversalId& id, + CSMDoc::Document& document) +{ + std::map::iterator iter = mSubViewFactories.find (id.getType()); + + if (iter==mSubViewFactories.end()) + throw std::runtime_error ("Failed to create a sub view for: " + id.toString()); + + return iter->second->makeSubView (id, document); +} \ No newline at end of file diff --git a/apps/opencs/view/doc/subviewfactory.hpp b/apps/opencs/view/doc/subviewfactory.hpp new file mode 100644 index 000000000..1f7c15480 --- /dev/null +++ b/apps/opencs/view/doc/subviewfactory.hpp @@ -0,0 +1,55 @@ +#ifndef CSV_DOC_SUBVIEWFACTORY_H +#define CSV_DOC_SUBVIEWFACTORY_H + +#include + +#include "../../model/world/universalid.hpp" + +namespace CSMDoc +{ + class Document; +} + +namespace CSVDoc +{ + class SubView; + + class SubViewFactoryBase + { + // not implemented + SubViewFactoryBase (const SubViewFactoryBase&); + SubViewFactoryBase& operator= (const SubViewFactoryBase&); + + public: + + SubViewFactoryBase(); + + virtual ~SubViewFactoryBase(); + + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) = 0; + ///< The ownership of the returned sub view is not transferred. + }; + + class SubViewFactoryManager + { + std::map mSubViewFactories; + + // not implemented + SubViewFactoryManager (const SubViewFactoryManager&); + SubViewFactoryManager& operator= (const SubViewFactoryManager&); + + public: + + SubViewFactoryManager(); + + ~SubViewFactoryManager(); + + void add (const CSMWorld::UniversalId::Type& id, SubViewFactoryBase *factory); + ///< The ownership of \a factory is transferred to this. + + SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); + ///< The ownership of the returned sub view is not transferred. + }; +} + +#endif diff --git a/apps/opencs/view/doc/subviewfactoryimp.hpp b/apps/opencs/view/doc/subviewfactoryimp.hpp new file mode 100644 index 000000000..d16e0b2b7 --- /dev/null +++ b/apps/opencs/view/doc/subviewfactoryimp.hpp @@ -0,0 +1,50 @@ +#ifndef CSV_DOC_SUBVIEWFACTORYIMP_H +#define CSV_DOC_SUBVIEWFACTORYIMP_H + +#include "../../model/doc/document.hpp" + +#include "subviewfactory.hpp" + +namespace CSVDoc +{ + template + class SubViewFactory : public SubViewFactoryBase + { + public: + + virtual CSVDoc::SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); + }; + + template + CSVDoc::SubView *SubViewFactory::makeSubView (const CSMWorld::UniversalId& id, + CSMDoc::Document& document) + { + return new SubViewT (id, document); + } + + template + class SubViewFactoryWithCreateFlag : public SubViewFactoryBase + { + bool mCreateAndDelete; + + public: + + SubViewFactoryWithCreateFlag (bool createAndDelete); + + virtual CSVDoc::SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); + }; + + template + SubViewFactoryWithCreateFlag::SubViewFactoryWithCreateFlag (bool createAndDelete) + : mCreateAndDelete (createAndDelete) + {} + + template + CSVDoc::SubView *SubViewFactoryWithCreateFlag::makeSubView (const CSMWorld::UniversalId& id, + CSMDoc::Document& document) + { + return new SubViewT (id, document, mCreateAndDelete); + } +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index c1659b388..47053192b 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -10,10 +10,11 @@ #include "../../model/doc/document.hpp" -#include "../world/tablesubview.hpp" +#include "../world/subviews.hpp" #include "viewmanager.hpp" #include "operations.hpp" +#include "subview.hpp" void CSVDoc::View::closeEvent (QCloseEvent *event) { @@ -120,15 +121,11 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to setupUi(); - mSubViewFactories.insert (std::make_pair (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), - new CSVWorld::SubViewFactoryWithCreateFlag (true))); + CSVWorld::addSubViewFactories (mSubViewFactory); } CSVDoc::View::~View() { - for (std::map::iterator iter (mSubViewFactories.begin()); - iter!=mSubViewFactories.end(); ++iter) - delete iter->second; } const CSMDoc::Document *CSVDoc::View::getDocument() const @@ -165,9 +162,9 @@ void CSVDoc::View::updateDocumentState() if (!(state & operations[i])) mOperations->quitOperation (operations[i]); - QList subViews = findChildren(); + QList subViews = findChildren(); - for (QList::iterator iter (subViews.begin()); iter!=subViews.end(); ++iter) + for (QList::iterator iter (subViews.begin()); iter!=subViews.end(); ++iter) (*iter)->setEditLock (state & CSMDoc::State_Locked); } @@ -186,12 +183,7 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id) /// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis) - std::map::iterator iter = mSubViewFactories.find (id); - - if (iter==mSubViewFactories.end()) - throw std::logic_error ("can't create subview for " + id.toString()); - - CSVWorld::SubView *view = iter->second->makeSubView (id, *mDocument); + SubView *view = mSubViewFactory.makeSubView (id, *mDocument); addDockWidget (Qt::TopDockWidgetArea, view); view->show(); } diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index c86c3b362..f7d4dd373 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -6,6 +6,8 @@ #include +#include "subviewfactory.hpp" + class QAction; namespace CSMDoc @@ -18,11 +20,6 @@ namespace CSMWorld class UniversalId; } -namespace CSVWorld -{ - struct SubViewFactoryBase; -} - namespace CSVDoc { class ViewManager; @@ -42,7 +39,7 @@ namespace CSVDoc QAction *mVerify; std::vector mEditingActions; Operations *mOperations; - std::map mSubViewFactories; + SubViewFactoryManager mSubViewFactory; // not implemented View (const View&); diff --git a/apps/opencs/view/world/subview.hpp b/apps/opencs/view/world/subview.hpp deleted file mode 100644 index ff130828b..000000000 --- a/apps/opencs/view/world/subview.hpp +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef CSV_WORLD_SUBVIEW_H -#define CSV_WORLD_SUBVIEW_H - -#include "../../model/doc/document.hpp" - -#include "../../model/world/universalid.hpp" - -#include - -class QUndoStack; - -namespace CSMWorld -{ - class Data; -} - -namespace CSVWorld -{ - class SubView : public QDockWidget - { - Q_OBJECT - - CSMWorld::UniversalId mUniversalId; - - // not implemented - SubView (const SubView&); - SubView& operator= (SubView&); - - public: - - SubView (const CSMWorld::UniversalId& id); - - CSMWorld::UniversalId getUniversalId() const; - - virtual void setEditLock (bool locked) = 0; - }; - - struct SubViewFactoryBase - { - virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) - = 0; - }; - - template - struct SubViewFactory : public SubViewFactoryBase - { - virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); - }; - - template - SubView *SubViewFactory::makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) - { - return new SubViewT (id, document.getData(), document.getUndoStack()); - } - - template - struct SubViewFactoryWithCreateFlag : public SubViewFactoryBase - { - bool mCreateAndDelete; - - SubViewFactoryWithCreateFlag (bool createAndDelete); - - virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); - }; - - template - SubViewFactoryWithCreateFlag::SubViewFactoryWithCreateFlag (bool createAndDelete) - : mCreateAndDelete (createAndDelete) - {} - - template - SubView *SubViewFactoryWithCreateFlag::makeSubView (const CSMWorld::UniversalId& id, - CSMDoc::Document& document) - { - return new SubViewT (id, document.getData(), document.getUndoStack(), mCreateAndDelete); - } -} - -#endif \ No newline at end of file diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp new file mode 100644 index 000000000..fdc0cb31d --- /dev/null +++ b/apps/opencs/view/world/subviews.cpp @@ -0,0 +1,12 @@ + +#include "subviews.hpp" + +#include "../doc/subviewfactoryimp.hpp" + +#include "tablesubview.hpp" + +void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) +{ + manager.add (CSMWorld::UniversalId::Type_Globals, + new CSVDoc::SubViewFactoryWithCreateFlag (true)); +} \ No newline at end of file diff --git a/apps/opencs/view/world/subviews.hpp b/apps/opencs/view/world/subviews.hpp new file mode 100644 index 000000000..51e4cb083 --- /dev/null +++ b/apps/opencs/view/world/subviews.hpp @@ -0,0 +1,14 @@ +#ifndef CSV_WORLD_SUBVIEWS_H +#define CSV_WORLD_SUBVIEWS_H + +namespace CSVDoc +{ + class SubViewFactoryManager; +} + +namespace CSVWorld +{ + void addSubViewFactories (CSVDoc::SubViewFactoryManager& manager); +} + +#endif diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index 3bc555a2d..4abd531d0 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -1,13 +1,15 @@ #include "tablesubview.hpp" +#include "../../model/doc/document.hpp" + #include "table.hpp" -CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, +CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, bool createAndDelete) : SubView (id) { - setWidget (mTable = new Table (id, data, undoStack, createAndDelete)); + setWidget (mTable = new Table (id, document.getData(), document.getUndoStack(), createAndDelete)); } void CSVWorld::TableSubView::setEditLock (bool locked) diff --git a/apps/opencs/view/world/tablesubview.hpp b/apps/opencs/view/world/tablesubview.hpp index b45b3c279..9b0785c47 100644 --- a/apps/opencs/view/world/tablesubview.hpp +++ b/apps/opencs/view/world/tablesubview.hpp @@ -1,22 +1,26 @@ #ifndef CSV_WORLD_TABLESUBVIEW_H #define CSV_WORLD_TABLESUBVIEW_H -#include "subview.hpp" +#include "../doc/subview.hpp" class QUndoStack; +namespace CSMDoc +{ + class Document; +} + namespace CSVWorld { class Table; - class TableSubView : public SubView + class TableSubView : public CSVDoc::SubView { Table *mTable; public: - TableSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, - bool createAndDelete); + TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, bool createAndDelete); virtual void setEditLock (bool locked); }; From c75563c184de28aca46ae2cfb52a4318771cfa1e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 11 Dec 2012 15:35:47 +0100 Subject: [PATCH 049/136] report model and view --- apps/opencs/CMakeLists.txt | 8 ++- apps/opencs/model/doc/document.cpp | 10 +++- apps/opencs/model/doc/document.hpp | 7 ++- apps/opencs/model/tools/reportmodel.cpp | 66 ++++++++++++++++++++++++ apps/opencs/model/tools/reportmodel.hpp | 35 +++++++++++++ apps/opencs/model/tools/tools.cpp | 28 +++++++--- apps/opencs/model/tools/tools.hpp | 13 ++++- apps/opencs/model/world/idtable.cpp | 2 +- apps/opencs/model/world/universalid.cpp | 3 +- apps/opencs/model/world/universalid.hpp | 5 +- apps/opencs/view/doc/view.cpp | 5 +- apps/opencs/view/tools/reportsubview.cpp | 25 +++++++++ apps/opencs/view/tools/reportsubview.hpp | 29 +++++++++++ apps/opencs/view/tools/subviews.cpp | 12 +++++ apps/opencs/view/tools/subviews.hpp | 14 +++++ 15 files changed, 246 insertions(+), 16 deletions(-) create mode 100644 apps/opencs/model/tools/reportmodel.cpp create mode 100644 apps/opencs/model/tools/reportmodel.hpp create mode 100644 apps/opencs/view/tools/reportsubview.cpp create mode 100644 apps/opencs/view/tools/reportsubview.hpp create mode 100644 apps/opencs/view/tools/subviews.cpp create mode 100644 apps/opencs/view/tools/subviews.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 67cbcc772..1f9fe85a2 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -8,12 +8,14 @@ set (OPENCS_SRC model/world/commands.cpp model/world/idtableproxymodel.cpp model/world/record.cpp model/tools/tools.cpp model/tools/operation.cpp model/tools/stage.cpp model/tools/verifier.cpp - model/tools/mandatoryid.cpp + model/tools/mandatoryid.cpp model/tools/reportmodel.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp view/doc/subviewfactory.cpp view/doc/subview.cpp view/world/table.cpp view/world/tablesubview.cpp view/world/subviews.cpp + + view/tools/reportsubview.cpp view/tools/subviews.cpp ) set (OPENCS_HDR @@ -26,12 +28,14 @@ set (OPENCS_HDR model/world/commands.hpp model/tools/tools.hpp model/tools/operation.hpp model/tools/stage.hpp model/tools/verifier.hpp - model/tools/mandatoryid.hpp + model/tools/mandatoryid.hpp model/tools/reportmodel.hpp view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp view/doc/subviewfactory.hpp view/doc/subview.hpp view/doc/subviewfactoryimp.hpp view/world/table.hpp view/world/tablesubview.hpp view/world/subviews.hpp + + view/tools/reportsubview.hpp view/tools/subviews.hpp ) set (OPENCS_US diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index f03344e08..9d2694483 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -50,10 +50,11 @@ void CSMDoc::Document::save() emit progress (1, 16, State_Saving, 1, this); } -void CSMDoc::Document::verify() +CSMWorld::UniversalId CSMDoc::Document::verify() { - mTools.runVerifier(); + CSMWorld::UniversalId id = mTools.runVerifier(); emit stateChanged (getState(), this); + return id; } void CSMDoc::Document::abortOperation (int type) @@ -102,6 +103,11 @@ CSMWorld::Data& CSMDoc::Document::getData() return mData; } +CSMTools::ReportModel *CSMDoc::Document::getReport (const CSMWorld::UniversalId& id) +{ + return mTools.getReport (id); +} + void CSMDoc::Document::progress (int current, int max, int type) { emit progress (current, max, type, 1, this); diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index f9d0a232c..43e8bba37 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -13,6 +13,8 @@ #include "state.hpp" +class QAbstractItemModel; + namespace CSMDoc { class Document : public QObject @@ -50,7 +52,7 @@ namespace CSMDoc void save(); - void verify(); + CSMWorld::UniversalId verify(); void abortOperation (int type); @@ -58,6 +60,9 @@ namespace CSMDoc CSMWorld::Data& getData(); + CSMTools::ReportModel *getReport (const CSMWorld::UniversalId& id); + ///< The ownership of the returned report is not transferred. + signals: void stateChanged (int state, CSMDoc::Document *document); diff --git a/apps/opencs/model/tools/reportmodel.cpp b/apps/opencs/model/tools/reportmodel.cpp new file mode 100644 index 000000000..f142d7669 --- /dev/null +++ b/apps/opencs/model/tools/reportmodel.cpp @@ -0,0 +1,66 @@ + +#include "reportmodel.hpp" + +#include + +int CSMTools::ReportModel::rowCount (const QModelIndex & parent) const +{ + if (parent.isValid()) + return 0; + + return mRows.size(); +} + +int CSMTools::ReportModel::columnCount (const QModelIndex & parent) const +{ + if (parent.isValid()) + return 0; + + return 2; +} + +QVariant CSMTools::ReportModel::data (const QModelIndex & index, int role) const +{ + if (role!=Qt::DisplayRole) + return QVariant(); + + if (index.column()==0) + return static_cast (mRows.at (index.row()).first.getType()); + else + return mRows.at (index.row()).second.c_str(); +} + +QVariant CSMTools::ReportModel::headerData (int section, Qt::Orientation orientation, int role) const +{ + if (role!=Qt::DisplayRole) + return QVariant(); + + if (orientation==Qt::Vertical) + return QVariant(); + + return tr (section==0 ? "Type" : "Description"); +} + +bool CSMTools::ReportModel::removeRows (int row, int count, const QModelIndex& parent) +{ + if (parent.isValid()) + return false; + + mRows.erase (mRows.begin()+row, mRows.begin()+row+count); + + return true; +} + +void CSMTools::ReportModel::add (const std::string& row) +{ + std::string::size_type index = row.find ('|'); + + if (index==std::string::npos) + throw std::logic_error ("invalid report message"); + + beginInsertRows (QModelIndex(), mRows.size(), mRows.size()); + + mRows.push_back (std::make_pair (row.substr (0, index), row.substr (index+1))); + + endInsertRows(); +} \ No newline at end of file diff --git a/apps/opencs/model/tools/reportmodel.hpp b/apps/opencs/model/tools/reportmodel.hpp new file mode 100644 index 000000000..8814b6d49 --- /dev/null +++ b/apps/opencs/model/tools/reportmodel.hpp @@ -0,0 +1,35 @@ +#ifndef CSM_TOOLS_REPORTMODEL_H +#define CSM_TOOLS_REPORTMODEL_H + +#include +#include + +#include + +#include "../world/universalid.hpp" + +namespace CSMTools +{ + class ReportModel : public QAbstractTableModel + { + Q_OBJECT + + std::vector > mRows; + + public: + + virtual int rowCount (const QModelIndex & parent = QModelIndex()) const; + + virtual int columnCount (const QModelIndex & parent = QModelIndex()) const; + + virtual QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + + virtual QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); + + void add (const std::string& row); + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index a3cdb7822..8dd1c0fe6 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -8,7 +8,9 @@ #include "../doc/state.hpp" #include "../world/data.hpp" +#include "../world/universalid.hpp" +#include "reportmodel.hpp" #include "mandatoryid.hpp" CSMTools::Operation *CSMTools::Tools::get (int type) @@ -54,9 +56,10 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier() return mVerifier; } -CSMTools::Tools::Tools (CSMWorld::Data& data) : mData (data), mVerifier (0) +CSMTools::Tools::Tools (CSMWorld::Data& data) : mData (data), mVerifier (0), mNextReportNumber (0) { - + for (std::map::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter) + delete iter->second; } CSMTools::Tools::~Tools() @@ -64,9 +67,14 @@ CSMTools::Tools::~Tools() delete mVerifier; } -void CSMTools::Tools::runVerifier() +CSMWorld::UniversalId CSMTools::Tools::runVerifier() { + mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel)); + mActiveReports[CSMDoc::State_Verifying] = mNextReportNumber-1; + getVerifier()->start(); + + return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_VerificationResults, mNextReportNumber-1); } void CSMTools::Tools::abortOperation (int type) @@ -93,15 +101,23 @@ int CSMTools::Tools::getRunningOperations() const return result; } +CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId& id) +{ + if (id.getType()!=CSMWorld::UniversalId::Type_VerificationResults) + throw std::logic_error ("invalid request for report model: " + id.toString()); + + return mReports.at (id.getIndex()); +} + void CSMTools::Tools::verifierDone() { emit done (CSMDoc::State_Verifying); } -#include void CSMTools::Tools::verifierMessage (const QString& message, int type) { - /// \todo store it in a result model instead + std::map::iterator iter = mActiveReports.find (type); - std::cout << message.toStdString() << std::endl; + if (iter!=mActiveReports.end()) + mReports[iter->second]->add (message.toStdString()); } \ No newline at end of file diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index da49fd8b8..652345c6d 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -3,15 +3,19 @@ #include +#include + namespace CSMWorld { class Data; + class UniversalId; } namespace CSMTools { class Verifier; class Operation; + class ReportModel; class Tools : public QObject { @@ -19,6 +23,9 @@ namespace CSMTools CSMWorld::Data& mData; Verifier *mVerifier; + std::map mReports; + int mNextReportNumber; + std::map mActiveReports; // type, report number // not implemented Tools (const Tools&); @@ -38,13 +45,17 @@ namespace CSMTools virtual ~Tools(); - void runVerifier(); + CSMWorld::UniversalId runVerifier(); + ///< \return ID of the report for this verification run void abortOperation (int type); ///< \attention The operation is not aborted immediately. int getRunningOperations() const; + ReportModel *getReport (const CSMWorld::UniversalId& id); + ///< The ownership of the returned report is not transferred. + private slots: void verifierDone(); diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index a2b0a3c1f..3fe1fadfe 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -35,7 +35,7 @@ QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const return QVariant(); if (role==Qt::EditRole && !mIdCollection->isEditable (index.column())) - return QVariant(); + return QVariant(); return mIdCollection->getData (index.row(), index.column()); } diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 98fb1d0b9..81561bcf4 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -30,6 +30,7 @@ namespace static const TypeData sIndexArg[] = { + { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; @@ -39,7 +40,7 @@ CSMWorld::UniversalId::UniversalId (const std::string& universalId) { std::string::size_type index = universalId.find (':'); - if (index!=std::string::npos) + if (index==std::string::npos) { std::string type = universalId.substr (0, index); diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 7b630ebc7..14c086510 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -31,7 +31,10 @@ namespace CSMWorld enum Type { Type_None, - Type_Globals + + Type_Globals, + + Type_VerificationResults }; private: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 47053192b..4ffd9d749 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -12,6 +12,8 @@ #include "../world/subviews.hpp" +#include "../tools/subviews.hpp" + #include "viewmanager.hpp" #include "operations.hpp" #include "subview.hpp" @@ -122,6 +124,7 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to setupUi(); CSVWorld::addSubViewFactories (mSubViewFactory); + CSVTools::addSubViewFactories (mSubViewFactory); } CSVDoc::View::~View() @@ -200,7 +203,7 @@ void CSVDoc::View::save() void CSVDoc::View::verify() { - mDocument->verify(); + addSubView (mDocument->verify()); } void CSVDoc::View::addGlobalsSubView() diff --git a/apps/opencs/view/tools/reportsubview.cpp b/apps/opencs/view/tools/reportsubview.cpp new file mode 100644 index 000000000..3c9283684 --- /dev/null +++ b/apps/opencs/view/tools/reportsubview.cpp @@ -0,0 +1,25 @@ + +#include "reportsubview.hpp" + +#include +#include + +#include "../../model/tools/reportmodel.hpp" + +CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) +: CSVDoc::SubView (id) +{ + setWidget (mTable = new QTableView (this)); + mTable->setModel (document.getReport (id)); + + mTable->horizontalHeader()->setResizeMode (QHeaderView::Interactive); + mTable->verticalHeader()->hide(); + mTable->setSortingEnabled (true); + mTable->setSelectionBehavior (QAbstractItemView::SelectRows); + mTable->setSelectionMode (QAbstractItemView::ExtendedSelection); +} + +void CSVTools::ReportSubView::setEditLock (bool locked) +{ + // ignored. We don't change document state anyway. +} \ No newline at end of file diff --git a/apps/opencs/view/tools/reportsubview.hpp b/apps/opencs/view/tools/reportsubview.hpp new file mode 100644 index 000000000..f81f3c386 --- /dev/null +++ b/apps/opencs/view/tools/reportsubview.hpp @@ -0,0 +1,29 @@ +#ifndef CSV_TOOLS_REPORTSUBVIEW_H +#define CSV_TOOLS_REPORTSUBVIEW_H + +#include "../doc/subview.hpp" + +class QTableView; + +namespace CSMDoc +{ + class Document; +} + +namespace CSVTools +{ + class Table; + + class ReportSubView : public CSVDoc::SubView + { + QTableView *mTable; + + public: + + ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); + + virtual void setEditLock (bool locked); + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/tools/subviews.cpp b/apps/opencs/view/tools/subviews.cpp new file mode 100644 index 000000000..781cf602e --- /dev/null +++ b/apps/opencs/view/tools/subviews.cpp @@ -0,0 +1,12 @@ + +#include "subviews.hpp" + +#include "../doc/subviewfactoryimp.hpp" + +#include "reportsubview.hpp" + +void CSVTools::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) +{ + manager.add (CSMWorld::UniversalId::Type_VerificationResults, + new CSVDoc::SubViewFactory); +} \ No newline at end of file diff --git a/apps/opencs/view/tools/subviews.hpp b/apps/opencs/view/tools/subviews.hpp new file mode 100644 index 000000000..1bac32228 --- /dev/null +++ b/apps/opencs/view/tools/subviews.hpp @@ -0,0 +1,14 @@ +#ifndef CSV_TOOLS_SUBVIEWS_H +#define CSV_TOOLS_SUBVIEWS_H + +namespace CSVDoc +{ + class SubViewFactoryManager; +} + +namespace CSVTools +{ + void addSubViewFactories (CSVDoc::SubViewFactoryManager& manager); +} + +#endif From e4ac7a4df4d030e9dcdb6cd6a9352fa8b839a1a6 Mon Sep 17 00:00:00 2001 From: psi29a Date: Wed, 12 Dec 2012 09:27:15 +0100 Subject: [PATCH 050/136] remove libboost1-xxx from deb depends since we can compile statically --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0abaf3403..68c3204fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -361,7 +361,7 @@ if(DPKG_PROGRAM) SET(CPACK_DEBIAN_PACKAGE_NAME "openmw") SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}") SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW esmtool;Esmtool omwlauncher;OMWLauncher mwiniimporter;MWiniImporter") - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libboost-filesystem1.46.1 (>= 1.46.1), libboost-program-options1.46.1 (>= 1.46.1), libboost-system1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.3.0 (>= 1.3.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.3.0 (>= 1.3.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)") SET(CPACK_DEBIAN_PACKAGE_SECTION "Games") From cc18b30e17fe054b4c7b6bd41baafe3aeaa8799a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 12 Dec 2012 22:36:20 +0100 Subject: [PATCH 051/136] open sub view on double click in report view --- apps/opencs/model/tools/reportmodel.cpp | 5 +++++ apps/opencs/model/tools/reportmodel.hpp | 2 ++ apps/opencs/model/world/universalid.hpp | 4 ++++ apps/opencs/view/doc/subview.hpp | 4 ++++ apps/opencs/view/doc/view.cpp | 4 ++++ apps/opencs/view/doc/view.hpp | 6 ++++-- apps/opencs/view/tools/reportsubview.cpp | 11 +++++++++-- apps/opencs/view/tools/reportsubview.hpp | 13 +++++++++++++ 8 files changed, 45 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/tools/reportmodel.cpp b/apps/opencs/model/tools/reportmodel.cpp index f142d7669..b12531875 100644 --- a/apps/opencs/model/tools/reportmodel.cpp +++ b/apps/opencs/model/tools/reportmodel.cpp @@ -63,4 +63,9 @@ void CSMTools::ReportModel::add (const std::string& row) mRows.push_back (std::make_pair (row.substr (0, index), row.substr (index+1))); endInsertRows(); +} + +const CSMWorld::UniversalId& CSMTools::ReportModel::getUniversalId (int row) const +{ + return mRows.at (row).first; } \ No newline at end of file diff --git a/apps/opencs/model/tools/reportmodel.hpp b/apps/opencs/model/tools/reportmodel.hpp index 8814b6d49..55c25d907 100644 --- a/apps/opencs/model/tools/reportmodel.hpp +++ b/apps/opencs/model/tools/reportmodel.hpp @@ -29,6 +29,8 @@ namespace CSMTools virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); void add (const std::string& row); + + const CSMWorld::UniversalId& getUniversalId (int row) const; }; } diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 14c086510..8f43bf083 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -4,6 +4,8 @@ #include #include +#include + namespace CSMWorld { class UniversalId @@ -87,4 +89,6 @@ namespace CSMWorld std::ostream& operator< (std::ostream& stream, const UniversalId& universalId); } +Q_DECLARE_METATYPE (CSMWorld::UniversalId) + #endif diff --git a/apps/opencs/view/doc/subview.hpp b/apps/opencs/view/doc/subview.hpp index 50ec511ab..985c5eb3c 100644 --- a/apps/opencs/view/doc/subview.hpp +++ b/apps/opencs/view/doc/subview.hpp @@ -35,6 +35,10 @@ namespace CSVDoc CSMWorld::UniversalId getUniversalId() const; virtual void setEditLock (bool locked) = 0; + + signals: + + void focusId (const CSMWorld::UniversalId& universalId); }; } diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 4ffd9d749..13edb6e74 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -188,6 +188,10 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id) SubView *view = mSubViewFactory.makeSubView (id, *mDocument); addDockWidget (Qt::TopDockWidgetArea, view); + + connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&)), this, + SLOT (addSubView (const CSMWorld::UniversalId&))); + view->show(); } diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index f7d4dd373..b1dedafe9 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -80,12 +80,14 @@ namespace CSVDoc void updateProgress (int current, int max, int type, int threads); - void addSubView (const CSMWorld::UniversalId& id); - signals: void newDocumentRequest(); + public slots: + + void addSubView (const CSMWorld::UniversalId& id); + private slots: void newView(); diff --git a/apps/opencs/view/tools/reportsubview.cpp b/apps/opencs/view/tools/reportsubview.cpp index 3c9283684..fe1be85d7 100644 --- a/apps/opencs/view/tools/reportsubview.cpp +++ b/apps/opencs/view/tools/reportsubview.cpp @@ -7,19 +7,26 @@ #include "../../model/tools/reportmodel.hpp" CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) -: CSVDoc::SubView (id) +: CSVDoc::SubView (id), mModel (document.getReport (id)) { setWidget (mTable = new QTableView (this)); - mTable->setModel (document.getReport (id)); + mTable->setModel (mModel); mTable->horizontalHeader()->setResizeMode (QHeaderView::Interactive); mTable->verticalHeader()->hide(); mTable->setSortingEnabled (true); mTable->setSelectionBehavior (QAbstractItemView::SelectRows); mTable->setSelectionMode (QAbstractItemView::ExtendedSelection); + + connect (mTable, SIGNAL (doubleClicked (const QModelIndex&)), this, SLOT (show (const QModelIndex&))); } void CSVTools::ReportSubView::setEditLock (bool locked) { // ignored. We don't change document state anyway. +} + +void CSVTools::ReportSubView::show (const QModelIndex& index) +{ + focusId (mModel->getUniversalId (index.row())); } \ No newline at end of file diff --git a/apps/opencs/view/tools/reportsubview.hpp b/apps/opencs/view/tools/reportsubview.hpp index f81f3c386..626ceb663 100644 --- a/apps/opencs/view/tools/reportsubview.hpp +++ b/apps/opencs/view/tools/reportsubview.hpp @@ -4,18 +4,27 @@ #include "../doc/subview.hpp" class QTableView; +class QModelIndex; namespace CSMDoc { class Document; } +namespace CSMTools +{ + class ReportModel; +} + namespace CSVTools { class Table; class ReportSubView : public CSVDoc::SubView { + Q_OBJECT + + CSMTools::ReportModel *mModel; QTableView *mTable; public: @@ -23,6 +32,10 @@ namespace CSVTools ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); virtual void setEditLock (bool locked); + + private slots: + + void show (const QModelIndex& index); }; } From 02184526e6988d34478fb28921f4ba2edd7fc2f4 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 13 Dec 2012 11:24:39 +0100 Subject: [PATCH 052/136] moved two helper classes from view/world/table into a separate translation unit --- apps/opencs/CMakeLists.txt | 4 +- apps/opencs/view/world/table.cpp | 94 +------------------------------- apps/opencs/view/world/util.cpp | 57 +++++++++++++++++++ apps/opencs/view/world/util.hpp | 50 +++++++++++++++++ 4 files changed, 110 insertions(+), 95 deletions(-) create mode 100644 apps/opencs/view/world/util.cpp create mode 100644 apps/opencs/view/world/util.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 1f9fe85a2..554607c73 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -13,7 +13,7 @@ set (OPENCS_SRC view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp view/doc/subviewfactory.cpp view/doc/subview.cpp - view/world/table.cpp view/world/tablesubview.cpp view/world/subviews.cpp + view/world/table.cpp view/world/tablesubview.cpp view/world/subviews.cpp view/world/util.cpp view/tools/reportsubview.cpp view/tools/subviews.cpp ) @@ -33,7 +33,7 @@ set (OPENCS_HDR view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp view/doc/subviewfactory.hpp view/doc/subview.hpp view/doc/subviewfactoryimp.hpp - view/world/table.hpp view/world/tablesubview.hpp view/world/subviews.hpp + view/world/table.hpp view/world/tablesubview.hpp view/world/subviews.hpp view/world/util.hpp view/tools/reportsubview.hpp view/tools/subviews.hpp ) diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 593dc8563..3a5ef7c34 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -1,7 +1,6 @@ #include "table.hpp" -#include #include #include #include @@ -14,98 +13,7 @@ #include "../../model/world/idtable.hpp" #include "../../model/world/record.hpp" -namespace CSVWorld -{ - ///< \brief Getting the data out of an editor widget - /// - /// Really, Qt? Really? - class NastyTableModelHack : public QAbstractTableModel - { - QAbstractItemModel& mModel; - QVariant mData; - - public: - - NastyTableModelHack (QAbstractItemModel& model); - - int rowCount (const QModelIndex & parent = QModelIndex()) const; - - int columnCount (const QModelIndex & parent = QModelIndex()) const; - - QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; - - bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); - - QVariant getData() const; - }; - - ///< \brief Use commands instead of manipulating the model directly - class CommandDelegate : public QStyledItemDelegate - { - QUndoStack& mUndoStack; - bool mEditLock; - - public: - - CommandDelegate (QUndoStack& undoStack, QObject *parent); - - void setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const; - - void setEditLock (bool locked); - }; - -} - -CSVWorld::NastyTableModelHack::NastyTableModelHack (QAbstractItemModel& model) -: mModel (model) -{} - -int CSVWorld::NastyTableModelHack::rowCount (const QModelIndex & parent) const -{ - return mModel.rowCount (parent); -} - -int CSVWorld::NastyTableModelHack::columnCount (const QModelIndex & parent) const -{ - return mModel.columnCount (parent); -} - -QVariant CSVWorld::NastyTableModelHack::data (const QModelIndex & index, int role) const -{ - return mModel.data (index, role); -} - -bool CSVWorld::NastyTableModelHack::setData ( const QModelIndex &index, const QVariant &value, int role) -{ - mData = value; - return true; -} - -QVariant CSVWorld::NastyTableModelHack::getData() const -{ - return mData; -} - -CSVWorld::CommandDelegate::CommandDelegate (QUndoStack& undoStack, QObject *parent) -: QStyledItemDelegate (parent), mUndoStack (undoStack), mEditLock (false) -{} - -void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemModel *model, - const QModelIndex& index) const -{ - if (!mEditLock) - { - NastyTableModelHack hack (*model); - QStyledItemDelegate::setModelData (editor, &hack, index); - mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData())); - } - ///< \todo provide some kind of feedback to the user, indicating that editing is currently not possible. -} - -void CSVWorld::CommandDelegate::setEditLock (bool locked) -{ - mEditLock = locked; -} +#include "util.hpp" void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) { diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp new file mode 100644 index 000000000..7181dd4d1 --- /dev/null +++ b/apps/opencs/view/world/util.cpp @@ -0,0 +1,57 @@ + +#include "util.hpp" + +#include + +#include "../../model/world/commands.hpp" + +CSVWorld::NastyTableModelHack::NastyTableModelHack (QAbstractItemModel& model) +: mModel (model) +{} + +int CSVWorld::NastyTableModelHack::rowCount (const QModelIndex & parent) const +{ + return mModel.rowCount (parent); +} + +int CSVWorld::NastyTableModelHack::columnCount (const QModelIndex & parent) const +{ + return mModel.columnCount (parent); +} + +QVariant CSVWorld::NastyTableModelHack::data (const QModelIndex & index, int role) const +{ + return mModel.data (index, role); +} + +bool CSVWorld::NastyTableModelHack::setData ( const QModelIndex &index, const QVariant &value, int role) +{ + mData = value; + return true; +} + +QVariant CSVWorld::NastyTableModelHack::getData() const +{ + return mData; +} + +CSVWorld::CommandDelegate::CommandDelegate (QUndoStack& undoStack, QObject *parent) +: QStyledItemDelegate (parent), mUndoStack (undoStack), mEditLock (false) +{} + +void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemModel *model, + const QModelIndex& index) const +{ + if (!mEditLock) + { + NastyTableModelHack hack (*model); + QStyledItemDelegate::setModelData (editor, &hack, index); + mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData())); + } + ///< \todo provide some kind of feedback to the user, indicating that editing is currently not possible. +} + +void CSVWorld::CommandDelegate::setEditLock (bool locked) +{ + mEditLock = locked; +} \ No newline at end of file diff --git a/apps/opencs/view/world/util.hpp b/apps/opencs/view/world/util.hpp new file mode 100644 index 000000000..136583118 --- /dev/null +++ b/apps/opencs/view/world/util.hpp @@ -0,0 +1,50 @@ +#ifndef CSV_WORLD_UTIL_H +#define CSV_WORLD_UTIL_H + +#include +#include + +class QUndoStack; + +namespace CSVWorld +{ + ///< \brief Getting the data out of an editor widget + /// + /// Really, Qt? Really? + class NastyTableModelHack : public QAbstractTableModel + { + QAbstractItemModel& mModel; + QVariant mData; + + public: + + NastyTableModelHack (QAbstractItemModel& model); + + int rowCount (const QModelIndex & parent = QModelIndex()) const; + + int columnCount (const QModelIndex & parent = QModelIndex()) const; + + QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + + bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + + QVariant getData() const; + }; + + ///< \brief Use commands instead of manipulating the model directly + class CommandDelegate : public QStyledItemDelegate + { + QUndoStack& mUndoStack; + bool mEditLock; + + public: + + CommandDelegate (QUndoStack& undoStack, QObject *parent); + + void setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const; + + void setEditLock (bool locked); + }; +} + +#endif From 3d4c8c5444ae35b45537a1d877270befa62de4b9 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 13 Dec 2012 13:35:08 +0100 Subject: [PATCH 053/136] added dialogue sub view (editing of a single record; not functional yet); fixed a bug in Universal to string conversion --- apps/opencs/CMakeLists.txt | 2 ++ apps/opencs/model/world/columns.hpp | 18 ++++++++++++++++ apps/opencs/model/world/data.cpp | 1 + apps/opencs/model/world/universalid.cpp | 5 +++-- apps/opencs/model/world/universalid.hpp | 2 ++ apps/opencs/view/world/dialoguesubview.cpp | 14 +++++++++++++ apps/opencs/view/world/dialoguesubview.hpp | 24 ++++++++++++++++++++++ apps/opencs/view/world/subviews.cpp | 4 ++++ apps/opencs/view/world/table.cpp | 9 +++++++- apps/opencs/view/world/table.hpp | 2 ++ apps/opencs/view/world/tablesubview.cpp | 7 +++++++ apps/opencs/view/world/tablesubview.hpp | 8 +++++++- 12 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 apps/opencs/view/world/dialoguesubview.cpp create mode 100644 apps/opencs/view/world/dialoguesubview.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 554607c73..1cfb5d9a9 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -14,6 +14,7 @@ set (OPENCS_SRC view/doc/subview.cpp view/world/table.cpp view/world/tablesubview.cpp view/world/subviews.cpp view/world/util.cpp + view/world/dialoguesubview.cpp view/tools/reportsubview.cpp view/tools/subviews.cpp ) @@ -34,6 +35,7 @@ set (OPENCS_HDR view/doc/subview.hpp view/doc/subviewfactoryimp.hpp view/world/table.hpp view/world/tablesubview.hpp view/world/subviews.hpp view/world/util.hpp + view/world/dialoguesubview.hpp view/tools/reportsubview.hpp view/tools/subviews.hpp ) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 188d3a2ac..0d2d42158 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -67,6 +67,24 @@ namespace CSMWorld return true; } }; + + template + struct FixedRecordTypeColumn : public Column + { + int mType; + + FixedRecordTypeColumn (int type) : Column ("Type"), mType (type) {} + + virtual QVariant get (const Record& record) const + { + return mType; + } + + virtual bool isEditable() const + { + return false; + } + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index f350299ec..0da0cba83 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -14,6 +14,7 @@ CSMWorld::Data::Data() { mGlobals.addColumn (new StringIdColumn); mGlobals.addColumn (new RecordStateColumn); + mGlobals.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Global)); mGlobals.addColumn (new FloatValueColumn); mModels.insert (std::make_pair ( diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 81561bcf4..d8775643a 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -24,6 +24,7 @@ namespace static const TypeData sIdArg[] = { + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; @@ -208,8 +209,8 @@ std::string CSMWorld::UniversalId::toString() const switch (mArgumentType) { case ArgumentType_None: break; - case ArgumentType_Id: stream << ": " << mId; - case ArgumentType_Index: stream << ": " << mIndex; + case ArgumentType_Id: stream << ": " << mId; break; + case ArgumentType_Index: stream << ": " << mIndex; break; } return stream.str(); diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 8f43bf083..4a73feb12 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -36,6 +36,8 @@ namespace CSMWorld Type_Globals, + Type_Global, + Type_VerificationResults }; diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp new file mode 100644 index 000000000..e2d16f1e3 --- /dev/null +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -0,0 +1,14 @@ + +#include "dialoguesubview.hpp" + +CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, + bool createAndDelete) +: SubView (id) +{ + +} + +void CSVWorld::DialogueSubView::setEditLock (bool locked) +{ + +} \ No newline at end of file diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp new file mode 100644 index 000000000..c57dab108 --- /dev/null +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -0,0 +1,24 @@ +#ifndef CSV_WORLD_DIALOGUESUBVIEW_H +#define CSV_WORLD_DIALOGUESUBVIEW_H + +#include "../doc/subview.hpp" + +namespace CSMDoc +{ + class Document; +} + +namespace CSVWorld +{ + class DialogueSubView : public CSVDoc::SubView + { + + public: + + DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, bool createAndDelete); + + virtual void setEditLock (bool locked); + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index fdc0cb31d..080a175ea 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -4,9 +4,13 @@ #include "../doc/subviewfactoryimp.hpp" #include "tablesubview.hpp" +#include "dialoguesubview.hpp" void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) { manager.add (CSMWorld::UniversalId::Type_Globals, new CSVDoc::SubViewFactoryWithCreateFlag (true)); + + manager.add (CSMWorld::UniversalId::Type_Global, + new CSVDoc::SubViewFactoryWithCreateFlag (true)); } \ No newline at end of file diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 3a5ef7c34..6892c7f61 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -2,7 +2,7 @@ #include "table.hpp" #include -#include + #include #include #include @@ -129,6 +129,13 @@ void CSVWorld::Table::setEditLock (bool locked) mEditLock = locked; } +CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const +{ + return CSMWorld::UniversalId ( + static_cast (mProxyModel->data (mProxyModel->index (row, 2)).toInt()), + mProxyModel->data (mProxyModel->index (row, 0)).toString().toStdString()); +} + #include /// \todo remove void CSVWorld::Table::createRecord() { diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index b58ba8328..df0224583 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -50,6 +50,8 @@ namespace CSVWorld void setEditLock (bool locked); + CSMWorld::UniversalId getUniversalId (int row) const; + private slots: void createRecord(); diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index 4abd531d0..bb4bb76c6 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -10,9 +10,16 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D : SubView (id) { setWidget (mTable = new Table (id, document.getData(), document.getUndoStack(), createAndDelete)); + + connect (mTable, SIGNAL (doubleClicked (const QModelIndex&)), this, SLOT (rowActivated (const QModelIndex&))); } void CSVWorld::TableSubView::setEditLock (bool locked) { mTable->setEditLock (locked); +} + +void CSVWorld::TableSubView::rowActivated (const QModelIndex& index) +{ + focusId (mTable->getUniversalId (index.row())); } \ No newline at end of file diff --git a/apps/opencs/view/world/tablesubview.hpp b/apps/opencs/view/world/tablesubview.hpp index 9b0785c47..0e7b8aa30 100644 --- a/apps/opencs/view/world/tablesubview.hpp +++ b/apps/opencs/view/world/tablesubview.hpp @@ -3,7 +3,7 @@ #include "../doc/subview.hpp" -class QUndoStack; +class QModelIndex; namespace CSMDoc { @@ -16,6 +16,8 @@ namespace CSVWorld class TableSubView : public CSVDoc::SubView { + Q_OBJECT + Table *mTable; public: @@ -23,6 +25,10 @@ namespace CSVWorld TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, bool createAndDelete); virtual void setEditLock (bool locked); + + private slots: + + void rowActivated (const QModelIndex& index); }; } From 640c218df392442b389b939e35a1ee7259c71caf Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 13 Dec 2012 13:52:26 +0100 Subject: [PATCH 054/136] made record state uneditable again --- apps/opencs/model/world/columns.hpp | 5 +++++ apps/opencs/model/world/idcollection.hpp | 19 +++++++++++++++++++ apps/opencs/model/world/idtable.cpp | 2 +- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 0d2d42158..00c688484 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -66,6 +66,11 @@ namespace CSMWorld { return true; } + + virtual bool isUserEditable() const + { + return false; + } }; template diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index 50afa715e..529e474d5 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -32,8 +32,17 @@ namespace CSMWorld } virtual bool isEditable() const = 0; + + virtual bool isUserEditable() const; + ///< Can this column be edited directly by the user? }; + template + bool Column::isUserEditable() const + { + return isEditable(); + } + class IdCollectionBase { // not implemented @@ -62,6 +71,8 @@ namespace CSMWorld virtual bool isEditable (int column) const = 0; + virtual bool isUserEditable (int column) const = 0; + virtual void merge() = 0; ///< Merge modified into base. @@ -129,6 +140,8 @@ namespace CSMWorld virtual bool isEditable (int column) const; + virtual bool isUserEditable (int column) const; + virtual void merge(); ///< Merge modified into base. @@ -250,6 +263,12 @@ namespace CSMWorld return mColumns.at (column)->isEditable(); } + template + bool IdCollection::isUserEditable (int column) const + { + return mColumns.at (column)->isUserEditable(); + } + template void IdCollection::addColumn (Column *column) { diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 3fe1fadfe..3ec2f3d17 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -70,7 +70,7 @@ Qt::ItemFlags CSMWorld::IdTable::flags (const QModelIndex & index) const { Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; - if (mIdCollection->isEditable (index.column())) + if (mIdCollection->isUserEditable (index.column())) flags |= Qt::ItemIsEditable; return flags; From faa5ef087463bd25e7e7bee47b6fcbd4f3b2de57 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 13 Dec 2012 14:53:16 +0100 Subject: [PATCH 055/136] rewrote column class --- apps/opencs/model/world/idcollection.cpp | 11 ++++ apps/opencs/model/world/idcollection.hpp | 69 +++++++++++------------- apps/opencs/model/world/idtable.cpp | 17 +++--- 3 files changed, 53 insertions(+), 44 deletions(-) diff --git a/apps/opencs/model/world/idcollection.cpp b/apps/opencs/model/world/idcollection.cpp index fc4bb1ef6..c6469ea98 100644 --- a/apps/opencs/model/world/idcollection.cpp +++ b/apps/opencs/model/world/idcollection.cpp @@ -1,6 +1,17 @@ #include "idcollection.hpp" +CSMWorld::ColumnBase::ColumnBase (const std::string& title, int flags) +: mTitle (title), mFlags (flags) +{} + +CSMWorld::ColumnBase::~ColumnBase() {} + +bool CSMWorld::ColumnBase::isUserEditable() const +{ + return isEditable(); +} + CSMWorld::IdCollectionBase::IdCollectionBase() {} CSMWorld::IdCollectionBase::~IdCollectionBase() {} \ No newline at end of file diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index 529e474d5..5d6f52aa0 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -15,21 +15,25 @@ namespace CSMWorld { - template - struct Column + struct ColumnBase { - std::string mTitle; + enum Roles + { + Role_Flags = Qt::UserRole + }; - Column (const std::string& title) : mTitle (title) {} + enum Flags + { + Flag_Table = 1, // column should be displayed in table view + Flag_Dialogue = 2 // column should be displayed in dialogue view + }; - virtual ~Column() {} + std::string mTitle; + int mFlags; - virtual QVariant get (const Record& record) const = 0; + ColumnBase (const std::string& title, int flag); - virtual void set (Record& record, const QVariant& data) - { - throw std::logic_error ("Column " + mTitle + " is not editable"); - } + virtual ~ColumnBase(); virtual bool isEditable() const = 0; @@ -38,10 +42,21 @@ namespace CSMWorld }; template - bool Column::isUserEditable() const + struct Column : public ColumnBase { - return isEditable(); - } + std::string mTitle; + int mFlags; + + Column (const std::string& title, int flags = Flag_Table | Flag_Dialogue) + : ColumnBase (title, flags) {} + + virtual QVariant get (const Record& record) const = 0; + + virtual void set (Record& record, const QVariant& data) + { + throw std::logic_error ("Column " + mTitle + " is not editable"); + } + }; class IdCollectionBase { @@ -63,16 +78,12 @@ namespace CSMWorld virtual int getColumns() const = 0; - virtual std::string getTitle (int column) const = 0; + virtual const ColumnBase& getColumn (int column) const = 0; virtual QVariant getData (int index, int column) const = 0; virtual void setData (int index, int column, const QVariant& data) = 0; - virtual bool isEditable (int column) const = 0; - - virtual bool isUserEditable (int column) const = 0; - virtual void merge() = 0; ///< Merge modified into base. @@ -136,11 +147,7 @@ namespace CSMWorld virtual void setData (int index, int column, const QVariant& data); - virtual std::string getTitle (int column) const; - - virtual bool isEditable (int column) const; - - virtual bool isUserEditable (int column) const; + virtual const ColumnBase& getColumn (int column) const; virtual void merge(); ///< Merge modified into base. @@ -252,21 +259,9 @@ namespace CSMWorld } template - std::string IdCollection::getTitle (int column) const - { - return mColumns.at (column)->mTitle; - } - - template - bool IdCollection::isEditable (int column) const - { - return mColumns.at (column)->isEditable(); - } - - template - bool IdCollection::isUserEditable (int column) const + const ColumnBase& IdCollection::getColumn (int column) const { - return mColumns.at (column)->isUserEditable(); + return *mColumns.at (column); } template diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 3ec2f3d17..2815e318c 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -34,7 +34,7 @@ QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const if (role!=Qt::DisplayRole && role!=Qt::EditRole) return QVariant(); - if (role==Qt::EditRole && !mIdCollection->isEditable (index.column())) + if (role==Qt::EditRole && !mIdCollection->getColumn (index.column()).isEditable()) return QVariant(); return mIdCollection->getData (index.row(), index.column()); @@ -42,18 +42,21 @@ QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const QVariant CSMWorld::IdTable::headerData (int section, Qt::Orientation orientation, int role) const { - if (role!=Qt::DisplayRole) - return QVariant(); - if (orientation==Qt::Vertical) return QVariant(); - return tr (mIdCollection->getTitle (section).c_str()); + if (role==Qt::DisplayRole) + return tr (mIdCollection->getColumn (section).mTitle.c_str()); + + if (role==ColumnBase::Role_Flags) + return mIdCollection->getColumn (section).mFlags; + + return QVariant(); } bool CSMWorld::IdTable::setData ( const QModelIndex &index, const QVariant &value, int role) { - if (mIdCollection->isEditable (index.column()) && role==Qt::EditRole) + if (mIdCollection->getColumn (index.column()).isEditable() && role==Qt::EditRole) { mIdCollection->setData (index.row(), index.column(), value); @@ -70,7 +73,7 @@ Qt::ItemFlags CSMWorld::IdTable::flags (const QModelIndex & index) const { Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; - if (mIdCollection->isUserEditable (index.column())) + if (mIdCollection->getColumn (index.column()).isUserEditable()) flags |= Qt::ItemIsEditable; return flags; From f95e72166c20cd6e64cebc5bb46b937e6ca62ccc Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 13 Dec 2012 15:03:35 +0100 Subject: [PATCH 056/136] hide type column in non-mixed type tables --- apps/opencs/model/world/columns.hpp | 2 +- apps/opencs/view/world/table.cpp | 25 ++++++++++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 00c688484..f58d77c90 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -78,7 +78,7 @@ namespace CSMWorld { int mType; - FixedRecordTypeColumn (int type) : Column ("Type"), mType (type) {} + FixedRecordTypeColumn (int type) : Column ("Type", 0), mType (type) {} virtual QVariant get (const Record& record) const { diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 6892c7f61..0721ead2c 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -84,15 +84,6 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q { mModel = &dynamic_cast (*data.getTableModel (id)); - int columns = mModel->columnCount(); - - for (int i=0; isetSourceModel (mModel); @@ -103,6 +94,22 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q setSelectionBehavior (QAbstractItemView::SelectRows); setSelectionMode (QAbstractItemView::ExtendedSelection); + int columns = mModel->columnCount(); + + for (int i=0; iheaderData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt(); + + if (flags & CSMWorld::ColumnBase::Flag_Table) + { + CommandDelegate *delegate = new CommandDelegate (undoStack, this); + mDelegates.push_back (delegate); + setItemDelegateForColumn (i, delegate); + } + else + hideColumn (i); + } + /// \todo make initial layout fill the whole width of the table if (createAndDelete) From a6c3e06e543bef88f25935d1aeb66ff357550f27 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 15 Dec 2012 20:36:17 +0100 Subject: [PATCH 057/136] fixed fog in some cells --- files/materials/objects.shader | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 5ea076342..25624351c 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -227,7 +227,7 @@ float4 worldNormal = shMatrixMult(worldMatrix, float4(normal.xyz, 0)); waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0,1,0), waterLevel); caustics = getCaustics(causticMap, worldPos, waterEyePos.xyz, worldNormal.xyz, lightDirectionWS0.xyz, waterLevel, waterTimer, windDir_windSpeed); - if (worldPos.y >= waterLevel || waterEnabled != 1) + if (worldPos.y >= waterLevel || waterEnabled != 1.f) caustics = float3(1,1,1); #endif @@ -269,7 +269,7 @@ #if UNDERWATER // regular fog only if fragment is above water - if (worldPos.y > waterLevel) + if (worldPos.y > waterLevel || waterEnabled != 1.f) #endif shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, gammaCorrectRead(fogColour), fogValue); #endif From 77852439ce561091596fe749f9b79b33570c3ec7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 16 Dec 2012 12:52:23 +0100 Subject: [PATCH 058/136] moved ColumnBase and Column struct into a separate translation unit --- apps/opencs/model/world/columnbase.cpp | 13 ++++++ apps/opencs/model/world/columnbase.hpp | 57 ++++++++++++++++++++++++ apps/opencs/model/world/idcollection.cpp | 11 ----- apps/opencs/model/world/idcollection.hpp | 45 +------------------ 4 files changed, 71 insertions(+), 55 deletions(-) create mode 100644 apps/opencs/model/world/columnbase.cpp create mode 100644 apps/opencs/model/world/columnbase.hpp diff --git a/apps/opencs/model/world/columnbase.cpp b/apps/opencs/model/world/columnbase.cpp new file mode 100644 index 000000000..7adc7e6c3 --- /dev/null +++ b/apps/opencs/model/world/columnbase.cpp @@ -0,0 +1,13 @@ + +#include "columnbase.hpp" + +CSMWorld::ColumnBase::ColumnBase (const std::string& title, int flags) +: mTitle (title), mFlags (flags) +{} + +CSMWorld::ColumnBase::~ColumnBase() {} + +bool CSMWorld::ColumnBase::isUserEditable() const +{ + return isEditable(); +} \ No newline at end of file diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp new file mode 100644 index 000000000..dc077eff6 --- /dev/null +++ b/apps/opencs/model/world/columnbase.hpp @@ -0,0 +1,57 @@ +#ifndef CSM_WOLRD_COLUMNBASE_H +#define CSM_WOLRD_COLUMNBASE_H + +#include + +#include +#include + +#include "record.hpp" + +namespace CSMWorld +{ + struct ColumnBase + { + enum Roles + { + Role_Flags = Qt::UserRole + }; + + enum Flags + { + Flag_Table = 1, // column should be displayed in table view + Flag_Dialogue = 2 // column should be displayed in dialogue view + }; + + std::string mTitle; + int mFlags; + + ColumnBase (const std::string& title, int flag); + + virtual ~ColumnBase(); + + virtual bool isEditable() const = 0; + + virtual bool isUserEditable() const; + ///< Can this column be edited directly by the user? + }; + + template + struct Column : public ColumnBase + { + std::string mTitle; + int mFlags; + + Column (const std::string& title, int flags = Flag_Table | Flag_Dialogue) + : ColumnBase (title, flags) {} + + virtual QVariant get (const Record& record) const = 0; + + virtual void set (Record& record, const QVariant& data) + { + throw std::logic_error ("Column " + mTitle + " is not editable"); + } + }; +} + +#endif diff --git a/apps/opencs/model/world/idcollection.cpp b/apps/opencs/model/world/idcollection.cpp index c6469ea98..fc4bb1ef6 100644 --- a/apps/opencs/model/world/idcollection.cpp +++ b/apps/opencs/model/world/idcollection.cpp @@ -1,17 +1,6 @@ #include "idcollection.hpp" -CSMWorld::ColumnBase::ColumnBase (const std::string& title, int flags) -: mTitle (title), mFlags (flags) -{} - -CSMWorld::ColumnBase::~ColumnBase() {} - -bool CSMWorld::ColumnBase::isUserEditable() const -{ - return isEditable(); -} - CSMWorld::IdCollectionBase::IdCollectionBase() {} CSMWorld::IdCollectionBase::~IdCollectionBase() {} \ No newline at end of file diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index 5d6f52aa0..1b2d1e349 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -11,53 +11,10 @@ #include -#include "record.hpp" +#include "columnbase.hpp" namespace CSMWorld { - struct ColumnBase - { - enum Roles - { - Role_Flags = Qt::UserRole - }; - - enum Flags - { - Flag_Table = 1, // column should be displayed in table view - Flag_Dialogue = 2 // column should be displayed in dialogue view - }; - - std::string mTitle; - int mFlags; - - ColumnBase (const std::string& title, int flag); - - virtual ~ColumnBase(); - - virtual bool isEditable() const = 0; - - virtual bool isUserEditable() const; - ///< Can this column be edited directly by the user? - }; - - template - struct Column : public ColumnBase - { - std::string mTitle; - int mFlags; - - Column (const std::string& title, int flags = Flag_Table | Flag_Dialogue) - : ColumnBase (title, flags) {} - - virtual QVariant get (const Record& record) const = 0; - - virtual void set (Record& record, const QVariant& data) - { - throw std::logic_error ("Column " + mTitle + " is not editable"); - } - }; - class IdCollectionBase { // not implemented From f0f521a4e0550ae454100065fc2a0a1b05fed5ac Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 16 Dec 2012 16:55:59 +0100 Subject: [PATCH 059/136] enableRestMenu -> enableRest --- apps/openmw/mwscript/guiextensions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/guiextensions.cpp b/apps/openmw/mwscript/guiextensions.cpp index 72c2db164..7d437f3c0 100644 --- a/apps/openmw/mwscript/guiextensions.cpp +++ b/apps/openmw/mwscript/guiextensions.cpp @@ -181,7 +181,7 @@ opcodeEnableStatsReviewMenu); extensions.registerInstruction ("enablemapmenu", "", opcodeEnableMapMenu); extensions.registerInstruction ("enablestatsmenu", "", opcodeEnableStatsMenu); - extensions.registerInstruction ("enablerestmenu", "", opcodeEnableRest); + extensions.registerInstruction ("enablerest", "", opcodeEnableRest); extensions.registerInstruction ("enablelevelupmenu", "", opcodeEnableRest); extensions.registerInstruction ("showrestmenu", "", opcodeShowRestMenu); From 32f051d61dfe6be90bfacc4413d560c63a31ed64 Mon Sep 17 00:00:00 2001 From: Thoronador Date: Mon, 17 Dec 2012 23:13:33 +0100 Subject: [PATCH 060/136] Remove 'GMST fixing' for dirty GMST records The 'fixing' for so-called dirty GMSTs does not work properly in its current state anyway, so it should be removed. Fixing the 'GMST fixing' might not be possible, because whether or not a GMST is 'dirty' depends on the language version of MW. Therefore different 'fixing' algorithms would be required for the different MW localisations, and I do not see a good reason why GMST values should be hard-coded in the GMST load procedure. In my opinion, it only clutters the code. Last but not least, I believe that it is not the task of the engine to clean ESM files from dirty entries. That is a job for the modders, who should only release clean ESM/ESP files in the first place. The engine should not need to worry about whether a file is 'dirty' or not. That is why I believe a feature for cleaning ESM/ESP files shall not be part of the engine. --- components/esm/loadgmst.cpp | 139 +----------------------------------- components/esm/loadgmst.hpp | 60 ---------------- 2 files changed, 1 insertion(+), 198 deletions(-) diff --git a/components/esm/loadgmst.cpp b/components/esm/loadgmst.cpp index 14e29f4ae..6ce20f935 100644 --- a/components/esm/loadgmst.cpp +++ b/components/esm/loadgmst.cpp @@ -10,138 +10,10 @@ namespace ESM { -/// \todo Review GMST "fixing". Probably remove completely or at least make it optional. Its definitely not -/// working properly in its current state and I doubt it can be fixed without breaking other stuff. - -// Some handy macros -#define cI(s,x) { label = (s); boost::algorithm::to_lower(label); if (mId == label) return (mI == (x)); } -#define cF(s,x) { label = (s); boost::algorithm::to_lower(label); if (mId == label) return (mF == (x)); } -#define cS(s,x) { label = (s); boost::algorithm::to_lower(label); if (mId == label) return (mStr == (x)); } - -bool GameSetting::isDirtyTribunal() -{ - /* - Here, mId contains the game setting name, and we check the - setting for certain values. If it matches, this is a "mDirty" - entry. The correct entry (as defined in Tribunal and Bloodmoon - esms) are given in the comments. Many of the values are correct, - and are marked as 'same'. We still ignore them though, as they - are still in the wrong file and might override custom values - from other mods. - */ - - std::string label; - // Strings - cS("sProfitValue", "Profit Value"); // 'Profit:' - cS("sEditNote", "Edit Note"); // same - cS("sDeleteNote", "Delete Note?"); // same - cS("sMaxSale", "Max Sale"); // 'Seller Max' - cS("sMagicFabricantID", "Fabricant"); // 'Fabricant_summon' - cS("sTeleportDisabled", - "Teleportation magic does not work here.");// same - cS("sLevitateDisabled", - "Levitation magic does not work here."); // same - cS("sCompanionShare", "Companion Share"); // 'Share' - cS("sCompanionWarningButtonOne", - "Let the mercenary quit."); // same - cS("sCompanionWarningButtonTwo", - "Return to Companion Share display."); // same - cS("sCompanionWarningMessage", - "Your mercenary is poorer now than when he contracted with you. Your mercenary will quit if you do not give him gold or goods to bring his Profit Value to a positive value."); - // 'Your mercenary is poorer now than when he contracted with - // you. Your mercenary will quit if you do not give him gold - // or goods to bring his Profit to a positive value.' - // [The difference here is "Profit Value" -> "Profit"] - - // Strings that matches the mId - cS("sEffectSummonFabricant", "sEffectSummonFabricant");// 'Summon Fabricant' - return false; -} - -// Bloodmoon variant -bool GameSetting::isDirtyBloodmoon() -{ - std::string label; - // Strings - cS("sWerewolfPopup", "Werewolf"); // same - cS("sWerewolfRestMessage", - "You cannot rest in werewolf form."); // same - cS("sWerewolfRefusal", - "You cannot do this as a werewolf."); // same - cS("sWerewolfAlarmMessage", - "You have been detected changing from a werewolf state."); - // 'You have been detected as a known werewolf.' - - // Strings that matches the mId - cS("sMagicCreature01ID", "sMagicCreature01ID"); // 'BM_wolf_grey_summon' - cS("sMagicCreature02ID", "sMagicCreature02ID"); // 'BM_bear_black_summon' - cS("sMagicCreature03ID", "sMagicCreature03ID"); // 'BM_wolf_bone_summon' - cS("sMagicCreature04ID", "sMagicCreature04ID"); // same - cS("sMagicCreature05ID", "sMagicCreature05ID"); // same - cS("sEffectSummonCreature01", "sEffectSummonCreature01"); // 'Calf Wolf' - cS("sEffectSummonCreature02", "sEffectSummonCreature02"); // 'Calf Bear' - cS("sEffectSummonCreature03", "sEffectSummonCreature03"); // 'Summon Bonewolf' - cS("sEffectSummonCreature04", "sEffectSummonCreature04"); // same - cS("sEffectSummonCreature05", "sEffectSummonCreature05"); // same - - // Integers - cI("iWereWolfBounty", 10000); // 1000 - cI("iWereWolfFightMod", 100); // same - cI("iWereWolfFleeMod", 100); // same - cI("iWereWolfLevelToAttack", 20); // same - - // Floats - cF("fFleeDistance", 3000); // same - cF("fCombatDistanceWerewolfMod", 0.3); // same - cF("fWereWolfFatigue", 400); // same - cF("fWereWolfEnchant", 1); // 0 - cF("fWereWolfArmorer", 1); // 0 - cF("fWereWolfBlock", 1); // 0 - cF("fWereWolfSneak", 1); // 95 - cF("fWereWolfDestruction", 1); // 0 - cF("fWereWolfEndurance", 150); // same - cF("fWereWolfConjuration", 1); // 0 - cF("fWereWolfRestoration", 1); // 0 - cF("fWereWolfAthletics", 150); // 50 - cF("fWereWolfLuck", 1); // 25 - cF("fWereWolfSilverWeaponDamageMult", 1.5); // 2 - cF("fWereWolfMediumArmor", 1); // 0 - cF("fWereWolfShortBlade", 1); // 0 - cF("fWereWolfAcrobatics", 150); // 80 - cF("fWereWolfSpeechcraft", 1); // 0 - cF("fWereWolfAlteration", 1); // 0 - cF("fWereWolfIllusion", 1); // 0 - cF("fWereWolfLongBlade", 1); // 0 - cF("fWereWolfMarksman", 1); // 0 - cF("fWereWolfHandtoHand", 100); // same - cF("fWereWolfIntellegence", 1); // 0 - cF("fWereWolfAlchemy", 1); // 0 - cF("fWereWolfUnarmored", 100); // same - cF("fWereWolfAxe", 1); // 0 - cF("fWereWolfRunMult", 1.5); // 1.3 - cF("fWereWolfMagicka", 100); // same - cF("fWereWolfAgility", 150); // same - cF("fWereWolfBluntWeapon", 1); // 0 - cF("fWereWolfSecurity", 1); // 0 - cF("fWereWolfPersonality", 1); // 0 - cF("fWereWolfMerchantile", 1); // 0 - cF("fWereWolfHeavyArmor", 1); // 0 - cF("fWereWolfSpear", 1); // 0 - cF("fWereWolfStrength", 150); // same - cF("fWereWolfHealth", 2); // same - cF("fWereWolfMysticism", 1); // 0 - cF("fWereWolfLightArmor", 1); // 0 - cF("fWereWolfWillPower", 1); // 0 - cF("fWereWolfSpeed", 150); // 90 - return false; -} - void GameSetting::load(ESMReader &esm) { assert(mId != ""); - mDirty = false; - // We are apparently allowed to be empty if (!esm.hasMoreSubs()) { @@ -169,17 +41,8 @@ void GameSetting::load(ESMReader &esm) } else esm.fail("Unwanted subrecord type"); - - int spf = esm.getSpecial(); - - // Check if this is one of the mDirty values mentioned above. If it - // is, we set the mDirty flag. This will ONLY work if you've set - // the 'id' string correctly before calling load(). - - if ((spf != SF_Tribunal && isDirtyTribunal()) || (spf != SF_Bloodmoon - && isDirtyBloodmoon())) - mDirty = true; } + void GameSetting::save(ESMWriter &esm) { switch(mType) diff --git a/components/esm/loadgmst.hpp b/components/esm/loadgmst.hpp index a3471598c..ab9a9551e 100644 --- a/components/esm/loadgmst.hpp +++ b/components/esm/loadgmst.hpp @@ -25,66 +25,6 @@ struct GameSetting float mF; VarType mType; - // Set to true if this is a 'dirty' entry which should be ignored - bool mDirty; - - /* - These functions check if this game setting is one of the "dirty" - GMST records found in many mods. These are due to a serious bug in - the official TES3 editor. It only occurs in the newer editor - versions that came with Tribunal and Bloodmoon, and only if a - modder tries to make a mod without loading the corresponding - expansion master file. For example, if you have Tribunal installed - and try to make a mod without loading Tribunal.esm, the editor - will insert these GMST records as a replacement for the entries it - cannot find in the ESMs. - - The values of these "dirty" records differ in general from their - values as defined in Tribunal.esm and Bloodmoon.esm, and are - always set to the same "default" values. Most of these values are - nonsensical, ie. changing the "Seller Max" string to "Max Sale", - or change the stats of werewolves to useless values like 1. Some - of them break certain spell effects. - - It is most likely that these values are just leftover values from - an early stage of development that are inserted as default values - by the editor code. They are supposed to be overridden when the - correct esm file is loaded. When it isn't loaded however, you get - stuck with the initial value, and this gets written to every mod - by the editor, for some reason. - - Bethesda themselves have fallen for this bug. If you install both - Tribunal and Bloodmoon, the updated Tribunal.esm will contain the - dirty GMST settings from Bloodmoon, and Bloodmoon.esm will contain - some of the dirty settings from Tribunal. In other words, this bug - affects the game EVEN IF YOU DO NOT USE ANY MODS! - - The guys at Bethesda are well aware of this bug (and many others), - as the mod community and fan base complained about them for a long - time. But unfortunately it was never fixed. - - There are several tools available to help modders remove these - records from their files, but not all modders use them, and they - really shouldn't have to. In this file we choose instead to reject - all the corrupt values at load time. - - These functions checks if the current game setting is one of the - "dirty" ones as described above. TODO: I have not checked this - against other sources yet, do that later. Currently recognizes 22 - values for tribunal and 50 for bloodmoon. Legitimate GMSTs in mods - (setting values other than the default "dirty" ones) are not - affected and will work correctly. - */ - - /* - Checks for dirty tribunal values. These will be ignored if found - in any file except when they are found in "Tribunal.esm". - */ - bool isDirtyTribunal(); - - // Bloodmoon variant - bool isDirtyBloodmoon(); - void load(ESMReader &esm); int getInt() const; From 5a7a8629b6477fb103709f21df394a936b595458 Mon Sep 17 00:00:00 2001 From: Thoronador Date: Mon, 17 Dec 2012 23:20:43 +0100 Subject: [PATCH 061/136] remove unnecessary include directive --- components/esm/loadgmst.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/esm/loadgmst.cpp b/components/esm/loadgmst.cpp index 6ce20f935..a73095a66 100644 --- a/components/esm/loadgmst.cpp +++ b/components/esm/loadgmst.cpp @@ -2,8 +2,6 @@ #include -#include - #include "esmreader.hpp" #include "esmwriter.hpp" From 1cf019a0070c718976005000af0b50a9ba229af1 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 18 Dec 2012 12:36:26 +0100 Subject: [PATCH 062/136] post merge fix --- apps/esmtool/record.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index b5f97e979..a732f1938 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -738,7 +738,6 @@ void Record::print() default: std::cout << "unknown type"; } - std::cout << "\n Dirty: " << mData.mDirty << std::endl; } template<> From f2c6907244a25949094dfe67529ec53992e44a91 Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Thu, 20 Dec 2012 23:16:34 +0000 Subject: [PATCH 063/136] Added in text escape sequences for dialogue, messageboxes and books. builtins are placeholders, global variables work --- apps/openmw/mwbase/world.hpp | 2 + apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 12 +- apps/openmw/mwgui/formatting.cpp | 12 ++ apps/openmw/mwscript/interpretercontext.cpp | 14 ++ apps/openmw/mwscript/interpretercontext.hpp | 4 + apps/openmw/mwworld/globals.cpp | 11 + apps/openmw/mwworld/globals.hpp | 3 + apps/openmw/mwworld/worldimp.cpp | 5 + apps/openmw/mwworld/worldimp.hpp | 2 + components/CMakeLists.txt | 2 +- components/interpreter/context.hpp | 4 + components/interpreter/defines.cpp | 200 ++++++++++++++++++ components/interpreter/defines.hpp | 12 ++ components/interpreter/miscopcodes.hpp | 4 +- 14 files changed, 282 insertions(+), 5 deletions(-) create mode 100644 components/interpreter/defines.cpp create mode 100644 components/interpreter/defines.hpp diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 40ebde246..0be732790 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -133,6 +133,8 @@ namespace MWBase virtual char getGlobalVariableType (const std::string& name) const = 0; ///< Return ' ', if there is no global variable with this name. + + virtual std::vector getGlobals () const = 0; virtual MWWorld::Ptr getPtr (const std::string& name, bool activeOnly) = 0; ///< Return a pointer to a liveCellRef with the given name. diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 80316c0f5..26d5af202 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -16,6 +16,7 @@ #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -155,7 +156,9 @@ namespace MWDialogue } parseText (info->mResponse); - win->addText (info->mResponse); + + MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor); + win->addText (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext)); executeScript (info->mResultScript); mLastTopic = it->mId; mLastDialogue = *info; @@ -267,7 +270,8 @@ namespace MWDialogue else win->addTitle (topic); - win->addText (info->mResponse); + MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor); + win->addText (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext)); executeScript (info->mResultScript); @@ -411,7 +415,9 @@ namespace MWDialogue mIsInChoice = false; std::string text = info->mResponse; parseText (text); - MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addText (text); + + MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor); + MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addText (Interpreter::fixDefinesDialog(text, interpreterContext)); executeScript (info->mResultScript); mLastTopic = mLastTopic; mLastDialogue = *info; diff --git a/apps/openmw/mwgui/formatting.cpp b/apps/openmw/mwgui/formatting.cpp index 53c23c25d..273034edd 100644 --- a/apps/openmw/mwgui/formatting.cpp +++ b/apps/openmw/mwgui/formatting.cpp @@ -1,5 +1,10 @@ #include "formatting.hpp" +#include + +#include "../mwscript/interpretercontext.hpp" +#include "../mwworld/ptr.hpp" + #include #include @@ -68,6 +73,9 @@ std::vector BookTextParser::split(std::string text, const int width { std::vector result; + MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor + text = Interpreter::fixDefinesDialog(text, interpreterContext); + boost::algorithm::replace_all(text, "
", "\n"); boost::algorithm::replace_all(text, "

", "\n\n"); @@ -167,6 +175,10 @@ std::vector BookTextParser::split(std::string text, const int width MyGUI::IntSize BookTextParser::parse(std::string text, MyGUI::Widget* parent, const int width) { + MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor + text = Interpreter::fixDefinesDialog(text, interpreterContext); + + mParent = parent; mWidth = width; mHeight = 0; diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 577ad008f..4ea984f9c 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -174,6 +174,20 @@ namespace MWScript MWBase::Environment::get().getWorld()->getGlobalVariable (name).mFloat = value; } + std::vector InterpreterContext::getGlobals () const + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + return world->getGlobals(); + + } + + char InterpreterContext::getGlobalType (const std::string& name) const + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + return world->getGlobalVariableType(name); + } + + bool InterpreterContext::isScriptRunning (const std::string& name) const { return MWBase::Environment::get().getScriptManager()->getGlobalScripts().isRunning (name); diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 6d97f7949..15578aa24 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -75,6 +75,10 @@ namespace MWScript virtual void setGlobalLong (const std::string& name, int value); virtual void setGlobalFloat (const std::string& name, float value); + + virtual std::vector getGlobals () const; + + virtual char getGlobalType (const std::string& name) const; virtual bool isScriptRunning (const std::string& name) const; diff --git a/apps/openmw/mwworld/globals.cpp b/apps/openmw/mwworld/globals.cpp index 76dede5a3..f010661b9 100644 --- a/apps/openmw/mwworld/globals.cpp +++ b/apps/openmw/mwworld/globals.cpp @@ -7,6 +7,17 @@ namespace MWWorld { + std::vector Globals::getGlobals () const + { + std::vector retval; + Collection::const_iterator it; + for(it = mVariables.begin(); it != mVariables.end(); ++it){ + retval.push_back(it->first); + } + + return retval; + } + Globals::Collection::const_iterator Globals::find (const std::string& name) const { Collection::const_iterator iter = mVariables.find (name); diff --git a/apps/openmw/mwworld/globals.hpp b/apps/openmw/mwworld/globals.hpp index c7aee5f93..681bd560e 100644 --- a/apps/openmw/mwworld/globals.hpp +++ b/apps/openmw/mwworld/globals.hpp @@ -1,6 +1,7 @@ #ifndef GAME_MWWORLD_GLOBALS_H #define GAME_MWWORLD_GLOBALS_H +#include #include #include @@ -53,6 +54,8 @@ namespace MWWorld char getType (const std::string& name) const; ///< If there is no global variable with this name, ' ' is returned. + + std::vector getGlobals () const; }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f0b2efcec..88ad917c3 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -296,6 +296,11 @@ namespace MWWorld return mGlobalVariables->getType (name); } + std::vector World::getGlobals () const + { + return mGlobalVariables->getGlobals(); + } + Ptr World::getPtr (const std::string& name, bool activeOnly) { // the player is always in an active cell. diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 0962c292c..15b13256a 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -153,6 +153,8 @@ namespace MWWorld virtual char getGlobalVariableType (const std::string& name) const; ///< Return ' ', if there is no global variable with this name. + + virtual std::vector getGlobals () const; virtual Ptr getPtr (const std::string& name, bool activeOnly); ///< Return a pointer to a liveCellRef with the given name. diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 29d6f46cd..bff99a69c 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -59,7 +59,7 @@ add_component_dir (compiler add_component_dir (interpreter context controlopcodes genericopcodes installopcodes interpreter localopcodes mathopcodes - miscopcodes opcodes runtime scriptopcodes spatialopcodes types + miscopcodes opcodes runtime scriptopcodes spatialopcodes types defines ) include_directories(${BULLET_INCLUDE_DIRS}) diff --git a/components/interpreter/context.hpp b/components/interpreter/context.hpp index 4221da36e..2cfc1c03d 100644 --- a/components/interpreter/context.hpp +++ b/components/interpreter/context.hpp @@ -49,6 +49,10 @@ namespace Interpreter virtual void setGlobalFloat (const std::string& name, float value) = 0; + virtual std::vector getGlobals () const = 0; + + virtual char getGlobalType (const std::string& name) const = 0; + virtual bool isScriptRunning (const std::string& name) const = 0; virtual void startScript (const std::string& name) = 0; diff --git a/components/interpreter/defines.cpp b/components/interpreter/defines.cpp new file mode 100644 index 000000000..d5e3e3d0d --- /dev/null +++ b/components/interpreter/defines.cpp @@ -0,0 +1,200 @@ +#include "defines.hpp" + +#include +#include +#include +#include + +namespace Interpreter{ + + bool Check(const std::string str, const std::string escword, unsigned int* i, unsigned int* start){ + bool retval = str.find(escword) == 0; + if(retval){ + (*i) += escword.length(); + (*start) = (*i) + 1; + } + return retval; + } + + std::vector globals; + + bool longerStr(const std::string a, const std::string b){ + return a.length() > b.length(); + } + + std::string fixDefinesReal(std::string text, char eschar, Context& context){ + + unsigned int start = 0; + std::string retval = ""; + for(unsigned int i = 0; i < text.length(); i++){ + if(text[i] == eschar){ + retval += text.substr(start, i - start); + std::string temp = text.substr(i+1, 100); + transform(temp.begin(), temp.end(), temp.begin(), ::tolower); + + bool found; + + if( (found = Check(temp, "actionslideright", &i, &start))){ + retval += "PLACEHOLDER_ACTION_SLIDE_RIGHT"; + } + else if((found = Check(temp, "actionreadymagic", &i, &start))){ + retval += "PLACEHOLDER_ACTION_READY_MAGIC"; + } + else if((found = Check(temp, "actionprevweapon", &i, &start))){ + retval += "PLACEHOLDER_ACTION_PREV_WEAPON"; + } + else if((found = Check(temp, "actionnextweapon", &i, &start))){ + retval += "PLACEHOLDER_ACTION_PREV_WEAPON"; + } + else if((found = Check(temp, "actiontogglerun", &i, &start))){ + retval += "PLACEHOLDER_ACTION_TOGGLE_RUN"; + } + else if((found = Check(temp, "actionslideleft", &i, &start))){ + retval += "PLACEHOLDER_ACTION_TOGGLE_RUN"; + } + else if((found = Check(temp, "actionreadyitem", &i, &start))){ + retval += "PLACEHOLDER_ACTION_READY_ITEM"; + } + else if((found = Check(temp, "actionprevspell", &i, &start))){ + retval += "PLACEHOLDER_ACTION_PREV_SPELL"; + } + else if((found = Check(temp, "actionnextspell", &i, &start))){ + retval += "PLACEHOLDER_ACTION_NEXT_SPELL"; + } + else if((found = Check(temp, "actionrestmenu", &i, &start))){ + retval += "PLACEHOLDER_ACTION_REST_MENU"; + } + else if((found = Check(temp, "actionmenumode", &i, &start))){ + retval += "PLACEHOLDER_ACTION_MENU_MODE"; + } + else if((found = Check(temp, "actionactivate", &i, &start))){ + retval += "PLACEHOLDER_ACTION_ACTIVATE"; + } + else if((found = Check(temp, "actionjournal", &i, &start))){ + retval += "PLACEHOLDER_ACTION_JOURNAL"; + } + else if((found = Check(temp, "actionforward", &i, &start))){ + retval += "PLACEHOLDER_ACTION_FORWARD"; + } + else if((found = Check(temp, "pccrimelevel", &i, &start))){ + retval += "PLACEHOLDER_PC_CRIME_LEVEL"; + } + else if((found = Check(temp, "actioncrouch", &i, &start))){ + retval += "PLACEHOLDER_ACTION_CROUCH"; + } + else if((found = Check(temp, "actionjump", &i, &start))){ + retval += "PLACEHOLDER_ACTION_JUMP"; + } + else if((found = Check(temp, "actionback", &i, &start))){ + retval += "PLACEHOLDER_ACTION_BACK"; + } + else if((found = Check(temp, "actionuse", &i, &start))){ + retval += "PLACEHOLDER_ACTION_USE"; + } + else if((found = Check(temp, "actionrun", &i, &start))){ + retval += "PLACEHOLDER_ACTION_RUN"; + } + else if((found = Check(temp, "pcclass", &i, &start))){ + retval += "PLACEHOLDER_PC_CLASS"; + } + else if((found = Check(temp, "pcrace", &i, &start))){ + retval += "PLACEHOLDER_PC_RACE"; + } + else if((found = Check(temp, "pcname", &i, &start))){ + retval += "PLACEHOLDER_PC_NAME"; + } + else if((found = Check(temp, "cell", &i, &start))){ + retval += "PLACEHOLDER_CELL"; + } + + else if(eschar == '%'){ // In Dialogue, not messagebox + if( (found = Check(temp, "faction", &i, &start))){ + retval += "PLACEHOLDER_FACTION"; + } + else if((found = Check(temp, "nextpcrank", &i, &start))){ + retval += "PLACEHOLDER_NEXT_PC_RANK"; + } + else if((found = Check(temp, "pcnextrank", &i, &start))){ + retval += "PLACEHOLDER_PC_NEXT_RANK"; + } + else if((found = Check(temp, "pcrank", &i, &start))){ + retval += "PLACEHOLDER_PC_RANK"; + } + else if((found = Check(temp, "rank", &i, &start))){ + retval += "PLACEHOLDER_RANK"; + } + + else if((found = Check(temp, "class", &i, &start))){ + retval += "PLACEHOLDER_CLASS"; + } + else if((found = Check(temp, "race", &i, &start))){ + retval += "PLACEHOLDER_RACE"; + } + else if((found = Check(temp, "name", &i, &start))){ + retval += "PLACEHOLDER_NAME"; + } + } + else if(eschar == '^') { // In messagebox, not dialogue + + /* empty in messageboxes */ + if( (found = Check(temp, "faction", &i, &start))); + else if((found = Check(temp, "nextpcrank", &i, &start))); + else if((found = Check(temp, "pcnextrank", &i, &start))); + else if((found = Check(temp, "pcrank", &i, &start))); + else if((found = Check(temp, "rank", &i, &start))); + + /* uses pc in messageboxes */ + else if((found = Check(temp, "class", &i, &start))){ + retval += "PLACEHOLDER_CLASS"; + } + else if((found = Check(temp, "race", &i, &start))){ + retval += "PLACEHOLDER_RACE"; + } + else if((found = Check(temp, "name", &i, &start))){ + retval += "PLACEHOLDER_NAME"; + } + } + + /* Not a builtin, try global variables */ + if(!found){ + /* if list of globals is empty, grab it and sort it by descending string length */ + if(globals.empty()){ + globals = context.getGlobals(); + sort(globals.begin(), globals.end(), longerStr); + } + + for(unsigned int j = 0; j < globals.size(); j++){ + if((found = Check(temp, globals[j], &i, &start))){ + char type = context.getGlobalType(globals[j]); + + switch(type){ + case 's': retval += std::to_string(context.getGlobalShort(globals[j])); break; + case 'l': retval += std::to_string(context.getGlobalLong(globals[j])); break; + case 'f': retval += std::to_string(context.getGlobalFloat(globals[j])); break; + } + break; + } + } + } + + /* Not found */ + if(!found){ + /* leave unmodified */ + i += 1; + start = i; + retval += eschar; + } + } + } + retval += text.substr(start, text.length() - start); + return retval; + } + + std::string fixDefinesDialog(std::string text, Context& context){ + return fixDefinesReal(text, '%', context); + } + + std::string fixDefinesMsgBox(std::string text, Context& context){ + return fixDefinesReal(text, '^', context); + } +} diff --git a/components/interpreter/defines.hpp b/components/interpreter/defines.hpp new file mode 100644 index 000000000..731284661 --- /dev/null +++ b/components/interpreter/defines.hpp @@ -0,0 +1,12 @@ +#ifndef GAME_MWMECHANICS_DEFINES_H +#define GAME_MWMECHANICS_DEFINES_H + +#include +#include "context.hpp" + +namespace Interpreter{ + std::string fixDefinesDialog(std::string text, Context& context); + std::string fixDefinesMsgBox(std::string text, Context& context); +} + +#endif diff --git a/components/interpreter/miscopcodes.hpp b/components/interpreter/miscopcodes.hpp index 37c38fc30..1b4c823a0 100644 --- a/components/interpreter/miscopcodes.hpp +++ b/components/interpreter/miscopcodes.hpp @@ -10,6 +10,7 @@ #include "opcodes.hpp" #include "runtime.hpp" +#include "defines.hpp" namespace Interpreter { @@ -69,7 +70,8 @@ namespace Interpreter } } } - + + formattedMessage = fixDefinesMsgBox(formattedMessage, runtime.getContext()); return formattedMessage; } From 8ac8fdff47b0fdf2523f8dadc2b370994b394f4d Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Fri, 21 Dec 2012 18:09:31 +0000 Subject: [PATCH 064/136] implemented all text defines except a few for keybindings that don't exist yet --- apps/openmw/mwbase/world.hpp | 2 + apps/openmw/mwscript/interpretercontext.cpp | 129 ++++++++++++++++++++ apps/openmw/mwscript/interpretercontext.hpp | 26 ++++ apps/openmw/mwworld/worldimp.cpp | 38 ++++++ apps/openmw/mwworld/worldimp.hpp | 2 + components/interpreter/context.hpp | 26 ++++ components/interpreter/defines.cpp | 58 ++++----- components/interpreter/defines.hpp | 4 +- 8 files changed, 254 insertions(+), 31 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 0be732790..cc625b306 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -136,6 +136,8 @@ namespace MWBase virtual std::vector getGlobals () const = 0; + virtual std::string getCurrentCellName() const = 0; + virtual MWWorld::Ptr getPtr (const std::string& name, bool activeOnly) = 0; ///< Return a pointer to a liveCellRef with the given name. /// \param activeOnly do non search inactive cells. diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 4ea984f9c..cb0e4a7f9 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -11,10 +11,13 @@ #include "../mwbase/world.hpp" #include "../mwbase/scriptmanager.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/inputmanager.hpp" #include "../mwworld/class.hpp" #include "../mwworld/player.hpp" +#include "../mwmechanics/npcstats.hpp" + #include "locals.hpp" #include "globalscripts.hpp" @@ -186,7 +189,133 @@ namespace MWScript MWBase::World *world = MWBase::Environment::get().getWorld(); return world->getGlobalVariableType(name); } + + std::string InterpreterContext::getActionBinding(const std::string& action) const + { + std::vector actions = MWBase::Environment::get().getInputManager()->getActionSorting (); + for (std::vector::const_iterator it = actions.begin(); it != actions.end(); ++it) + { + std::string desc = MWBase::Environment::get().getInputManager()->getActionDescription (*it); + if(desc == "") + continue; + + if(desc == action) + return MWBase::Environment::get().getInputManager()->getActionBindingName (*it); + } + + return "None"; + } + + std::string InterpreterContext::getNPCName() const + { + ESM::NPC npc = *mReference.get()->mBase; + return npc.mName; + } + + std::string InterpreterContext::getNPCRace() const + { + ESM::NPC npc = *mReference.get()->mBase; + return npc.mRace; + } + + std::string InterpreterContext::getNPCClass() const + { + ESM::NPC npc = *mReference.get()->mBase; + return npc.mClass; + } + + std::string InterpreterContext::getNPCFaction() const + { + ESM::NPC npc = *mReference.get()->mBase; + return npc.mFaction; + } + + std::string InterpreterContext::getNPCRank() const + { + std::map ranks = MWWorld::Class::get (mReference).getNpcStats (mReference).getFactionRanks(); + std::map::const_iterator it = ranks.begin(); + + MWBase::World *world = MWBase::Environment::get().getWorld(); + const MWWorld::ESMStore &store = world->getStore(); + const ESM::Faction *faction = store.get().find(it->first); + + return faction->mRanks[it->second]; + } + std::string InterpreterContext::getPCName() const + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + ESM::NPC player = *world->getPlayer().getPlayer().get()->mBase; + return player.mName; + } + + std::string InterpreterContext::getPCRace() const + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + ESM::NPC player = *world->getPlayer().getPlayer().get()->mBase; + return player.mRace; + } + + std::string InterpreterContext::getPCClass() const + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + ESM::NPC player = *world->getPlayer().getPlayer().get()->mBase; + return player.mClass; + } + + std::string InterpreterContext::getPCRank() const + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + MWWorld::Ptr player = world->getPlayer().getPlayer(); + + std::string factionId = MWWorld::Class::get (mReference).getNpcStats (mReference).getFactionRanks().begin()->first; + + std::map ranks = MWWorld::Class::get (player).getNpcStats (player).getFactionRanks(); + std::map::const_iterator it = ranks.begin(); + + const MWWorld::ESMStore &store = world->getStore(); + const ESM::Faction *faction = store.get().find(factionId); + + if(it->second < 0 || it->second > 9) // there are only 10 ranks + return ""; + + return faction->mRanks[it->second]; + } + + std::string InterpreterContext::getPCNextRank() const + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + MWWorld::Ptr player = world->getPlayer().getPlayer(); + + std::string factionId = MWWorld::Class::get (mReference).getNpcStats (mReference).getFactionRanks().begin()->first; + + std::map ranks = MWWorld::Class::get (player).getNpcStats (player).getFactionRanks(); + std::map::const_iterator it = ranks.begin(); + + const MWWorld::ESMStore &store = world->getStore(); + const ESM::Faction *faction = store.get().find(factionId); + + if(it->second < 0 || it->second > 9) + return ""; + + if(it->second <= 8) // If player is at max rank, there is no next rank + return faction->mRanks[it->second + 1]; + else + return faction->mRanks[it->second]; + } + + int InterpreterContext::getPCBounty() const + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + MWWorld::Ptr player = world->getPlayer().getPlayer(); + return MWWorld::Class::get (player).getNpcStats (player).getBounty(); + } + + std::string InterpreterContext::getCurrentCellName() const + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + return world->getCurrentCellName(); + } bool InterpreterContext::isScriptRunning (const std::string& name) const { diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 15578aa24..f0b2758d9 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -79,6 +79,32 @@ namespace MWScript virtual std::vector getGlobals () const; virtual char getGlobalType (const std::string& name) const; + + virtual std::string getActionBinding(const std::string& action) const; + + virtual std::string getNPCName() const; + + virtual std::string getNPCRace() const; + + virtual std::string getNPCClass() const; + + virtual std::string getNPCFaction() const; + + virtual std::string getNPCRank() const; + + virtual std::string getPCName() const; + + virtual std::string getPCRace() const; + + virtual std::string getPCClass() const; + + virtual std::string getPCRank() const; + + virtual std::string getPCNextRank() const; + + virtual int getPCBounty() const; + + virtual std::string getCurrentCellName() const; virtual bool isScriptRunning (const std::string& name) const; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 88ad917c3..343b5dcfc 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -300,6 +300,44 @@ namespace MWWorld { return mGlobalVariables->getGlobals(); } + + std::string World::getCurrentCellName () const + { + std::string name; + + Ptr::CellStore *cell = mWorldScene->getCurrentCell(); + if (cell->mCell->isExterior()) + { + if (cell->mCell->mName != "") + { + name = cell->mCell->mName; + } + else + { + const ESM::Region* region = + MWBase::Environment::get().getWorld()->getStore().get().search(cell->mCell->mRegion); + if (region) + name = region->mName; + else + { + const ESM::GameSetting *setting = + MWBase::Environment::get().getWorld()->getStore().get().search("sDefaultCellname"); + + if (setting && setting->mType == ESM::VT_String) + name = setting->getString(); + else + name = "Wilderness"; + } + + } + } + else + { + name = cell->mCell->mName; + } + + return name; + } Ptr World::getPtr (const std::string& name, bool activeOnly) { diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 15b13256a..ba90dd403 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -155,6 +155,8 @@ namespace MWWorld ///< Return ' ', if there is no global variable with this name. virtual std::vector getGlobals () const; + + virtual std::string getCurrentCellName () const; virtual Ptr getPtr (const std::string& name, bool activeOnly); ///< Return a pointer to a liveCellRef with the given name. diff --git a/components/interpreter/context.hpp b/components/interpreter/context.hpp index 2cfc1c03d..bdba7b6af 100644 --- a/components/interpreter/context.hpp +++ b/components/interpreter/context.hpp @@ -53,6 +53,32 @@ namespace Interpreter virtual char getGlobalType (const std::string& name) const = 0; + virtual std::string getActionBinding(const std::string& action) const = 0; + + virtual std::string getNPCName() const = 0; + + virtual std::string getNPCRace() const = 0; + + virtual std::string getNPCClass() const = 0; + + virtual std::string getNPCFaction() const = 0; + + virtual std::string getNPCRank() const = 0; + + virtual std::string getPCName() const = 0; + + virtual std::string getPCRace() const = 0; + + virtual std::string getPCClass() const = 0; + + virtual std::string getPCRank() const = 0; + + virtual std::string getPCNextRank() const = 0; + + virtual int getPCBounty() const = 0; + + virtual std::string getCurrentCellName() const = 0; + virtual bool isScriptRunning (const std::string& name) const = 0; virtual void startScript (const std::string& name) = 0; diff --git a/components/interpreter/defines.cpp b/components/interpreter/defines.cpp index d5e3e3d0d..bd355fd7c 100644 --- a/components/interpreter/defines.cpp +++ b/components/interpreter/defines.cpp @@ -35,10 +35,10 @@ namespace Interpreter{ bool found; if( (found = Check(temp, "actionslideright", &i, &start))){ - retval += "PLACEHOLDER_ACTION_SLIDE_RIGHT"; + retval += context.getActionBinding("#{sRight}"); } else if((found = Check(temp, "actionreadymagic", &i, &start))){ - retval += "PLACEHOLDER_ACTION_READY_MAGIC"; + retval += context.getActionBinding("#{sReady_Magic}"); } else if((found = Check(temp, "actionprevweapon", &i, &start))){ retval += "PLACEHOLDER_ACTION_PREV_WEAPON"; @@ -47,13 +47,13 @@ namespace Interpreter{ retval += "PLACEHOLDER_ACTION_PREV_WEAPON"; } else if((found = Check(temp, "actiontogglerun", &i, &start))){ - retval += "PLACEHOLDER_ACTION_TOGGLE_RUN"; + retval += context.getActionBinding("#{sAuto_Run}"); } else if((found = Check(temp, "actionslideleft", &i, &start))){ - retval += "PLACEHOLDER_ACTION_TOGGLE_RUN"; + retval += context.getActionBinding("#{sLeft}"); } else if((found = Check(temp, "actionreadyitem", &i, &start))){ - retval += "PLACEHOLDER_ACTION_READY_ITEM"; + retval += context.getActionBinding("#{sReady_Weapon}"); } else if((found = Check(temp, "actionprevspell", &i, &start))){ retval += "PLACEHOLDER_ACTION_PREV_SPELL"; @@ -62,31 +62,31 @@ namespace Interpreter{ retval += "PLACEHOLDER_ACTION_NEXT_SPELL"; } else if((found = Check(temp, "actionrestmenu", &i, &start))){ - retval += "PLACEHOLDER_ACTION_REST_MENU"; + retval += context.getActionBinding("#{sRestKey}"); } else if((found = Check(temp, "actionmenumode", &i, &start))){ - retval += "PLACEHOLDER_ACTION_MENU_MODE"; + retval += context.getActionBinding("#{sJournal}"); } else if((found = Check(temp, "actionactivate", &i, &start))){ - retval += "PLACEHOLDER_ACTION_ACTIVATE"; + retval += context.getActionBinding("#{sActivate}"); } else if((found = Check(temp, "actionjournal", &i, &start))){ - retval += "PLACEHOLDER_ACTION_JOURNAL"; + retval += context.getActionBinding("#{sJournal}"); } else if((found = Check(temp, "actionforward", &i, &start))){ - retval += "PLACEHOLDER_ACTION_FORWARD"; + retval += context.getActionBinding("#{sForward}"); } else if((found = Check(temp, "pccrimelevel", &i, &start))){ - retval += "PLACEHOLDER_PC_CRIME_LEVEL"; + retval += std::to_string(context.getPCBounty()); } else if((found = Check(temp, "actioncrouch", &i, &start))){ - retval += "PLACEHOLDER_ACTION_CROUCH"; + retval += context.getActionBinding("#{sCrouch_Sneak}"); } else if((found = Check(temp, "actionjump", &i, &start))){ - retval += "PLACEHOLDER_ACTION_JUMP"; + retval += context.getActionBinding("#{sJump}"); } else if((found = Check(temp, "actionback", &i, &start))){ - retval += "PLACEHOLDER_ACTION_BACK"; + retval += context.getActionBinding("#{sBack}"); } else if((found = Check(temp, "actionuse", &i, &start))){ retval += "PLACEHOLDER_ACTION_USE"; @@ -95,43 +95,43 @@ namespace Interpreter{ retval += "PLACEHOLDER_ACTION_RUN"; } else if((found = Check(temp, "pcclass", &i, &start))){ - retval += "PLACEHOLDER_PC_CLASS"; + retval += context.getPCClass(); } else if((found = Check(temp, "pcrace", &i, &start))){ - retval += "PLACEHOLDER_PC_RACE"; + retval += context.getPCRace(); } else if((found = Check(temp, "pcname", &i, &start))){ - retval += "PLACEHOLDER_PC_NAME"; + retval += context.getPCName(); } else if((found = Check(temp, "cell", &i, &start))){ - retval += "PLACEHOLDER_CELL"; + retval += context.getCurrentCellName(); } else if(eschar == '%'){ // In Dialogue, not messagebox if( (found = Check(temp, "faction", &i, &start))){ - retval += "PLACEHOLDER_FACTION"; + retval += context.getNPCFaction(); } else if((found = Check(temp, "nextpcrank", &i, &start))){ - retval += "PLACEHOLDER_NEXT_PC_RANK"; + retval += context.getPCNextRank(); } else if((found = Check(temp, "pcnextrank", &i, &start))){ - retval += "PLACEHOLDER_PC_NEXT_RANK"; + retval += context.getPCNextRank(); } else if((found = Check(temp, "pcrank", &i, &start))){ - retval += "PLACEHOLDER_PC_RANK"; + retval += context.getPCRank(); } else if((found = Check(temp, "rank", &i, &start))){ - retval += "PLACEHOLDER_RANK"; + retval += context.getNPCRank(); } else if((found = Check(temp, "class", &i, &start))){ - retval += "PLACEHOLDER_CLASS"; + retval += context.getNPCClass(); } else if((found = Check(temp, "race", &i, &start))){ - retval += "PLACEHOLDER_RACE"; + retval += context.getNPCRace(); } else if((found = Check(temp, "name", &i, &start))){ - retval += "PLACEHOLDER_NAME"; + retval += context.getNPCName(); } } else if(eschar == '^') { // In messagebox, not dialogue @@ -145,13 +145,13 @@ namespace Interpreter{ /* uses pc in messageboxes */ else if((found = Check(temp, "class", &i, &start))){ - retval += "PLACEHOLDER_CLASS"; + retval += context.getPCClass(); } else if((found = Check(temp, "race", &i, &start))){ - retval += "PLACEHOLDER_RACE"; + retval += context.getPCRace(); } else if((found = Check(temp, "name", &i, &start))){ - retval += "PLACEHOLDER_NAME"; + retval += context.getPCName(); } } diff --git a/components/interpreter/defines.hpp b/components/interpreter/defines.hpp index 731284661..4cfba21ea 100644 --- a/components/interpreter/defines.hpp +++ b/components/interpreter/defines.hpp @@ -1,5 +1,5 @@ -#ifndef GAME_MWMECHANICS_DEFINES_H -#define GAME_MWMECHANICS_DEFINES_H +#ifndef INTERPRETER_DEFINES_H_INCLUDED +#define INTERPRETER_DEFINES_H_INCLUDED #include #include "context.hpp" From 74ae47978009d6a0b187284615bc924e4c9ad971 Mon Sep 17 00:00:00 2001 From: lazydev Date: Sun, 23 Dec 2012 23:23:24 +0400 Subject: [PATCH 065/136] Cell names localization fix --- apps/esmtool/esmtool.cpp | 22 ++-- apps/launcher/model/datafilesmodel.cpp | 4 +- apps/openmw/engine.cpp | 9 +- apps/openmw/engine.hpp | 4 +- apps/openmw/main.cpp | 17 +-- apps/openmw/mwclass/door.cpp | 56 ++++++---- apps/openmw/mwclass/door.hpp | 3 + apps/openmw/mwgui/hud.cpp | 2 +- apps/openmw/mwgui/map_window.cpp | 2 +- apps/openmw/mwgui/windowmanagerimp.cpp | 28 +++-- apps/openmw/mwgui/windowmanagerimp.hpp | 5 +- apps/openmw/mwworld/esmstore.hpp | 8 +- apps/openmw/mwworld/recordcmp.hpp | 56 +--------- apps/openmw/mwworld/store.hpp | 26 ++--- apps/openmw/mwworld/worldimp.cpp | 39 ++----- apps/openmw/mwworld/worldimp.hpp | 6 +- components/CMakeLists.txt | 4 + components/esm/esmreader.cpp | 16 +-- components/esm/esmreader.hpp | 2 +- components/misc/stringops.hpp | 50 +++++++++ components/to_utf8/to_utf8.cpp | 20 ++++ components/to_utf8/to_utf8.hpp | 3 + .../translation_data/translation_data.cpp | 104 ++++++++++++++++++ .../translation_data/translation_data.hpp | 36 ++++++ 24 files changed, 339 insertions(+), 183 deletions(-) create mode 100644 components/translation_data/translation_data.cpp create mode 100644 components/translation_data/translation_data.hpp diff --git a/apps/esmtool/esmtool.cpp b/apps/esmtool/esmtool.cpp index 4f6d9dbfc..963656af5 100644 --- a/apps/esmtool/esmtool.cpp +++ b/apps/esmtool/esmtool.cpp @@ -59,7 +59,7 @@ struct Arguments std::string outname; std::vector types; - + ESMData data; ESM::ESMReader reader; ESM::ESMWriter writer; @@ -74,7 +74,7 @@ bool parseOptions (int argc, char** argv, Arguments &info) ("version,v", "print version information and quit.") ("raw,r", "Show an unformatted list of all records and subrecords.") // The intention is that this option would interact better - // with other modes including clone, dump, and raw. + // with other modes including clone, dump, and raw. ("type,t", bpo::value< std::vector >(), "Show only records of this type (four character record code). May " "be specified multiple times. Only affects dump mode.") @@ -262,7 +262,7 @@ void printRaw(ESM::ESMReader &esm) int load(Arguments& info) { ESM::ESMReader& esm = info.reader; - esm.setEncoding(info.encoding); + esm.setEncoding(ToUTF8::CalculateEncoding(info.encoding)); std::string filename = info.filename; std::cout << "Loading file: " << filename << std::endl; @@ -321,7 +321,7 @@ int load(Arguments& info) if (info.types.size() > 0) { std::vector::iterator match; - match = std::find(info.types.begin(), info.types.end(), + match = std::find(info.types.begin(), info.types.end(), n.toString()); if (match == info.types.end()) interested = false; } @@ -425,7 +425,7 @@ int clone(Arguments& info) if (++i % 3 == 0) std::cout << std::endl; } - + if (i % 3 != 0) std::cout << std::endl; @@ -450,7 +450,7 @@ int clone(Arguments& info) for (Records::iterator it = records.begin(); it != records.end() && i > 0; ++it) { EsmTool::RecordBase *record = *it; - + name.val = record->getType().val; esm.startRecord(name.toString(), record->getFlags()); @@ -485,7 +485,7 @@ int clone(Arguments& info) std::cerr << "\r" << perc << "%"; } } - + std::cout << "\rDone!" << std::endl; esm.close(); @@ -513,7 +513,7 @@ int comp(Arguments& info) fileOne.encoding = info.encoding; fileTwo.encoding = info.encoding; - + fileOne.filename = info.filename; fileTwo.filename = info.outname; @@ -534,9 +534,9 @@ int comp(Arguments& info) std::cout << "Not equal, different amount of records." << std::endl; return 1; } - - - + + + return 0; } diff --git a/apps/launcher/model/datafilesmodel.cpp b/apps/launcher/model/datafilesmodel.cpp index d85a15e73..6d70c6031 100644 --- a/apps/launcher/model/datafilesmodel.cpp +++ b/apps/launcher/model/datafilesmodel.cpp @@ -272,7 +272,7 @@ void DataFilesModel::addMasters(const QString &path) foreach (const QString &path, dir.entryList()) { try { ESM::ESMReader fileReader; - fileReader.setEncoding(mEncoding.toStdString()); + fileReader.setEncoding(ToUTF8::CalculateEncoding(mEncoding.toStdString())); fileReader.open(dir.absoluteFilePath(path).toStdString()); ESM::ESMReader::MasterList mlist = fileReader.getMasters(); @@ -335,7 +335,7 @@ void DataFilesModel::addPlugins(const QString &path) try { ESM::ESMReader fileReader; - fileReader.setEncoding(mEncoding.toStdString()); + fileReader.setEncoding(ToUTF8::CalculateEncoding(mEncoding.toStdString())); fileReader.open(dir.absoluteFilePath(path).toStdString()); ESM::ESMReader::MasterList mlist = fileReader.getMasters(); diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 2299053cd..9c31124b4 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -334,12 +335,16 @@ void OMW::Engine::go() mEnvironment.setWorld (new MWWorld::World (*mOgre, mFileCollections, mMaster, mResDir, mCfgMgr.getCachePath(), mNewGame, mEncoding, mFallbackMap)); + //Load translation data + std::unique_ptr translationDataStorage(new TranslationData::Storage(mEncoding)); + translationDataStorage->loadTranslationData(mFileCollections, mMaster); + // Create window manager - this manages all the MW-specific GUI windows MWScript::registerExtensions (mExtensions); mEnvironment.setWindowManager (new MWGui::WindowManager( mExtensions, mFpsLevel, mNewGame, mOgre, mCfgMgr.getLogPath().string() + std::string("/"), - mCfgMgr.getCachePath ().string(), mScriptConsoleMode)); + mCfgMgr.getCachePath ().string(), mScriptConsoleMode, translationDataStorage.release())); // Create sound system mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound)); @@ -487,7 +492,7 @@ void OMW::Engine::showFPS(int level) mFpsLevel = level; } -void OMW::Engine::setEncoding(const std::string& encoding) +void OMW::Engine::setEncoding(const ToUTF8::FromType& encoding) { mEncoding = encoding; } diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 57402c91e..2d2d58234 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -59,7 +59,7 @@ namespace OMW class Engine : private Ogre::FrameListener { MWBase::Environment mEnvironment; - std::string mEncoding; + ToUTF8::FromType mEncoding; Files::PathContainer mDataDirs; boost::filesystem::path mResDir; OEngine::Render::OgreRenderer *mOgre; @@ -154,7 +154,7 @@ namespace OMW void setCompileAll (bool all); /// Font encoding - void setEncoding(const std::string& encoding); + void setEncoding(const ToUTF8::FromType& encoding); void setAnimationVerbose(bool animverbose); diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 0563fdbbb..8b5c5c6d6 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -181,21 +181,8 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat // Font encoding settings std::string encoding(variables["encoding"].as()); - if (encoding == "win1250") - { - std::cout << "Using Central and Eastern European font encoding." << std::endl; - engine.setEncoding(encoding); - } - else if (encoding == "win1251") - { - std::cout << "Using Cyrillic font encoding." << std::endl; - engine.setEncoding(encoding); - } - else - { - std::cout << "Using default (English) font encoding." << std::endl; - engine.setEncoding("win1252"); - } + std::cout << ToUTF8::EncodingUsingMessage(encoding) << std::endl; + engine.setEncoding(ToUTF8::CalculateEncoding(encoding)); // directory settings engine.enableFSStrict(variables["fs-strict"].as()); diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 843d1af4c..09a15a2cb 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -204,33 +204,10 @@ namespace MWClass std::string text; - const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); - if (ref->mRef.mTeleport) { - std::string dest; - if (ref->mRef.mDestCell != "") - { - // door leads to an interior, use interior name as tooltip - dest = ref->mRef.mDestCell; - } - else - { - // door leads to exterior, use cell name (if any), otherwise translated region name - int x,y; - MWBase::Environment::get().getWorld()->positionToIndex (ref->mRef.mDoorDest.pos[0], ref->mRef.mDoorDest.pos[1], x, y); - const ESM::Cell* cell = store.get().find(x,y); - if (cell->mName != "") - dest = cell->mName; - else - { - const ESM::Region* region = - store.get().find(cell->mRegion); - dest = region->mName; - } - } text += "\n#{sTo}"; - text += "\n"+dest; + text += "\n" + getDestination(*ref); } if (ref->mRef.mLockLevel > 0) @@ -246,6 +223,37 @@ namespace MWClass return info; } + std::string Door::getDestination (const MWWorld::LiveCellRef& door) + { + const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + + std::string dest; + if (door.mRef.mDestCell != "") + { + // door leads to an interior, use interior name as tooltip + dest = door.mRef.mDestCell; + } + else + { + // door leads to exterior, use cell name (if any), otherwise translated region name + int x,y; + MWBase::Environment::get().getWorld()->positionToIndex (door.mRef.mDoorDest.pos[0], door.mRef.mDoorDest.pos[1], x, y); + const ESM::Cell* cell = store.get().find(x,y); + if (cell->mName != "") + dest = cell->mName; + else + { + const ESM::Region* region = + store.get().find(cell->mRegion); + + //name as is, not a token + return region->mName; + } + } + + return "#{sCell=" + dest + "}"; + } + MWWorld::Ptr Door::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index b0f86f12d..05ba0248b 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -31,6 +31,9 @@ namespace MWClass virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::Ptr& ptr) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. + static std::string getDestination (const MWWorld::LiveCellRef& door); + ///< @return destination cell name or token + virtual void lock (const MWWorld::Ptr& ptr, int lockLevel) const; ///< Lock object diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 9b4075f57..689baf488 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -319,7 +319,7 @@ void HUD::setCellName(const std::string& cellName) mCellNameTimer = 5.0f; mCellName = cellName; - mCellNameBox->setCaption(mCellName); + mCellNameBox->setCaptionWithReplacing("#{sCell=" + mCellName + "}"); mCellNameBox->setVisible(mMapVisible); } } diff --git a/apps/openmw/mwgui/map_window.cpp b/apps/openmw/mwgui/map_window.cpp index 0a26ebb8f..4e2ee517e 100644 --- a/apps/openmw/mwgui/map_window.cpp +++ b/apps/openmw/mwgui/map_window.cpp @@ -299,7 +299,7 @@ MapWindow::~MapWindow() void MapWindow::setCellName(const std::string& cellName) { - setTitle(cellName); + setTitle("#{sCell=" + cellName + "}"); } void MapWindow::addVisitedLocation(const std::string& name, int x, int y) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 376eca88d..fbe1250e3 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -55,7 +55,8 @@ using namespace MWGui; WindowManager::WindowManager( const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, - const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts) + const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, + TranslationData::Storage* pTranslationDataStorage) : mGuiManager(NULL) , mHud(NULL) , mMap(NULL) @@ -104,6 +105,7 @@ WindowManager::WindowManager( , mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD")) , mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI")) , mHudEnabled(true) + , mTranslationDataStorage(pTranslationDataStorage) { // Set up the GUI system @@ -612,7 +614,7 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell) if (cell->mCell->mName != "") { name = cell->mCell->mName; - mMap->addVisitedLocation (name, cell->mCell->getGridX (), cell->mCell->getGridY ()); + mMap->addVisitedLocation ("#{sCell=" + name + "}", cell->mCell->getGridX (), cell->mCell->getGridY ()); } else { @@ -722,13 +724,25 @@ void WindowManager::setDragDrop(bool dragDrop) void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _result) { - const ESM::GameSetting *setting = - MWBase::Environment::get().getWorld()->getStore().get().find(_tag); + std::string tag(_tag); - if (setting && setting->mType == ESM::VT_String) - _result = setting->getString(); + std::string tokenToFind = "sCell="; + size_t tokenLength = tokenToFind.length(); + + if (tag.substr(0, tokenLength) == tokenToFind) + { + _result = mTranslationDataStorage->translateCellName(tag.substr(tokenLength)); + } else - _result = _tag; + { + const ESM::GameSetting *setting = + MWBase::Environment::get().getWorld()->getStore().get().find(tag); + + if (setting && setting->mType == ESM::VT_String) + _result = setting->getString(); + else + _result = tag; + } } void WindowManager::processChangedSettings(const Settings::CategorySettingVector& changed) diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 2e684b5da..40bff0eb0 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -14,6 +14,7 @@ #include #include +#include #include "../mwbase/windowmanager.hpp" @@ -76,7 +77,8 @@ namespace MWGui WindowManager(const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string& logpath, - const std::string& cacheDir, bool consoleOnlyScripts); + const std::string& cacheDir, bool consoleOnlyScripts, + TranslationData::Storage* pTranslationDataStorage); virtual ~WindowManager(); /** @@ -250,6 +252,7 @@ namespace MWGui SpellCreationDialog* mSpellCreationDialog; EnchantingDialog* mEnchantingDialog; TrainingWindow* mTrainingWindow; + std::unique_ptr mTranslationDataStorage; CharacterCreation* mCharGen; diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index 9917254ee..e14219aae 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -6,7 +6,7 @@ #include #include "store.hpp" -namespace MWWorld +namespace MWWorld { class ESMStore { @@ -158,7 +158,7 @@ namespace MWWorld std::ostringstream id; id << "$dynamic" << mDynamicCount++; record.mId = id.str(); - + T *ptr = store.insert(record); for (iterator it = mStores.begin(); it != mStores.end(); ++it) { if (it->second == &store) { @@ -179,7 +179,7 @@ namespace MWWorld template <> inline const ESM::NPC *ESMStore::insert(const ESM::NPC &npc) { - if (StringUtils::ciEqual(npc.mId, "player")) { + if (Misc::StringUtils::ciEqual(npc.mId, "player")) { return mNpcs.insert(npc); } else if (mNpcs.search(npc.mId) != 0) { std::ostringstream msg; @@ -191,7 +191,7 @@ namespace MWWorld std::ostringstream id; id << "$dynamic" << mDynamicCount++; record.mId = id.str(); - + ESM::NPC *ptr = mNpcs.insert(record); mIds[ptr->mId] = ESM::REC_NPC_; return ptr; diff --git a/apps/openmw/mwworld/recordcmp.hpp b/apps/openmw/mwworld/recordcmp.hpp index 0b1655100..7de4f5565 100644 --- a/apps/openmw/mwworld/recordcmp.hpp +++ b/apps/openmw/mwworld/recordcmp.hpp @@ -1,62 +1,12 @@ #ifndef OPENMW_MWWORLD_RECORDCMP_H #define OPENMW_MWWORLD_RECORDCMP_H -#include #include -#include #include namespace MWWorld { - /// \todo move this to another location - class StringUtils - { - struct ci - { - bool operator()(int x, int y) const { - return std::tolower(x) < std::tolower(y); - } - }; - - public: - static bool ciLess(const std::string &x, const std::string &y) { - return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), ci()); - } - - static bool ciEqual(const std::string &x, const std::string &y) { - if (x.size() != y.size()) { - return false; - } - std::string::const_iterator xit = x.begin(); - std::string::const_iterator yit = y.begin(); - for (; xit != x.end(); ++xit, ++yit) { - if (std::tolower(*xit) != std::tolower(*yit)) { - return false; - } - } - return true; - } - - /// Transforms input string to lower case w/o copy - static std::string &toLower(std::string &inout) { - std::transform( - inout.begin(), - inout.end(), - inout.begin(), - (int (*)(int)) std::tolower - ); - return inout; - } - - /// Returns lower case copy of input string - static std::string lowerCase(const std::string &in) - { - std::string out = in; - return toLower(out); - } - }; - struct RecordCmp { template @@ -67,17 +17,17 @@ namespace MWWorld template <> inline bool RecordCmp::operator()(const ESM::Dialogue &x, const ESM::Dialogue &y) const { - return StringUtils::ciLess(x.mId, y.mId); + return Misc::StringUtils::ciLess(x.mId, y.mId); } template <> inline bool RecordCmp::operator()(const ESM::Cell &x, const ESM::Cell &y) const { - return StringUtils::ciLess(x.mName, y.mName); + return Misc::StringUtils::ciLess(x.mName, y.mName); } template <> inline bool RecordCmp::operator()(const ESM::Pathgrid &x, const ESM::Pathgrid &y) const { - return StringUtils::ciLess(x.mCell, y.mCell); + return Misc::StringUtils::ciLess(x.mCell, y.mCell); } } // end namespace diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 046de8c63..431cd3cf9 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -105,12 +105,12 @@ namespace MWWorld const T *search(const std::string &id) const { T item; - item.mId = StringUtils::lowerCase(id); + item.mId = Misc::StringUtils::lowerCase(id); typename std::vector::const_iterator it = std::lower_bound(mStatic.begin(), mStatic.end(), item, RecordCmp()); - if (it != mStatic.end() && StringUtils::ciEqual(it->mId, id)) { + if (it != mStatic.end() && Misc::StringUtils::ciEqual(it->mId, id)) { return &(*it); } @@ -134,7 +134,7 @@ namespace MWWorld void load(ESM::ESMReader &esm, const std::string &id) { mStatic.push_back(T()); - mStatic.back().mId = StringUtils::lowerCase(id); + mStatic.back().mId = Misc::StringUtils::lowerCase(id); mStatic.back().load(esm); } @@ -169,7 +169,7 @@ namespace MWWorld } T *insert(const T &item) { - std::string id = StringUtils::lowerCase(item.mId); + std::string id = Misc::StringUtils::lowerCase(item.mId); std::pair result = mDynamic.insert(std::pair(id, item)); T *ptr = &result.first->second; @@ -182,7 +182,7 @@ namespace MWWorld } bool erase(const std::string &id) { - std::string key = StringUtils::lowerCase(id); + std::string key = Misc::StringUtils::lowerCase(id); typename Dynamic::iterator it = mDynamic.find(key); if (it == mDynamic.end()) { return false; @@ -213,7 +213,7 @@ namespace MWWorld inline void Store::load(ESM::ESMReader &esm, const std::string &id) { mStatic.push_back(ESM::Script()); mStatic.back().load(esm); - StringUtils::toLower(mStatic.back().mId); + Misc::StringUtils::toLower(mStatic.back().mId); } template <> @@ -385,12 +385,12 @@ namespace MWWorld const ESM::Cell *search(const std::string &id) const { ESM::Cell cell; - cell.mName = StringUtils::lowerCase(id); + cell.mName = Misc::StringUtils::lowerCase(id); std::vector::const_iterator it = std::lower_bound(mInt.begin(), mInt.end(), cell, RecordCmp()); - if (it != mInt.end() && StringUtils::ciEqual(it->mName, id)) { + if (it != mInt.end() && Misc::StringUtils::ciEqual(it->mName, id)) { return &(*it); } @@ -490,7 +490,7 @@ namespace MWWorld const ESM::Cell *searchExtByName(const std::string &id) const { std::vector::const_iterator it = mSharedExt.begin(); for (; it != mSharedExt.end(); ++it) { - if (StringUtils::ciEqual((*it)->mName, id)) { + if (Misc::StringUtils::ciEqual((*it)->mName, id)) { return *it; } } @@ -501,7 +501,7 @@ namespace MWWorld const ESM::Cell *searchExtByRegion(const std::string &id) const { std::vector::const_iterator it = mSharedExt.begin(); for (; it != mSharedExt.end(); ++it) { - if (StringUtils::ciEqual((*it)->mRegion, id)) { + if (Misc::StringUtils::ciEqual((*it)->mRegion, id)) { return *it; } } @@ -541,7 +541,7 @@ namespace MWWorld ptr = &result.first->second; mSharedExt.push_back(ptr); } else { - std::string key = StringUtils::lowerCase(cell.mName); + std::string key = Misc::StringUtils::lowerCase(cell.mName); // duplicate insertions are avoided by search(ESM::Cell &) std::pair result = @@ -561,7 +561,7 @@ namespace MWWorld } bool erase(const std::string &id) { - std::string key = StringUtils::lowerCase(id); + std::string key = Misc::StringUtils::lowerCase(id); DynamicInt::iterator it = mDynamicInt.find(key); if (it == mDynamicInt.end()) { @@ -691,7 +691,7 @@ namespace MWWorld pg.mCell = name; iterator it = std::lower_bound(mIntBegin, mIntEnd, pg, RecordCmp()); - if (it != mIntEnd && StringUtils::ciEqual(it->mCell, name)) { + if (it != mIntEnd && Misc::StringUtils::ciEqual(it->mCell, name)) { return &(*it); } return 0; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f0b2efcec..97f9d0f11 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -11,6 +11,8 @@ #include "../mwrender/sky.hpp" #include "../mwrender/player.hpp" +#include "../mwclass/door.hpp" + #include "player.hpp" #include "manualref.hpp" #include "cellfunctors.hpp" @@ -168,7 +170,7 @@ namespace MWWorld World::World (OEngine::Render::OgreRenderer& renderer, const Files::Collections& fileCollections, const std::string& master, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, - const std::string& encoding, std::map fallbackMap) + const ToUTF8::FromType& encoding, std::map fallbackMap) : mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), mSky (true), mCells (mStore, mEsm), mNumFacing(0) @@ -237,7 +239,7 @@ namespace MWWorld MWWorld::Store::iterator it = regions.begin(); for (; it != regions.end(); ++it) { - if (MWWorld::StringUtils::ciEqual(cellName, it->mName)) + if (Misc::StringUtils::ciEqual(cellName, it->mName)) { return mStore.get().searchExtByRegion(it->mId); } @@ -805,7 +807,7 @@ namespace MWWorld { bool update = false; - if (StringUtils::ciEqual(record.mId, "player")) + if (Misc::StringUtils::ciEqual(record.mId, "player")) { static const char *sRaces[] = { @@ -816,7 +818,7 @@ namespace MWWorld int i=0; for (; sRaces[i]; ++i) - if (StringUtils::ciEqual (sRaces[i], record.mRace)) + if (Misc::StringUtils::ciEqual (sRaces[i], record.mRace)) break; mGlobalVariables->setInt ("pcrace", sRaces[i] ? i+1 : 0); @@ -825,9 +827,9 @@ namespace MWWorld mPlayer->getPlayer().get()->mBase; update = record.isMale() != player->isMale() || - !StringUtils::ciEqual(record.mRace, player->mRace) || - !StringUtils::ciEqual(record.mHead, player->mHead) || - !StringUtils::ciEqual(record.mHair, player->mHair); + !Misc::StringUtils::ciEqual(record.mRace, player->mRace) || + !Misc::StringUtils::ciEqual(record.mHead, player->mHead) || + !Misc::StringUtils::ciEqual(record.mHair, player->mHair); } const ESM::NPC *ret = mStore.insert(record); if (update) { @@ -1080,28 +1082,7 @@ namespace MWWorld if (ref.mRef.mTeleport) { World::DoorMarker newMarker; - - std::string dest; - if (ref.mRef.mDestCell != "") - { - // door leads to an interior, use interior name - dest = ref.mRef.mDestCell; - } - else - { - // door leads to exterior, use cell name (if any), otherwise translated region name - int x,y; - positionToIndex (ref.mRef.mDoorDest.pos[0], ref.mRef.mDoorDest.pos[1], x, y); - const ESM::Cell* cell = mStore.get().find(x,y); - if (cell->mName != "") - dest = cell->mName; - else - { - dest = mStore.get().find(cell->mRegion)->mName; - } - } - - newMarker.name = dest; + newMarker.name = MWClass::Door::getDestination(ref); ESM::Position pos = ref.mData.getPosition (); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 0962c292c..a7634a57c 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -95,7 +95,7 @@ namespace MWWorld World (OEngine::Render::OgreRenderer& renderer, const Files::Collections& fileCollections, const std::string& master, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, - const std::string& encoding, std::map fallbackMap); + const ToUTF8::FromType& encoding, std::map fallbackMap); virtual ~World(); @@ -228,7 +228,7 @@ namespace MWWorld virtual void rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust = false); virtual void safePlaceObject(const MWWorld::Ptr& ptr,MWWorld::CellStore &Cell,ESM::Position pos); - ///< place an object in a "safe" location (ie not in the void, etc). Makes a copy of the Ptr. + ///< place an object in a "safe" location (ie not in the void, etc). Makes a copy of the Ptr. virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false) const; @@ -323,7 +323,7 @@ namespace MWWorld } virtual void renderPlayer(); - + virtual void setupExternalRendering (MWRender::ExternalRendering& rendering); virtual int canRest(); diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 29d6f46cd..2d2e21633 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -62,6 +62,10 @@ add_component_dir (interpreter miscopcodes opcodes runtime scriptopcodes spatialopcodes types ) +add_component_dir (translation_data + translation_data + ) + include_directories(${BULLET_INCLUDE_DIRS}) add_library(components STATIC ${COMPONENT_FILES}) diff --git a/components/esm/esmreader.cpp b/components/esm/esmreader.cpp index 2915a1ce7..580e006df 100644 --- a/components/esm/esmreader.cpp +++ b/components/esm/esmreader.cpp @@ -347,21 +347,9 @@ void ESMReader::fail(const std::string &msg) throw std::runtime_error(ss.str()); } -void ESMReader::setEncoding(const std::string& encoding) +void ESMReader::setEncoding(const ToUTF8::FromType& encoding) { - if (encoding == "win1250") - { - mEncoding = ToUTF8::WINDOWS_1250; - } - else if (encoding == "win1251") - { - mEncoding = ToUTF8::WINDOWS_1251; - } - else - { - // Default Latin encoding - mEncoding = ToUTF8::WINDOWS_1252; - } + mEncoding = encoding; } } diff --git a/components/esm/esmreader.hpp b/components/esm/esmreader.hpp index 6a74c53e8..1d0f6f580 100644 --- a/components/esm/esmreader.hpp +++ b/components/esm/esmreader.hpp @@ -234,7 +234,7 @@ public: void fail(const std::string &msg); /// Sets font encoding for ESM strings - void setEncoding(const std::string& encoding); + void setEncoding(const ToUTF8::FromType& encoding); private: Ogre::DataStreamPtr mEsm; diff --git a/components/misc/stringops.hpp b/components/misc/stringops.hpp index a32104bf3..112d66bb8 100644 --- a/components/misc/stringops.hpp +++ b/components/misc/stringops.hpp @@ -1,8 +1,58 @@ #ifndef MISC_STRINGOPS_H #define MISC_STRINGOPS_H +#include +#include + namespace Misc { +class StringUtils +{ + struct ci + { + bool operator()(int x, int y) const { + return std::tolower(x) < std::tolower(y); + } + }; + +public: + static bool ciLess(const std::string &x, const std::string &y) { + return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), ci()); + } + + static bool ciEqual(const std::string &x, const std::string &y) { + if (x.size() != y.size()) { + return false; + } + std::string::const_iterator xit = x.begin(); + std::string::const_iterator yit = y.begin(); + for (; xit != x.end(); ++xit, ++yit) { + if (std::tolower(*xit) != std::tolower(*yit)) { + return false; + } + } + return true; + } + + /// Transforms input string to lower case w/o copy + static std::string &toLower(std::string &inout) { + std::transform( + inout.begin(), + inout.end(), + inout.begin(), + (int (*)(int)) std::tolower + ); + return inout; + } + + /// Returns lower case copy of input string + static std::string lowerCase(const std::string &in) + { + std::string out = in; + return toLower(out); + } +}; + /// Returns true if str1 begins with substring str2 bool begins(const char* str1, const char* str2); diff --git a/components/to_utf8/to_utf8.cpp b/components/to_utf8/to_utf8.cpp index 6f0ed8bfd..ee1e56229 100644 --- a/components/to_utf8/to_utf8.cpp +++ b/components/to_utf8/to_utf8.cpp @@ -357,3 +357,23 @@ std::string ToUTF8::getLegacyEnc(ToUTF8::FromType to) // Return a string return std::string(&output[0], outlen); } + +ToUTF8::FromType ToUTF8::CalculateEncoding(const std::string& encodingName) +{ + if (encodingName == "win1250") + return ToUTF8::WINDOWS_1250; + else if (encodingName == "win1251") + return ToUTF8::WINDOWS_1251; + else + return ToUTF8::WINDOWS_1252; +} + +std::string ToUTF8::EncodingUsingMessage(const std::string& encodingName) +{ + if (encodingName == "win1250") + return "Using Central and Eastern European font encoding."; + else if (encodingName == "win1251") + return "Using Cyrillic font encoding."; + else + return "Using default (English) font encoding."; +} diff --git a/components/to_utf8/to_utf8.hpp b/components/to_utf8/to_utf8.hpp index 69e9fc92c..9982213c9 100644 --- a/components/to_utf8/to_utf8.hpp +++ b/components/to_utf8/to_utf8.hpp @@ -22,6 +22,9 @@ namespace ToUTF8 // page. std::string getUtf8(FromType from); std::string getLegacyEnc(FromType to); + + FromType CalculateEncoding(const std::string& encodingName); + std::string EncodingUsingMessage(const std::string& encodingName); } #endif diff --git a/components/translation_data/translation_data.cpp b/components/translation_data/translation_data.cpp new file mode 100644 index 000000000..cd124bfbc --- /dev/null +++ b/components/translation_data/translation_data.cpp @@ -0,0 +1,104 @@ +#include "translation_data.hpp" +#include + +#include + +namespace TranslationData +{ + void Storage::loadTranslationData(const Files::Collections& dataFileCollections, + const std::string& esmFileName) + { + std::string esmNameNoExtension(Misc::StringUtils::lowerCase(esmFileName)); + //changing the extension + size_t dotPos = esmNameNoExtension.rfind('.'); + if (dotPos != std::string::npos) + esmNameNoExtension.resize(dotPos); + + loadData(mCellNamesTranslations, esmNameNoExtension, ".cel", dataFileCollections); + loadData(mPhraseForms, esmNameNoExtension, ".top", dataFileCollections); + loadData(mTopicIDs, esmNameNoExtension, ".mrk", dataFileCollections); + } + + void Storage::loadData(ContainerType& container, + const std::string& fileNameNoExtension, + const std::string& extension, + const Files::Collections& dataFileCollections) + { + std::string path; + try + { + path = dataFileCollections.getCollection(extension).getPath(fileNameNoExtension + extension).string(); + } + catch(...) + { + //no file + return; + } + + std::ifstream stream(path); + if (stream.is_open()) + { + loadDataFromStream(container, stream); + stream.close(); + } + } + + void Storage::loadDataFromStream(ContainerType& container, std::istream& stream) + { + std::string line; + while (!stream.eof()) + { + std::getline( stream, line ); + if (!line.empty() && *line.rbegin() == '\r') + line.resize(line.size() - 1); + + if (!line.empty()) + { + char* buffer = ToUTF8::getBuffer(line.size() + 1); + //buffer has at least line.size() + 1 bytes, so it must be safe + strcpy(buffer, line.c_str()); + line = ToUTF8::getUtf8(mEncoding); + + size_t tab_pos = line.find('\t'); + if (tab_pos != std::string::npos && tab_pos > 0 && tab_pos < line.size() - 1) + { + std::string key = line.substr(0, tab_pos); + std::string value = line.substr(tab_pos + 1); + + if (!key.empty() && !value.empty()) + container.insert(std::make_pair(key, value)); + } + } + } + } + + std::string Storage::translateCellName(const std::string& cellName) const + { + auto entry = mCellNamesTranslations.find(cellName); + + if (entry == mCellNamesTranslations.end()) + return cellName; + + return entry->second; + } + + std::string Storage::topicID(const std::string& phrase) const + { + std::string result; + + //seeking for the standard phrase form + auto phraseFormsIterator = mPhraseForms.find(phrase); + if (phraseFormsIterator != mPhraseForms.end()) + result = phraseFormsIterator->second; + else + result = phrase; + + + //seeking for the topic ID + auto topicIDIterator = mTopicIDs.find(result); + if (topicIDIterator != mTopicIDs.end()) + result = topicIDIterator->second; + + return result; + } +} diff --git a/components/translation_data/translation_data.hpp b/components/translation_data/translation_data.hpp new file mode 100644 index 000000000..7f4162c09 --- /dev/null +++ b/components/translation_data/translation_data.hpp @@ -0,0 +1,36 @@ +#ifndef COMPONENTS_TRANSLATION_DATA_H +#define COMPONENTS_TRANSLATION_DATA_H + +#include +#include + +namespace TranslationData +{ + class Storage + { + public: + Storage(const ToUTF8::FromType& encoding) : mEncoding(encoding) {} + + void loadTranslationData(const Files::Collections& dataFileCollections, + const std::string& esmFileName); + + std::string translateCellName(const std::string& cellName) const; + std::string topicID(const std::string& phrase) const; + + private: + typedef std::map ContainerType; + + void loadData(ContainerType& container, + const std::string& fileNameNoExtension, + const std::string& extension, + const Files::Collections& dataFileCollections); + + void loadDataFromStream(ContainerType& container, std::istream& stream); + + + ToUTF8::FromType mEncoding; + std::map mCellNamesTranslations, mTopicIDs, mPhraseForms; + }; +} + +#endif From 1f71395660d75ef5eedfb8c2eeac028345aaafb8 Mon Sep 17 00:00:00 2001 From: lazydev Date: Tue, 25 Dec 2012 23:20:39 +0400 Subject: [PATCH 066/136] renaming of translation component; removing of C++11 features --- apps/openmw/engine.cpp | 4 ++-- apps/openmw/mwgui/windowmanagerimp.hpp | 4 ++-- components/CMakeLists.txt | 4 ++-- .../translation.cpp} | 13 +++++++++---- .../translation.hpp} | 0 5 files changed, 15 insertions(+), 10 deletions(-) rename components/{translation_data/translation_data.cpp => translation/translation.cpp} (89%) rename components/{translation_data/translation_data.hpp => translation/translation.hpp} (100%) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 9c31124b4..3a7b6f6cf 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include @@ -336,7 +336,7 @@ void OMW::Engine::go() mResDir, mCfgMgr.getCachePath(), mNewGame, mEncoding, mFallbackMap)); //Load translation data - std::unique_ptr translationDataStorage(new TranslationData::Storage(mEncoding)); + std::auto_ptr translationDataStorage(new TranslationData::Storage(mEncoding)); translationDataStorage->loadTranslationData(mFileCollections, mMaster); // Create window manager - this manages all the MW-specific GUI windows diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 40bff0eb0..ad3c9b736 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include "../mwbase/windowmanager.hpp" @@ -252,7 +252,7 @@ namespace MWGui SpellCreationDialog* mSpellCreationDialog; EnchantingDialog* mEnchantingDialog; TrainingWindow* mTrainingWindow; - std::unique_ptr mTranslationDataStorage; + std::auto_ptr mTranslationDataStorage; CharacterCreation* mCharGen; diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 2d2e21633..140bef771 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -62,8 +62,8 @@ add_component_dir (interpreter miscopcodes opcodes runtime scriptopcodes spatialopcodes types ) -add_component_dir (translation_data - translation_data +add_component_dir (translation + translation ) include_directories(${BULLET_INCLUDE_DIRS}) diff --git a/components/translation_data/translation_data.cpp b/components/translation/translation.cpp similarity index 89% rename from components/translation_data/translation_data.cpp rename to components/translation/translation.cpp index cd124bfbc..a178a053c 100644 --- a/components/translation_data/translation_data.cpp +++ b/components/translation/translation.cpp @@ -1,4 +1,4 @@ -#include "translation_data.hpp" +#include "translation.hpp" #include #include @@ -74,7 +74,8 @@ namespace TranslationData std::string Storage::translateCellName(const std::string& cellName) const { - auto entry = mCellNamesTranslations.find(cellName); + std::map::const_iterator entry = + mCellNamesTranslations.find(cellName); if (entry == mCellNamesTranslations.end()) return cellName; @@ -87,7 +88,9 @@ namespace TranslationData std::string result; //seeking for the standard phrase form - auto phraseFormsIterator = mPhraseForms.find(phrase); + std::map::const_iterator phraseFormsIterator = + mPhraseForms.find(phrase); + if (phraseFormsIterator != mPhraseForms.end()) result = phraseFormsIterator->second; else @@ -95,7 +98,9 @@ namespace TranslationData //seeking for the topic ID - auto topicIDIterator = mTopicIDs.find(result); + std::map::const_iterator topicIDIterator = + mTopicIDs.find(result); + if (topicIDIterator != mTopicIDs.end()) result = topicIDIterator->second; diff --git a/components/translation_data/translation_data.hpp b/components/translation/translation.hpp similarity index 100% rename from components/translation_data/translation_data.hpp rename to components/translation/translation.hpp From 2d468fec028d0ea3d324cdd2a5acab6da997edf6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 26 Dec 2012 16:19:59 +0100 Subject: [PATCH 067/136] made previous commits naming standard compliant --- apps/esmtool/esmtool.cpp | 2 +- apps/launcher/model/datafilesmodel.cpp | 4 ++-- apps/openmw/main.cpp | 4 ++-- components/to_utf8/to_utf8.cpp | 4 ++-- components/to_utf8/to_utf8.hpp | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/esmtool/esmtool.cpp b/apps/esmtool/esmtool.cpp index 963656af5..0cd6e3905 100644 --- a/apps/esmtool/esmtool.cpp +++ b/apps/esmtool/esmtool.cpp @@ -262,7 +262,7 @@ void printRaw(ESM::ESMReader &esm) int load(Arguments& info) { ESM::ESMReader& esm = info.reader; - esm.setEncoding(ToUTF8::CalculateEncoding(info.encoding)); + esm.setEncoding(ToUTF8::calculateEncoding(info.encoding)); std::string filename = info.filename; std::cout << "Loading file: " << filename << std::endl; diff --git a/apps/launcher/model/datafilesmodel.cpp b/apps/launcher/model/datafilesmodel.cpp index 6d70c6031..716c9e902 100644 --- a/apps/launcher/model/datafilesmodel.cpp +++ b/apps/launcher/model/datafilesmodel.cpp @@ -272,7 +272,7 @@ void DataFilesModel::addMasters(const QString &path) foreach (const QString &path, dir.entryList()) { try { ESM::ESMReader fileReader; - fileReader.setEncoding(ToUTF8::CalculateEncoding(mEncoding.toStdString())); + fileReader.setEncoding(ToUTF8::calculateEncoding(mEncoding.toStdString())); fileReader.open(dir.absoluteFilePath(path).toStdString()); ESM::ESMReader::MasterList mlist = fileReader.getMasters(); @@ -335,7 +335,7 @@ void DataFilesModel::addPlugins(const QString &path) try { ESM::ESMReader fileReader; - fileReader.setEncoding(ToUTF8::CalculateEncoding(mEncoding.toStdString())); + fileReader.setEncoding(ToUTF8::calculateEncoding(mEncoding.toStdString())); fileReader.open(dir.absoluteFilePath(path).toStdString()); ESM::ESMReader::MasterList mlist = fileReader.getMasters(); diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 8b5c5c6d6..96dbf8987 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -181,8 +181,8 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat // Font encoding settings std::string encoding(variables["encoding"].as()); - std::cout << ToUTF8::EncodingUsingMessage(encoding) << std::endl; - engine.setEncoding(ToUTF8::CalculateEncoding(encoding)); + std::cout << ToUTF8::encodingUsingMessage(encoding) << std::endl; + engine.setEncoding(ToUTF8::calculateEncoding(encoding)); // directory settings engine.enableFSStrict(variables["fs-strict"].as()); diff --git a/components/to_utf8/to_utf8.cpp b/components/to_utf8/to_utf8.cpp index ee1e56229..7db611247 100644 --- a/components/to_utf8/to_utf8.cpp +++ b/components/to_utf8/to_utf8.cpp @@ -358,7 +358,7 @@ std::string ToUTF8::getLegacyEnc(ToUTF8::FromType to) return std::string(&output[0], outlen); } -ToUTF8::FromType ToUTF8::CalculateEncoding(const std::string& encodingName) +ToUTF8::FromType ToUTF8::calculateEncoding(const std::string& encodingName) { if (encodingName == "win1250") return ToUTF8::WINDOWS_1250; @@ -368,7 +368,7 @@ ToUTF8::FromType ToUTF8::CalculateEncoding(const std::string& encodingName) return ToUTF8::WINDOWS_1252; } -std::string ToUTF8::EncodingUsingMessage(const std::string& encodingName) +std::string ToUTF8::encodingUsingMessage(const std::string& encodingName) { if (encodingName == "win1250") return "Using Central and Eastern European font encoding."; diff --git a/components/to_utf8/to_utf8.hpp b/components/to_utf8/to_utf8.hpp index 9982213c9..f52ae73bd 100644 --- a/components/to_utf8/to_utf8.hpp +++ b/components/to_utf8/to_utf8.hpp @@ -23,8 +23,8 @@ namespace ToUTF8 std::string getUtf8(FromType from); std::string getLegacyEnc(FromType to); - FromType CalculateEncoding(const std::string& encodingName); - std::string EncodingUsingMessage(const std::string& encodingName); + FromType calculateEncoding(const std::string& encodingName); + std::string encodingUsingMessage(const std::string& encodingName); } #endif From 206c613b52e599b9366cbfa92278bf961e07bc8c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 26 Dec 2012 17:03:37 +0100 Subject: [PATCH 068/136] moved translation storage from GUI manager to engine --- apps/openmw/engine.cpp | 6 +++--- apps/openmw/engine.hpp | 3 ++- apps/openmw/mwgui/windowmanagerimp.cpp | 6 +++--- apps/openmw/mwgui/windowmanagerimp.hpp | 4 ++-- components/translation/translation.cpp | 5 +++++ components/translation/translation.hpp | 3 ++- 6 files changed, 17 insertions(+), 10 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 3a7b6f6cf..b995300d5 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -336,15 +336,14 @@ void OMW::Engine::go() mResDir, mCfgMgr.getCachePath(), mNewGame, mEncoding, mFallbackMap)); //Load translation data - std::auto_ptr translationDataStorage(new TranslationData::Storage(mEncoding)); - translationDataStorage->loadTranslationData(mFileCollections, mMaster); + mTranslationDataStorage.loadTranslationData(mFileCollections, mMaster); // Create window manager - this manages all the MW-specific GUI windows MWScript::registerExtensions (mExtensions); mEnvironment.setWindowManager (new MWGui::WindowManager( mExtensions, mFpsLevel, mNewGame, mOgre, mCfgMgr.getLogPath().string() + std::string("/"), - mCfgMgr.getCachePath ().string(), mScriptConsoleMode, translationDataStorage.release())); + mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage)); // Create sound system mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound)); @@ -495,6 +494,7 @@ void OMW::Engine::showFPS(int level) void OMW::Engine::setEncoding(const ToUTF8::FromType& encoding) { mEncoding = encoding; + mTranslationDataStorage.setEncoding (encoding); } void OMW::Engine::setFallbackValues(std::map fallbackMap) diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 2d2d58234..cbc627b83 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -5,6 +5,7 @@ #include #include +#include #include "mwbase/environment.hpp" @@ -79,9 +80,9 @@ namespace OMW Compiler::Extensions mExtensions; Compiler::Context *mScriptContext; - Files::Collections mFileCollections; bool mFSStrict; + TranslationData::Storage mTranslationDataStorage; // not implemented Engine (const Engine&); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index fbe1250e3..cdcb615dc 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -56,7 +56,7 @@ using namespace MWGui; WindowManager::WindowManager( const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, - TranslationData::Storage* pTranslationDataStorage) + TranslationData::Storage& translationDataStorage) : mGuiManager(NULL) , mHud(NULL) , mMap(NULL) @@ -105,7 +105,7 @@ WindowManager::WindowManager( , mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD")) , mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI")) , mHudEnabled(true) - , mTranslationDataStorage(pTranslationDataStorage) + , mTranslationDataStorage (translationDataStorage) { // Set up the GUI system @@ -731,7 +731,7 @@ void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _r if (tag.substr(0, tokenLength) == tokenToFind) { - _result = mTranslationDataStorage->translateCellName(tag.substr(tokenLength)); + _result = mTranslationDataStorage.translateCellName(tag.substr(tokenLength)); } else { diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index ad3c9b736..b252254a0 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -78,7 +78,7 @@ namespace MWGui WindowManager(const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, - TranslationData::Storage* pTranslationDataStorage); + TranslationData::Storage& translationDataStorage); virtual ~WindowManager(); /** @@ -252,7 +252,7 @@ namespace MWGui SpellCreationDialog* mSpellCreationDialog; EnchantingDialog* mEnchantingDialog; TrainingWindow* mTrainingWindow; - std::auto_ptr mTranslationDataStorage; + TranslationData::Storage& mTranslationDataStorage; CharacterCreation* mCharGen; diff --git a/components/translation/translation.cpp b/components/translation/translation.cpp index a178a053c..e6c6a0233 100644 --- a/components/translation/translation.cpp +++ b/components/translation/translation.cpp @@ -106,4 +106,9 @@ namespace TranslationData return result; } + + void Storage::setEncoding (const ToUTF8::FromType& encoding) + { + mEncoding = encoding; + } } diff --git a/components/translation/translation.hpp b/components/translation/translation.hpp index 7f4162c09..0160bc48a 100644 --- a/components/translation/translation.hpp +++ b/components/translation/translation.hpp @@ -9,7 +9,6 @@ namespace TranslationData class Storage { public: - Storage(const ToUTF8::FromType& encoding) : mEncoding(encoding) {} void loadTranslationData(const Files::Collections& dataFileCollections, const std::string& esmFileName); @@ -17,6 +16,8 @@ namespace TranslationData std::string translateCellName(const std::string& cellName) const; std::string topicID(const std::string& phrase) const; + void setEncoding (const ToUTF8::FromType& encoding); + private: typedef std::map ContainerType; From afc2e840aeff2dc43a4020a2c333a22c4ef6d6fd Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 26 Dec 2012 17:06:33 +0100 Subject: [PATCH 069/136] renamed namespace TranslationData to Translation --- apps/openmw/engine.hpp | 2 +- apps/openmw/mwgui/windowmanagerimp.cpp | 3 ++- apps/openmw/mwgui/windowmanagerimp.hpp | 10 +++++++--- components/translation/translation.cpp | 2 +- components/translation/translation.hpp | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index cbc627b83..00889197e 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -82,7 +82,7 @@ namespace OMW Files::Collections mFileCollections; bool mFSStrict; - TranslationData::Storage mTranslationDataStorage; + Translation::Storage mTranslationDataStorage; // not implemented Engine (const Engine&); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index cdcb615dc..caf6a4ab0 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -9,6 +9,7 @@ #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/mechanicsmanager.hpp" @@ -56,7 +57,7 @@ using namespace MWGui; WindowManager::WindowManager( const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, - TranslationData::Storage& translationDataStorage) + Translation::Storage& translationDataStorage) : mGuiManager(NULL) , mHud(NULL) , mMap(NULL) diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index b252254a0..aaa856aef 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -14,7 +14,6 @@ #include #include -#include #include "../mwbase/windowmanager.hpp" @@ -30,6 +29,11 @@ namespace Compiler class Extensions; } +namespace Translation +{ + class Storage; +} + namespace OEngine { namespace GUI @@ -78,7 +82,7 @@ namespace MWGui WindowManager(const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, - TranslationData::Storage& translationDataStorage); + Translation::Storage& translationDataStorage); virtual ~WindowManager(); /** @@ -252,7 +256,7 @@ namespace MWGui SpellCreationDialog* mSpellCreationDialog; EnchantingDialog* mEnchantingDialog; TrainingWindow* mTrainingWindow; - TranslationData::Storage& mTranslationDataStorage; + Translation::Storage& mTranslationDataStorage; CharacterCreation* mCharGen; diff --git a/components/translation/translation.cpp b/components/translation/translation.cpp index e6c6a0233..feda76f6f 100644 --- a/components/translation/translation.cpp +++ b/components/translation/translation.cpp @@ -3,7 +3,7 @@ #include -namespace TranslationData +namespace Translation { void Storage::loadTranslationData(const Files::Collections& dataFileCollections, const std::string& esmFileName) diff --git a/components/translation/translation.hpp b/components/translation/translation.hpp index 0160bc48a..668d4c067 100644 --- a/components/translation/translation.hpp +++ b/components/translation/translation.hpp @@ -4,7 +4,7 @@ #include #include -namespace TranslationData +namespace Translation { class Storage { From e9ba7339f32fecbb974cb80ffd258a6bb8731620 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 26 Dec 2012 17:15:53 +0100 Subject: [PATCH 070/136] improved error handling --- components/files/multidircollection.cpp | 5 +++++ components/files/multidircollection.hpp | 3 +++ components/translation/translation.cpp | 22 +++++++++------------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/components/files/multidircollection.cpp b/components/files/multidircollection.cpp index b44c42986..347de96a6 100644 --- a/components/files/multidircollection.cpp +++ b/components/files/multidircollection.cpp @@ -95,6 +95,11 @@ namespace Files return iter->second; } + bool MultiDirCollection::doesExist (const std::string& file) const + { + return mFiles.find (file)!=mFiles.end(); + } + MultiDirCollection::TIter MultiDirCollection::begin() const { return mFiles.begin(); diff --git a/components/files/multidircollection.hpp b/components/files/multidircollection.hpp index e8abeb45d..3b420d677 100644 --- a/components/files/multidircollection.hpp +++ b/components/files/multidircollection.hpp @@ -73,6 +73,9 @@ namespace Files /// If the file does not exist, an exception is thrown. \a file must include /// the extension. + bool doesExist (const std::string& file) const; + ///< \return Does a file with the given name exist? + TIter begin() const; ///< Return iterator pointing to the first file. diff --git a/components/translation/translation.cpp b/components/translation/translation.cpp index feda76f6f..b559c6c1c 100644 --- a/components/translation/translation.cpp +++ b/components/translation/translation.cpp @@ -24,22 +24,18 @@ namespace Translation const std::string& extension, const Files::Collections& dataFileCollections) { - std::string path; - try - { - path = dataFileCollections.getCollection(extension).getPath(fileNameNoExtension + extension).string(); - } - catch(...) - { - //no file - return; - } + std::string fileName = fileNameNoExtension + extension; - std::ifstream stream(path); - if (stream.is_open()) + if (dataFileCollections.getCollection (extension).doesExist (fileName)) { + std::string path = dataFileCollections.getCollection (extension).getPath (fileName).string(); + + std::ifstream stream (path); + + if (!stream.is_open()) + throw std::runtime_error ("failed to open translation file: " + fileName); + loadDataFromStream(container, stream); - stream.close(); } } From a14b7e4a0fe80f07949b5fc7e019f4c5827b1baa Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Wed, 26 Dec 2012 18:07:56 +0000 Subject: [PATCH 071/136] small fixes on text defines --- apps/openmw/mwgui/formatting.cpp | 4 ++-- components/interpreter/defines.cpp | 22 +++++++++++++++------- components/interpreter/defines.hpp | 1 + 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwgui/formatting.cpp b/apps/openmw/mwgui/formatting.cpp index 273034edd..4090b592d 100644 --- a/apps/openmw/mwgui/formatting.cpp +++ b/apps/openmw/mwgui/formatting.cpp @@ -74,7 +74,7 @@ std::vector BookTextParser::split(std::string text, const int width std::vector result; MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor - text = Interpreter::fixDefinesDialog(text, interpreterContext); + text = Interpreter::fixDefinesBook(text, interpreterContext); boost::algorithm::replace_all(text, "
", "\n"); boost::algorithm::replace_all(text, "

", "\n\n"); @@ -176,7 +176,7 @@ std::vector BookTextParser::split(std::string text, const int width MyGUI::IntSize BookTextParser::parse(std::string text, MyGUI::Widget* parent, const int width) { MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor - text = Interpreter::fixDefinesDialog(text, interpreterContext); + text = Interpreter::fixDefinesBook(text, interpreterContext); mParent = parent; diff --git a/components/interpreter/defines.cpp b/components/interpreter/defines.cpp index bd355fd7c..29c78200d 100644 --- a/components/interpreter/defines.cpp +++ b/components/interpreter/defines.cpp @@ -1,6 +1,5 @@ #include "defines.hpp" -#include #include #include #include @@ -22,7 +21,7 @@ namespace Interpreter{ return a.length() > b.length(); } - std::string fixDefinesReal(std::string text, char eschar, Context& context){ + std::string fixDefinesReal(std::string text, char eschar, bool isBook, Context& context){ unsigned int start = 0; std::string retval = ""; @@ -107,7 +106,7 @@ namespace Interpreter{ retval += context.getCurrentCellName(); } - else if(eschar == '%'){ // In Dialogue, not messagebox + else if(eschar == '%' && !isBook) { // In Dialogue, not messagebox if( (found = Check(temp, "faction", &i, &start))){ retval += context.getNPCFaction(); } @@ -134,9 +133,9 @@ namespace Interpreter{ retval += context.getNPCName(); } } - else if(eschar == '^') { // In messagebox, not dialogue + else { // In messagebox or book, not dialogue - /* empty in messageboxes */ + /* empty outside dialogue */ if( (found = Check(temp, "faction", &i, &start))); else if((found = Check(temp, "nextpcrank", &i, &start))); else if((found = Check(temp, "pcnextrank", &i, &start))); @@ -164,6 +163,11 @@ namespace Interpreter{ } for(unsigned int j = 0; j < globals.size(); j++){ + if(globals[j].length() > temp.length()){ // Just in case there's a global with a huuuge name + std::string temp = text.substr(i+1, globals[j].length()); + transform(temp.begin(), temp.end(), temp.begin(), ::tolower); + } + if((found = Check(temp, globals[j], &i, &start))){ char type = context.getGlobalType(globals[j]); @@ -191,10 +195,14 @@ namespace Interpreter{ } std::string fixDefinesDialog(std::string text, Context& context){ - return fixDefinesReal(text, '%', context); + return fixDefinesReal(text, '%', false, context); } std::string fixDefinesMsgBox(std::string text, Context& context){ - return fixDefinesReal(text, '^', context); + return fixDefinesReal(text, '^', false, context); + } + + std::string fixDefinesBook(std::string text, Context& context){ + return fixDefinesReal(text, '%', true, context); } } diff --git a/components/interpreter/defines.hpp b/components/interpreter/defines.hpp index 4cfba21ea..00c4386b8 100644 --- a/components/interpreter/defines.hpp +++ b/components/interpreter/defines.hpp @@ -7,6 +7,7 @@ namespace Interpreter{ std::string fixDefinesDialog(std::string text, Context& context); std::string fixDefinesMsgBox(std::string text, Context& context); + std::string fixDefinesBook(std::string text, Context& context); } #endif From 716fbbbd74d3474fb0a36f8eff00fdd7da8152b5 Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Wed, 26 Dec 2012 22:57:53 +0000 Subject: [PATCH 072/136] messageboxes during dialogue show up in dialogue window, and messageboxes are generated when an item is removed from inventory --- apps/openmw/mwgui/dialogue.cpp | 5 +++ apps/openmw/mwgui/dialogue.hpp | 1 + apps/openmw/mwgui/windowmanagerimp.cpp | 22 +++++++++----- apps/openmw/mwscript/containerextensions.cpp | 32 ++++++++++++++++++++ 4 files changed, 52 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 258e9174c..e2b9f461a 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -370,6 +370,11 @@ void DialogueWindow::addText(std::string text) mHistory->addDialogText("#B29154"+parseText(text)+"#B29154"); } +void DialogueWindow::addMessageBox(std::string text) +{ + mHistory->addDialogText("\n#FFFFFF"+text+"#B29154"); +} + void DialogueWindow::addTitle(std::string text) { // This is called from the dialogue manager, so text is diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index 082d92524..c4b86e6c8 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -65,6 +65,7 @@ namespace MWGui void setKeywords(std::list keyWord); void removeKeyword(std::string keyWord); void addText(std::string text); + void addMessageBox(std::string text); void addTitle(std::string text); void askQuestion(std::string question); void goodbye(); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index caf6a4ab0..ebef71409 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -537,14 +537,20 @@ void WindowManager::removeDialog(OEngine::GUI::Layout*dialog) void WindowManager::messageBox (const std::string& message, const std::vector& buttons) { - if (buttons.empty()) - { - mMessageBoxManager->createMessageBox(message); - } - else - { - mMessageBoxManager->createInteractiveMessageBox(message, buttons); - pushGuiMode(GM_InterMessageBox); + /* If there are no buttons, and there is a dialogue window open, messagebox goes to the dialogue window */ + if(buttons.empty() && std::find(mGuiModes.begin(), mGuiModes.end(), GM_Dialogue) != mGuiModes.end()) + mDialogueWindow->addMessageBox(MyGUI::LanguageManager::getInstance().replaceTags(message)); + + else{ + if (buttons.empty()) + { + mMessageBoxManager->createMessageBox(message); + } + else + { + mMessageBoxManager->createInteractiveMessageBox(message, buttons); + pushGuiMode(GM_InterMessageBox); + } } } diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 7f4913b8a..07cf3b9e3 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -10,6 +10,7 @@ #include #include "../mwbase/environment.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/manualref.hpp" #include "../mwworld/class.hpp" @@ -106,12 +107,41 @@ namespace MWScript throw std::runtime_error ("second argument for RemoveItem must be non-negative"); MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr); + + std::string itemName = ""; for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end() && count; ++iter) { if (toLower(iter->getCellRef().mRefID) == toLower(item)) { + switch(iter.getType()){ + case MWWorld::ContainerStore::Type_Potion: + itemName = iter->get()->mBase->mName; break; + case MWWorld::ContainerStore::Type_Apparatus: + itemName = iter->get()->mBase->mName; break; + case MWWorld::ContainerStore::Type_Armor: + itemName = iter->get()->mBase->mName; break; + case MWWorld::ContainerStore::Type_Book: + itemName = iter->get()->mBase->mName; break; + case MWWorld::ContainerStore::Type_Clothing: + itemName = iter->get()->mBase->mName; break; + case MWWorld::ContainerStore::Type_Ingredient: + itemName = iter->get()->mBase->mName; break; + case MWWorld::ContainerStore::Type_Light: + itemName = iter->get()->mBase->mName; break; + case MWWorld::ContainerStore::Type_Lockpick: + itemName = iter->get()->mBase->mName; break; + case MWWorld::ContainerStore::Type_Miscellaneous: + itemName = iter->get()->mBase->mName; break; + case MWWorld::ContainerStore::Type_Probe: + itemName = iter->get()->mBase->mName; break; + case MWWorld::ContainerStore::Type_Repair: + itemName = iter->get()->mBase->mName; break; + case MWWorld::ContainerStore::Type_Weapon: + itemName = iter->get()->mBase->mName; break; + } + if (iter->getRefData().getCount()<=count) { count -= iter->getRefData().getCount(); @@ -124,6 +154,8 @@ namespace MWScript } } } + + MWBase::Environment::get().getWindowManager()->messageBox(itemName + " has been removed from your inventory.", std::vector()); // To be fully compatible with original Morrowind, we would need to check if // count is >= 0 here and throw an exception. But let's be tollerant instead. From 299a1f32ed59855c3be4305d1336799efaca3ec2 Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Wed, 26 Dec 2012 23:52:16 +0000 Subject: [PATCH 073/136] cleanup --- apps/openmw/mwgui/windowmanagerimp.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index ebef71409..fe3cb7b11 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -537,20 +537,19 @@ void WindowManager::removeDialog(OEngine::GUI::Layout*dialog) void WindowManager::messageBox (const std::string& message, const std::vector& buttons) { - /* If there are no buttons, and there is a dialogue window open, messagebox goes to the dialogue window */ - if(buttons.empty() && std::find(mGuiModes.begin(), mGuiModes.end(), GM_Dialogue) != mGuiModes.end()) - mDialogueWindow->addMessageBox(MyGUI::LanguageManager::getInstance().replaceTags(message)); + if(buttons.empty()){ + /* If there are no buttons, and there is a dialogue window open, messagebox goes to the dialogue window */ + if(std::find(mGuiModes.begin(), mGuiModes.end(), GM_Dialogue) != mGuiModes.end()) + mDialogueWindow->addMessageBox(MyGUI::LanguageManager::getInstance().replaceTags(message)); - else{ - if (buttons.empty()) - { - mMessageBoxManager->createMessageBox(message); - } else - { - mMessageBoxManager->createInteractiveMessageBox(message, buttons); - pushGuiMode(GM_InterMessageBox); - } + mMessageBoxManager->createMessageBox(message); + } + + else + { + mMessageBoxManager->createInteractiveMessageBox(message, buttons); + pushGuiMode(GM_InterMessageBox); } } From ba2301a1566e0655cbcb0d57d658ca7d3c145d39 Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Thu, 27 Dec 2012 00:49:39 +0000 Subject: [PATCH 074/136] removed redundant code thanks to scrawl --- apps/openmw/mwscript/containerextensions.cpp | 27 +------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 07cf3b9e3..813ac555f 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -115,32 +115,7 @@ namespace MWScript { if (toLower(iter->getCellRef().mRefID) == toLower(item)) { - switch(iter.getType()){ - case MWWorld::ContainerStore::Type_Potion: - itemName = iter->get()->mBase->mName; break; - case MWWorld::ContainerStore::Type_Apparatus: - itemName = iter->get()->mBase->mName; break; - case MWWorld::ContainerStore::Type_Armor: - itemName = iter->get()->mBase->mName; break; - case MWWorld::ContainerStore::Type_Book: - itemName = iter->get()->mBase->mName; break; - case MWWorld::ContainerStore::Type_Clothing: - itemName = iter->get()->mBase->mName; break; - case MWWorld::ContainerStore::Type_Ingredient: - itemName = iter->get()->mBase->mName; break; - case MWWorld::ContainerStore::Type_Light: - itemName = iter->get()->mBase->mName; break; - case MWWorld::ContainerStore::Type_Lockpick: - itemName = iter->get()->mBase->mName; break; - case MWWorld::ContainerStore::Type_Miscellaneous: - itemName = iter->get()->mBase->mName; break; - case MWWorld::ContainerStore::Type_Probe: - itemName = iter->get()->mBase->mName; break; - case MWWorld::ContainerStore::Type_Repair: - itemName = iter->get()->mBase->mName; break; - case MWWorld::ContainerStore::Type_Weapon: - itemName = iter->get()->mBase->mName; break; - } + itemName = MWWorld::Class::get(*iter).getName(*iter); if (iter->getRefData().getCount()<=count) { From 2736e84e496220eb0f4e3381d190c1edba740e7f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 27 Dec 2012 11:04:53 +0100 Subject: [PATCH 075/136] updated credits file --- credits.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/credits.txt b/credits.txt index 063e9940a..84a596a6b 100644 --- a/credits.txt +++ b/credits.txt @@ -26,6 +26,7 @@ Jacob Essex (Yacoby) Jannik Heller (scrawl) Jason Hooks (jhooks) Karl-Felix Glatzer (k1ll) +lazydev Leon Saunders (emoose) Lukasz Gromanowski (lgro) Marcin Hulist (Gohan) From ad9b86058b503cc1f3b4ee5821e2bc02f0bde9b0 Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Thu, 27 Dec 2012 15:28:13 +0000 Subject: [PATCH 076/136] replaced explicit text with GMST entries, thanks to zinnschlag --- apps/openmw/mwgui/dialogue.cpp | 2 +- apps/openmw/mwgui/dialogue.hpp | 2 +- apps/openmw/mwscript/containerextensions.cpp | 27 ++++++++++++++++++-- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index e2b9f461a..2809e842a 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -370,7 +370,7 @@ void DialogueWindow::addText(std::string text) mHistory->addDialogText("#B29154"+parseText(text)+"#B29154"); } -void DialogueWindow::addMessageBox(std::string text) +void DialogueWindow::addMessageBox(const std::string& text) { mHistory->addDialogText("\n#FFFFFF"+text+"#B29154"); } diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index c4b86e6c8..72bb6d19a 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -65,7 +65,7 @@ namespace MWGui void setKeywords(std::list keyWord); void removeKeyword(std::string keyWord); void addText(std::string text); - void addMessageBox(std::string text); + void addMessageBox(const std::string& text); void addTitle(std::string text); void askQuestion(std::string question); void goodbye(); diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 813ac555f..2ac18a554 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -3,6 +3,10 @@ #include +#include + +#include + #include #include @@ -102,13 +106,14 @@ namespace MWScript Interpreter::Type_Integer count = runtime[0].mInteger; runtime.pop(); - + if (count<0) throw std::runtime_error ("second argument for RemoveItem must be non-negative"); MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr); std::string itemName = ""; + Interpreter::Type_Integer originalCount = count; for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end() && count; ++iter) @@ -129,8 +134,26 @@ namespace MWScript } } } + + /* The two GMST entries below expand to strings informing the player of what, and how many of it has been removed from their inventory */ + std::string msgBox; + if(originalCount - count > 1) + { + msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage63}"); + std::stringstream temp; + temp << boost::format(msgBox) % (originalCount - count) % itemName; + msgBox = temp.str(); + } + else + { + msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage62}"); + std::stringstream temp; + temp << boost::format(msgBox) % itemName; + msgBox = temp.str(); + } - MWBase::Environment::get().getWindowManager()->messageBox(itemName + " has been removed from your inventory.", std::vector()); + if(originalCount - count > 0) + MWBase::Environment::get().getWindowManager()->messageBox(msgBox, std::vector()); // To be fully compatible with original Morrowind, we would need to check if // count is >= 0 here and throw an exception. But let's be tollerant instead. From 8545667bbde8579e596ff1d302ab673504b4175b Mon Sep 17 00:00:00 2001 From: eduard Date: Fri, 28 Dec 2012 17:54:56 +0100 Subject: [PATCH 077/136] string compare and tolower --- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 78 +++++++------------ apps/openmw/mwgui/inventorywindow.cpp | 15 +--- apps/openmw/mwscript/containerextensions.cpp | 17 +--- apps/openmw/mwworld/containerstore.cpp | 18 ++--- apps/openmw/mwworld/worldimp.cpp | 16 +--- components/esm_store/reclists.hpp | 41 ++++------ components/misc/stringops.cpp | 37 +++++++++ components/misc/stringops.hpp | 9 +++ 8 files changed, 101 insertions(+), 130 deletions(-) diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 62f7df679..2c30ebf06 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -41,30 +41,6 @@ namespace { - std::string toLower (const std::string& name) - { - std::string lowerCase; - - std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), - (int(*)(int)) std::tolower); - - return lowerCase; - } - - bool stringCompareNoCase (std::string first, std::string second) - { - unsigned int i=0; - while ( (itolower(second[i])) return false; - ++i; - } - if (first.length() bool selectCompare (char comp, T1 value1, T2 value2) @@ -72,7 +48,7 @@ namespace switch (comp) { case '0': return value1==value2; - case '1': return value1!=value2; +// case '1': return value1!=value2; case '2': return value1>value2; case '3': return value1>=value2; case '4': return value1first; - if(PCstats.getFactionRanks().find(toLower(NPCFaction)) != PCstats.getFactionRanks().end()) sameFaction = 1; + if(PCstats.getFactionRanks().find(Misc::toLower(NPCFaction)) != PCstats.getFactionRanks().end()) sameFaction = 1; } if(!selectCompare(comp,sameFaction,select.mI)) return false; } @@ -307,12 +283,12 @@ namespace MWDialogue if (select.mType==ESM::VT_Short || select.mType==ESM::VT_Int || select.mType==ESM::VT_Long) { - if (!checkGlobal (comp, toLower (name), select.mI)) + if (!checkGlobal (comp, Misc::toLower (name), select.mI)) return false; } else if (select.mType==ESM::VT_Float) { - if (!checkGlobal (comp, toLower (name), select.mF)) + if (!checkGlobal (comp, Misc::toLower (name), select.mF)) return false; } else @@ -326,13 +302,13 @@ namespace MWDialogue if (select.mType==ESM::VT_Short || select.mType==ESM::VT_Int || select.mType==ESM::VT_Long) { - if (!checkLocal (comp, toLower (name), select.mI, actor, + if (!checkLocal (comp, Misc::toLower (name), select.mI, actor, MWBase::Environment::get().getWorld()->getStore())) return false; } else if (select.mType==ESM::VT_Float) { - if (!checkLocal (comp, toLower (name), select.mF, actor, + if (!checkLocal (comp, Misc::toLower (name), select.mF, actor, MWBase::Environment::get().getWorld()->getStore())) return false; } @@ -345,7 +321,7 @@ namespace MWDialogue case '4'://journal if(select.mType==ESM::VT_Int) { - if(!selectCompare(comp,MWBase::Environment::get().getJournal()->getJournalIndex(toLower(name)),select.mI)) return false; + if(!selectCompare(comp,MWBase::Environment::get().getJournal()->getJournalIndex(Misc::toLower(name)),select.mI)) return false; } else throw std::runtime_error ( @@ -361,7 +337,7 @@ namespace MWDialogue int sum = 0; for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) - if (toLower(iter->getCellRef().mRefID) == toLower(name)) + if (Misc::toLower(iter->getCellRef().mRefID) == Misc::toLower(name)) sum += iter->getRefData().getCount(); if(!selectCompare(comp,sum,select.mI)) return false; } @@ -375,7 +351,7 @@ namespace MWDialogue case '7':// not ID if(select.mType==ESM::VT_String ||select.mType==ESM::VT_Int)//bug in morrowind here? it's not a short, it's a string { - int isID = int(toLower(name)==toLower(MWWorld::Class::get (actor).getId (actor))); + int isID = int(Misc::toLower(name)==Misc::toLower(MWWorld::Class::get (actor).getId (actor))); if (selectCompare(comp,!isID,select.mI)) return false; } else @@ -391,7 +367,7 @@ namespace MWDialogue if(select.mType==ESM::VT_Int) { MWWorld::LiveCellRef* npc = actor.get(); - int isFaction = int(toLower(npc->base->mFaction) == toLower(name)); + int isFaction = int(Misc::toLower(npc->base->mFaction) == Misc::toLower(name)); if(selectCompare(comp,!isFaction,select.mI)) return false; } @@ -408,7 +384,7 @@ namespace MWDialogue if(select.mType==ESM::VT_Int) { MWWorld::LiveCellRef* npc = actor.get(); - int isClass = int(toLower(npc->base->mClass) == toLower(name)); + int isClass = int(Misc::toLower(npc->base->mClass) == Misc::toLower(name)); if(selectCompare(comp,!isClass,select.mI)) return false; } @@ -425,7 +401,7 @@ namespace MWDialogue if(select.mType==ESM::VT_Int) { MWWorld::LiveCellRef* npc = actor.get(); - int isRace = int(toLower(npc->base->mRace) == toLower(name)); + int isRace = int(Misc::toLower(npc->base->mRace) == Misc::toLower(name)); if(selectCompare(comp,!isRace,select.mI)) return false; } @@ -438,7 +414,7 @@ namespace MWDialogue case 'B'://not Cell if(select.mType==ESM::VT_Int) { - int isCell = int(toLower(actor.getCell()->cell->mName) == toLower(name)); + int isCell = int(Misc::toLower(actor.getCell()->cell->mName) == Misc::toLower(name)); if(selectCompare(comp,!isCell,select.mI)) return false; } @@ -451,13 +427,13 @@ namespace MWDialogue if (select.mType==ESM::VT_Short || select.mType==ESM::VT_Int || select.mType==ESM::VT_Long) { - if (checkLocal (comp, toLower (name), select.mI, actor, + if (checkLocal (comp, Misc::toLower (name), select.mI, actor, MWBase::Environment::get().getWorld()->getStore())) return false; } else if (select.mType==ESM::VT_Float) { - if (checkLocal (comp, toLower (name), select.mF, actor, + if (checkLocal (comp, Misc::toLower (name), select.mF, actor, MWBase::Environment::get().getWorld()->getStore())) return false; } @@ -482,7 +458,7 @@ namespace MWDialogue // actor id if (!info.mActor.empty()) - if (toLower (info.mActor)!=MWWorld::Class::get (actor).getId (actor)) + if (Misc::toLower (info.mActor)!=MWWorld::Class::get (actor).getId (actor)) return false; //NPC race @@ -496,7 +472,7 @@ namespace MWDialogue if (!cellRef) return false; - if (toLower (info.mRace)!=toLower (cellRef->base->mRace)) + if (Misc::toLower (info.mRace)!=Misc::toLower (cellRef->base->mRace)) return false; } @@ -511,7 +487,7 @@ namespace MWDialogue if (!cellRef) return false; - if (toLower (info.mClass)!=toLower (cellRef->base->mClass)) + if (Misc::toLower (info.mClass)!=Misc::toLower (cellRef->base->mClass)) return false; } @@ -523,7 +499,7 @@ namespace MWDialogue //MWWorld::Class npcClass = MWWorld::Class::get(actor); MWMechanics::NpcStats stats = MWWorld::Class::get(actor).getNpcStats(actor); - std::map::iterator it = stats.getFactionRanks().find(toLower(info.mNpcFaction)); + std::map::iterator it = stats.getFactionRanks().find(Misc::toLower(info.mNpcFaction)); if(it!=stats.getFactionRanks().end()) { //check rank @@ -540,7 +516,7 @@ namespace MWDialogue if(!info.mPcFaction.empty()) { MWMechanics::NpcStats stats = MWWorld::Class::get(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()).getNpcStats(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); - std::map::iterator it = stats.getFactionRanks().find(toLower(info.mPcFaction)); + std::map::iterator it = stats.getFactionRanks().find(Misc::toLower(info.mPcFaction)); if(it!=stats.getFactionRanks().end()) { //check rank @@ -593,13 +569,13 @@ namespace MWDialogue ESMS::RecListCaseT::MapType dialogueList = MWBase::Environment::get().getWorld()->getStore().dialogs.list; for(ESMS::RecListCaseT::MapType::iterator it = dialogueList.begin(); it!=dialogueList.end();it++) { - mDialogueMap[toLower(it->first)] = it->second; + mDialogueMap[Misc::toLower(it->first)] = it->second; } } void DialogueManager::addTopic (const std::string& topic) { - mKnownTopics[toLower(topic)] = true; + mKnownTopics[Misc::toLower(topic)] = true; } void DialogueManager::parseText (std::string text) @@ -753,9 +729,9 @@ namespace MWDialogue { if (isMatching (mActor, *iter) && functionFilter(mActor,*iter,true)) { - mActorKnownTopics.push_back(toLower(it->first)); + mActorKnownTopics.push_back(Misc::toLower(it->first)); //does the player know the topic? - if(mKnownTopics.find(toLower(it->first)) != mKnownTopics.end()) + if(mKnownTopics.find(Misc::toLower(it->first)) != mKnownTopics.end()) { keywordList.push_back(it->first); break; @@ -813,7 +789,7 @@ namespace MWDialogue win->setServices (windowServices); // sort again, because the previous sort was case-sensitive - keywordList.sort(stringCompareNoCase); + keywordList.sort(Misc::stringCompareNoCase); win->setKeywords(keywordList); mChoice = choice; @@ -907,7 +883,7 @@ namespace MWDialogue { MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); win->askQuestion(question); - mChoiceMap[toLower(question)] = choice; + mChoiceMap[Misc::toLower(question)] = choice; mIsInChoice = true; } diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index bb3dc67e6..1ac5b2fc6 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -24,19 +24,6 @@ #include "scrollwindow.hpp" #include "spellwindow.hpp" -namespace -{ - std::string toLower (const std::string& name) - { - std::string lowerCase; - - std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), - (int(*)(int)) std::tolower); - - return lowerCase; - } -} - namespace MWGui { @@ -284,7 +271,7 @@ namespace MWGui for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it) { - if (toLower(it->getCellRef().mRefID) == "gold_001") + if (Misc::toLower(it->getCellRef().mRefID) == "gold_001") return it->getRefData().getCount(); } return 0; diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 5e9746b2f..725885e41 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -18,19 +18,6 @@ #include "interpretercontext.hpp" #include "ref.hpp" -namespace -{ - std::string toLower (const std::string& name) - { - std::string lowerCase; - - std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), - (int(*)(int)) std::tolower); - - return lowerCase; - } -} - namespace MWScript { namespace Container @@ -78,7 +65,7 @@ namespace MWScript Interpreter::Type_Integer sum = 0; for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) - if (toLower(iter->getCellRef().mRefID) == toLower(item)) + if (Misc::toLower(iter->getCellRef().mRefID) == Misc::toLower(item)) sum += iter->getRefData().getCount(); runtime.push (sum); @@ -108,7 +95,7 @@ namespace MWScript for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end() && count; ++iter) { - if (toLower(iter->getCellRef().mRefID) == toLower(item)) + if (Misc::toLower(iter->getCellRef().mRefID) == Misc::toLower(item)) { if (iter->getRefData().getCount()<=count) { diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 5c4dd03a4..f736a5253 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -34,12 +34,6 @@ namespace return sum; } - - bool compare_string_ci(std::string str1, std::string str2) - { - boost::algorithm::to_lower(str1); - return str1 == str2; - } } MWWorld::ContainerStore::ContainerStore() : mStateId (0), mCachedWeight (0), mWeightUpToDate (false) {} @@ -81,11 +75,11 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& ptr) MWWorld::LiveCellRef *gold = ptr.get(); - if (compare_string_ci(gold->ref.mRefID, "gold_001") - || compare_string_ci(gold->ref.mRefID, "gold_005") - || compare_string_ci(gold->ref.mRefID, "gold_010") - || compare_string_ci(gold->ref.mRefID, "gold_025") - || compare_string_ci(gold->ref.mRefID, "gold_100")) + if (Misc::compare_string_ci(gold->ref.mRefID, "gold_001") + || Misc::compare_string_ci(gold->ref.mRefID, "gold_005") + || Misc::compare_string_ci(gold->ref.mRefID, "gold_010") + || Misc::compare_string_ci(gold->ref.mRefID, "gold_025") + || Misc::compare_string_ci(gold->ref.mRefID, "gold_100")) { MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), "Gold_001"); @@ -93,7 +87,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& ptr) ref.getPtr().getRefData().setCount(count); for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter) { - if (compare_string_ci((*iter).get()->ref.mRefID, "gold_001")) + if (Misc::compare_string_ci((*iter).get()->ref.mRefID, "gold_001")) { (*iter).getRefData().setCount( (*iter).getRefData().getCount() + count); flagAsModified(); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index c7f0de245..fe8aeb90b 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -228,12 +228,12 @@ namespace MWWorld return cell; // didn't work -> now check for regions - std::string cellName2 = ESMS::RecListT::toLower (cellName); + std::string cellName2 = Misc::toLower (cellName); for (ESMS::RecListT::MapType::const_iterator iter (mStore.regions.list.begin()); iter!=mStore.regions.list.end(); ++iter) { - if (ESMS::RecListT::toLower (iter->second.mName)==cellName2) + if (Misc::toLower (iter->second.mName)==cellName2) { if (const ESM::Cell *cell = mStore.cells.searchExtByRegion (iter->first)) return cell; @@ -563,16 +563,6 @@ namespace MWWorld } } - std::string toLower (const std::string& name) - { - std::string lowerCase; - - std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), - (int(*)(int)) std::tolower); - - return lowerCase; - } - void World::moveObject(const Ptr &ptr, CellStore &newCell, float x, float y, float z) { ESM::Position &pos = ptr.getRefData().getPosition(); @@ -585,7 +575,7 @@ namespace MWWorld if (*currCell != newCell) { if (isPlayer) { if (!newCell.isExterior()) { - changeToInteriorCell(toLower(newCell.cell->mName), pos); + changeToInteriorCell(Misc::toLower(newCell.cell->mName), pos); } else { int cellX = newCell.cell->mData.mX; int cellY = newCell.cell->mData.mY; diff --git a/components/esm_store/reclists.hpp b/components/esm_store/reclists.hpp index 0b265a566..f9f74244b 100644 --- a/components/esm_store/reclists.hpp +++ b/components/esm_store/reclists.hpp @@ -28,15 +28,6 @@ namespace ESMS virtual int getSize() = 0; virtual void listIdentifier (std::vector& identifier) const = 0; - static std::string toLower (const std::string& name) - { - std::string lowerCase; - - std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), - (int(*)(int)) std::tolower); - - return lowerCase; - } }; typedef std::map RecListList; @@ -53,14 +44,14 @@ namespace ESMS // Load one object of this type void load(ESMReader &esm, const std::string &id) { - std::string id2 = toLower (id); + std::string id2 = Misc::toLower (id); list[id2].load(esm); } // Find the given object ID, or return NULL if not found. const X* search(const std::string &id) const { - std::string id2 = toLower (id); + std::string id2 = Misc::toLower (id); typename MapType::const_iterator iter = list.find (id2); @@ -104,7 +95,7 @@ namespace ESMS // Load one object of this type void load(ESMReader &esm, const std::string &id) { - //std::string id2 = toLower (id); + //std::string id2 = Misc::toLower (id); list[id].load(esm); } @@ -112,12 +103,12 @@ namespace ESMS // Find the given object ID, or return NULL if not found. const X* search(const std::string &id) const { - std::string id2 = toLower (id); + std::string id2 = Misc::toLower (id); for (typename MapType::const_iterator iter = list.begin(); iter != list.end(); ++iter) { - if (toLower(iter->first) == id2) + if (Misc::toLower(iter->first) == id2) return &iter->second; } @@ -127,12 +118,12 @@ namespace ESMS // non-const version X* search(const std::string &id) { - std::string id2 = toLower (id); + std::string id2 = Misc::toLower (id); for (typename MapType::iterator iter = list.begin(); iter != list.end(); ++iter) { - if (toLower(iter->first) == id2) + if (Misc::toLower(iter->first) == id2) return &iter->second; } @@ -172,7 +163,7 @@ namespace ESMS // Load one object of this type void load(ESMReader &esm, const std::string &id) { - std::string id2 = toLower (id); + std::string id2 = Misc::toLower (id); list[id2].mId = id2; list[id2].load(esm); } @@ -180,7 +171,7 @@ namespace ESMS // Find the given object ID, or return NULL if not found. const X* search(const std::string &id) const { - std::string id2 = toLower (id); + std::string id2 = Misc::toLower (id); typename MapType::const_iterator iter = list.find (id2); @@ -223,7 +214,7 @@ namespace ESMS void load(ESMReader &esm, const std::string &id) { - std::string id2 = toLower (id); + std::string id2 = Misc::toLower (id); X& ref = list[id2]; ref.mId = id; @@ -233,7 +224,7 @@ namespace ESMS // Find the given object ID, or return NULL if not found. const X* search(const std::string &id) const { - std::string id2 = toLower (id); + std::string id2 = Misc::toLower (id); typename MapType::const_iterator iter = list.find (id2); @@ -440,7 +431,7 @@ namespace ESMS { for (ExtCells::const_iterator iter = extCells.begin(); iter!=extCells.end(); ++iter) { - if (toLower (iter->second->mName) == toLower (id)) + if (Misc::toLower (iter->second->mName) == Misc::toLower (id)) return iter->second; } @@ -449,10 +440,10 @@ namespace ESMS const ESM::Cell *searchExtByRegion (const std::string& id) const { - std::string id2 = toLower (id); + std::string id2 = Misc::toLower (id); for (ExtCells::const_iterator iter = extCells.begin(); iter!=extCells.end(); ++iter) - if (toLower (iter->second->mRegion)==id) + if (Misc::toLower (iter->second->mRegion)==id) return iter->second; return 0; @@ -586,7 +577,7 @@ namespace ESMS X ref; ref.load (esm); - std::string realId = toLower (ref.mData.mName.toString()); + std::string realId = Misc::toLower (ref.mData.mName.toString()); std::swap (list[realId], ref); } @@ -594,7 +585,7 @@ namespace ESMS // Find the given object ID, or return NULL if not found. const X* search(const std::string &id) const { - std::string id2 = toLower (id); + std::string id2 = Misc::toLower (id); typename MapType::const_iterator iter = list.find (id2); diff --git a/components/misc/stringops.cpp b/components/misc/stringops.cpp index 53eed1fdc..f209bf46b 100644 --- a/components/misc/stringops.cpp +++ b/components/misc/stringops.cpp @@ -1,7 +1,14 @@ #include "stringops.hpp" +#include +#include +#include + #include #include +#include + + namespace Misc { @@ -61,4 +68,34 @@ bool iends(const char* str1, const char* str2) return strcasecmp(str2, str1+len1-len2) == 0; } +std::string toLower (const std::string& name) +{ + std::string lowerCase; + + std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), + (int(*)(int)) std::tolower); + + return lowerCase; +} + +bool stringCompareNoCase (std::string first, std::string second) +{ + unsigned int i=0; + while ( (itolower(second[i])) return false; + ++i; + } + if (first.length() + namespace Misc { @@ -16,6 +18,13 @@ bool ibegins(const char* str1, const char* str2); /// Case insensitive, returns true if str1 ends with substring str2 bool iends(const char* str1, const char* str2); + +std::string toLower (const std::string& name); + +bool stringCompareNoCase (std::string first, std::string second); + +bool compare_string_ci (std::string first, std::string second); + } #endif From c75a5ae212bc01d1b3d37ffcf0f3cf879f7775a4 Mon Sep 17 00:00:00 2001 From: eduard Date: Fri, 28 Dec 2012 18:05:52 +0100 Subject: [PATCH 078/136] string compare and tolower --- apps/openmw/mwworld/containerstore.cpp | 18 ++++++++++++------ components/misc/stringops.cpp | 7 +------ components/misc/stringops.hpp | 5 ++--- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index f736a5253..5c4dd03a4 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -34,6 +34,12 @@ namespace return sum; } + + bool compare_string_ci(std::string str1, std::string str2) + { + boost::algorithm::to_lower(str1); + return str1 == str2; + } } MWWorld::ContainerStore::ContainerStore() : mStateId (0), mCachedWeight (0), mWeightUpToDate (false) {} @@ -75,11 +81,11 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& ptr) MWWorld::LiveCellRef *gold = ptr.get(); - if (Misc::compare_string_ci(gold->ref.mRefID, "gold_001") - || Misc::compare_string_ci(gold->ref.mRefID, "gold_005") - || Misc::compare_string_ci(gold->ref.mRefID, "gold_010") - || Misc::compare_string_ci(gold->ref.mRefID, "gold_025") - || Misc::compare_string_ci(gold->ref.mRefID, "gold_100")) + if (compare_string_ci(gold->ref.mRefID, "gold_001") + || compare_string_ci(gold->ref.mRefID, "gold_005") + || compare_string_ci(gold->ref.mRefID, "gold_010") + || compare_string_ci(gold->ref.mRefID, "gold_025") + || compare_string_ci(gold->ref.mRefID, "gold_100")) { MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), "Gold_001"); @@ -87,7 +93,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& ptr) ref.getPtr().getRefData().setCount(count); for (MWWorld::ContainerStoreIterator iter (begin(type)); iter!=end(); ++iter) { - if (Misc::compare_string_ci((*iter).get()->ref.mRefID, "gold_001")) + if (compare_string_ci((*iter).get()->ref.mRefID, "gold_001")) { (*iter).getRefData().setCount( (*iter).getRefData().getCount() + count); flagAsModified(); diff --git a/components/misc/stringops.cpp b/components/misc/stringops.cpp index f209bf46b..51cf2105a 100644 --- a/components/misc/stringops.cpp +++ b/components/misc/stringops.cpp @@ -6,7 +6,6 @@ #include #include -#include @@ -92,10 +91,6 @@ bool stringCompareNoCase (std::string first, std::string second) else return false; } -bool compare_string_ci(std::string str1, std::string str2) -{ - boost::algorithm::to_lower(str1); - return str1 == str2; -} + } diff --git a/components/misc/stringops.hpp b/components/misc/stringops.hpp index 6403a7128..4dbfd40d4 100644 --- a/components/misc/stringops.hpp +++ b/components/misc/stringops.hpp @@ -18,13 +18,12 @@ bool ibegins(const char* str1, const char* str2); /// Case insensitive, returns true if str1 ends with substring str2 bool iends(const char* str1, const char* str2); - +/// std::string toLower (const std::string& name); +/// Case fold compare bool stringCompareNoCase (std::string first, std::string second); -bool compare_string_ci (std::string first, std::string second); - } #endif From bed8fb69e65048166cef300ffe2bbe2354def3d3 Mon Sep 17 00:00:00 2001 From: Tom Mason Date: Fri, 28 Dec 2012 22:26:21 +0000 Subject: [PATCH 079/136] added bounty related scripting functions --- apps/openmw/mwscript/docs/vmformat.txt | 5 ++- apps/openmw/mwscript/statsextensions.cpp | 52 ++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 835a3e3ff..df1a52329 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -291,8 +291,11 @@ op 0x20001e8: RaiseRank op 0x20001e9: RaiseRank, explicit op 0x20001ea: LowerRank op 0x20001eb: LowerRank, explicit +op 0x20001ec: GetPCCrimeLevel +op 0x20001ed: SetPCCrimeLevel +op 0x20001ee: SetPCCrimeLevel -opcodes 0x20001ec-0x3ffffff unused +opcodes 0x20001ef-0x3ffffff unused diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index c67782168..9e630aedf 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -392,6 +392,46 @@ namespace MWScript } }; + class OpGetPCCrimeLevel : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + MWWorld::Ptr player = world->getPlayer().getPlayer(); + runtime.push (static_cast (MWWorld::Class::get (player).getNpcStats (player).getBounty())); + } + }; + + class OpSetPCCrimeLevel : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + MWWorld::Ptr player = world->getPlayer().getPlayer(); + + MWWorld::Class::get (player).getNpcStats (player).setBounty(runtime[0].mFloat); + runtime.pop(); + } + }; + + class OpModPCCrimeLevel : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWBase::World *world = MWBase::Environment::get().getWorld(); + MWWorld::Ptr player = world->getPlayer().getPlayer(); + + MWWorld::Class::get (player).getNpcStats (player).setBounty(runtime[0].mFloat + MWWorld::Class::get (player).getNpcStats (player).getBounty()); + runtime.pop(); + } + }; + template class OpAddSpell : public Interpreter::Opcode0 { @@ -1016,6 +1056,10 @@ namespace MWScript const int opcodeModSkill = 0x20000fa; const int opcodeModSkillExplicit = 0x2000115; + const int opcodeGetPCCrimeLevel = 0x20001ec; + const int opcodeSetPCCrimeLevel = 0x20001ed; + const int opcodeModPCCrimeLevel = 0x20001ee; + const int opcodeAddSpell = 0x2000147; const int opcodeAddSpellExplicit = 0x2000148; const int opcodeRemoveSpell = 0x2000149; @@ -1141,6 +1185,10 @@ namespace MWScript opcodeModSkill+i, opcodeModSkillExplicit+i); } + extensions.registerFunction ("getpccrimelevel", 'f', "", opcodeGetPCCrimeLevel); + extensions.registerInstruction ("setpccrimelevel", "f", opcodeSetPCCrimeLevel); + extensions.registerInstruction ("modpccrimelevel", "f", opcodeModPCCrimeLevel); + extensions.registerInstruction ("addspell", "c", opcodeAddSpell, opcodeAddSpellExplicit); extensions.registerInstruction ("removespell", "c", opcodeRemoveSpell, opcodeRemoveSpellExplicit); @@ -1235,6 +1283,10 @@ namespace MWScript interpreter.installSegment5 (opcodeModSkillExplicit+i, new OpModSkill (i)); } + interpreter.installSegment5 (opcodeGetPCCrimeLevel, new OpGetPCCrimeLevel); + interpreter.installSegment5 (opcodeSetPCCrimeLevel, new OpSetPCCrimeLevel); + interpreter.installSegment5 (opcodeModPCCrimeLevel, new OpModPCCrimeLevel); + interpreter.installSegment5 (opcodeAddSpell, new OpAddSpell); interpreter.installSegment5 (opcodeAddSpellExplicit, new OpAddSpell); interpreter.installSegment5 (opcodeRemoveSpell, new OpRemoveSpell); From 8d4afe3bf5abfe2703a782eb5c7338a2d4efb0ce Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 28 Dec 2012 23:45:13 +0100 Subject: [PATCH 080/136] post merge fix --- apps/opencs/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 1cfb5d9a9..abbc953ca 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -6,6 +6,7 @@ set (OPENCS_SRC model/world/universalid.cpp model/world/idcollection.cpp model/world/data.cpp model/world/idtable.cpp model/world/commands.cpp model/world/idtableproxymodel.cpp model/world/record.cpp + model/world/columnbase.cpp model/tools/tools.cpp model/tools/operation.cpp model/tools/stage.cpp model/tools/verifier.cpp model/tools/mandatoryid.cpp model/tools/reportmodel.cpp @@ -26,7 +27,7 @@ set (OPENCS_HDR model/world/universalid.hpp model/world/record.hpp model/world/idcollection.hpp model/world/data.hpp model/world/idtable.hpp model/world/columns.hpp model/world/idtableproxymodel.hpp - model/world/commands.hpp + model/world/commands.hpp model/world/columnbase.hpp model/tools/tools.hpp model/tools/operation.hpp model/tools/stage.hpp model/tools/verifier.hpp model/tools/mandatoryid.hpp model/tools/reportmodel.hpp From 92623921add0d6e16a34973dcf6f2ee1f52dbbe7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 29 Dec 2012 09:23:06 +0100 Subject: [PATCH 081/136] updated credits file --- credits.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/credits.txt b/credits.txt index 84a596a6b..72451c3d0 100644 --- a/credits.txt +++ b/credits.txt @@ -37,7 +37,7 @@ Pieter van der Kloet (pvdk) Roman Melnik (Kromgart) Sebastian Wick (swick) Sylvain T. (Garvek) - +Tom Mason (wheybags) Packagers: Alexander Olofsson (Ace) - Windows From b2203d22fce8483ed2cbce48a55cb65d175445c9 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Sat, 29 Dec 2012 15:22:29 +0100 Subject: [PATCH 082/136] mwiniimporter: added fallback values Ugly comments included. I will merge it on another branch to clean this up later. --- apps/mwiniimporter/importer.cpp | 564 ++++++++++++++++++++++++++++++++ 1 file changed, 564 insertions(+) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 19b69794f..1236dcaf0 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -18,8 +18,572 @@ MwIniImporter::MwIniImporter() { 0, 0 } }; const char *fallback[] = { + + /* + "Fonts:Font 0", + "Fonts:Font 1", + "Fonts:Font 2", + */ + + /* + "FontColor:color_normal", + "FontColor:color_normal_over", + "FontColor:color_normal_pressed", + "FontColor:color_active", + "FontColor:color_active_over", + "FontColor:color_active_pressed", + "FontColor:color_disabled", + "FontColor:color_disabled_over", + "FontColor:color_disabled_pressed", + "FontColor:color_link", + "FontColor:color_link_over", + "FontColor:color_link_pressed", + "FontColor:color_journal_link", + "FontColor:color_journal_link_over", + "FontColor:color_journal_link_pressed", + "FontColor:color_journal_topic", + "FontColor:color_journal_topic_over", + "FontColor:color_journal_topic_pressed", + "FontColor:color_answer", + "FontColor:color_answer_over", + "FontColor:color_answer_pressed", + "FontColor:color_header", + "FontColor:color_notify", + "FontColor:color_big_normal", + "FontColor:color_big_normal_over", + "FontColor:color_big_normal_pressed", + "FontColor:color_big_link", + "FontColor:color_big_link_over", + "FontColor:color_big_link_pressed", + "FontColor:color_big_answer", + "FontColor:color_big_answer_over", + "FontColor:color_big_answer_pressed", + "FontColor:color_big_header", + "FontColor:color_big_notify", + "FontColor:color_background", + "FontColor:color_focus", + "FontColor:color_health", + "FontColor:color_magic", + "FontColor:color_fatigue", + "FontColor:color_misc", + "FontColor:color_weapon_fill", + "FontColor:color_magic_fill", + "FontColor:color_positive", + "FontColor:color_negative", + "FontColor:color_count", + */ + + /* + "Cursors:Cursor 0", + "Cursors:Cursor 1", + "Cursors:Cursor 2", + "Cursors:Cursor 3", + "Cursors:Cursor 4", + */ + + // level up messages + // not used for now + "Level Up:Level2", + "Level Up:Level3", + "Level Up:Level4", + "Level Up:Level5", + "Level Up:Level6", + "Level Up:Level7", + "Level Up:Level8", + "Level Up:Level9", + "Level Up:Level10", + "Level Up:Level11", + "Level Up:Level12", + "Level Up:Level13", + "Level Up:Level14", + "Level Up:Level15", + "Level Up:Level16", + "Level Up:Level17", + "Level Up:Level18", + "Level Up:Level19", + "Level Up:Level20", + "Level Up:Default", + + // character creation multiple choice test + // hardcoded in mwgui/charactercreation.cpp + "Question 1:Question", + "Question 1:AnswerOne", + "Question 1:AnswerTwo", + "Question 1:AnswerThree", + "Question 1:Sound", + "Question 2:Question", + "Question 2:AnswerOne", + "Question 2:AnswerTwo", + "Question 2:AnswerThree", + "Question 2:Sound", + "Question 3:Question", + "Question 3:AnswerOne", + "Question 3:AnswerTwo", + "Question 3:AnswerThree", + "Question 3:Sound", + "Question 4:Question", + "Question 4:AnswerOne", + "Question 4:AnswerTwo", + "Question 4:AnswerThree", + "Question 4:Sound", + "Question 5:Question", + "Question 5:AnswerOne", + "Question 5:AnswerTwo", + "Question 5:AnswerThree", + "Question 5:Sound", + "Question 6:Question", + "Question 6:AnswerOne", + "Question 6:AnswerTwo", + "Question 6:AnswerThree", + "Question 6:Sound", + "Question 7:Question", + "Question 7:AnswerOne", + "Question 7:AnswerTwo", + "Question 7:AnswerThree", + "Question 7:Sound", + "Question 8:Question", + "Question 8:AnswerOne", + "Question 8:AnswerTwo", + "Question 8:AnswerThree", + "Question 8:Sound", + "Question 9:Question", + "Question 9:AnswerOne", + "Question 9:AnswerTwo", + "Question 9:AnswerThree", + "Question 9:Sound", + "Question 10:Question", + "Question 10:AnswerOne", + "Question 10:AnswerTwo", + "Question 10:AnswerThree", + "Question 10:Sound", + + // blood textures and models + // not used for now + "Blood:Model 0", + "Blood:Model 1", + "Blood:Model 2", + "Blood:Texture 0", + "Blood:Texture 1", + "Blood:Texture 2", + "Blood:Texture Name 0", + "Blood:Texture Name 1", + "Blood:Texture Name 2", + + // movies + // not used for now + "Movies:Company Logo", + "Movies:Morrowind Logo", + "Movies:New Game", + "Movies:Loading", + "Movies:Options Menu", + + // weather related values + // hardcoded in mwworld/wheather.cpp + // Some are easy to replace, others are used as magic number + + // globals + "Weather Thunderstorm:Thunder Sound ID 0", + "Weather Thunderstorm:Thunder Sound ID 1", + "Weather Thunderstorm:Thunder Sound ID 2", + "Weather Thunderstorm:Thunder Sound ID 3", "Weather:Sunrise Time", "Weather:Sunset Time", + "Weather:Sunrise Duration", + "Weather:Sunset Duration", + "Weather:Hours Between Weather Changes", // AKA weather update time + "Weather Thunderstorm:Thunder Frequency", + "Weather Thunderstorm:Thunder Threshold", + // thunder sound delay? + + "Weather Clear:Cloud Texture", + "Weather Clear:Clouds Maximum Percent", + "Weather Clear:Transition Delta", + "Weather Clear:Sky Sunrise Color", + "Weather Clear:Sky Day Color", + "Weather Clear:Sky Sunset Color", + "Weather Clear:Sky Night Color", + "Weather Clear:Fog Sunrise Color", + "Weather Clear:Fog Day Color", + "Weather Clear:Fog Sunset Color", + "Weather Clear:Fog Night Color", + "Weather Clear:Ambient Sunrise Color", + "Weather Clear:Ambient Day Color", + "Weather Clear:Ambient Sunset Color", + "Weather Clear:Ambient Night Color", + "Weather Clear:Sun Sunrise Color", + "Weather Clear:Sun Day Color", + "Weather Clear:Sun Sunset Color", + "Weather Clear:Sun Night Color", + "Weather Clear:Sun Disc Sunset Color", + "Weather Clear:Land Fog Day Depth", + "Weather Clear:Land Fog Night Depth", + "Weather Clear:Wind Speed", + "Weather Clear:Cloud Speed", + "Weather Clear:Glare View", + + "Weather Cloudy:Cloud Texture", + "Weather Cloudy:Clouds Maximum Percent", + "Weather Cloudy:Transition Delta", + "Weather Cloudy:Sky Sunrise Color", + "Weather Cloudy:Sky Day Color", + "Weather Cloudy:Sky Sunset Color", + "Weather Cloudy:Sky Night Color", + "Weather Cloudy:Fog Sunrise Color", + "Weather Cloudy:Fog Day Color", + "Weather Cloudy:Fog Sunset Color", + "Weather Cloudy:Fog Night Color", + "Weather Cloudy:Ambient Sunrise Color", + "Weather Cloudy:Ambient Day Color", + "Weather Cloudy:Ambient Sunset Color", + "Weather Cloudy:Ambient Night Color", + "Weather Cloudy:Sun Sunrise Color", + "Weather Cloudy:Sun Day Color", + "Weather Cloudy:Sun Sunset Color", + "Weather Cloudy:Sun Night Color", + "Weather Cloudy:Sun Disc Sunset Color", + "Weather Cloudy:Land Fog Day Depth", + "Weather Cloudy:Land Fog Night Depth", + "Weather Cloudy:Wind Speed", + "Weather Cloudy:Cloud Speed", + "Weather Cloudy:Glare View", + + "Weather Foggy:Cloud Texture", + "Weather Foggy:Clouds Maximum Percent", + "Weather Foggy:Transition Delta", + "Weather Foggy:Sky Sunrise Color", + "Weather Foggy:Sky Day Color", + "Weather Foggy:Sky Sunset Color", + "Weather Foggy:Sky Night Color", + "Weather Foggy:Fog Sunrise Color", + "Weather Foggy:Fog Day Color", + "Weather Foggy:Fog Sunset Color", + "Weather Foggy:Fog Night Color", + "Weather Foggy:Ambient Sunrise Color", + "Weather Foggy:Ambient Day Color", + "Weather Foggy:Ambient Sunset Color", + "Weather Foggy:Ambient Night Color", + "Weather Foggy:Sun Sunrise Color", + "Weather Foggy:Sun Day Color", + "Weather Foggy:Sun Sunset Color", + "Weather Foggy:Sun Night Color", + "Weather Foggy:Sun Disc Sunset Color", + "Weather Foggy:Land Fog Day Depth", + "Weather Foggy:Land Fog Night Depth", + "Weather Foggy:Wind Speed", + "Weather Foggy:Cloud Speed", + "Weather Foggy:Glare View", + + "Weather Thunderstorm:Cloud Texture", + "Weather Thunderstorm:Clouds Maximum Percent", + "Weather Thunderstorm:Transition Delta", + "Weather Thunderstorm:Sky Sunrise Color", + "Weather Thunderstorm:Sky Day Color", + "Weather Thunderstorm:Sky Sunset Color", + "Weather Thunderstorm:Sky Night Color", + "Weather Thunderstorm:Fog Sunrise Color", + "Weather Thunderstorm:Fog Day Color", + "Weather Thunderstorm:Fog Sunset Color", + "Weather Thunderstorm:Fog Night Color", + "Weather Thunderstorm:Ambient Sunrise Color", + "Weather Thunderstorm:Ambient Day Color", + "Weather Thunderstorm:Ambient Sunset Color", + "Weather Thunderstorm:Ambient Night Color", + "Weather Thunderstorm:Sun Sunrise Color", + "Weather Thunderstorm:Sun Day Color", + "Weather Thunderstorm:Sun Sunset Color", + "Weather Thunderstorm:Sun Night Color", + "Weather Thunderstorm:Sun Disc Sunset Color", + "Weather Thunderstorm:Land Fog Day Depth", + "Weather Thunderstorm:Land Fog Night Depth", + "Weather Thunderstorm:Wind Speed", + "Weather Thunderstorm:Cloud Speed", + "Weather Thunderstorm:Glare View", + "Weather Thunderstorm:Rain Loop Sound ID", + + "Weather Rain:Cloud Texture", + "Weather Rain:Clouds Maximum Percent", + "Weather Rain:Transition Delta", + "Weather Rain:Sky Sunrise Color", + "Weather Rain:Sky Day Color", + "Weather Rain:Sky Sunset Color", + "Weather Rain:Sky Night Color", + "Weather Rain:Fog Sunrise Color", + "Weather Rain:Fog Day Color", + "Weather Rain:Fog Sunset Color", + "Weather Rain:Fog Night Color", + "Weather Rain:Ambient Sunrise Color", + "Weather Rain:Ambient Day Color", + "Weather Rain:Ambient Sunset Color", + "Weather Rain:Ambient Night Color", + "Weather Rain:Sun Sunrise Color", + "Weather Rain:Sun Day Color", + "Weather Rain:Sun Sunset Color", + "Weather Rain:Sun Night Color", + "Weather Rain:Sun Disc Sunset Color", + "Weather Rain:Land Fog Day Depth", + "Weather Rain:Land Fog Night Depth", + "Weather Rain:Wind Speed", + "Weather Rain:Cloud Speed", + "Weather Rain:Glare View", + "Weather Rain:Rain Loop Sound ID", + + "Weather Overcast:Cloud Texture", + "Weather Overcast:Clouds Maximum Percent", + "Weather Overcast:Transition Delta", + "Weather Overcast:Sky Sunrise Color", + "Weather Overcast:Sky Day Color", + "Weather Overcast:Sky Sunset Color", + "Weather Overcast:Sky Night Color", + "Weather Overcast:Fog Sunrise Color", + "Weather Overcast:Fog Day Color", + "Weather Overcast:Fog Sunset Color", + "Weather Overcast:Fog Night Color", + "Weather Overcast:Ambient Sunrise Color", + "Weather Overcast:Ambient Day Color", + "Weather Overcast:Ambient Sunset Color", + "Weather Overcast:Ambient Night Color", + "Weather Overcast:Sun Sunrise Color", + "Weather Overcast:Sun Day Color", + "Weather Overcast:Sun Sunset Color", + "Weather Overcast:Sun Night Color", + "Weather Overcast:Sun Disc Sunset Color", + "Weather Overcast:Land Fog Day Depth", + "Weather Overcast:Land Fog Night Depth", + "Weather Overcast:Wind Speed", + "Weather Overcast:Cloud Speed", + "Weather Overcast:Glare View", + + "Weather Ashstorm:Cloud Texture", + "Weather Ashstorm:Clouds Maximum Percent", + "Weather Ashstorm:Transition Delta", + "Weather Ashstorm:Sky Sunrise Color", + "Weather Ashstorm:Sky Day Color", + "Weather Ashstorm:Sky Sunset Color", + "Weather Ashstorm:Sky Night Color", + "Weather Ashstorm:Fog Sunrise Color", + "Weather Ashstorm:Fog Day Color", + "Weather Ashstorm:Fog Sunset Color", + "Weather Ashstorm:Fog Night Color", + "Weather Ashstorm:Ambient Sunrise Color", + "Weather Ashstorm:Ambient Day Color", + "Weather Ashstorm:Ambient Sunset Color", + "Weather Ashstorm:Ambient Night Color", + "Weather Ashstorm:Sun Sunrise Color", + "Weather Ashstorm:Sun Day Color", + "Weather Ashstorm:Sun Sunset Color", + "Weather Ashstorm:Sun Night Color", + "Weather Ashstorm:Sun Disc Sunset Color", + "Weather Ashstorm:Land Fog Day Depth", + "Weather Ashstorm:Land Fog Night Depth", + "Weather Ashstorm:Wind Speed", + "Weather Ashstorm:Cloud Speed", + "Weather Ashstorm:Glare View", + "Weather Ashstorm:Ambient Loop Sound ID", + + "Weather Blight:Cloud Texture", + "Weather Blight:Clouds Maximum Percent", + "Weather Blight:Transition Delta", + "Weather Blight:Sky Sunrise Color", + "Weather Blight:Sky Day Color", + "Weather Blight:Sky Sunset Color", + "Weather Blight:Sky Night Color", + "Weather Blight:Fog Sunrise Color", + "Weather Blight:Fog Day Color", + "Weather Blight:Fog Sunset Color", + "Weather Blight:Fog Night Color", + "Weather Blight:Ambient Sunrise Color", + "Weather Blight:Ambient Day Color", + "Weather Blight:Ambient Sunset Color", + "Weather Blight:Ambient Night Color", + "Weather Blight:Sun Sunrise Color", + "Weather Blight:Sun Day Color", + "Weather Blight:Sun Sunset Color", + "Weather Blight:Sun Night Color", + "Weather Blight:Sun Disc Sunset Color", + "Weather Blight:Land Fog Day Depth", + "Weather Blight:Land Fog Night Depth", + "Weather Blight:Wind Speed", + "Weather Blight:Cloud Speed", + "Weather Blight:Glare View", + "Weather Blight:Ambient Loop Sound ID", + + // not used for now (todo) + "Weather Blight:Disease Chance", + + // for Bloodmoon + "Weather Snow:Cloud Texture", + "Weather Snow:Clouds Maximum Percent", + "Weather Snow:Transition Delta", + "Weather Snow:Sky Sunrise Color", + "Weather Snow:Sky Day Color", + "Weather Snow:Sky Sunset Color", + "Weather Snow:Sky Night Color", + "Weather Snow:Fog Sunrise Color", + "Weather Snow:Fog Day Color", + "Weather Snow:Fog Sunset Color", + "Weather Snow:Fog Night Color", + "Weather Snow:Ambient Sunrise Color", + "Weather Snow:Ambient Day Color", + "Weather Snow:Ambient Sunset Color", + "Weather Snow:Ambient Night Color", + "Weather Snow:Sun Sunrise Color", + "Weather Snow:Sun Day Color", + "Weather Snow:Sun Sunset Color", + "Weather Snow:Sun Night Color", + "Weather Snow:Sun Disc Sunset Color", + "Weather Snow:Land Fog Day Depth", + "Weather Snow:Land Fog Night Depth", + "Weather Snow:Wind Speed", + "Weather Snow:Cloud Speed", + "Weather Snow:Glare View", + + // for Bloodmoon + "Weather Blizzard:Cloud Texture", + "Weather Blizzard:Clouds Maximum Percent", + "Weather Blizzard:Transition Delta", + "Weather Blizzard:Sky Sunrise Color", + "Weather Blizzard:Sky Day Color", + "Weather Blizzard:Sky Sunset Color", + "Weather Blizzard:Sky Night Color", + "Weather Blizzard:Fog Sunrise Color", + "Weather Blizzard:Fog Day Color", + "Weather Blizzard:Fog Sunset Color", + "Weather Blizzard:Fog Night Color", + "Weather Blizzard:Ambient Sunrise Color", + "Weather Blizzard:Ambient Day Color", + "Weather Blizzard:Ambient Sunset Color", + "Weather Blizzard:Ambient Night Color", + "Weather Blizzard:Sun Sunrise Color", + "Weather Blizzard:Sun Day Color", + "Weather Blizzard:Sun Sunset Color", + "Weather Blizzard:Sun Night Color", + "Weather Blizzard:Sun Disc Sunset Color", + "Weather Blizzard:Land Fog Day Depth", + "Weather Blizzard:Land Fog Night Depth", + "Weather Blizzard:Wind Speed", + "Weather Blizzard:Cloud Speed", + "Weather Blizzard:Glare View", + "Weather Blizzard:Ambient Loop Sound ID", + + // not used + "Weather Clear:Ambient Loop Sound ID", + "Weather Cloudy:Ambient Loop Sound ID", + "Weather Foggy:Ambient Loop Sound ID", + "Weather Overcast:Ambient Loop Sound ID", + "Weather Snow:Ambient Loop Sound ID", + // + "Weather Ashstorm:Storm Threshold", + "Weather Blight:Storm Threshold", + "Weather Snow:Snow Threshold", + "Weather Blizzard:Storm Threshold", + // + "Weather Snow:Snow Diameter", + "Weather Snow:Snow Height Min", + "Weather Snow:Snow Height Max", + "Weather Snow:Snow Entrance Speed", + "Weather Snow:Max Snowflakes", + // + "Weather:EnvReduceColor", + "Weather:LerpCloseColor", + "Weather:BumpFadeColor", + "Weather:AlphaReduce", + "Weather:Minimum Time Between Environmental Sounds", + "Weather:Maximum Time Between Environmental Sounds", + "Weather:Sun Glare Fader Max", + "Weather:Sun Glare Fader Angle Max", + "Weather:Sun Glare Fader Color", + "Weather:Timescale Clouds", + "Weather:Precip Gravity", + "Weather:Rain Ripples", + "Weather:Rain Ripple Radius", + "Weather:Rain Ripples Per Drop", + "Weather:Rain Ripple Scale", + "Weather:Rain Ripple Speed", + "Weather:Fog Depth Change Speed", + "Weather:Sky Pre-Sunrise Time", + "Weather:Sky Post-Sunrise Time", + "Weather:Sky Pre-Sunset Time", + "Weather:Sky Post-Sunset Time", + "Weather:Ambient Pre-Sunrise Time", + "Weather:Ambient Post-Sunrise Time", + "Weather:Ambient Pre-Sunset Time", + "Weather:Ambient Post-Sunset Time", + "Weather:Fog Pre-Sunrise Time", + "Weather:Fog Post-Sunrise Time", + "Weather:Fog Pre-Sunset Time", + "Weather:Fog Post-Sunset Time", + "Weather:Sun Pre-Sunrise Time", + "Weather:Sun Post-Sunrise Time", + "Weather:Sun Pre-Sunset Time", + "Weather:Sun Post-Sunset Time", + "Weather:Stars Post-Sunset Start", + "Weather:Stars Pre-Sunrise Finish", + "Weather:Stars Fading Duration", + "Weather:Snow Ripples", + "Weather:Snow Ripple Radius", + "Weather:Snow Ripples Per Flake", + "Weather:Snow Ripple Scale", + "Weather:Snow Ripple Speed", + "Weather:Snow Gravity Scale", + "Weather:Snow High Kill", + "Weather:Snow Low Kill", + // + "Weather Rain:Using Precip", + "Weather Rain:Rain Diameter", + "Weather Rain:Rain Height Min", + "Weather Rain:Rain Height Max", + "Weather Rain:Rain Threshold", + "Weather Rain:Rain Entrance Speed", + "Weather Rain:Ambient Loop Sound ID", + "Weather Rain:Max Raindrops", + // + "Weather Thunderstorm:Using Precip", + "Weather Thunderstorm:Rain Diameter", + "Weather Thunderstorm:Rain Height Min", + "Weather Thunderstorm:Rain Height Max", + "Weather Thunderstorm:Rain Threshold", + "Weather Thunderstorm:Max Raindrops", + "Weather Thunderstorm:Rain Entrance Speed", + "Weather Thunderstorm:Ambient Loop Sound ID", + "Weather Thunderstorm:Flash Decrement", + + // moons + + // these are hardcoded in mwworld/weather.cpp + // l.642..665 (masser_angle_fade) + "Moons:Secunda Fade Start Angle", // = 50 + "Moons:Secunda Fade End Angle", // = 40 + "Moons:Masser Fade Start Angle", // = 50 + "Moons:Masser Fade End Angle", // = 30 + + // hardcoded in weather.cpp l.635 to 641 (hour_fade) + "Moons:Secunda Fade In Start", // = 14 + "Moons:Secunda Fade In Finish", // = 15 + "Moons:Secunda Fade Out Start", // = 7 + "Moons:Secunda Fade Out Finish", // = 10 + + // same values as Secunda + "Moons:Masser Fade In Start", + "Moons:Masser Fade In Finish", + "Moons:Masser Fade Out Start", + "Moons:Masser Fade Out Finish", + + // color code hardcoded in mwrender/sky.cpp (l.417, mMoonRed) + // as float values (divided by 255) + "Moons:Script Color", + + // not used + "Moons:Secunda Size", + "Moons:Secunda Axis Offset", + "Moons:Secunda Speed", + "Moons:Secunda Daily Increment", + "Moons:Secunda Moon Shadow Early Fade Angle", + "Moons:Masser Size", + "Moons:Masser Axis Offset", + "Moons:Masser Speed", + "Moons:Masser Daily Increment", + "Moons:Masser Moon Shadow Early Fade Angle", + 0 }; From 9d043d0193b3a35c2f7bb0946c39f20469f771c8 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Sat, 29 Dec 2012 17:15:53 +0100 Subject: [PATCH 083/136] mwiniimporter: fix string cutting --- apps/mwiniimporter/importer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 1236dcaf0..0bf0ae4ec 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -618,7 +618,7 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(std::string filename) { if(line[0] == '[') { if(line.length() > 2) { - section = line.substr(1, line.length()-3); + section = line.substr(1, line.length()-2); } continue; } @@ -711,7 +711,7 @@ void MwIniImporter::mergeFallback(multistrmap &cfg, multistrmap &ini) { std::string value(*it); std::replace( value.begin(), value.end(), ' ', '_' ); std::replace( value.begin(), value.end(), ':', '_' ); - value.append(",").append(vc->substr(0,vc->length()-1)); + value.append(",").append(vc->substr(0,vc->length())); insertMultistrmap(cfg, "fallback", value); } } From fb25f407fbcd2e392e63a8c1f1b7393ecfe65e01 Mon Sep 17 00:00:00 2001 From: eduard Date: Sun, 30 Dec 2012 13:37:19 +0100 Subject: [PATCH 084/136] dialoguemanager conflict --- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 533 +----------------- apps/openmw/mwdialogue/dialoguemanagerimp.hpp | 1 + 2 files changed, 4 insertions(+), 530 deletions(-) diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 743db9a43..8e74894b9 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -43,89 +43,6 @@ namespace { -<<<<<<< HEAD - template - bool selectCompare (char comp, T1 value1, T2 value2) - { - switch (comp) - { - case '0': return value1==value2; -// case '1': return value1!=value2; - case '2': return value1>value2; - case '3': return value1>=value2; - case '4': return value1 - bool checkLocal (char comp, const std::string& name, T value, const MWWorld::Ptr& actor, - const ESMS::ESMStore& store) - { - std::string scriptName = MWWorld::Class::get (actor).getScript (actor); - - if (scriptName.empty()) - return false; // no script - - const ESM::Script *script = store.scripts.find (scriptName); - - int i = 0; - - for (; i (script->mVarNames.size()); ++i) - if (script->mVarNames[i]==name) - break; - - if (i>=static_cast (script->mVarNames.size())) - return false; // script does not have a variable of this name - - const MWScript::Locals& locals = actor.getRefData().getLocals(); - - if (imData.mNumShorts) - return selectCompare (comp, locals.mShorts[i], value); - else - i -= script->mData.mNumShorts; - - if (imData.mNumLongs) - return selectCompare (comp, locals.mLongs[i], value); - else - i -= script->mData.mNumShorts; - - return selectCompare (comp, locals.mFloats.at (i), value); - } - - template - bool checkGlobal (char comp, const std::string& name, T value) - { - switch (MWBase::Environment::get().getWorld()->getGlobalVariableType (name)) - { - case 's': - return selectCompare (comp, MWBase::Environment::get().getWorld()->getGlobalVariable (name).mShort, value); - - case 'l': - - return selectCompare (comp, MWBase::Environment::get().getWorld()->getGlobalVariable (name).mLong, value); - - case 'f': - - return selectCompare (comp, MWBase::Environment::get().getWorld()->getGlobalVariable (name).mFloat, value); - - case ' ': - - MWBase::Environment::get().getWorld()->getGlobalVariable (name); // trigger exception - break; - - default: - - throw std::runtime_error ("unsupported gobal variable type"); - } - - return false; - } - -======= ->>>>>>> 92623921add0d6e16a34973dcf6f2ee1f52dbbe7 //helper function std::string::size_type find_str_ci(const std::string& str, const std::string& substr,size_t pos) { @@ -135,437 +52,7 @@ namespace namespace MWDialogue { -<<<<<<< HEAD - - - bool DialogueManager::functionFilter(const MWWorld::Ptr& actor, const ESM::DialInfo& info,bool choice) - { - bool isCreature = (actor.getTypeName() != typeid(ESM::NPC).name()); - - for (std::vector::const_iterator iter (info.mSelects.begin()); - iter != info.mSelects.end(); ++iter) - { - ESM::DialInfo::SelectStruct select = *iter; - char type = select.mSelectRule[1]; - if(type == '1') - { - char comp = select.mSelectRule[4]; - std::string name = select.mSelectRule.substr (5); - std::string function = select.mSelectRule.substr(2,2); - - int ifunction; - std::istringstream iss(function); - iss >> ifunction; - switch(ifunction) - { - case 39://PC Expelled - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 40://PC Common Disease - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 41://PC Blight Disease - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 43://PC Crime level - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 46://Same faction - { - if (isCreature) - return false; - - MWMechanics::NpcStats PCstats = MWWorld::Class::get(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()).getNpcStats(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); - MWMechanics::NpcStats NPCstats = MWWorld::Class::get(actor).getNpcStats(actor); - int sameFaction = 0; - if(!NPCstats.getFactionRanks().empty()) - { - std::string NPCFaction = NPCstats.getFactionRanks().begin()->first; - if(PCstats.getFactionRanks().find(Misc::toLower(NPCFaction)) != PCstats.getFactionRanks().end()) sameFaction = 1; - } - if(!selectCompare(comp,sameFaction,select.mI)) return false; - } - break; - - case 48://Detected - if(!selectCompare(comp,1,select.mI)) return false; - break; - - case 49://Alarmed - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 50://choice - if(choice) - { - if(!selectCompare(comp,mChoice,select.mI)) return false; - } - break; - - case 60://PC Vampire - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 61://Level - if(!selectCompare(comp,1,select.mI)) return false; - break; - - case 62://Attacked - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 63://Talked to PC - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 64://PC Health - if(!selectCompare(comp,50,select.mI)) return false; - break; - - case 65://Creature target - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 66://Friend hit - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 67://Fight - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 68://Hello???? - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 69://Alarm - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 70://Flee - if(!selectCompare(comp,0,select.mI)) return false; - break; - - case 71://Should Attack - if(!selectCompare(comp,0,select.mI)) return false; - break; - - default: - break; - - } - } - } - - return true; - } - - bool DialogueManager::isMatching (const MWWorld::Ptr& actor, - const ESM::DialInfo::SelectStruct& select) const - { - bool isCreature = (actor.getTypeName() != typeid(ESM::NPC).name()); - - char type = select.mSelectRule[1]; - - if (type!='0') - { - char comp = select.mSelectRule[4]; - std::string name = select.mSelectRule.substr (5); - std::string function = select.mSelectRule.substr(1,2); - - switch (type) - { - case '1': // function - - return true; // Done elsewhere. - - case '2': // global - - if (select.mType==ESM::VT_Short || select.mType==ESM::VT_Int || - select.mType==ESM::VT_Long) - { - if (!checkGlobal (comp, Misc::toLower (name), select.mI)) - return false; - } - else if (select.mType==ESM::VT_Float) - { - if (!checkGlobal (comp, Misc::toLower (name), select.mF)) - return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - - return true; - - case '3': // local - - if (select.mType==ESM::VT_Short || select.mType==ESM::VT_Int || - select.mType==ESM::VT_Long) - { - if (!checkLocal (comp, Misc::toLower (name), select.mI, actor, - MWBase::Environment::get().getWorld()->getStore())) - return false; - } - else if (select.mType==ESM::VT_Float) - { - if (!checkLocal (comp, Misc::toLower (name), select.mF, actor, - MWBase::Environment::get().getWorld()->getStore())) - return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - - return true; - - case '4'://journal - if(select.mType==ESM::VT_Int) - { - if(!selectCompare(comp,MWBase::Environment::get().getJournal()->getJournalIndex(Misc::toLower(name)),select.mI)) return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - - return true; - - case '5'://item - { - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); - MWWorld::ContainerStore& store = MWWorld::Class::get (player).getContainerStore (player); - - int sum = 0; - - for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) - if (Misc::toLower(iter->getCellRef().mRefID) == Misc::toLower(name)) - sum += iter->getRefData().getCount(); - if(!selectCompare(comp,sum,select.mI)) return false; - } - - return true; - - - case '6'://dead - if(!selectCompare(comp,0,select.mI)) return false; - - case '7':// not ID - if(select.mType==ESM::VT_String ||select.mType==ESM::VT_Int)//bug in morrowind here? it's not a short, it's a string - { - int isID = int(Misc::toLower(name)==Misc::toLower(MWWorld::Class::get (actor).getId (actor))); - if (selectCompare(comp,!isID,select.mI)) return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - - return true; - - case '8':// not faction - if (isCreature) - return false; - - if(select.mType==ESM::VT_Int) - { - MWWorld::LiveCellRef* npc = actor.get(); - int isFaction = int(Misc::toLower(npc->base->mFaction) == Misc::toLower(name)); - if(selectCompare(comp,!isFaction,select.mI)) - return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - - return true; - - case '9':// not class - if (isCreature) - return false; - - if(select.mType==ESM::VT_Int) - { - MWWorld::LiveCellRef* npc = actor.get(); - int isClass = int(Misc::toLower(npc->base->mClass) == Misc::toLower(name)); - if(selectCompare(comp,!isClass,select.mI)) - return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - - return true; - - case 'A'://not Race - if (isCreature) - return false; - - if(select.mType==ESM::VT_Int) - { - MWWorld::LiveCellRef* npc = actor.get(); - int isRace = int(Misc::toLower(npc->base->mRace) == Misc::toLower(name)); - if(selectCompare(comp,!isRace,select.mI)) - return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - - return true; - - case 'B'://not Cell - if(select.mType==ESM::VT_Int) - { - int isCell = int(Misc::toLower(actor.getCell()->cell->mName) == Misc::toLower(name)); - if(selectCompare(comp,!isCell,select.mI)) - return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - return true; - - case 'C'://not local - if (select.mType==ESM::VT_Short || select.mType==ESM::VT_Int || - select.mType==ESM::VT_Long) - { - if (checkLocal (comp, Misc::toLower (name), select.mI, actor, - MWBase::Environment::get().getWorld()->getStore())) - return false; - } - else if (select.mType==ESM::VT_Float) - { - if (checkLocal (comp, Misc::toLower (name), select.mF, actor, - MWBase::Environment::get().getWorld()->getStore())) - return false; - } - else - throw std::runtime_error ( - "unsupported variable type in dialogue info select"); - return true; - - - default: - - std::cout << "unchecked select: " << type << " " << comp << " " << name << std::endl; - } - } - - return true; - } - - bool DialogueManager::isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const - { - bool isCreature = (actor.getTypeName() != typeid(ESM::NPC).name()); - - // actor id - if (!info.mActor.empty()) - if (Misc::toLower (info.mActor)!=MWWorld::Class::get (actor).getId (actor)) - return false; - - //NPC race - if (!info.mRace.empty()) - { - if (isCreature) - return false; - - MWWorld::LiveCellRef *cellRef = actor.get(); - - if (!cellRef) - return false; - - if (Misc::toLower (info.mRace)!=Misc::toLower (cellRef->base->mRace)) - return false; - } - - //NPC class - if (!info.mClass.empty()) - { - if (isCreature) - return false; - - MWWorld::LiveCellRef *cellRef = actor.get(); - - if (!cellRef) - return false; - - if (Misc::toLower (info.mClass)!=Misc::toLower (cellRef->base->mClass)) - return false; - } - - //NPC faction - if (!info.mNpcFaction.empty()) - { - if (isCreature) - return false; - - //MWWorld::Class npcClass = MWWorld::Class::get(actor); - MWMechanics::NpcStats stats = MWWorld::Class::get(actor).getNpcStats(actor); - std::map::iterator it = stats.getFactionRanks().find(Misc::toLower(info.mNpcFaction)); - if(it!=stats.getFactionRanks().end()) - { - //check rank - if(it->second < (int)info.mData.mRank) return false; - } - else - { - //not in the faction - return false; - } - } - - // TODO check player faction - if(!info.mPcFaction.empty()) - { - MWMechanics::NpcStats stats = MWWorld::Class::get(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()).getNpcStats(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); - std::map::iterator it = stats.getFactionRanks().find(Misc::toLower(info.mPcFaction)); - if(it!=stats.getFactionRanks().end()) - { - //check rank - if(it->second < (int)info.mData.mPCrank) return false; - } - else - { - //not in the faction - return false; - } - } - - //check gender - if (!isCreature) - { - MWWorld::LiveCellRef* npc = actor.get(); - if(npc->base->mFlags & npc->base->Female) - { - if(static_cast (info.mData.mGender)==0) return false; - } - else - { - if(static_cast (info.mData.mGender)==1) return false; - } - } - - // check cell - if (!info.mCell.empty()) - if (MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->cell->mName != info.mCell) - return false; - - // TODO check DATAstruct - for (std::vector::const_iterator iter (info.mSelects.begin()); - iter != info.mSelects.end(); ++iter) - if (!isMatching (actor, *iter)) - return false; - - return true; - } - - DialogueManager::DialogueManager (const Compiler::Extensions& extensions) : -======= DialogueManager::DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose) : ->>>>>>> 92623921add0d6e16a34973dcf6f2ee1f52dbbe7 mCompilerContext (MWScript::CompilerContext::Type_Dialgoue), mErrorStream(std::cout.rdbuf()),mErrorHandler(mErrorStream) , mTemporaryDispositionChange(0.f) @@ -583,11 +70,7 @@ namespace MWDialogue MWWorld::Store::iterator it = dialogs.begin(); for (; it != dialogs.end(); ++it) { -<<<<<<< HEAD - mDialogueMap[Misc::toLower(it->first)] = it->second; -======= - mDialogueMap[toLower(it->mId)] = *it; ->>>>>>> 92623921add0d6e16a34973dcf6f2ee1f52dbbe7 + mDialogueMap[Misc::toLower(it->mId)] = *it; } } @@ -791,22 +274,12 @@ namespace MWDialogue { if (filter.search (*iter)) { - mActorKnownTopics.push_back (toLower (iter->mId)); + mActorKnownTopics.push_back (Misc::toLower (iter->mId)); //does the player know the topic? - if (mKnownTopics.find (toLower (iter->mId)) != mKnownTopics.end()) + if (mKnownTopics.find (Misc::toLower (iter->mId)) != mKnownTopics.end()) { -<<<<<<< HEAD - mActorKnownTopics.push_back(Misc::toLower(it->first)); - //does the player know the topic? - if(mKnownTopics.find(Misc::toLower(it->first)) != mKnownTopics.end()) - { - keywordList.push_back(it->first); - break; - } -======= keywordList.push_back (iter->mId); ->>>>>>> 92623921add0d6e16a34973dcf6f2ee1f52dbbe7 } } } diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp index 98b27f774..b0bef5ea0 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp @@ -71,6 +71,7 @@ namespace MWDialogue virtual void persuade (int type); virtual int getTemporaryDispositionChange () const; virtual void applyTemporaryDispositionChange (int delta); + void toLower(std::string question); }; } From 98103e15eb55a7c63bf7796edf83e2c67d6acd0b Mon Sep 17 00:00:00 2001 From: eduard Date: Sun, 30 Dec 2012 13:46:07 +0100 Subject: [PATCH 085/136] conflict resolution --- apps/openmw/mwworld/worldimp.cpp | 21 +-------------------- components/misc/stringops.hpp | 3 --- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 5e7a19caa..83c6b20e5 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -235,20 +235,11 @@ namespace MWWorld } // didn't work -> now check for regions -<<<<<<< HEAD - std::string cellName2 = Misc::toLower (cellName); - - for (ESMS::RecListT::MapType::const_iterator iter (mStore.regions.list.begin()); - iter!=mStore.regions.list.end(); ++iter) - { - if (Misc::toLower (iter->second.mName)==cellName2) -======= const MWWorld::Store ®ions = mStore.get(); MWWorld::Store::iterator it = regions.begin(); for (; it != regions.end(); ++it) { if (Misc::StringUtils::ciEqual(cellName, it->mName)) ->>>>>>> 92623921add0d6e16a34973dcf6f2ee1f52dbbe7 { return mStore.get().searchExtByRegion(it->mId); } @@ -625,26 +616,16 @@ namespace MWWorld CellStore *currCell = ptr.getCell(); bool isPlayer = ptr == mPlayer->getPlayer(); bool haveToMove = mWorldScene->isCellActive(*currCell) || isPlayer; -<<<<<<< HEAD - if (*currCell != newCell) { - if (isPlayer) { - if (!newCell.isExterior()) { - changeToInteriorCell(Misc::toLower(newCell.cell->mName), pos); - } else { - int cellX = newCell.cell->mData.mX; - int cellY = newCell.cell->mData.mY; -======= if (*currCell != newCell) { if (isPlayer) if (!newCell.isExterior()) - changeToInteriorCell(toLower(newCell.mCell->mName), pos); + changeToInteriorCell(Misc::toLower(newCell.mCell->mName), pos); else { int cellX = newCell.mCell->getGridX(); int cellY = newCell.mCell->getGridY(); ->>>>>>> 92623921add0d6e16a34973dcf6f2ee1f52dbbe7 mWorldScene->changeCell(cellX, cellY, pos, false); } else { diff --git a/components/misc/stringops.hpp b/components/misc/stringops.hpp index cfe7ba028..71c96b652 100644 --- a/components/misc/stringops.hpp +++ b/components/misc/stringops.hpp @@ -2,10 +2,7 @@ #define MISC_STRINGOPS_H #include -<<<<<<< HEAD -======= #include ->>>>>>> 92623921add0d6e16a34973dcf6f2ee1f52dbbe7 namespace Misc { From 714b1924a5758c6c7ef5c87cd25ba895e23cbcaf Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 30 Dec 2012 14:01:52 +0100 Subject: [PATCH 086/136] partial dialogue subview implementation --- apps/opencs/model/world/columns.hpp | 2 +- apps/opencs/model/world/data.cpp | 23 ++++++++++++------- apps/opencs/model/world/data.hpp | 16 +++++++++---- apps/opencs/view/world/dialoguesubview.cpp | 26 ++++++++++++++++++++++ 4 files changed, 54 insertions(+), 13 deletions(-) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index f58d77c90..5abf4ea8b 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -1,7 +1,7 @@ #ifndef CSM_WOLRD_COLUMNS_H #define CSM_WOLRD_COLUMNS_H -#include "idcollection.hpp" +#include "columnbase.hpp" namespace CSMWorld { diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 0da0cba83..a3522503e 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -10,6 +10,16 @@ #include "idtable.hpp" #include "columns.hpp" +void CSMWorld::Data::addModel (QAbstractTableModel *model, UniversalId::Type type1, + UniversalId::Type type2) +{ + mModels.push_back (model); + mModelIndex.insert (std::make_pair (type1, model)); + + if (type2!=UniversalId::Type_None) + mModelIndex.insert (std::make_pair (type2, model)); +} + CSMWorld::Data::Data() { mGlobals.addColumn (new StringIdColumn); @@ -17,16 +27,13 @@ CSMWorld::Data::Data() mGlobals.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Global)); mGlobals.addColumn (new FloatValueColumn); - mModels.insert (std::make_pair ( - UniversalId (UniversalId::Type_Globals), - new IdTable (&mGlobals) - )); + addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); } CSMWorld::Data::~Data() { - for (std::map::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter) - delete iter->second; + for (std::vector::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter) + delete *iter; } const CSMWorld::IdCollection& CSMWorld::Data::getGlobals() const @@ -41,9 +48,9 @@ CSMWorld::IdCollection& CSMWorld::Data::getGlobals() QAbstractTableModel *CSMWorld::Data::getTableModel (const UniversalId& id) { - std::map::iterator iter = mModels.find (id); + std::map::iterator iter = mModelIndex.find (id.getType()); - if (iter==mModels.end()) + if (iter==mModelIndex.end()) throw std::logic_error ("No table model available for " + id.toString()); return iter->second; diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index a8a21e205..f7748cb5d 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -1,7 +1,8 @@ -#ifndef CSM_WOLRD_IDLIST_H -#define CSM_WOLRD_IDLIST_H +#ifndef CSM_WOLRD_DATA_H +#define CSM_WOLRD_DATA_H #include +#include #include @@ -15,12 +16,16 @@ namespace CSMWorld class Data { IdCollection mGlobals; - std::map mModels; + std::vector mModels; + std::map mModelIndex; // not implemented Data (const Data&); Data& operator= (const Data&); + void addModel (QAbstractTableModel *model, UniversalId::Type type1, + UniversalId::Type type2 = UniversalId::Type_None); + public: Data(); @@ -32,7 +37,10 @@ namespace CSMWorld IdCollection& getGlobals(); QAbstractTableModel *getTableModel (const UniversalId& id); - ///< If no table model is available for \æ id, an exception is thrown. + ///< If no table model is available for \a id, an exception is thrown. + /// + /// \note The returned table may either be the model for the ID itself or the model that + /// contains the record specified by the ID. void merge(); ///< Merge modified into base. diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index e2d16f1e3..354223757 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -1,11 +1,37 @@ #include "dialoguesubview.hpp" +#include +#include +#include + +#include "../../model/world/columnbase.hpp" + CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, bool createAndDelete) : SubView (id) { + QWidget *widget = new QWidget (this); + + setWidget (widget); + + QGridLayout *layout = new QGridLayout; + + widget->setLayout (layout); + + QAbstractTableModel *model = document.getData().getTableModel (id); + + int columns = model->columnCount(); + + for (int i=0; iheaderData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt(); + if (flags & CSMWorld::ColumnBase::Flag_Dialogue) + { + layout->addWidget (new QLabel (model->headerData (i, Qt::Horizontal).toString()), i, 0); + } + } } void CSVWorld::DialogueSubView::setEditLock (bool locked) From 38e7dbb970b523ea68be73aa3732f73c82e237b5 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Sun, 30 Dec 2012 16:41:25 +0100 Subject: [PATCH 087/136] mwininimporter: add more fallback values --- apps/mwiniimporter/importer.cpp | 75 +++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 0bf0ae4ec..335b7aecf 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -19,6 +19,81 @@ MwIniImporter::MwIniImporter() }; const char *fallback[] = { + // light + "LightAttenuation:UseConstant", + "LightAttenuation:ConstantValue", + "LightAttenuation:UseLinear", + "LightAttenuation:LinearMethod", + "LightAttenuation:LinearValue", + "LightAttenuation:LinearRadiusMult", + "LightAttenuation:UseQuadratic", + "LightAttenuation:QuadraticMethod", + "LightAttenuation:QuadraticValue", + "LightAttenuation:QuadraticRadiusMult", + "LightAttenuation:OutQuadInLin", + + // inventory + "Inventory:DirectionalDiffuseR", + "Inventory:DirectionalDiffuseG", + "Inventory:DirectionalDiffuseB", + "Inventory:DirectionalAmbientR", + "Inventory:DirectionalAmbientG", + "Inventory:DirectionalAmbientB", + "Inventory:DirectionalRotationX", + "Inventory:DirectionalRotationY", + "Inventory:UniformScaling", + + // map + "Map:Travel Siltstrider Red", + "Map:Travel Siltstrider Green", + "Map:Travel Siltstrider Blue", + "Map:Travel Boat Red", + "Map:Travel Boat Green", + "Map:Travel Boat Blue", + "Map:Travel Magic Red", + "Map:Travel Magic Green", + "Map:Travel Magic Blue", + "Map:Show Travel Lines", + + // water + "Water:Map Alpha", + "Water:World Alpha", + "Water:SurfaceTextureSize", + "Water:SurfaceTileCount", + "Water:SurfaceFPS", + "Water:SurfaceTexture", + "Water:SurfaceFrameCount", + "Water:TileTextureDivisor", + "Water:RippleTexture", + "Water:RippleFrameCount", + "Water:RippleLifetime", + "Water:MaxNumberRipples", + "Water:RippleScale", + "Water:RippleRotSpeed", + "Water:RippleAlphas", + "Water:PSWaterReflectTerrain", + "Water:PSWaterReflectUpdate", + "Water:NearWaterRadius", + "Water:NearWaterPoints", + "Water:NearWaterUnderwaterFreq", + "Water:NearWaterUnderwaterVolume", + "Water:NearWaterIndoorTolerance", + "Water:NearWaterOutdoorTolerance", + "Water:NearWaterIndoorID", + "Water:NearWaterOutdoorID", + "Water:UnderwaterSunriseFog", + "Water:UnderwaterDayFog", + "Water:UnderwaterSunsetFog", + "Water:UnderwaterNightFog", + "Water:UnderwaterIndoorFog", + "Water:UnderwaterColor", + "Water:UnderwaterColorWeight", + + // pixelwater + "PixelWater:SurfaceFPS", + "PixelWater:TileCount", + "PixelWater:Resolution", + /* "Fonts:Font 0", "Fonts:Font 1", From cb71efc4279146467e53098748d87e7f9a649325 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Sun, 30 Dec 2012 16:44:52 +0100 Subject: [PATCH 088/136] mwiniimporter: clean up --- apps/mwiniimporter/importer.cpp | 213 ++++++++++++++------------------ 1 file changed, 91 insertions(+), 122 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 335b7aecf..dda8fd8ba 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -94,13 +94,12 @@ MwIniImporter::MwIniImporter() "PixelWater:TileCount", "PixelWater:Resolution", - /* + // fonts "Fonts:Font 0", "Fonts:Font 1", "Fonts:Font 2", - */ - /* + // UI colors "FontColor:color_normal", "FontColor:color_normal_over", "FontColor:color_normal_pressed", @@ -146,18 +145,15 @@ MwIniImporter::MwIniImporter() "FontColor:color_positive", "FontColor:color_negative", "FontColor:color_count", - */ - /* + // cursors "Cursors:Cursor 0", "Cursors:Cursor 1", "Cursors:Cursor 2", "Cursors:Cursor 3", "Cursors:Cursor 4", - */ // level up messages - // not used for now "Level Up:Level2", "Level Up:Level3", "Level Up:Level4", @@ -180,7 +176,6 @@ MwIniImporter::MwIniImporter() "Level Up:Default", // character creation multiple choice test - // hardcoded in mwgui/charactercreation.cpp "Question 1:Question", "Question 1:AnswerOne", "Question 1:AnswerTwo", @@ -233,7 +228,6 @@ MwIniImporter::MwIniImporter() "Question 10:Sound", // blood textures and models - // not used for now "Blood:Model 0", "Blood:Model 1", "Blood:Model 2", @@ -245,7 +239,6 @@ MwIniImporter::MwIniImporter() "Blood:Texture Name 2", // movies - // not used for now "Movies:Company Logo", "Movies:Morrowind Logo", "Movies:New Game", @@ -253,10 +246,7 @@ MwIniImporter::MwIniImporter() "Movies:Options Menu", // weather related values - // hardcoded in mwworld/wheather.cpp - // Some are easy to replace, others are used as magic number - // globals "Weather Thunderstorm:Thunder Sound ID 0", "Weather Thunderstorm:Thunder Sound ID 1", "Weather Thunderstorm:Thunder Sound ID 2", @@ -268,7 +258,51 @@ MwIniImporter::MwIniImporter() "Weather:Hours Between Weather Changes", // AKA weather update time "Weather Thunderstorm:Thunder Frequency", "Weather Thunderstorm:Thunder Threshold", - // thunder sound delay? + + "Weather:EnvReduceColor", + "Weather:LerpCloseColor", + "Weather:BumpFadeColor", + "Weather:AlphaReduce", + "Weather:Minimum Time Between Environmental Sounds", + "Weather:Maximum Time Between Environmental Sounds", + "Weather:Sun Glare Fader Max", + "Weather:Sun Glare Fader Angle Max", + "Weather:Sun Glare Fader Color", + "Weather:Timescale Clouds", + "Weather:Precip Gravity", + "Weather:Rain Ripples", + "Weather:Rain Ripple Radius", + "Weather:Rain Ripples Per Drop", + "Weather:Rain Ripple Scale", + "Weather:Rain Ripple Speed", + "Weather:Fog Depth Change Speed", + "Weather:Sky Pre-Sunrise Time", + "Weather:Sky Post-Sunrise Time", + "Weather:Sky Pre-Sunset Time", + "Weather:Sky Post-Sunset Time", + "Weather:Ambient Pre-Sunrise Time", + "Weather:Ambient Post-Sunrise Time", + "Weather:Ambient Pre-Sunset Time", + "Weather:Ambient Post-Sunset Time", + "Weather:Fog Pre-Sunrise Time", + "Weather:Fog Post-Sunrise Time", + "Weather:Fog Pre-Sunset Time", + "Weather:Fog Post-Sunset Time", + "Weather:Sun Pre-Sunrise Time", + "Weather:Sun Post-Sunrise Time", + "Weather:Sun Pre-Sunset Time", + "Weather:Sun Post-Sunset Time", + "Weather:Stars Post-Sunset Start", + "Weather:Stars Pre-Sunrise Finish", + "Weather:Stars Fading Duration", + "Weather:Snow Ripples", + "Weather:Snow Ripple Radius", + "Weather:Snow Ripples Per Flake", + "Weather:Snow Ripple Scale", + "Weather:Snow Ripple Speed", + "Weather:Snow Gravity Scale", + "Weather:Snow High Kill", + "Weather:Snow Low Kill", "Weather Clear:Cloud Texture", "Weather Clear:Clouds Maximum Percent", @@ -295,6 +329,7 @@ MwIniImporter::MwIniImporter() "Weather Clear:Wind Speed", "Weather Clear:Cloud Speed", "Weather Clear:Glare View", + "Weather Clear:Ambient Loop Sound ID", "Weather Cloudy:Cloud Texture", "Weather Cloudy:Clouds Maximum Percent", @@ -321,6 +356,7 @@ MwIniImporter::MwIniImporter() "Weather Cloudy:Wind Speed", "Weather Cloudy:Cloud Speed", "Weather Cloudy:Glare View", + "Weather Cloudy:Ambient Loop Sound ID", "Weather Foggy:Cloud Texture", "Weather Foggy:Clouds Maximum Percent", @@ -347,6 +383,7 @@ MwIniImporter::MwIniImporter() "Weather Foggy:Wind Speed", "Weather Foggy:Cloud Speed", "Weather Foggy:Glare View", + "Weather Foggy:Ambient Loop Sound ID", "Weather Thunderstorm:Cloud Texture", "Weather Thunderstorm:Clouds Maximum Percent", @@ -374,6 +411,15 @@ MwIniImporter::MwIniImporter() "Weather Thunderstorm:Cloud Speed", "Weather Thunderstorm:Glare View", "Weather Thunderstorm:Rain Loop Sound ID", + "Weather Thunderstorm:Using Precip", + "Weather Thunderstorm:Rain Diameter", + "Weather Thunderstorm:Rain Height Min", + "Weather Thunderstorm:Rain Height Max", + "Weather Thunderstorm:Rain Threshold", + "Weather Thunderstorm:Max Raindrops", + "Weather Thunderstorm:Rain Entrance Speed", + "Weather Thunderstorm:Ambient Loop Sound ID", + "Weather Thunderstorm:Flash Decrement", "Weather Rain:Cloud Texture", "Weather Rain:Clouds Maximum Percent", @@ -401,6 +447,14 @@ MwIniImporter::MwIniImporter() "Weather Rain:Cloud Speed", "Weather Rain:Glare View", "Weather Rain:Rain Loop Sound ID", + "Weather Rain:Using Precip", + "Weather Rain:Rain Diameter", + "Weather Rain:Rain Height Min", + "Weather Rain:Rain Height Max", + "Weather Rain:Rain Threshold", + "Weather Rain:Rain Entrance Speed", + "Weather Rain:Ambient Loop Sound ID", + "Weather Rain:Max Raindrops", "Weather Overcast:Cloud Texture", "Weather Overcast:Clouds Maximum Percent", @@ -427,6 +481,7 @@ MwIniImporter::MwIniImporter() "Weather Overcast:Wind Speed", "Weather Overcast:Cloud Speed", "Weather Overcast:Glare View", + "Weather Overcast:Ambient Loop Sound ID", "Weather Ashstorm:Cloud Texture", "Weather Ashstorm:Clouds Maximum Percent", @@ -454,6 +509,7 @@ MwIniImporter::MwIniImporter() "Weather Ashstorm:Cloud Speed", "Weather Ashstorm:Glare View", "Weather Ashstorm:Ambient Loop Sound ID", + "Weather Ashstorm:Storm Threshold", "Weather Blight:Cloud Texture", "Weather Blight:Clouds Maximum Percent", @@ -481,8 +537,7 @@ MwIniImporter::MwIniImporter() "Weather Blight:Cloud Speed", "Weather Blight:Glare View", "Weather Blight:Ambient Loop Sound ID", - - // not used for now (todo) + "Weather Blight:Storm Threshold", "Weather Blight:Disease Chance", // for Bloodmoon @@ -511,6 +566,13 @@ MwIniImporter::MwIniImporter() "Weather Snow:Wind Speed", "Weather Snow:Cloud Speed", "Weather Snow:Glare View", + "Weather Snow:Snow Diameter", + "Weather Snow:Snow Height Min", + "Weather Snow:Snow Height Max", + "Weather Snow:Snow Entrance Speed", + "Weather Snow:Max Snowflakes", + "Weather Snow:Ambient Loop Sound ID", + "Weather Snow:Snow Threshold", // for Bloodmoon "Weather Blizzard:Cloud Texture", @@ -539,125 +601,32 @@ MwIniImporter::MwIniImporter() "Weather Blizzard:Cloud Speed", "Weather Blizzard:Glare View", "Weather Blizzard:Ambient Loop Sound ID", - - // not used - "Weather Clear:Ambient Loop Sound ID", - "Weather Cloudy:Ambient Loop Sound ID", - "Weather Foggy:Ambient Loop Sound ID", - "Weather Overcast:Ambient Loop Sound ID", - "Weather Snow:Ambient Loop Sound ID", - // - "Weather Ashstorm:Storm Threshold", - "Weather Blight:Storm Threshold", - "Weather Snow:Snow Threshold", "Weather Blizzard:Storm Threshold", - // - "Weather Snow:Snow Diameter", - "Weather Snow:Snow Height Min", - "Weather Snow:Snow Height Max", - "Weather Snow:Snow Entrance Speed", - "Weather Snow:Max Snowflakes", - // - "Weather:EnvReduceColor", - "Weather:LerpCloseColor", - "Weather:BumpFadeColor", - "Weather:AlphaReduce", - "Weather:Minimum Time Between Environmental Sounds", - "Weather:Maximum Time Between Environmental Sounds", - "Weather:Sun Glare Fader Max", - "Weather:Sun Glare Fader Angle Max", - "Weather:Sun Glare Fader Color", - "Weather:Timescale Clouds", - "Weather:Precip Gravity", - "Weather:Rain Ripples", - "Weather:Rain Ripple Radius", - "Weather:Rain Ripples Per Drop", - "Weather:Rain Ripple Scale", - "Weather:Rain Ripple Speed", - "Weather:Fog Depth Change Speed", - "Weather:Sky Pre-Sunrise Time", - "Weather:Sky Post-Sunrise Time", - "Weather:Sky Pre-Sunset Time", - "Weather:Sky Post-Sunset Time", - "Weather:Ambient Pre-Sunrise Time", - "Weather:Ambient Post-Sunrise Time", - "Weather:Ambient Pre-Sunset Time", - "Weather:Ambient Post-Sunset Time", - "Weather:Fog Pre-Sunrise Time", - "Weather:Fog Post-Sunrise Time", - "Weather:Fog Pre-Sunset Time", - "Weather:Fog Post-Sunset Time", - "Weather:Sun Pre-Sunrise Time", - "Weather:Sun Post-Sunrise Time", - "Weather:Sun Pre-Sunset Time", - "Weather:Sun Post-Sunset Time", - "Weather:Stars Post-Sunset Start", - "Weather:Stars Pre-Sunrise Finish", - "Weather:Stars Fading Duration", - "Weather:Snow Ripples", - "Weather:Snow Ripple Radius", - "Weather:Snow Ripples Per Flake", - "Weather:Snow Ripple Scale", - "Weather:Snow Ripple Speed", - "Weather:Snow Gravity Scale", - "Weather:Snow High Kill", - "Weather:Snow Low Kill", - // - "Weather Rain:Using Precip", - "Weather Rain:Rain Diameter", - "Weather Rain:Rain Height Min", - "Weather Rain:Rain Height Max", - "Weather Rain:Rain Threshold", - "Weather Rain:Rain Entrance Speed", - "Weather Rain:Ambient Loop Sound ID", - "Weather Rain:Max Raindrops", - // - "Weather Thunderstorm:Using Precip", - "Weather Thunderstorm:Rain Diameter", - "Weather Thunderstorm:Rain Height Min", - "Weather Thunderstorm:Rain Height Max", - "Weather Thunderstorm:Rain Threshold", - "Weather Thunderstorm:Max Raindrops", - "Weather Thunderstorm:Rain Entrance Speed", - "Weather Thunderstorm:Ambient Loop Sound ID", - "Weather Thunderstorm:Flash Decrement", // moons - - // these are hardcoded in mwworld/weather.cpp - // l.642..665 (masser_angle_fade) - "Moons:Secunda Fade Start Angle", // = 50 - "Moons:Secunda Fade End Angle", // = 40 - "Moons:Masser Fade Start Angle", // = 50 - "Moons:Masser Fade End Angle", // = 30 - - // hardcoded in weather.cpp l.635 to 641 (hour_fade) - "Moons:Secunda Fade In Start", // = 14 - "Moons:Secunda Fade In Finish", // = 15 - "Moons:Secunda Fade Out Start", // = 7 - "Moons:Secunda Fade Out Finish", // = 10 - - // same values as Secunda - "Moons:Masser Fade In Start", - "Moons:Masser Fade In Finish", - "Moons:Masser Fade Out Start", - "Moons:Masser Fade Out Finish", - - // color code hardcoded in mwrender/sky.cpp (l.417, mMoonRed) - // as float values (divided by 255) - "Moons:Script Color", - - // not used "Moons:Secunda Size", "Moons:Secunda Axis Offset", "Moons:Secunda Speed", "Moons:Secunda Daily Increment", "Moons:Secunda Moon Shadow Early Fade Angle", + "Moons:Secunda Fade Start Angle", + "Moons:Secunda Fade End Angle", + "Moons:Secunda Fade In Start", + "Moons:Secunda Fade In Finish", + "Moons:Secunda Fade Out Start", + "Moons:Secunda Fade Out Finish", "Moons:Masser Size", "Moons:Masser Axis Offset", "Moons:Masser Speed", "Moons:Masser Daily Increment", "Moons:Masser Moon Shadow Early Fade Angle", + "Moons:Masser Fade Start Angle", + "Moons:Masser Fade End Angle", + "Moons:Masser Fade In Start", + "Moons:Masser Fade In Finish", + "Moons:Masser Fade Out Start", + "Moons:Masser Fade Out Finish", + "Moons:Script Color", 0 }; From f56182cac28631740e139b963ebcf3545d157529 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 30 Dec 2012 17:06:17 +0100 Subject: [PATCH 089/136] fix journal window not rendering any text --- apps/openmw/mwgui/journalwindow.cpp | 13 ++++--------- apps/openmw/mwgui/journalwindow.hpp | 4 +--- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 9d5d236be..bbd3d4d28 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -84,9 +84,9 @@ book formatText(std::string text,book mBook,int maxLine, int lineSize) MWGui::JournalWindow::JournalWindow (MWBase::WindowManager& parWindowManager) : WindowBase("openmw_journal.layout", parWindowManager) , mLastPos(0) - , mVisible(false) , mPageNumber(0) { + mMainWidget->setVisible(false); //setCoord(0,0,498, 342); center(); @@ -115,20 +115,15 @@ MWGui::JournalWindow::JournalWindow (MWBase::WindowManager& parWindowManager) //displayLeftText(list.front()); } -void MWGui::JournalWindow::setVisible(bool visible) +void MWGui::JournalWindow::close() { - if (mVisible && !visible) - MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); - mVisible = visible; - - mMainWidget->setVisible(visible); + MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); } void MWGui::JournalWindow::open() { mPageNumber = 0; - std::string journalOpenSound = "book open"; - MWBase::Environment::get().getSoundManager()->playSound (journalOpenSound, 1.0, 1.0); + MWBase::Environment::get().getSoundManager()->playSound ("book open", 1.0, 1.0); if(MWBase::Environment::get().getJournal()->begin()!=MWBase::Environment::get().getJournal()->end()) { book journal; diff --git a/apps/openmw/mwgui/journalwindow.hpp b/apps/openmw/mwgui/journalwindow.hpp index a62e48803..3317880cd 100644 --- a/apps/openmw/mwgui/journalwindow.hpp +++ b/apps/openmw/mwgui/journalwindow.hpp @@ -15,8 +15,7 @@ namespace MWGui public: JournalWindow(MWBase::WindowManager& parWindowManager); virtual void open(); - - virtual void setVisible(bool visible); // only used to play close sound + virtual void close(); private: void displayLeftText(std::string text); @@ -41,7 +40,6 @@ namespace MWGui std::vector mLeftPages; std::vector mRightPages; int mPageNumber; //store the number of the current left page - bool mVisible; }; } From 69d9d22579c4ddf2b4b5fffb7355bd0b5413f0cb Mon Sep 17 00:00:00 2001 From: eduard Date: Sun, 30 Dec 2012 19:56:38 +0100 Subject: [PATCH 090/136] comparestring --- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 16 +- apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwscript/containerextensions.cpp | 15 +- apps/openmw/mwworld/worldimp.cpp | 2 +- components/esm_store/reclists.hpp | 674 ------------------ components/misc/stringops.cpp | 26 - components/misc/stringops.hpp | 6 - 7 files changed, 18 insertions(+), 723 deletions(-) delete mode 100644 components/esm_store/reclists.hpp diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 8e74894b9..80999c5ff 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -45,8 +45,8 @@ namespace //helper function std::string::size_type find_str_ci(const std::string& str, const std::string& substr,size_t pos) - { - return Misc::toLower(str).find(Misc::toLower(substr),pos); + { + return Misc::StringUtils::toLower(const_cast(str)).find(Misc::StringUtils::toLower(const_cast(substr)).c_str(),pos); } } @@ -70,13 +70,13 @@ namespace MWDialogue MWWorld::Store::iterator it = dialogs.begin(); for (; it != dialogs.end(); ++it) { - mDialogueMap[Misc::toLower(it->mId)] = *it; + mDialogueMap[Misc::StringUtils::toLower(const_cast(it->mId))] = *it; } } void DialogueManager::addTopic (const std::string& topic) { - mKnownTopics[Misc::toLower(topic)] = true; + mKnownTopics[Misc::StringUtils::toLower(const_cast(topic))] = true; } void DialogueManager::parseText (const std::string& text) @@ -274,10 +274,10 @@ namespace MWDialogue { if (filter.search (*iter)) { - mActorKnownTopics.push_back (Misc::toLower (iter->mId)); + mActorKnownTopics.push_back ( Misc::StringUtils::toLower(const_cast(iter->mId))); //does the player know the topic? - if (mKnownTopics.find (Misc::toLower (iter->mId)) != mKnownTopics.end()) + if (mKnownTopics.find ( Misc::StringUtils::toLower(const_cast(iter->mId))) != mKnownTopics.end()) { keywordList.push_back (iter->mId); } @@ -335,7 +335,7 @@ namespace MWDialogue win->setServices (windowServices); // sort again, because the previous sort was case-sensitive - keywordList.sort(Misc::stringCompareNoCase); + keywordList.sort(Misc::StringUtils::ciEqual); win->setKeywords(keywordList); mChoice = choice; @@ -415,7 +415,7 @@ namespace MWDialogue { MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); win->askQuestion(question); - mChoiceMap[Misc::toLower(question)] = choice; + mChoiceMap[Misc::StringUtils::toLower(const_cast(question))] = choice; mIsInChoice = true; } diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 1ac5b2fc6..dd75b8216 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -271,7 +271,7 @@ namespace MWGui for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it) { - if (Misc::toLower(it->getCellRef().mRefID) == "gold_001") + if (Misc::StringUtils::toLower(it->getCellRef().mRefID) == "gold_001") return it->getRefData().getCount(); } return 0; diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 114704388..2cdad2a90 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -72,7 +72,7 @@ namespace MWScript Interpreter::Type_Integer sum = 0; for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) - if (Misc::toLower(iter->getCellRef().mRefID) == Misc::toLower(item)) + if (Misc::StringUtils::toLower(iter->getCellRef().mRefID) == Misc::StringUtils::toLower(item)) sum += iter->getRefData().getCount(); runtime.push (sum); @@ -105,7 +105,7 @@ namespace MWScript for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end() && count; ++iter) { - if (Misc::toLower(iter->getCellRef().mRefID) == Misc::toLower(item)) + if (Misc::StringUtils::toLower(iter->getCellRef().mRefID) == Misc::StringUtils::toLower(item)) { itemName = MWWorld::Class::get(*iter).getName(*iter); @@ -163,7 +163,7 @@ namespace MWScript MWWorld::ContainerStoreIterator it = invStore.begin(); for (; it != invStore.end(); ++it) { - if (toLower(it->getCellRef().mRefID) == toLower(item)) + if (Misc::StringUtils::toLower(it->getCellRef().mRefID) == Misc::StringUtils::toLower(item)) break; } if (it == invStore.end()) @@ -263,7 +263,7 @@ namespace MWScript for (int slot = 0; slot < MWWorld::InventoryStore::Slots; ++slot) { MWWorld::ContainerStoreIterator it = invStore.getSlot (slot); - if (it != invStore.end() && toLower(it->getCellRef().mRefID) == toLower(item)) + if (it != invStore.end() && Misc::StringUtils::toLower(it->getCellRef().mRefID) == Misc::StringUtils::toLower(item)) { runtime.push(1); return; @@ -281,8 +281,9 @@ namespace MWScript virtual void execute(Interpreter::Runtime &runtime) { MWWorld::Ptr ptr = R()(runtime); - - std::string creatureName = toLower (runtime.getStringLiteral (runtime[0].mInteger)); + + const std::string &name = runtime.getStringLiteral (runtime[0].mInteger); + std::string creatureName = Misc::StringUtils::toLower (const_cast(name)); runtime.pop(); MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore (ptr); @@ -290,7 +291,7 @@ namespace MWScript it != invStore.end(); ++it) { - if (toLower(it->getCellRef().mSoul) == toLower(creatureName)) + if (Misc::StringUtils::toLower(it->getCellRef().mSoul) == Misc::StringUtils::toLower(creatureName)) { runtime.push(1); return; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 83c6b20e5..e38fcf717 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -621,7 +621,7 @@ namespace MWWorld { if (isPlayer) if (!newCell.isExterior()) - changeToInteriorCell(Misc::toLower(newCell.mCell->mName), pos); + changeToInteriorCell(Misc::StringUtils::toLower(const_cast (newCell.mCell->mName)), pos); else { int cellX = newCell.mCell->getGridX(); diff --git a/components/esm_store/reclists.hpp b/components/esm_store/reclists.hpp deleted file mode 100644 index f9f74244b..000000000 --- a/components/esm_store/reclists.hpp +++ /dev/null @@ -1,674 +0,0 @@ -#ifndef _GAME_ESM_RECLISTS_H -#define _GAME_ESM_RECLISTS_H - -#include "components/esm/records.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - -using namespace boost::algorithm; - -namespace ESMS -{ - using namespace ESM; - - struct RecList - { - virtual ~RecList() {} - - virtual void load(ESMReader &esm, const std::string &id) = 0; - virtual int getSize() = 0; - virtual void listIdentifier (std::vector& identifier) const = 0; - - }; - - typedef std::map RecListList; - - template - struct RecListT : RecList - { - virtual ~RecListT() {} - - typedef std::map MapType; - - MapType list; - - // Load one object of this type - void load(ESMReader &esm, const std::string &id) - { - std::string id2 = Misc::toLower (id); - list[id2].load(esm); - } - - // Find the given object ID, or return NULL if not found. - const X* search(const std::string &id) const - { - std::string id2 = Misc::toLower (id); - - typename MapType::const_iterator iter = list.find (id2); - - if (iter == list.end()) - return NULL; - - return &iter->second; - } - - // Find the given object ID (throws an exception if not found) - const X* find(const std::string &id) const - { - const X *object = search (id); - - if (!object) - throw std::runtime_error ("object " + id + " not found"); - - return object; - } - - int getSize() { return list.size(); } - - virtual void listIdentifier (std::vector& identifier) const - { - for (typename MapType::const_iterator iter (list.begin()); iter!=list.end(); ++iter) - identifier.push_back (iter->first); - } - }; - - // Same as RecListT, but does not case-smash the IDs - // Note that lookups (search or find) are still case insensitive - template - struct RecListCaseT : RecList - { - virtual ~RecListCaseT() {} - - typedef std::map MapType; - - MapType list; - - // Load one object of this type - void load(ESMReader &esm, const std::string &id) - { - //std::string id2 = Misc::toLower (id); - - list[id].load(esm); - } - - // Find the given object ID, or return NULL if not found. - const X* search(const std::string &id) const - { - std::string id2 = Misc::toLower (id); - - for (typename MapType::const_iterator iter = list.begin(); - iter != list.end(); ++iter) - { - if (Misc::toLower(iter->first) == id2) - return &iter->second; - } - - return NULL; - } - - // non-const version - X* search(const std::string &id) - { - std::string id2 = Misc::toLower (id); - - for (typename MapType::iterator iter = list.begin(); - iter != list.end(); ++iter) - { - if (Misc::toLower(iter->first) == id2) - return &iter->second; - } - - return NULL; - } - - // Find the given object ID (throws an exception if not found) - const X* find(const std::string &id) const - { - const X *object = search (id); - - if (!object) - throw std::runtime_error ("object " + id + " not found"); - - return object; - } - - int getSize() { return list.size(); } - - virtual void listIdentifier (std::vector& identifier) const - { - for (typename MapType::const_iterator iter (list.begin()); iter!=list.end(); ++iter) - identifier.push_back (iter->first); - } - }; - - /// Modified version of RecListT for records, that need to store their own ID - template - struct RecListWithIDT : RecList - { - virtual ~RecListWithIDT() {} - - typedef std::map MapType; - - MapType list; - - // Load one object of this type - void load(ESMReader &esm, const std::string &id) - { - std::string id2 = Misc::toLower (id); - list[id2].mId = id2; - list[id2].load(esm); - } - - // Find the given object ID, or return NULL if not found. - const X* search(const std::string &id) const - { - std::string id2 = Misc::toLower (id); - - typename MapType::const_iterator iter = list.find (id2); - - if (iter == list.end()) - return NULL; - return &iter->second; - } - - // Find the given object ID (throws an exception if not found) - const X* find(const std::string &id) const - { - const X *object = search (id); - - if (!object) - throw std::runtime_error ("object " + id + " not found"); - - return object; - } - - int getSize() { return list.size(); } - - virtual void listIdentifier (std::vector& identifier) const - { - for (typename MapType::const_iterator iter (list.begin()); iter!=list.end(); ++iter) - identifier.push_back (iter->first); - } - }; - - // The only difference to the above is a slight change to the load() - // function. We might merge these together later, and store the id - // in all the structs. - template - struct RecIDListT : RecList - { - virtual ~RecIDListT() {} - - typedef std::map MapType; - - MapType list; - - void load(ESMReader &esm, const std::string &id) - { - std::string id2 = Misc::toLower (id); - X& ref = list[id2]; - - ref.mId = id; - ref.load(esm); - } - - // Find the given object ID, or return NULL if not found. - const X* search(const std::string &id) const - { - std::string id2 = Misc::toLower (id); - - typename MapType::const_iterator iter = list.find (id2); - - if (iter == list.end()) - return NULL; - - return &iter->second; - } - - // Find the given object ID (throws an exception if not found) - const X* find(const std::string &id) const - { - const X *object = search (id); - - if (!object) - throw std::runtime_error ("object " + id + " not found"); - - return object; - } - - int getSize() { return list.size(); } - - virtual void listIdentifier (std::vector& identifier) const - { - for (typename MapType::const_iterator iter (list.begin()); iter!=list.end(); ++iter) - identifier.push_back (iter->first); - } - }; - - /* Land textures are indexed by an integer number - */ - struct LTexList : RecList - { - virtual ~LTexList() {} - - // TODO: For multiple ESM/ESP files we need one list per file. - std::vector ltex; - - LTexList() - { - // More than enough to hold Morrowind.esm. - ltex.reserve(128); - } - - const LandTexture* search(size_t index) const - { - assert(index < ltex.size()); - return <ex.at(index); - } - - int getSize() { return ltex.size(); } - int getSize() const { return ltex.size(); } - - virtual void listIdentifier (std::vector& identifier) const {} - - void load(ESMReader &esm, const std::string &id) - { - LandTexture lt; - lt.load(esm); - lt.mId = id; - - // Make sure we have room for the structure - if(lt.mIndex + 1 > (int)ltex.size()) - ltex.resize(lt.mIndex+1); - - // Store it - ltex[lt.mIndex] = lt; - } - }; - - /* Landscapes are indexed by the X,Y coordinates of the exterior - cell they belong to. - */ - struct LandList : RecList - { - virtual ~LandList() - { - for ( LandMap::iterator itr = lands.begin(); itr != lands.end(); ++itr ) - { - delete itr->second; - } - } - - // Map containing all landscapes - typedef std::pair LandCoord; - typedef std::map LandMap; - LandMap lands; - - int count; - LandList() : count(0) {} - int getSize() { return count; } - - virtual void listIdentifier (std::vector& identifier) const {} - - // Find land for the given coordinates. Return null if no mData. - Land *search(int x, int y) const - { - LandMap::const_iterator itr = lands.find(std::make_pair (x, y)); - if ( itr == lands.end() ) - { - return NULL; - } - - return itr->second; - } - - void load(ESMReader &esm, const std::string &id) - { - count++; - - // Create the structure and load it. This actually skips the - // landscape data and remembers the file position for later. - Land *land = new Land(); - land->load(esm); - - // Store the structure - lands[std::make_pair (land->mX, land->mY)] = land; - } - }; - - struct ciLessBoost : std::binary_function -{ - bool operator() (const std::string & s1, const std::string & s2) const { - //case insensitive version of is_less - return lexicographical_compare(s1, s2, is_iless()); - } -}; - - - // Cells aren't simply indexed by name. Exterior cells are treated - // separately. - // TODO: case handling (cell names are case-insensitive, but they are also showen to the - // player, so we can't simply smash case. - struct CellList : RecList - { - // Total cell count. Used for statistics. - int count; - CellList() : count(0) {} - int getSize() { return count; } - - // List of interior cells. Indexed by cell name. - typedef std::map IntCells; - IntCells intCells; - - // List of exterior cells. Indexed as extCells[mX][mY]. - typedef std::map, ESM::Cell*> ExtCells; - ExtCells extCells; - - virtual void listIdentifier (std::vector& identifier) const - { - for (IntCells::const_iterator iter (intCells.begin()); iter!=intCells.end(); ++iter) - identifier.push_back (iter->first); - } - - virtual ~CellList() - { - for (IntCells::iterator it = intCells.begin(); it!=intCells.end(); ++it) - delete it->second; - - for (ExtCells::iterator it = extCells.begin(); it!=extCells.end(); ++it) - delete it->second; - } - - const ESM::Cell* searchInt(const std::string &id) const - { - IntCells::const_iterator iter = intCells.find(id); - - if (iter!=intCells.end()) - return iter->second; - - return 0; - } - - const ESM::Cell* findInt(const std::string &id) const - { - const ESM::Cell *cell = searchInt (id); - - if (!cell) - throw std::runtime_error ("Interior cell not found - " + id); - - return cell; - } - - const ESM::Cell *searchExt (int x, int y) const - { - ExtCells::const_iterator it = extCells.find (std::make_pair (x, y)); - - if (it==extCells.end()) - return 0; - - return it->second; - } - - const ESM::Cell *findExt (int x, int y) const - { - const ESM::Cell *cell = searchExt (x, y); - - if (!cell) - throw std::runtime_error ("Exterior cell not found"); - - return cell; - } - const ESM::Cell *searchExtByName (const std::string& id) const - { - for (ExtCells::const_iterator iter = extCells.begin(); iter!=extCells.end(); ++iter) - { - if (Misc::toLower (iter->second->mName) == Misc::toLower (id)) - return iter->second; - } - - return 0; - } - - const ESM::Cell *searchExtByRegion (const std::string& id) const - { - std::string id2 = Misc::toLower (id); - - for (ExtCells::const_iterator iter = extCells.begin(); iter!=extCells.end(); ++iter) - if (Misc::toLower (iter->second->mRegion)==id) - return iter->second; - - return 0; - } - - void load(ESMReader &esm, const std::string &id) - { - count++; - - // All cells have a name record, even nameless exterior cells. - ESM::Cell *cell = new ESM::Cell; - cell->mName = id; - - // The cell itself takes care of all the hairy details - cell->load(esm); - - if(cell->mData.mFlags & ESM::Cell::Interior) - { - // Store interior cell by name - intCells[id] = cell; - } - else - { - // Store exterior cells by grid position - extCells[std::make_pair (cell->mData.mX, cell->mData.mY)] = cell; - } - } - }; - - struct PathgridList : RecList - { - int count; - - // List of grids for interior cells. Indexed by cell name. - typedef std::map IntGrids; - IntGrids intGrids; - - // List of grids for exterior cells. Indexed as extCells[mX][mY]. - typedef std::map, ESM::Pathgrid*> ExtGrids; - ExtGrids extGrids; - - PathgridList() : count(0) {} - - virtual ~PathgridList() - { - for (IntGrids::iterator it = intGrids.begin(); it!=intGrids.end(); ++it) - delete it->second; - - for (ExtGrids::iterator it = extGrids.begin(); it!=extGrids.end(); ++it) - delete it->second; - } - - int getSize() { return count; } - - virtual void listIdentifier (std::vector& identifier) const - { - // do nothing - } - - void load(ESMReader &esm, const std::string &id) - { - count++; - ESM::Pathgrid *grid = new ESM::Pathgrid; - grid->load(esm); - if (grid->mData.mX == 0 && grid->mData.mY == 0) - { - intGrids[grid->mCell] = grid; - } - else - { - extGrids[std::make_pair(grid->mData.mX, grid->mData.mY)] = grid; - } - } - - Pathgrid *find(int cellX, int cellY, const std::string &cellName) const - { - Pathgrid *result = search(cellX, cellY, cellName); - if (!result) - { - throw std::runtime_error("no pathgrid found for cell " + cellName); - } - return result; - } - - Pathgrid *search(int cellX, int cellY, const std::string &cellName) const - { - Pathgrid *result = NULL; - if (cellX == 0 && cellY == 0) // possibly interior - { - IntGrids::const_iterator it = intGrids.find(cellName); - if (it != intGrids.end()) - result = it->second; - } - else - { - ExtGrids::const_iterator it = extGrids.find(std::make_pair(cellX, cellY)); - if (it != extGrids.end()) - result = it->second; - } - return result; - } - - Pathgrid *search(const ESM::Cell &cell) const - { - int cellX, cellY; - if (cell.mData.mFlags & ESM::Cell::Interior) - { - cellX = cellY = 0; - } - else - { - cellX = cell.mData.mX; - cellY = cell.mData.mY; - } - return search(cellX, cellY, cell.mName); - } - }; - - template - struct ScriptListT : RecList - { - virtual ~ScriptListT() {} - - typedef std::map MapType; - - MapType list; - - // Load one object of this type - void load(ESMReader &esm, const std::string &id) - { - X ref; - ref.load (esm); - - std::string realId = Misc::toLower (ref.mData.mName.toString()); - - std::swap (list[realId], ref); - } - - // Find the given object ID, or return NULL if not found. - const X* search(const std::string &id) const - { - std::string id2 = Misc::toLower (id); - - typename MapType::const_iterator iter = list.find (id2); - - if (iter == list.end()) - return NULL; - - return &iter->second; - } - - // Find the given object ID (throws an exception if not found) - const X* find(const std::string &id) const - { - const X *object = search (id); - - if (!object) - throw std::runtime_error ("object " + id + " not found"); - - return object; - } - - int getSize() { return list.size(); } - - virtual void listIdentifier (std::vector& identifier) const - { - for (typename MapType::const_iterator iter (list.begin()); iter!=list.end(); ++iter) - identifier.push_back (iter->first); - } - }; - - template - struct IndexListT - { - virtual ~IndexListT() {} - - typedef std::map MapType; - - MapType list; - - void load(ESMReader &esm) - { - X ref; - ref.load (esm); - int index = ref.mIndex; - list[index] = ref; - } - - int getSize() - { - return list.size(); - } - - virtual void listIdentifier (std::vector& identifier) const {} - - // Find the given object ID, or return NULL if not found. - const X* search (int id) const - { - typename MapType::const_iterator iter = list.find (id); - - if (iter == list.end()) - return NULL; - - return &iter->second; - } - - // Find the given object ID (throws an exception if not found) - const X* find (int id) const - { - const X *object = search (id); - - if (!object) - { - std::ostringstream error; - error << "object " << id << " not found"; - throw std::runtime_error (error.str()); - } - - return object; - } - }; - - /* We need special lists for: - - Path grids - */ -} -#endif diff --git a/components/misc/stringops.cpp b/components/misc/stringops.cpp index 51cf2105a..0bc8e290a 100644 --- a/components/misc/stringops.cpp +++ b/components/misc/stringops.cpp @@ -67,30 +67,4 @@ bool iends(const char* str1, const char* str2) return strcasecmp(str2, str1+len1-len2) == 0; } -std::string toLower (const std::string& name) -{ - std::string lowerCase; - - std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), - (int(*)(int)) std::tolower); - - return lowerCase; -} - -bool stringCompareNoCase (std::string first, std::string second) -{ - unsigned int i=0; - while ( (itolower(second[i])) return false; - ++i; - } - if (first.length() Date: Mon, 31 Dec 2012 04:15:47 +0400 Subject: [PATCH 091/136] 1. Dialogs in Russian version now works. 2. Destination names it travel window are now translated --- apps/openmw/engine.cpp | 2 +- apps/openmw/mwbase/windowmanager.hpp | 4 + apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 103 ++++++++++++++++-- apps/openmw/mwdialogue/dialoguemanagerimp.hpp | 19 +++- apps/openmw/mwgui/dialogue.cpp | 83 ++++++++++++-- apps/openmw/mwgui/dialogue.hpp | 12 +- apps/openmw/mwgui/travelwindow.cpp | 2 +- apps/openmw/mwgui/windowmanagerimp.cpp | 5 + apps/openmw/mwgui/windowmanagerimp.hpp | 2 + components/translation/translation.cpp | 30 +++-- components/translation/translation.hpp | 7 +- 11 files changed, 236 insertions(+), 33 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index b995300d5..e2d28a808 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -360,7 +360,7 @@ void OMW::Engine::go() // Create dialog system mEnvironment.setJournal (new MWDialogue::Journal); - mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts)); + mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts, mTranslationDataStorage)); // Sets up the input system mEnvironment.setInputManager (new MWInput::InputManager (*mOgre, diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index c177912d4..30bfced06 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -7,6 +7,8 @@ #include +#include + #include "../mwmechanics/stat.hpp" #include "../mwgui/mode.hpp" @@ -233,6 +235,8 @@ namespace MWBase virtual void startSpellMaking(MWWorld::Ptr actor) = 0; virtual void startEnchanting(MWWorld::Ptr actor) = 0; virtual void startTraining(MWWorld::Ptr actor) = 0; + + virtual const Translation::Storage& getTranslationDataStorage() const = 0; }; } diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 26d5af202..68837be3c 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -52,7 +52,7 @@ namespace return lowerCase; } - bool stringCompareNoCase (std::string first, std::string second) + bool stringCompareNoCase (const std::string& first, const std::string& second) { unsigned int i=0; while ( (i::iterator it; - for(it = mActorKnownTopics.begin();it != mActorKnownTopics.end();++it) + std::vector hypertext = ParseHyperText(text); + + //calculation of standard form fir all hyperlinks + for (size_t i = 0; i < hypertext.size(); ++i) { - size_t pos = find_str_ci(text,*it,0); - if(pos !=std::string::npos) + if (hypertext[i].mLink) { - mKnownTopics[*it] = true; + size_t asterisk_count = MWDialogue::RemovePseudoAsterisks(hypertext[i].mText); + for(; asterisk_count > 0; --asterisk_count) + hypertext[i].mText.append("*"); + + hypertext[i].mText = mTranslationDataStorage.topicStandardForm(hypertext[i].mText); } } + + for (size_t i = 0; i < hypertext.size(); ++i) + { + std::list::iterator it; + for(it = mActorKnownTopics.begin(); it != mActorKnownTopics.end(); ++it) + { + if (hypertext[i].mLink) + { + if( hypertext[i].mText == *it ) + { + mKnownTopics[hypertext[i].mText] = true; + } + } + else if( !mTranslationDataStorage.hasTranslation() ) + { + size_t pos = find_str_ci(hypertext[i].mText, *it, 0); + if(pos !=std::string::npos) + { + mKnownTopics[*it] = true; + } + } + } + } + updateTopics(); } @@ -156,7 +186,7 @@ namespace MWDialogue } parseText (info->mResponse); - + MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor); win->addText (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext)); executeScript (info->mResultScript); @@ -298,7 +328,7 @@ namespace MWDialogue { if (filter.search (*iter)) { - mActorKnownTopics.push_back (toLower (iter->mId)); + mActorKnownTopics.push_back(toLower (iter->mId)); //does the player know the topic? if (mKnownTopics.find (toLower (iter->mId)) != mKnownTopics.end()) @@ -415,7 +445,7 @@ namespace MWDialogue mIsInChoice = false; std::string text = info->mResponse; parseText (text); - + MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor); MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addText (Interpreter::fixDefinesDialog(text, interpreterContext)); executeScript (info->mResultScript); @@ -499,4 +529,57 @@ namespace MWDialogue { mTemporaryDispositionChange += delta; } + + std::vector ParseHyperText(const std::string& text) + { + std::vector result; + + MyGUI::UString utext(text); + + size_t pos_begin, pos_end, iteration_pos = 0; + for(;;) + { + pos_begin = utext.find('@', iteration_pos); + if (pos_begin != std::string::npos) + pos_end = utext.find('#', pos_begin); + + if (pos_begin != std::string::npos && pos_end != std::string::npos) + { + result.push_back( HyperTextToken(utext.substr(iteration_pos, pos_begin - iteration_pos), false) ); + + std::string link = utext.substr(pos_begin + 1, pos_end - pos_begin - 1); + result.push_back( HyperTextToken(link, true) ); + + iteration_pos = pos_end + 1; + } + else + { + result.push_back( HyperTextToken(utext.substr(iteration_pos), false) ); + break; + } + } + + return result; + } + + size_t RemovePseudoAsterisks(std::string& phrase) + { + size_t pseudoAsterisksCount = 0; + const char specialPseudoAsteriskCharacter = 127; + + if( !phrase.empty() ) + { + std::string::reverse_iterator rit = phrase.rbegin(); + + while( rit != phrase.rend() && *rit == specialPseudoAsteriskCharacter ) + { + pseudoAsterisksCount++; + ++rit; + } + } + + phrase = phrase.substr(0, phrase.length() - pseudoAsterisksCount); + + return pseudoAsterisksCount; + } } diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp index 98b27f774..1ca2ae5eb 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp @@ -7,6 +7,7 @@ #include #include +#include #include "../mwworld/ptr.hpp" @@ -20,6 +21,7 @@ namespace MWDialogue std::map mKnownTopics;// Those are the topics the player knows. std::list mActorKnownTopics; + Translation::Storage& mTranslationDataStorage; MWScript::CompilerContext mCompilerContext; std::ostream mErrorStream; Compiler::StreamErrorHandler mErrorHandler; @@ -50,7 +52,7 @@ namespace MWDialogue public: - DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose); + DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose, Translation::Storage& translationDataStorage); virtual void startDialogue (const MWWorld::Ptr& actor); @@ -72,6 +74,21 @@ namespace MWDialogue virtual int getTemporaryDispositionChange () const; virtual void applyTemporaryDispositionChange (int delta); }; + + + struct HyperTextToken + { + HyperTextToken(const std::string& text, bool link) : mText(text), mLink(link) {} + + std::string mText; + bool mLink; + }; + + // In translations (at least Russian) the links are marked with @#, so + // it should be a function to parse it + std::vector ParseHyperText(const std::string& text); + + size_t RemovePseudoAsterisks(std::string& phrase); } #endif diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 258e9174c..0dbe37941 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -16,6 +16,8 @@ #include "../mwmechanics/npcstats.hpp" +#include "../mwdialogue/dialoguemanagerimp.hpp" + #include "dialogue_history.hpp" #include "widgets.hpp" #include "list.hpp" @@ -52,7 +54,6 @@ bool sortByLength (const std::string& left, const std::string& right) { return left.size() > right.size(); } - } @@ -131,6 +132,7 @@ DialogueWindow::DialogueWindow(MWBase::WindowManager& parWindowManager) , mPersuasionDialog(parWindowManager) , mEnabled(false) , mServices(0) + , mWindowManager(parWindowManager) { // Centre dialog center(); @@ -180,9 +182,30 @@ void DialogueWindow::onHistoryClicked(MyGUI::Widget* _sender) if(color != "#B29154") { MyGUI::UString key = mHistory->getColorTextAt(cursorPosition); - if(color == "#686EBA") MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(key)); - if(color == "#572D21") MWBase::Environment::get().getDialogueManager()->questionAnswered(lower_string(key)); + if(color == "#686EBA") + { + std::map::iterator i = mHyperLinks.upper_bound(cursorPosition); + if( !mHyperLinks.empty() ) + { + --i; + + if( i->first + i->second.mLength > cursorPosition) + { + MWBase::Environment::get().getDialogueManager()->keywordSelected(i->second.mTrueValue); + } + } + else + { + // the link was colored, but it is not in mHyperLinks. + // It means that those liunks are not marked with @# and found + // by topic name search + MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(key)); + } + } + + if(color == "#572D21") + MWBase::Environment::get().getDialogueManager()->questionAnswered(lower_string(key)); } } @@ -258,6 +281,7 @@ void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName) setTitle(npcName); mTopicsList->clear(); + mHyperLinks.clear(); mHistory->setCaption(""); updateOptions(); } @@ -340,7 +364,7 @@ void addColorInString(std::string& str, const std::string& keyword,std::string c } } -std::string DialogueWindow::parseText(std::string text) +std::string DialogueWindow::parseText(const std::string& text) { bool separatorReached = false; // only parse topics that are below the separator (this prevents actions like "Barter" that are not topics from getting blue-colored) @@ -358,11 +382,55 @@ std::string DialogueWindow::parseText(std::string text) // sort by length to make sure longer topics are replaced first std::sort(topics.begin(), topics.end(), sortByLength); - for(std::vector::const_iterator it = topics.begin(); it != topics.end(); ++it) + std::vector hypertext = MWDialogue::ParseHyperText(text); + + size_t historySize = 0; + if(mHistory->getClient()->getSubWidgetText() != nullptr) + { + historySize = mHistory->getOnlyText().size(); + } + + std::string result; + size_t hypertextPos = 0; + for (size_t i = 0; i < hypertext.size(); ++i) { - addColorInString(text,*it,"#686EBA","#B29154"); + if (hypertext[i].mLink) + { + size_t asterisk_count = MWDialogue::RemovePseudoAsterisks(hypertext[i].mText); + std::string standardForm = hypertext[i].mText; + for(; asterisk_count > 0; --asterisk_count) + standardForm.append("*"); + + standardForm = + mWindowManager.getTranslationDataStorage().topicStandardForm(standardForm); + + if( std::find(topics.begin(), topics.end(), std::string(standardForm) ) != topics.end() ) + { + result.append("#686EBA").append(hypertext[i].mText).append("#B29154"); + + mHyperLinks[historySize+hypertextPos].mLength = MyGUI::UString(hypertext[i].mText).length(); + mHyperLinks[historySize+hypertextPos].mTrueValue = lower_string(standardForm); + } + else + result += hypertext[i].mText; + } + else + { + if( !mWindowManager.getTranslationDataStorage().hasTranslation() ) + { + for(std::vector::const_iterator it = topics.begin(); it != topics.end(); ++it) + { + addColorInString(hypertext[i].mText, *it, "#686EBA", "#B29154"); + } + } + + result += hypertext[i].mText; + } + + hypertextPos += MyGUI::UString(hypertext[i].mText).length(); } - return text; + + return result; } void DialogueWindow::addText(std::string text) @@ -394,6 +462,7 @@ void DialogueWindow::updateOptions() { //Clear the list of topics mTopicsList->clear(); + mHyperLinks.clear(); mHistory->eraseText(0, mHistory->getTextLength()); if (mPtr.getTypeName() == typeid(ESM::NPC).name()) diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index 082d92524..3eeea01cd 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -92,12 +92,18 @@ namespace MWGui virtual void onReferenceUnavailable(); + struct HyperLink + { + size_t mLength; + std::string mTrueValue; + }; + private: void updateOptions(); /** *Helper function that add topic keyword in blue in a text. */ - std::string parseText(std::string text); + std::string parseText(const std::string& text); int mServices; @@ -109,6 +115,10 @@ namespace MWGui MyGUI::EditPtr mDispositionText; PersuasionDialog mPersuasionDialog; + + MWBase::WindowManager& mWindowManager; + + std::map mHyperLinks; }; } #endif diff --git a/apps/openmw/mwgui/travelwindow.cpp b/apps/openmw/mwgui/travelwindow.cpp index abbc6172f..9615e95f7 100644 --- a/apps/openmw/mwgui/travelwindow.cpp +++ b/apps/openmw/mwgui/travelwindow.cpp @@ -82,7 +82,7 @@ namespace MWGui oss << price; toAdd->setUserString("price",oss.str()); - toAdd->setCaptionWithReplacing(travelId+" - "+boost::lexical_cast(price)+"#{sgp}"); + toAdd->setCaptionWithReplacing("#{sCell=" + travelId + "} - " + boost::lexical_cast(price)+"#{sgp}"); toAdd->setSize(toAdd->getTextSize().width,sLineHeight); toAdd->eventMouseWheel += MyGUI::newDelegate(this, &TravelWindow::onMouseWheel); toAdd->setUserString("Destination", travelId); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index caf6a4ab0..12e72eaa9 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1050,3 +1050,8 @@ void WindowManager::startTraining(MWWorld::Ptr actor) { mTrainingWindow->startTraining(actor); } + +const Translation::Storage& WindowManager::getTranslationDataStorage() const +{ + return mTranslationDataStorage; +} diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index aaa856aef..8bcb88e22 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -225,6 +225,8 @@ namespace MWGui virtual void startEnchanting(MWWorld::Ptr actor); virtual void startTraining(MWWorld::Ptr actor); + virtual const Translation::Storage& getTranslationDataStorage() const; + private: OEngine::GUI::MyGUIManager *mGuiManager; HUD *mHud; diff --git a/components/translation/translation.cpp b/components/translation/translation.cpp index b559c6c1c..fb5b03861 100644 --- a/components/translation/translation.cpp +++ b/components/translation/translation.cpp @@ -81,17 +81,7 @@ namespace Translation std::string Storage::topicID(const std::string& phrase) const { - std::string result; - - //seeking for the standard phrase form - std::map::const_iterator phraseFormsIterator = - mPhraseForms.find(phrase); - - if (phraseFormsIterator != mPhraseForms.end()) - result = phraseFormsIterator->second; - else - result = phrase; - + std::string result = topicStandardForm(phrase); //seeking for the topic ID std::map::const_iterator topicIDIterator = @@ -103,8 +93,26 @@ namespace Translation return result; } + std::string Storage::topicStandardForm(const std::string& phrase) const + { + std::map::const_iterator phraseFormsIterator = + mPhraseForms.find(phrase); + + if (phraseFormsIterator != mPhraseForms.end()) + return phraseFormsIterator->second; + else + return phrase; + } + void Storage::setEncoding (const ToUTF8::FromType& encoding) { mEncoding = encoding; } + + bool Storage::hasTranslation() const + { + return !mCellNamesTranslations.empty() || + !mTopicIDs.empty() || + !mPhraseForms.empty(); + } } diff --git a/components/translation/translation.hpp b/components/translation/translation.hpp index 668d4c067..80d44d871 100644 --- a/components/translation/translation.hpp +++ b/components/translation/translation.hpp @@ -16,8 +16,13 @@ namespace Translation std::string translateCellName(const std::string& cellName) const; std::string topicID(const std::string& phrase) const; + // Standard form usually means nominative case + std::string topicStandardForm(const std::string& phrase) const; + void setEncoding (const ToUTF8::FromType& encoding); + bool hasTranslation() const; + private: typedef std::map ContainerType; @@ -30,7 +35,7 @@ namespace Translation ToUTF8::FromType mEncoding; - std::map mCellNamesTranslations, mTopicIDs, mPhraseForms; + ContainerType mCellNamesTranslations, mTopicIDs, mPhraseForms; }; } From 7e0713f6c4d414a0df087f7d4954c36709b02ce0 Mon Sep 17 00:00:00 2001 From: greye Date: Mon, 31 Dec 2012 11:22:40 +0400 Subject: [PATCH 092/136] fix string case update --- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 23 ++++++------------- apps/openmw/mwdialogue/dialoguemanagerimp.hpp | 1 - apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwscript/containerextensions.cpp | 13 +++++------ apps/openmw/mwworld/worldimp.cpp | 2 +- 5 files changed, 15 insertions(+), 26 deletions(-) diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 80999c5ff..d81421f81 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -40,16 +40,6 @@ #include "filter.hpp" -namespace -{ - - //helper function - std::string::size_type find_str_ci(const std::string& str, const std::string& substr,size_t pos) - { - return Misc::StringUtils::toLower(const_cast(str)).find(Misc::StringUtils::toLower(const_cast(substr)).c_str(),pos); - } -} - namespace MWDialogue { DialogueManager::DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose) : @@ -70,13 +60,13 @@ namespace MWDialogue MWWorld::Store::iterator it = dialogs.begin(); for (; it != dialogs.end(); ++it) { - mDialogueMap[Misc::StringUtils::toLower(const_cast(it->mId))] = *it; + mDialogueMap[Misc::StringUtils::lowerCase(it->mId)] = *it; } } void DialogueManager::addTopic (const std::string& topic) { - mKnownTopics[Misc::StringUtils::toLower(const_cast(topic))] = true; + mKnownTopics[Misc::StringUtils::lowerCase(topic)] = true; } void DialogueManager::parseText (const std::string& text) @@ -84,7 +74,7 @@ namespace MWDialogue std::list::iterator it; for(it = mActorKnownTopics.begin();it != mActorKnownTopics.end();++it) { - size_t pos = find_str_ci(text,*it,0); + size_t pos = Misc::StringUtils::lowerCase(text).find(*it, 0); if(pos !=std::string::npos) { mKnownTopics[*it] = true; @@ -274,10 +264,11 @@ namespace MWDialogue { if (filter.search (*iter)) { - mActorKnownTopics.push_back ( Misc::StringUtils::toLower(const_cast(iter->mId))); + std::string lower = Misc::StringUtils::lowerCase(iter->mId); + mActorKnownTopics.push_back (lower); //does the player know the topic? - if (mKnownTopics.find ( Misc::StringUtils::toLower(const_cast(iter->mId))) != mKnownTopics.end()) + if (mKnownTopics.find (lower) != mKnownTopics.end()) { keywordList.push_back (iter->mId); } @@ -415,7 +406,7 @@ namespace MWDialogue { MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); win->askQuestion(question); - mChoiceMap[Misc::StringUtils::toLower(const_cast(question))] = choice; + mChoiceMap[Misc::StringUtils::lowerCase(question)] = choice; mIsInChoice = true; } diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp index b0bef5ea0..98b27f774 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp @@ -71,7 +71,6 @@ namespace MWDialogue virtual void persuade (int type); virtual int getTemporaryDispositionChange () const; virtual void applyTemporaryDispositionChange (int delta); - void toLower(std::string question); }; } diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index dd75b8216..ffb6c5282 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -271,7 +271,7 @@ namespace MWGui for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it) { - if (Misc::StringUtils::toLower(it->getCellRef().mRefID) == "gold_001") + if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, "gold_001")) return it->getRefData().getCount(); } return 0; diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 2cdad2a90..1fa69d1fd 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -72,7 +72,7 @@ namespace MWScript Interpreter::Type_Integer sum = 0; for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) - if (Misc::StringUtils::toLower(iter->getCellRef().mRefID) == Misc::StringUtils::toLower(item)) + if (Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, item)) sum += iter->getRefData().getCount(); runtime.push (sum); @@ -105,7 +105,7 @@ namespace MWScript for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end() && count; ++iter) { - if (Misc::StringUtils::toLower(iter->getCellRef().mRefID) == Misc::StringUtils::toLower(item)) + if (Misc::StringUtils::ciEqual(iter->getCellRef().mRefID, item)) { itemName = MWWorld::Class::get(*iter).getName(*iter); @@ -163,7 +163,7 @@ namespace MWScript MWWorld::ContainerStoreIterator it = invStore.begin(); for (; it != invStore.end(); ++it) { - if (Misc::StringUtils::toLower(it->getCellRef().mRefID) == Misc::StringUtils::toLower(item)) + if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, item)) break; } if (it == invStore.end()) @@ -263,7 +263,7 @@ namespace MWScript for (int slot = 0; slot < MWWorld::InventoryStore::Slots; ++slot) { MWWorld::ContainerStoreIterator it = invStore.getSlot (slot); - if (it != invStore.end() && Misc::StringUtils::toLower(it->getCellRef().mRefID) == Misc::StringUtils::toLower(item)) + if (it != invStore.end() && Misc::StringUtils::ciEqual(it->getCellRef().mRefID, item)) { runtime.push(1); return; @@ -282,8 +282,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - const std::string &name = runtime.getStringLiteral (runtime[0].mInteger); - std::string creatureName = Misc::StringUtils::toLower (const_cast(name)); + const std::string &name = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore (ptr); @@ -291,7 +290,7 @@ namespace MWScript it != invStore.end(); ++it) { - if (Misc::StringUtils::toLower(it->getCellRef().mSoul) == Misc::StringUtils::toLower(creatureName)) + if (Misc::StringUtils::ciEqual(it->getCellRef().mSoul, name)) { runtime.push(1); return; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index e38fcf717..3995123b0 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -621,7 +621,7 @@ namespace MWWorld { if (isPlayer) if (!newCell.isExterior()) - changeToInteriorCell(Misc::StringUtils::toLower(const_cast (newCell.mCell->mName)), pos); + changeToInteriorCell(Misc::StringUtils::lowerCase(newCell.mCell->mName), pos); else { int cellX = newCell.mCell->getGridX(); From e2b348de9620c23695064f585d7ea4600b2abe88 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Mon, 31 Dec 2012 16:44:22 +0100 Subject: [PATCH 093/136] mwiniimporter: fix line ending problem --- apps/mwiniimporter/importer.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index dda8fd8ba..30822516e 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -660,10 +660,19 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(std::string filename) { std::string line; while (std::getline(file, line)) { + // unify Unix-style and Windows file ending + if (!(line.empty()) && (line[line.length()-1]) == '\r') { + line = line.substr(0, line.length()-1); + } + if(line[0] == '[') { - if(line.length() > 2) { - section = line.substr(1, line.length()-2); + int pos = line.find(']'); + if(pos < 2) { + std::cout << "Warning: ini file wrongly formatted (" << line << "). Line ignored." << std::endl; + continue; } + + section = line.substr(1, line.find(']')-1); continue; } From e9a464c9f7463c175f38e4966600ef3f839f68d1 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Mon, 31 Dec 2012 16:45:24 +0100 Subject: [PATCH 094/136] mwiniimporter: remove fallback values for Cursors --- apps/mwiniimporter/importer.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 30822516e..c15818ae3 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -146,13 +146,6 @@ MwIniImporter::MwIniImporter() "FontColor:color_negative", "FontColor:color_count", - // cursors - "Cursors:Cursor 0", - "Cursors:Cursor 1", - "Cursors:Cursor 2", - "Cursors:Cursor 3", - "Cursors:Cursor 4", - // level up messages "Level Up:Level2", "Level Up:Level3", From 008d6d6589e9709efdede92a94f1bd706df9fe06 Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Sun, 30 Dec 2012 14:59:09 -0800 Subject: [PATCH 095/136] added additional library search paths to find bullet This allowed CMake to correctly build Visual Studio 2010 project files against a windows compiled version of bullet (2.81 rev 2613) --- cmake/FindBullet.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/FindBullet.cmake b/cmake/FindBullet.cmake index 8d5ea2f1e..97feddffe 100644 --- a/cmake/FindBullet.cmake +++ b/cmake/FindBullet.cmake @@ -27,6 +27,8 @@ macro(_FIND_BULLET_LIBRARY _var) ${ARGN} PATHS ${BULLET_ROOT} + ${BULLET_ROOT}/lib/Debug + ${BULLET_ROOT}/lib/Release ${BULLET_ROOT}/out/release8/libs ${BULLET_ROOT}/out/debug8/libs PATH_SUFFIXES lib From 7228f5d696fa641a0bced370b86bb875330f2534 Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Sun, 30 Dec 2012 21:16:54 -0800 Subject: [PATCH 096/136] added missing reference to added missing reference to that was causing Visual Studio 2010 to fail to compile stringops.hpp --- components/misc/stringops.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/components/misc/stringops.hpp b/components/misc/stringops.hpp index 112d66bb8..029b617e1 100644 --- a/components/misc/stringops.hpp +++ b/components/misc/stringops.hpp @@ -1,6 +1,7 @@ #ifndef MISC_STRINGOPS_H #define MISC_STRINGOPS_H +#include #include #include From a842fc2c11e30d189a41be930cf9db55eaddddfa Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Sun, 30 Dec 2012 22:02:55 -0800 Subject: [PATCH 097/136] added hack to fix an alignment issue in MSVC 2010 The default allocator in Visual Studio 2010 does not respect the alignment requirements of classes it is allocating memory for. This results in a potential crash when using OEngine::Physics::PhysicActor that has been allocated on the heap if it is built against a version of Bullet that has SSE intrinsics enabled. --- libs/openengine/bullet/physic.hpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index f320d009d..76bdb491d 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -122,8 +122,13 @@ namespace Physic */ void runPmove(); - - +//HACK: in Visual Studio 2010 and presumably above, this structures alignment +// must be 16, but the built in operator new & delete don't properly +// perform this alignment. +#if _MSC_VER >= 1600 + void * operator new (size_t Size) { return _aligned_malloc (Size, 16); } + void operator delete (void * Data) { _aligned_free (Data); } +#endif private: From 08fa9dcd3ebe6a92eb38be671dfe63800647c4fc Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Tue, 1 Jan 2013 11:59:05 -0800 Subject: [PATCH 098/136] replaced std::string concatenation with std::ostringstream Changed a block of code that was performing a series of string concatenations to use an ostringstream instead. This allowed the removal of calls to std::to_string (not C++03 compliant) and fixes an compile error in MSVC 2010 (ambigous overload when calling std::to_string). --- components/interpreter/defines.cpp | 87 +++++++++++++++--------------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/components/interpreter/defines.cpp b/components/interpreter/defines.cpp index 29c78200d..18e5f81c1 100644 --- a/components/interpreter/defines.cpp +++ b/components/interpreter/defines.cpp @@ -1,6 +1,7 @@ #include "defines.hpp" #include +#include #include #include @@ -24,113 +25,113 @@ namespace Interpreter{ std::string fixDefinesReal(std::string text, char eschar, bool isBook, Context& context){ unsigned int start = 0; - std::string retval = ""; + std::ostringstream retval; for(unsigned int i = 0; i < text.length(); i++){ if(text[i] == eschar){ - retval += text.substr(start, i - start); + retval << text.substr(start, i - start); std::string temp = text.substr(i+1, 100); transform(temp.begin(), temp.end(), temp.begin(), ::tolower); bool found; if( (found = Check(temp, "actionslideright", &i, &start))){ - retval += context.getActionBinding("#{sRight}"); + retval << context.getActionBinding("#{sRight}"); } else if((found = Check(temp, "actionreadymagic", &i, &start))){ - retval += context.getActionBinding("#{sReady_Magic}"); + retval << context.getActionBinding("#{sReady_Magic}"); } else if((found = Check(temp, "actionprevweapon", &i, &start))){ - retval += "PLACEHOLDER_ACTION_PREV_WEAPON"; + retval << "PLACEHOLDER_ACTION_PREV_WEAPON"; } else if((found = Check(temp, "actionnextweapon", &i, &start))){ - retval += "PLACEHOLDER_ACTION_PREV_WEAPON"; + retval << "PLACEHOLDER_ACTION_PREV_WEAPON"; } else if((found = Check(temp, "actiontogglerun", &i, &start))){ - retval += context.getActionBinding("#{sAuto_Run}"); + retval << context.getActionBinding("#{sAuto_Run}"); } else if((found = Check(temp, "actionslideleft", &i, &start))){ - retval += context.getActionBinding("#{sLeft}"); + retval << context.getActionBinding("#{sLeft}"); } else if((found = Check(temp, "actionreadyitem", &i, &start))){ - retval += context.getActionBinding("#{sReady_Weapon}"); + retval << context.getActionBinding("#{sReady_Weapon}"); } else if((found = Check(temp, "actionprevspell", &i, &start))){ - retval += "PLACEHOLDER_ACTION_PREV_SPELL"; + retval << "PLACEHOLDER_ACTION_PREV_SPELL"; } else if((found = Check(temp, "actionnextspell", &i, &start))){ - retval += "PLACEHOLDER_ACTION_NEXT_SPELL"; + retval << "PLACEHOLDER_ACTION_NEXT_SPELL"; } else if((found = Check(temp, "actionrestmenu", &i, &start))){ - retval += context.getActionBinding("#{sRestKey}"); + retval << context.getActionBinding("#{sRestKey}"); } else if((found = Check(temp, "actionmenumode", &i, &start))){ - retval += context.getActionBinding("#{sJournal}"); + retval << context.getActionBinding("#{sJournal}"); } else if((found = Check(temp, "actionactivate", &i, &start))){ - retval += context.getActionBinding("#{sActivate}"); + retval << context.getActionBinding("#{sActivate}"); } else if((found = Check(temp, "actionjournal", &i, &start))){ - retval += context.getActionBinding("#{sJournal}"); + retval << context.getActionBinding("#{sJournal}"); } else if((found = Check(temp, "actionforward", &i, &start))){ - retval += context.getActionBinding("#{sForward}"); + retval << context.getActionBinding("#{sForward}"); } else if((found = Check(temp, "pccrimelevel", &i, &start))){ - retval += std::to_string(context.getPCBounty()); + retval << context.getPCBounty(); } else if((found = Check(temp, "actioncrouch", &i, &start))){ - retval += context.getActionBinding("#{sCrouch_Sneak}"); + retval << context.getActionBinding("#{sCrouch_Sneak}"); } else if((found = Check(temp, "actionjump", &i, &start))){ - retval += context.getActionBinding("#{sJump}"); + retval << context.getActionBinding("#{sJump}"); } else if((found = Check(temp, "actionback", &i, &start))){ - retval += context.getActionBinding("#{sBack}"); + retval << context.getActionBinding("#{sBack}"); } else if((found = Check(temp, "actionuse", &i, &start))){ - retval += "PLACEHOLDER_ACTION_USE"; + retval << "PLACEHOLDER_ACTION_USE"; } else if((found = Check(temp, "actionrun", &i, &start))){ - retval += "PLACEHOLDER_ACTION_RUN"; + retval << "PLACEHOLDER_ACTION_RUN"; } else if((found = Check(temp, "pcclass", &i, &start))){ - retval += context.getPCClass(); + retval << context.getPCClass(); } else if((found = Check(temp, "pcrace", &i, &start))){ - retval += context.getPCRace(); + retval << context.getPCRace(); } else if((found = Check(temp, "pcname", &i, &start))){ - retval += context.getPCName(); + retval << context.getPCName(); } else if((found = Check(temp, "cell", &i, &start))){ - retval += context.getCurrentCellName(); + retval << context.getCurrentCellName(); } else if(eschar == '%' && !isBook) { // In Dialogue, not messagebox if( (found = Check(temp, "faction", &i, &start))){ - retval += context.getNPCFaction(); + retval << context.getNPCFaction(); } else if((found = Check(temp, "nextpcrank", &i, &start))){ - retval += context.getPCNextRank(); + retval << context.getPCNextRank(); } else if((found = Check(temp, "pcnextrank", &i, &start))){ - retval += context.getPCNextRank(); + retval << context.getPCNextRank(); } else if((found = Check(temp, "pcrank", &i, &start))){ - retval += context.getPCRank(); + retval << context.getPCRank(); } else if((found = Check(temp, "rank", &i, &start))){ - retval += context.getNPCRank(); + retval << context.getNPCRank(); } else if((found = Check(temp, "class", &i, &start))){ - retval += context.getNPCClass(); + retval << context.getNPCClass(); } else if((found = Check(temp, "race", &i, &start))){ - retval += context.getNPCRace(); + retval << context.getNPCRace(); } else if((found = Check(temp, "name", &i, &start))){ - retval += context.getNPCName(); + retval << context.getNPCName(); } } else { // In messagebox or book, not dialogue @@ -144,13 +145,13 @@ namespace Interpreter{ /* uses pc in messageboxes */ else if((found = Check(temp, "class", &i, &start))){ - retval += context.getPCClass(); + retval << context.getPCClass(); } else if((found = Check(temp, "race", &i, &start))){ - retval += context.getPCRace(); + retval << context.getPCRace(); } else if((found = Check(temp, "name", &i, &start))){ - retval += context.getPCName(); + retval << context.getPCName(); } } @@ -172,9 +173,9 @@ namespace Interpreter{ char type = context.getGlobalType(globals[j]); switch(type){ - case 's': retval += std::to_string(context.getGlobalShort(globals[j])); break; - case 'l': retval += std::to_string(context.getGlobalLong(globals[j])); break; - case 'f': retval += std::to_string(context.getGlobalFloat(globals[j])); break; + case 's': retval << context.getGlobalShort(globals[j]); break; + case 'l': retval << context.getGlobalLong(globals[j]); break; + case 'f': retval << context.getGlobalFloat(globals[j]); break; } break; } @@ -186,12 +187,12 @@ namespace Interpreter{ /* leave unmodified */ i += 1; start = i; - retval += eschar; + retval << eschar; } } } - retval += text.substr(start, text.length() - start); - return retval; + retval << text.substr(start, text.length() - start); + return retval.str (); } std::string fixDefinesDialog(std::string text, Context& context){ From 2a7336c310eb668015e39265c5e4f4f2d1216edb Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Tue, 1 Jan 2013 21:59:30 +0100 Subject: [PATCH 099/136] mwiniimporter: handle ini file encodings Use components/to_utf8 to handle encodings. Add an --encoding option for choosing between win1250, win1251 and win1252 encodings for the imported ini file. --- apps/mwiniimporter/importer.cpp | 15 +++++++++++++++ apps/mwiniimporter/importer.hpp | 5 +++++ apps/mwiniimporter/main.cpp | 9 +++++++++ 3 files changed, 29 insertions(+) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index c15818ae3..def70615b 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -653,6 +653,8 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(std::string filename) { std::string line; while (std::getline(file, line)) { + line = toUTF8(line); + // unify Unix-style and Windows file ending if (!(line.empty()) && (line[line.length()-1]) == '\r') { line = line.substr(0, line.length()-1); @@ -826,3 +828,16 @@ void MwIniImporter::writeToFile(boost::iostreams::stream #include +#include "../../components/to_utf8/to_utf8.hpp" + class MwIniImporter { public: typedef std::map strmap; typedef std::map > multistrmap; MwIniImporter(); + void setInputEncoding(const ToUTF8::FromType& encoding); void setVerbose(bool verbose); multistrmap loadIniFile(std::string filename); multistrmap loadCfgFile(std::string filename); @@ -25,9 +28,11 @@ class MwIniImporter { private: void insertMultistrmap(multistrmap &cfg, std::string key, std::string value); std::string numberToString(int n); + std::string toUTF8(const std::string &str); bool mVerbose; strmap mMergeMap; std::vector mMergeFallback; + ToUTF8::FromType mEncoding; }; diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index 234d7d57d..e90f26dd2 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -18,6 +18,11 @@ int main(int argc, char *argv[]) { ("cfg,c", bpo::value(), "openmw.cfg file") ("output,o", bpo::value()->default_value(""), "openmw.cfg file") ("game-files,g", "import esm and esp files") + ("encoding,e", bpo::value()-> default_value("win1252"), + "Character encoding used in OpenMW game messages:\n" + "\n\twin1250 - Central and Eastern European such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian, Serbian (Latin script), Romanian and Albanian languages\n" + "\n\twin1251 - Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages\n" + "\n\twin1252 - Western European (Latin) alphabet, used by default") ; p_desc.add("ini", 1).add("cfg", 1); @@ -57,6 +62,10 @@ int main(int argc, char *argv[]) { MwIniImporter importer; importer.setVerbose(vm.count("verbose")); + // Font encoding settings + std::string encoding(vm["encoding"].as()); + importer.setInputEncoding(ToUTF8::calculateEncoding(encoding)); + MwIniImporter::multistrmap ini = importer.loadIniFile(iniFile); MwIniImporter::multistrmap cfg = importer.loadCfgFile(cfgFile); From 86f30992d7f1979f3ac187add917e793a1671c1b Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 1 Jan 2013 22:00:14 +0100 Subject: [PATCH 100/136] fix message boxes not appearing properly when e.g. trading --- apps/openmw/mwgui/windowmanagerimp.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 6164f9037..7f5d34939 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -539,9 +539,8 @@ void WindowManager::messageBox (const std::string& message, const std::vectoraddMessageBox(MyGUI::LanguageManager::getInstance().replaceTags(message)); - else mMessageBoxManager->createMessageBox(message); } From c613f07b84f1ebabd758c1e4a993e883b22f7c1b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 2 Jan 2013 10:10:10 +0100 Subject: [PATCH 101/136] updated credits file --- credits.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/credits.txt b/credits.txt index 72451c3d0..713fbe9ac 100644 --- a/credits.txt +++ b/credits.txt @@ -32,6 +32,7 @@ Lukasz Gromanowski (lgro) Marcin Hulist (Gohan) Michael Mc Donnell Michael Papageorgiou (werdanith) +Nathan Jeffords (blunted2night) Nikolay Kasyanov (corristo) Pieter van der Kloet (pvdk) Roman Melnik (Kromgart) From 04cca2a1ce85e73e9fe0d4a6e3b948b7ebf5d603 Mon Sep 17 00:00:00 2001 From: lazydev Date: Wed, 2 Jan 2013 18:58:52 +0400 Subject: [PATCH 102/136] fix for http://bugs.openmw.org/issues/517 --- apps/openmw/mwgui/container.cpp | 8 ++++---- apps/openmw/mwgui/tradewindow.cpp | 16 ++++++++++------ apps/openmw/mwgui/tradewindow.hpp | 4 ++-- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 20bc95445..479a82efa 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -195,13 +195,13 @@ void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count) if (isInventory()) { MWBase::Environment::get().getWindowManager()->getTradeWindow()->addItem(object, count); - MWBase::Environment::get().getWindowManager()->getTradeWindow()->buyFromNpc(object, count); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->sellToNpc(object, count, true); MWBase::Environment::get().getWindowManager()->getTradeWindow()->drawItems(); } else { MWBase::Environment::get().getWindowManager()->getInventoryWindow()->addItem(object, count); - MWBase::Environment::get().getWindowManager()->getTradeWindow()->sellToNpc(object, count); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->buyFromNpc(object, count, true); MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); } @@ -218,13 +218,13 @@ void ContainerBase::sellItem(MyGUI::Widget* _sender, int count) if (isInventory()) { MWBase::Environment::get().getWindowManager()->getTradeWindow()->addBarteredItem(object, count); - MWBase::Environment::get().getWindowManager()->getTradeWindow()->buyFromNpc(object, count); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->sellToNpc(object, count, false); MWBase::Environment::get().getWindowManager()->getTradeWindow()->drawItems(); } else { MWBase::Environment::get().getWindowManager()->getInventoryWindow()->addBarteredItem(object, count); - MWBase::Environment::get().getWindowManager()->getTradeWindow()->sellToNpc(object, count); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->buyFromNpc(object, count, false); MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); } diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index a005c618f..51eb3d87e 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -401,19 +401,23 @@ namespace MWGui return items; } - void TradeWindow::sellToNpc(MWWorld::Ptr item, int count) + void TradeWindow::sellToNpc(MWWorld::Ptr item, int count, bool boughtItem) { + int diff = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count, boughtItem); + + mCurrentBalance += diff; + mCurrentMerchantOffer += diff; - mCurrentBalance -= MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count,true); - mCurrentMerchantOffer -= MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count,true); updateLabels(); } - void TradeWindow::buyFromNpc(MWWorld::Ptr item, int count) + void TradeWindow::buyFromNpc(MWWorld::Ptr item, int count, bool soldItem) { + int diff = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count, !soldItem); + + mCurrentBalance -= diff; + mCurrentMerchantOffer -= diff; - mCurrentBalance += MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count,false); - mCurrentMerchantOffer += MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count,false); updateLabels(); } diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index db386d8b6..219e44036 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -27,8 +27,8 @@ namespace MWGui void startTrade(MWWorld::Ptr actor); - void sellToNpc(MWWorld::Ptr item, int count); ///< only used for adjusting the gold balance - void buyFromNpc(MWWorld::Ptr item, int count); ///< only used for adjusting the gold balance + void sellToNpc(MWWorld::Ptr item, int count, bool boughtItem); ///< only used for adjusting the gold balance + void buyFromNpc(MWWorld::Ptr item, int count, bool soldItem); ///< only used for adjusting the gold balance bool npcAcceptsItem(MWWorld::Ptr item); From ddbe13e5694230b889a6d5606cc36e3a3098b1c1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 3 Jan 2013 01:07:17 +0100 Subject: [PATCH 103/136] Workaround for http://bugs.openmw.org/issues/475 --- apps/openmw/mwinput/inputmanagerimp.cpp | 9 ++++++++- apps/openmw/mwinput/inputmanagerimp.hpp | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 6a1c3aa9b..995da8f34 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -40,6 +40,7 @@ namespace MWInput , mMouseLookEnabled(true) , mMouseX(ogre.getWindow()->getWidth ()/2.f) , mMouseY(ogre.getWindow()->getHeight ()/2.f) + , mMouseWheel(0) , mUserFile(userFile) , mDragDrop(false) , mGuiCursorEnabled(false) @@ -242,6 +243,11 @@ namespace MWInput mKeyboard->capture(); mMouse->capture(); + // inject some fake mouse movement to force updating MyGUI's widget states + // this shouldn't do any harm since we're moving back to the original position afterwards + MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX+1), int(mMouseY+1), mMouseWheel); + MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX), int(mMouseY), mMouseWheel); + // update values of channels (as a result of pressed keys) if (!loading) mInputCtrl->update(dt); @@ -486,8 +492,9 @@ namespace MWInput mMouseY += float(arg.state.Y.rel) * mUISensitivity * mUIYMultiplier; mMouseX = std::max(0.f, std::min(mMouseX, float(viewSize.width))); mMouseY = std::max(0.f, std::min(mMouseY, float(viewSize.height))); + mMouseWheel = arg.state.Z.abs; - MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX), int(mMouseY), arg.state.Z.abs); + MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX), int(mMouseY), mMouseWheel); } if (mMouseLookEnabled) diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 718d6b76f..9deed1f28 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -147,6 +147,7 @@ namespace MWInput float mMouseX; float mMouseY; + int mMouseWheel; std::map mControlSwitch; From 1718d735b566786809de51803f308176d3e594a4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 3 Jan 2013 01:09:03 +0100 Subject: [PATCH 104/136] Fix menu/journal/book/scroll buttons when using localised MW-installations This patch implements a custom widget that can switch its texture on-the-fly, making it obsolete having to use an atlas to get a hover animation. This also removes the predefined size restriction and should now work with all button texture sizes. --- CMakeLists.txt | 1 - apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwgui/bookwindow.cpp | 8 +- apps/openmw/mwgui/bookwindow.hpp | 18 ++-- apps/openmw/mwgui/cursorreplace.cpp | 4 - apps/openmw/mwgui/imagebutton.cpp | 63 ++++++++++++++ apps/openmw/mwgui/imagebutton.hpp | 33 ++++++++ apps/openmw/mwgui/journalwindow.cpp | 5 +- apps/openmw/mwgui/journalwindow.hpp | 14 ++- apps/openmw/mwgui/mainmenu.cpp | 92 +++++++++----------- apps/openmw/mwgui/mainmenu.hpp | 16 ++-- apps/openmw/mwgui/scrollwindow.hpp | 5 +- apps/openmw/mwgui/windowmanagerimp.cpp | 2 + files/mygui/CMakeLists.txt | 2 - files/mygui/atlas1.cfg | 51 ----------- files/mygui/mainmenu.cfg | 95 --------------------- files/mygui/openmw_book.layout | 24 ++++-- files/mygui/openmw_journal.layout | 12 ++- files/mygui/openmw_mainmenu_skin.xml | 30 ------- files/mygui/openmw_scroll.layout | 12 ++- libs/openengine/ogre/atlas.cpp | 113 ------------------------- libs/openengine/ogre/atlas.hpp | 27 ------ 22 files changed, 202 insertions(+), 427 deletions(-) create mode 100644 apps/openmw/mwgui/imagebutton.cpp create mode 100644 apps/openmw/mwgui/imagebutton.hpp delete mode 100644 files/mygui/atlas1.cfg delete mode 100644 files/mygui/mainmenu.cfg delete mode 100644 libs/openengine/ogre/atlas.cpp delete mode 100644 libs/openengine/ogre/atlas.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d7115583f..36e45d78a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,7 +104,6 @@ set(OENGINE_OGRE ${LIBDIR}/openengine/ogre/renderer.cpp ${LIBDIR}/openengine/ogre/fader.cpp ${LIBDIR}/openengine/ogre/imagerotate.cpp - ${LIBDIR}/openengine/ogre/atlas.cpp ${LIBDIR}/openengine/ogre/selectionbuffer.cpp ) set(OENGINE_GUI diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index e2a2e7f14..56147b500 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -30,7 +30,7 @@ add_openmw_dir (mwgui formatting inventorywindow container hud countdialog tradewindow settingswindow confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog - enchantingdialog trainingwindow travelwindow + enchantingdialog trainingwindow travelwindow imagebutton ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index bc3cd7b40..659795e18 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -88,7 +88,7 @@ void BookWindow::setTakeButtonShow(bool show) mTakeButton->setVisible(show); } -void BookWindow::onCloseButtonClicked (MyGUI::Widget* _sender) +void BookWindow::onCloseButtonClicked (MyGUI::Widget* sender) { // no 3d sounds because the object could be in a container. MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); @@ -96,7 +96,7 @@ void BookWindow::onCloseButtonClicked (MyGUI::Widget* _sender) mWindowManager.removeGuiMode(GM_Book); } -void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender) +void BookWindow::onTakeButtonClicked (MyGUI::Widget* sender) { MWBase::Environment::get().getSoundManager()->playSound ("Item Book Up", 1.0, 1.0, MWBase::SoundManager::Play_NoTrack); @@ -106,7 +106,7 @@ void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender) mWindowManager.removeGuiMode(GM_Book); } -void BookWindow::onNextPageButtonClicked (MyGUI::Widget* _sender) +void BookWindow::onNextPageButtonClicked (MyGUI::Widget* sender) { if ((mCurrentPage+1)*2 < mPages.size()) { @@ -118,7 +118,7 @@ void BookWindow::onNextPageButtonClicked (MyGUI::Widget* _sender) } } -void BookWindow::onPrevPageButtonClicked (MyGUI::Widget* _sender) +void BookWindow::onPrevPageButtonClicked (MyGUI::Widget* sender) { if (mCurrentPage > 0) { diff --git a/apps/openmw/mwgui/bookwindow.hpp b/apps/openmw/mwgui/bookwindow.hpp index fedb783b2..5887975ea 100644 --- a/apps/openmw/mwgui/bookwindow.hpp +++ b/apps/openmw/mwgui/bookwindow.hpp @@ -5,6 +5,8 @@ #include "../mwworld/ptr.hpp" +#include "imagebutton.hpp" + namespace MWGui { class BookWindow : public WindowBase @@ -16,19 +18,19 @@ namespace MWGui void setTakeButtonShow(bool show); protected: - void onNextPageButtonClicked (MyGUI::Widget* _sender); - void onPrevPageButtonClicked (MyGUI::Widget* _sender); - void onCloseButtonClicked (MyGUI::Widget* _sender); - void onTakeButtonClicked (MyGUI::Widget* _sender); + void onNextPageButtonClicked (MyGUI::Widget* sender); + void onPrevPageButtonClicked (MyGUI::Widget* sender); + void onCloseButtonClicked (MyGUI::Widget* sender); + void onTakeButtonClicked (MyGUI::Widget* sender); void updatePages(); void clearPages(); private: - MyGUI::Button* mCloseButton; - MyGUI::Button* mTakeButton; - MyGUI::Button* mNextPageButton; - MyGUI::Button* mPrevPageButton; + MWGui::ImageButton* mCloseButton; + MWGui::ImageButton* mTakeButton; + MWGui::ImageButton* mNextPageButton; + MWGui::ImageButton* mPrevPageButton; MyGUI::TextBox* mLeftPageNumber; MyGUI::TextBox* mRightPageNumber; MyGUI::Widget* mLeftPage; diff --git a/apps/openmw/mwgui/cursorreplace.cpp b/apps/openmw/mwgui/cursorreplace.cpp index a4b6a100b..2079538fc 100644 --- a/apps/openmw/mwgui/cursorreplace.cpp +++ b/apps/openmw/mwgui/cursorreplace.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #include @@ -14,7 +13,4 @@ CursorReplace::CursorReplace() OEngine::Render::ImageRotate::rotate("textures\\tx_cursormove.dds", "mwpointer_vresize.png", 90); OEngine::Render::ImageRotate::rotate("textures\\tx_cursormove.dds", "mwpointer_dresize1.png", -45); OEngine::Render::ImageRotate::rotate("textures\\tx_cursormove.dds", "mwpointer_dresize2.png", 45); - - OEngine::Render::Atlas::createFromFile("atlas1.cfg", "mwgui1", "textures\\"); - OEngine::Render::Atlas::createFromFile("mainmenu.cfg", "mwgui2", "textures\\"); } diff --git a/apps/openmw/mwgui/imagebutton.cpp b/apps/openmw/mwgui/imagebutton.cpp new file mode 100644 index 000000000..98f05373b --- /dev/null +++ b/apps/openmw/mwgui/imagebutton.cpp @@ -0,0 +1,63 @@ +#include "imagebutton.hpp" + +#include + +namespace MWGui +{ + + void ImageButton::setPropertyOverride(const std::string &_key, const std::string &_value) + { + if (_key == "ImageHighlighted") + mImageHighlighted = _value; + else if (_key == "ImagePushed") + mImagePushed = _value; + else if (_key == "ImageNormal") + { + if (mImageNormal == "") + { + setImageTexture(_value); + } + mImageNormal = _value; + } + else + ImageBox::setPropertyOverride(_key, _value); + } + void ImageButton::onMouseSetFocus(Widget* _old) + { + setImageTexture(mImageHighlighted); + ImageBox::onMouseSetFocus(_old); + } + + void ImageButton::onMouseLostFocus(Widget* _new) + { + setImageTexture(mImageNormal); + ImageBox::onMouseLostFocus(_new); + } + + void ImageButton::onMouseButtonPressed(int _left, int _top, MyGUI::MouseButton _id) + { + if (_id == MyGUI::MouseButton::Left) + setImageTexture(mImagePushed); + + ImageBox::onMouseButtonPressed(_left, _top, _id); + } + + MyGUI::IntSize ImageButton::getRequestedSize() + { + Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().getByName(mImageNormal); + if (texture.isNull()) + { + std::cerr << "ImageButton: can't find " << mImageNormal << std::endl; + return MyGUI::IntSize(0,0); + } + return MyGUI::IntSize (texture->getWidth(), texture->getHeight()); + } + + void ImageButton::onMouseButtonReleased(int _left, int _top, MyGUI::MouseButton _id) + { + if (_id == MyGUI::MouseButton::Left) + setImageTexture(mImageHighlighted); + + ImageBox::onMouseButtonReleased(_left, _top, _id); + } +} diff --git a/apps/openmw/mwgui/imagebutton.hpp b/apps/openmw/mwgui/imagebutton.hpp new file mode 100644 index 000000000..9fce12da1 --- /dev/null +++ b/apps/openmw/mwgui/imagebutton.hpp @@ -0,0 +1,33 @@ +#ifndef MWGUI_IMAGEBUTTON_H +#define MWGUI_IMAGEBUTTON_H + +#include "MyGUI_ImageBox.h" + +namespace MWGui +{ + + /** + * @brief allows using different image textures depending on the button state + */ + class ImageButton : public MyGUI::ImageBox + { + MYGUI_RTTI_DERIVED(ImageButton) + + public: + MyGUI::IntSize getRequestedSize(); + + protected: + virtual void setPropertyOverride(const std::string& _key, const std::string& _value); + virtual void onMouseLostFocus(MyGUI::Widget* _new); + virtual void onMouseSetFocus(MyGUI::Widget* _old); + virtual void onMouseButtonPressed(int _left, int _top, MyGUI::MouseButton _id); + virtual void onMouseButtonReleased(int _left, int _top, MyGUI::MouseButton _id); + + std::string mImageHighlighted; + std::string mImageNormal; + std::string mImagePushed; + }; + +} + +#endif diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index bbd3d4d28..ba39b0101 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -83,7 +83,6 @@ book formatText(std::string text,book mBook,int maxLine, int lineSize) MWGui::JournalWindow::JournalWindow (MWBase::WindowManager& parWindowManager) : WindowBase("openmw_journal.layout", parWindowManager) - , mLastPos(0) , mPageNumber(0) { mMainWidget->setVisible(false); @@ -177,7 +176,7 @@ void MWGui::JournalWindow::displayRightText(std::string text) } -void MWGui::JournalWindow::notifyNextPage(MyGUI::WidgetPtr _sender) +void MWGui::JournalWindow::notifyNextPage(MyGUI::Widget* _sender) { if(mPageNumber < int(mLeftPages.size())-1) { @@ -189,7 +188,7 @@ void MWGui::JournalWindow::notifyNextPage(MyGUI::WidgetPtr _sender) } } -void MWGui::JournalWindow::notifyPrevPage(MyGUI::WidgetPtr _sender) +void MWGui::JournalWindow::notifyPrevPage(MyGUI::Widget* _sender) { if(mPageNumber > 0) { diff --git a/apps/openmw/mwgui/journalwindow.hpp b/apps/openmw/mwgui/journalwindow.hpp index 3317880cd..044a2b2a4 100644 --- a/apps/openmw/mwgui/journalwindow.hpp +++ b/apps/openmw/mwgui/journalwindow.hpp @@ -7,6 +7,7 @@ #include #include "window_base.hpp" +#include "imagebutton.hpp" namespace MWGui { @@ -25,18 +26,13 @@ namespace MWGui /** *Called when next/prev button is used. */ - void notifyNextPage(MyGUI::WidgetPtr _sender); - void notifyPrevPage(MyGUI::WidgetPtr _sender); + void notifyNextPage(MyGUI::Widget* _sender); + void notifyPrevPage(MyGUI::Widget* _sender); - static const int sLineHeight; - - MyGUI::WidgetPtr mSkillAreaWidget, mSkillClientWidget; - MyGUI::ScrollBar* mSkillScrollerWidget; - int mLastPos, mClientHeight; MyGUI::EditPtr mLeftTextWidget; MyGUI::EditPtr mRightTextWidget; - MyGUI::ButtonPtr mPrevBtn; - MyGUI::ButtonPtr mNextBtn; + MWGui::ImageButton* mPrevBtn; + MWGui::ImageButton* mNextBtn; std::vector mLeftPages; std::vector mRightPages; int mPageNumber; //store the number of the current left page diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index e98b75e9b..14309abc5 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -20,65 +20,57 @@ namespace MWGui { setCoord(0,0,w,h); - int height = 64 * 3; if (mButtonBox) MyGUI::Gui::getInstance ().destroyWidget(mButtonBox); - mButtonBox = mMainWidget->createWidget("", MyGUI::IntCoord(w/2 - 64, h/2 - height/2, 128, height), MyGUI::Align::Default); + mButtonBox = mMainWidget->createWidget("", MyGUI::IntCoord(0, 0, 0, 0), MyGUI::Align::Default); int curH = 0; - mReturn = mButtonBox->createWidget ("ButtonImage", MyGUI::IntCoord(0, curH, 128, 64), MyGUI::Align::Default); - mReturn->setImageResource ("Menu_Return"); - mReturn->eventMouseButtonClick += MyGUI::newDelegate(this, &MainMenu::returnToGame); - curH += 64; - - - /* - mNewGame = mButtonBox->createWidget ("ButtonImage", MyGUI::IntCoord(0, curH, 128, 64), MyGUI::Align::Default); - mNewGame->setImageResource ("Menu_NewGame"); - curH += 64; - - mLoadGame = mButtonBox->createWidget ("ButtonImage", MyGUI::IntCoord(0, curH, 128, 64), MyGUI::Align::Default); - mLoadGame->setImageResource ("Menu_LoadGame"); - curH += 64; - - - mSaveGame = mButtonBox->createWidget ("ButtonImage", MyGUI::IntCoord(0, curH, 128, 64), MyGUI::Align::Default); - mSaveGame->setImageResource ("Menu_SaveGame"); - curH += 64; - */ - - mOptions = mButtonBox->createWidget ("ButtonImage", MyGUI::IntCoord(0, curH, 128, 64), MyGUI::Align::Default); - mOptions->setImageResource ("Menu_Options"); - mOptions->eventMouseButtonClick += MyGUI::newDelegate(this, &MainMenu::showOptions); - curH += 64; - - /* - mCredits = mButtonBox->createWidget ("ButtonImage", MyGUI::IntCoord(0, curH, 128, 64), MyGUI::Align::Default); - mCredits->setImageResource ("Menu_Credits"); - curH += 64; - */ - - mExitGame = mButtonBox->createWidget ("ButtonImage", MyGUI::IntCoord(0, curH, 128, 64), MyGUI::Align::Default); - mExitGame->setImageResource ("Menu_ExitGame"); - mExitGame->eventMouseButtonClick += MyGUI::newDelegate(this, &MainMenu::exitGame); - curH += 64; - } - - void MainMenu::returnToGame(MyGUI::Widget* sender) - { - MWBase::Environment::get().getWindowManager ()->removeGuiMode (GM_MainMenu); - } - - void MainMenu::showOptions(MyGUI::Widget* sender) - { - MWBase::Environment::get().getWindowManager ()->pushGuiMode (GM_Settings); + std::vector buttons; + buttons.push_back("return"); + //buttons.push_back("newgame"); + //buttons.push_back("loadgame"); + //buttons.push_back("savegame"); + buttons.push_back("options"); + //buttons.push_back("credits"); + buttons.push_back("exitgame"); + + int maxwidth = 0; + + mButtons.clear(); + for (std::vector::iterator it = buttons.begin(); it != buttons.end(); ++it) + { + MWGui::ImageButton* button = mButtonBox->createWidget + ("ImageBox", MyGUI::IntCoord(0, curH, 0, 0), MyGUI::Align::Default); + button->setProperty("ImageHighlighted", "textures\\menu_" + *it + "_over.dds"); + button->setProperty("ImageNormal", "textures\\menu_" + *it + ".dds"); + button->setProperty("ImagePushed", "textures\\menu_" + *it + "_pressed.dds"); + MyGUI::IntSize requested = button->getRequestedSize(); + button->eventMouseButtonClick += MyGUI::newDelegate(this, &MainMenu::onButtonClicked); + mButtons[*it] = button; + curH += requested.height; + + if (requested.width > maxwidth) + maxwidth = requested.width; + } + for (std::map::iterator it = mButtons.begin(); it != mButtons.end(); ++it) + { + MyGUI::IntSize requested = it->second->getRequestedSize(); + it->second->setCoord((maxwidth-requested.width) / 2, it->second->getTop(), requested.width, requested.height); + } + + mButtonBox->setCoord (w/2 - maxwidth/2, h/2 - curH/2, maxwidth, curH); } - void MainMenu::exitGame(MyGUI::Widget* sender) + void MainMenu::onButtonClicked(MyGUI::Widget *sender) { - Ogre::Root::getSingleton ().queueEndRendering (); + if (sender == mButtons["return"]) + MWBase::Environment::get().getWindowManager ()->removeGuiMode (GM_MainMenu); + else if (sender == mButtons["options"]) + MWBase::Environment::get().getWindowManager ()->pushGuiMode (GM_Settings); + else if (sender == mButtons["exitgame"]) + Ogre::Root::getSingleton ().queueEndRendering (); } } diff --git a/apps/openmw/mwgui/mainmenu.hpp b/apps/openmw/mwgui/mainmenu.hpp index fd583d187..4e76a64df 100644 --- a/apps/openmw/mwgui/mainmenu.hpp +++ b/apps/openmw/mwgui/mainmenu.hpp @@ -1,5 +1,7 @@ #include +#include "imagebutton.hpp" + namespace MWGui { @@ -11,19 +13,11 @@ namespace MWGui void onResChange(int w, int h); private: - MyGUI::Button* mReturn; - MyGUI::Button* mNewGame; - MyGUI::Button* mLoadGame; - MyGUI::Button* mSaveGame; - MyGUI::Button* mOptions; - MyGUI::Button* mCredits; - MyGUI::Button* mExitGame; - MyGUI::Widget* mButtonBox; - void returnToGame(MyGUI::Widget* sender); - void showOptions(MyGUI::Widget* sender); - void exitGame(MyGUI::Widget* sender); + std::map mButtons; + + void onButtonClicked (MyGUI::Widget* sender); }; } diff --git a/apps/openmw/mwgui/scrollwindow.hpp b/apps/openmw/mwgui/scrollwindow.hpp index b8f52fb65..7932a215b 100644 --- a/apps/openmw/mwgui/scrollwindow.hpp +++ b/apps/openmw/mwgui/scrollwindow.hpp @@ -2,6 +2,7 @@ #define MWGUI_SCROLLWINDOW_H #include "window_base.hpp" +#include "imagebutton.hpp" #include "../mwworld/ptr.hpp" @@ -20,8 +21,8 @@ namespace MWGui void onTakeButtonClicked (MyGUI::Widget* _sender); private: - MyGUI::Button* mCloseButton; - MyGUI::Button* mTakeButton; + MWGui::ImageButton* mCloseButton; + MWGui::ImageButton* mTakeButton; MyGUI::ScrollView* mTextView; MWWorld::Ptr mScroll; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 7f5d34939..099dafa6b 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -51,6 +51,7 @@ #include "spellcreationdialog.hpp" #include "enchantingdialog.hpp" #include "trainingwindow.hpp" +#include "imagebutton.hpp" using namespace MWGui; @@ -126,6 +127,7 @@ WindowManager::WindowManager( MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); + MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::LanguageManager::getInstance().eventRequestTag = MyGUI::newDelegate(this, &WindowManager::onRetrieveTag); diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index 562668a90..871be93d1 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -4,8 +4,6 @@ set(SDIR ${CMAKE_CURRENT_SOURCE_DIR}) set(DDIR ${OpenMW_BINARY_DIR}/resources/mygui) set(MYGUI_FILES - atlas1.cfg - mainmenu.cfg bigbars.png black.png core.skin diff --git a/files/mygui/atlas1.cfg b/files/mygui/atlas1.cfg deleted file mode 100644 index d1e05e041..000000000 --- a/files/mygui/atlas1.cfg +++ /dev/null @@ -1,51 +0,0 @@ -[settings] - size_x = 512 - size_y = 512 - -[tx_menubook_close_idle.dds] - x = 0 - y = 0 - -[tx_menubook_close_over.dds] - x = 128 - y = 0 - -[tx_menubook_close_pressed.dds] - x = 256 - y = 0 - -[tx_menubook_take_idle.dds] - x = 384 - y = 0 - -[tx_menubook_take_over.dds] - x = 0 - y = 32 - -[tx_menubook_take_pressed.dds] - x = 128 - y = 32 - -[tx_menubook_next_idle.dds] - x = 256 - y = 32 - -[tx_menubook_next_over.dds] - x = 384 - y = 32 - -[tx_menubook_next_pressed.dds] - x = 0 - y = 64 - -[tx_menubook_prev_idle.dds] - x = 128 - y = 64 - -[tx_menubook_prev_over.dds] - x = 256 - y = 64 - -[tx_menubook_prev_pressed.dds] - x = 384 - y = 64 diff --git a/files/mygui/mainmenu.cfg b/files/mygui/mainmenu.cfg deleted file mode 100644 index 7aaf8c1c7..000000000 --- a/files/mygui/mainmenu.cfg +++ /dev/null @@ -1,95 +0,0 @@ -[settings] - size_x = 512 - size_y = 512 - - -[menu_newgame.dds] - x = 0 - y = 0 - -[menu_newgame_pressed.dds] - x = 128 - y = 0 - -[menu_newgame_over.dds] - x = 256 - y = 0 - - -[menu_loadgame.dds] - x = 384 - y = 0 - -[menu_loadgame_pressed.dds] - x = 0 - y = 64 - -[menu_loadgame_over.dds] - x = 128 - y = 64 - - -[menu_options.dds] - x = 256 - y = 64 - -[menu_options_pressed.dds] - x = 384 - y = 64 - -[menu_options_over.dds] - x = 0 - y = 128 - - -[menu_credits.dds] - x = 128 - y = 128 - -[menu_credits_pressed.dds] - x = 256 - y = 128 - -[menu_credits_over.dds] - x = 384 - y = 128 - - -[menu_exitgame.dds] - x = 0 - y = 192 - -[menu_exitgame_pressed.dds] - x = 128 - y = 192 - -[menu_exitgame_over.dds] - x = 256 - y = 192 - - -[menu_savegame.dds] - x = 384 - y = 192 - -[menu_savegame_pressed.dds] - x = 0 - y = 256 - -[menu_savegame_over.dds] - x = 128 - y = 256 - - -[menu_return.dds] - x = 256 - y = 256 - -[menu_return_pressed.dds] - x = 384 - y = 256 - -[menu_return_over.dds] - x = 0 - y = 320 - diff --git a/files/mygui/openmw_book.layout b/files/mygui/openmw_book.layout index 6c708cdd3..894c1dbeb 100644 --- a/files/mygui/openmw_book.layout +++ b/files/mygui/openmw_book.layout @@ -7,17 +7,25 @@ - - + + + + - - + + + + - - + + + + - - + + + + diff --git a/files/mygui/openmw_journal.layout b/files/mygui/openmw_journal.layout index e4c3c7e47..fdf82e4de 100644 --- a/files/mygui/openmw_journal.layout +++ b/files/mygui/openmw_journal.layout @@ -7,11 +7,15 @@ - - + + + + - - + + + + diff --git a/files/mygui/openmw_mainmenu_skin.xml b/files/mygui/openmw_mainmenu_skin.xml index 4100a2eb7..c7f2fbce3 100644 --- a/files/mygui/openmw_mainmenu_skin.xml +++ b/files/mygui/openmw_mainmenu_skin.xml @@ -1,34 +1,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/files/mygui/openmw_scroll.layout b/files/mygui/openmw_scroll.layout index 0f4a0be3e..6315c0241 100644 --- a/files/mygui/openmw_scroll.layout +++ b/files/mygui/openmw_scroll.layout @@ -7,12 +7,16 @@ - - + + + + - - + + + + diff --git a/libs/openengine/ogre/atlas.cpp b/libs/openengine/ogre/atlas.cpp deleted file mode 100644 index 01b84afab..000000000 --- a/libs/openengine/ogre/atlas.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "atlas.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace Ogre; -using namespace OEngine::Render; - -void Atlas::createFromFile (const std::string& filename, const std::string& textureName, const std::string& texturePrefix) -{ - ConfigFile file; - file.load(filename, ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME, "\t:=", true); - - Root* root = Ogre::Root::getSingletonPtr(); - - SceneManager* sceneMgr = root->createSceneManager(ST_GENERIC); - Camera* camera = sceneMgr->createCamera("AtlasCamera"); - - int width = StringConverter::parseInt(file.getSetting("size_x", "settings")); - int height = StringConverter::parseInt(file.getSetting("size_y", "settings")); - - std::vector rectangles; - int i = 0; - - ConfigFile::SectionIterator seci = file.getSectionIterator(); - while (seci.hasMoreElements()) - { - Ogre::String sectionName = seci.peekNextKey(); - seci.getNext(); - - if (sectionName == "settings" || sectionName == "") - continue; - - MaterialPtr material = MaterialManager::getSingleton().create("AtlasMaterial" + StringConverter::toString(i), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - material->getTechnique(0)->getPass(0)->setLightingEnabled(false); - material->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); - TextureUnitState* tus = material->getTechnique(0)->getPass(0)->createTextureUnitState(texturePrefix + sectionName); - tus->setTextureBorderColour(ColourValue(0, 0, 0, 0)); - - Rectangle2D* rect = new Rectangle2D(true); - rect->setMaterial("AtlasMaterial" + StringConverter::toString(i)); - rect->setRenderQueueGroup(RENDER_QUEUE_BACKGROUND); - - int x = StringConverter::parseInt(file.getSetting("x", sectionName)); - int y = StringConverter::parseInt(file.getSetting("y", sectionName)); - - TexturePtr texture = TextureManager::getSingleton().getByName(texturePrefix + sectionName); - if (texture.isNull()) - { - std::cerr << "OEngine::Render::Atlas: Can't find texture " << texturePrefix + sectionName << ", skipping..." << std::endl; - continue; - } - int textureWidth = texture->getWidth(); - int textureHeight = texture->getHeight(); - - float left = x/float(width) * 2 - 1; - float top = (1-(y/float(height))) * 2 - 1; - float right = ((x+textureWidth))/float(width) * 2 - 1; - float bottom = (1-((y+textureHeight)/float(height))) * 2 - 1; - rect->setCorners(left, top, right, bottom); - - // Use infinite AAB to always stay visible - AxisAlignedBox aabInf; - aabInf.setInfinite(); - rect->setBoundingBox(aabInf); - - // Attach background to the scene - SceneNode* node = sceneMgr->getRootSceneNode()->createChildSceneNode(); - node->attachObject(rect); - - rectangles.push_back(rect); - ++i; - } - - TexturePtr destTexture = TextureManager::getSingleton().createManual( - textureName, - ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - TEX_TYPE_2D, - width, height, - 0, - PF_FLOAT16_RGBA, - TU_RENDERTARGET); - - RenderTarget* rtt = destTexture->getBuffer()->getRenderTarget(); - rtt->setAutoUpdated(false); - Viewport* vp = rtt->addViewport(camera); - vp->setOverlaysEnabled(false); - vp->setShadowsEnabled(false); - vp->setBackgroundColour(ColourValue(0,0,0,0)); - - rtt->update(); - - // remove all the junk we've created - for (std::vector::iterator it=rectangles.begin(); - it!=rectangles.end(); ++it) - { - delete (*it); - } - while (i > 0) - { - MaterialManager::getSingleton().remove("AtlasMaterial" + StringConverter::toString(i-1)); - --i; - } - root->destroySceneManager(sceneMgr); -} diff --git a/libs/openengine/ogre/atlas.hpp b/libs/openengine/ogre/atlas.hpp deleted file mode 100644 index 5dcd409ca..000000000 --- a/libs/openengine/ogre/atlas.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef OENGINE_OGRE_ATLAS_HPP -#define OENGINE_OGRE_ATLAS_HPP - -#include - -namespace OEngine -{ -namespace Render -{ - - /// \brief Creates a texture atlas at runtime - class Atlas - { - public: - /** - * @param absolute path to file that specifies layout of the texture (positions of the textures it contains) - * @param name of the destination texture to save to (in memory) - * @param texture directory prefix - */ - static void createFromFile (const std::string& filename, const std::string& textureName, const std::string& texturePrefix="textures\\"); - }; - -} -} - -#endif - From ba7086cadf88ecc9aaf15908e2cbc83e7ab8080f Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 3 Jan 2013 02:05:05 +0100 Subject: [PATCH 105/136] Use race/class names (instead of ID) in replaced escape sequences --- apps/openmw/mwscript/interpretercontext.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index cb0e4a7f9..a8d615d89 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -252,15 +252,17 @@ namespace MWScript std::string InterpreterContext::getPCRace() const { MWBase::World *world = MWBase::Environment::get().getWorld(); - ESM::NPC player = *world->getPlayer().getPlayer().get()->mBase; - return player.mRace; + std::string race = world->getPlayer().getPlayer().get()->mBase->mRace; + const ESM::Race* _race = world->getStore().get().find(race); + return _race->mName; } std::string InterpreterContext::getPCClass() const { MWBase::World *world = MWBase::Environment::get().getWorld(); - ESM::NPC player = *world->getPlayer().getPlayer().get()->mBase; - return player.mClass; + std::string _class = world->getPlayer().getPlayer().get()->mBase->mClass; + const ESM::Class* __class = world->getStore().get().find(_class); + return __class->mName; } std::string InterpreterContext::getPCRank() const From 42e0501c671b2034f5d6f8a7c90dc85f34d1dd51 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 3 Jan 2013 02:40:21 +0100 Subject: [PATCH 106/136] fix typo --- apps/openmw/mwscript/docs/vmformat.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 8a0913517..89cacf65c 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -4,7 +4,7 @@ Segment 0: (not implemented yet) opcodes 0x20-0x3f unused -Segment 1:< +Segment 1: (not implemented yet) opcodes 0x20-0x3f unused From 25d9918765e32fd6b4d0aa4f0bd4108d7e4a9e80 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 3 Jan 2013 09:55:48 +0100 Subject: [PATCH 107/136] post merge fix: bringing code more in line with our naming standards and fixing an invalid name (names starting with double underscore are reserved in C++) --- apps/openmw/mwscript/interpretercontext.cpp | 48 ++++++++++----------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index a8d615d89..c74e3f163 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -179,17 +179,17 @@ namespace MWScript std::vector InterpreterContext::getGlobals () const { - MWBase::World *world = MWBase::Environment::get().getWorld(); + MWBase::World *world = MWBase::Environment::get().getWorld(); return world->getGlobals(); } - + char InterpreterContext::getGlobalType (const std::string& name) const { - MWBase::World *world = MWBase::Environment::get().getWorld(); + MWBase::World *world = MWBase::Environment::get().getWorld(); return world->getGlobalVariableType(name); } - + std::string InterpreterContext::getActionBinding(const std::string& action) const { std::vector actions = MWBase::Environment::get().getInputManager()->getActionSorting (); @@ -205,19 +205,19 @@ namespace MWScript return "None"; } - + std::string InterpreterContext::getNPCName() const { ESM::NPC npc = *mReference.get()->mBase; return npc.mName; } - + std::string InterpreterContext::getNPCRace() const { ESM::NPC npc = *mReference.get()->mBase; return npc.mRace; } - + std::string InterpreterContext::getNPCClass() const { ESM::NPC npc = *mReference.get()->mBase; @@ -238,7 +238,7 @@ namespace MWScript MWBase::World *world = MWBase::Environment::get().getWorld(); const MWWorld::ESMStore &store = world->getStore(); const ESM::Faction *faction = store.get().find(it->first); - + return faction->mRanks[it->second]; } @@ -253,66 +253,64 @@ namespace MWScript { MWBase::World *world = MWBase::Environment::get().getWorld(); std::string race = world->getPlayer().getPlayer().get()->mBase->mRace; - const ESM::Race* _race = world->getStore().get().find(race); - return _race->mName; + return world->getStore().get().find(race)->mName; } std::string InterpreterContext::getPCClass() const { MWBase::World *world = MWBase::Environment::get().getWorld(); - std::string _class = world->getPlayer().getPlayer().get()->mBase->mClass; - const ESM::Class* __class = world->getStore().get().find(_class); - return __class->mName; + std::string class_ = world->getPlayer().getPlayer().get()->mBase->mClass; + return world->getStore().get().find(class_)->mName; } - + std::string InterpreterContext::getPCRank() const { MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayer().getPlayer(); - + std::string factionId = MWWorld::Class::get (mReference).getNpcStats (mReference).getFactionRanks().begin()->first; - + std::map ranks = MWWorld::Class::get (player).getNpcStats (player).getFactionRanks(); std::map::const_iterator it = ranks.begin(); const MWWorld::ESMStore &store = world->getStore(); const ESM::Faction *faction = store.get().find(factionId); - + if(it->second < 0 || it->second > 9) // there are only 10 ranks return ""; - + return faction->mRanks[it->second]; - } + } std::string InterpreterContext::getPCNextRank() const { MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayer().getPlayer(); - + std::string factionId = MWWorld::Class::get (mReference).getNpcStats (mReference).getFactionRanks().begin()->first; - + std::map ranks = MWWorld::Class::get (player).getNpcStats (player).getFactionRanks(); std::map::const_iterator it = ranks.begin(); const MWWorld::ESMStore &store = world->getStore(); const ESM::Faction *faction = store.get().find(factionId); - + if(it->second < 0 || it->second > 9) return ""; - + if(it->second <= 8) // If player is at max rank, there is no next rank return faction->mRanks[it->second + 1]; else return faction->mRanks[it->second]; } - + int InterpreterContext::getPCBounty() const { MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayer().getPlayer(); return MWWorld::Class::get (player).getNpcStats (player).getBounty(); } - + std::string InterpreterContext::getCurrentCellName() const { MWBase::World *world = MWBase::Environment::get().getWorld(); From 5c007cd52714779c071ef8bf5b82c808090edc8d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 3 Jan 2013 10:05:37 +0100 Subject: [PATCH 108/136] updated credits file --- credits.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/credits.txt b/credits.txt index 713fbe9ac..e1905c88b 100644 --- a/credits.txt +++ b/credits.txt @@ -21,6 +21,7 @@ Cris Mihalache (Mirceam) Douglas Diniz (Dgdiniz) Eduard Cot (trombonecot) Eli2 +Emanuel "potatoesmaster" Guével gugus / gus Jacob Essex (Yacoby) Jannik Heller (scrawl) From 9afe4467d8e5ea3f6fc9960e338bc16bcc1d7bbc Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Wed, 2 Jan 2013 13:50:44 -0800 Subject: [PATCH 109/136] cache results of query for spash screen names ResourceGroupManager::listResourceNames returns a list of all resource accessable which is expensive, this change caches the result of the processed query so additional splash screen changes are quicker. --- apps/openmw/mwgui/loadingscreen.cpp | 28 ++++++++++++++++------------ apps/openmw/mwgui/loadingscreen.hpp | 1 + 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index d721e209a..a508bcd34 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -213,22 +213,26 @@ namespace MWGui void LoadingScreen::changeWallpaper () { - std::vector splash; - - Ogre::StringVectorPtr resources = Ogre::ResourceGroupManager::getSingleton ().listResourceNames ("General", false); - for (Ogre::StringVector::const_iterator it = resources->begin(); it != resources->end(); ++it) + if (mResources.isNull ()) { - if (it->size() < 6) - continue; - std::string start = it->substr(0, 6); - boost::to_lower(start); + mResources = Ogre::StringVectorPtr (new Ogre::StringVector); + + Ogre::StringVectorPtr resources = Ogre::ResourceGroupManager::getSingleton ().listResourceNames ("General", false); + for (Ogre::StringVector::const_iterator it = resources->begin(); it != resources->end(); ++it) + { + if (it->size() < 6) + continue; + std::string start = it->substr(0, 6); + boost::to_lower(start); - if (start == "splash") - splash.push_back (*it); + if (start == "splash") + mResources->push_back (*it); + } } - if (splash.size()) + + if (mResources->size()) { - std::string randomSplash = splash[rand() % splash.size()]; + std::string randomSplash = mResources->at (rand() % mResources->size()); Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton ().load (randomSplash, "General"); mBackgroundImage->setImageTexture (randomSplash); diff --git a/apps/openmw/mwgui/loadingscreen.hpp b/apps/openmw/mwgui/loadingscreen.hpp index a012793ca..c14087a3b 100644 --- a/apps/openmw/mwgui/loadingscreen.hpp +++ b/apps/openmw/mwgui/loadingscreen.hpp @@ -42,6 +42,7 @@ namespace MWGui Ogre::Rectangle2D* mRectangle; Ogre::MaterialPtr mBackgroundMaterial; + Ogre::StringVectorPtr mResources; bool mLoadingOn; From 740e2b5769d85bec22b8478846bd3800d2552049 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Wed, 2 Jan 2013 23:02:13 +0100 Subject: [PATCH 110/136] components/to_utf8: add class Utf8Encoder --- components/to_utf8/to_utf8.cpp | 795 ++++++++++++++++++++++----------- components/to_utf8/to_utf8.hpp | 67 ++- 2 files changed, 589 insertions(+), 273 deletions(-) diff --git a/components/to_utf8/to_utf8.cpp b/components/to_utf8/to_utf8.cpp index 7db611247..8ac582b81 100644 --- a/components/to_utf8/to_utf8.cpp +++ b/components/to_utf8/to_utf8.cpp @@ -2,6 +2,8 @@ #include #include +#include +#include /* This file contains the code to translate from WINDOWS-1252 (native charset used in English version of Morrowind) to UTF-8. The library @@ -46,334 +48,611 @@ static std::vector buf (50*1024); static std::vector output (50*1024); static int size; -// Make sure the given vector is large enough for 'size' bytes, +using namespace ToUTF8; + +Utf8Encoder::Utf8Encoder(void): + mOutput(50*1024) +{ +} + +void Utf8Encoder::setEncoding(const FromType sourceEncoding) +{ + mEncoding = sourceEncoding; + + switch (mEncoding) + { + case ToUTF8::WINDOWS_1252: + { + translationArray = ToUTF8::windows_1252; + break; + } + case ToUTF8::WINDOWS_1250: + { + translationArray = ToUTF8::windows_1250; + break; + } + case ToUTF8::WINDOWS_1251: + { + translationArray = ToUTF8::windows_1251; + break; + } + default: + { + assert(0); + } + } +} + +std::string Utf8Encoder::getUtf8(const char* input, int size) +{ + // Double check that the input string stops at some point (it might + // contain zero terminators before this, inside its own data, which + // is also ok.) + assert(input[size] == 0); + + // TODO: The rest of this function is designed for single-character + // input encodings only. It also assumes that the input the input + // encoding shares its first 128 values (0-127) with ASCII. These + // conditions must be checked again if you add more input encodings + // later. + + // Compute output length, and check for pure ascii input at the same + // time. + bool ascii; + size_t outlen = getLength(input, ascii); + + // If we're pure ascii, then don't bother converting anything. + if(ascii) + return std::string(input, outlen); + + // Make sure the output is large enough + resize(outlen); + char *out = &mOutput[0]; + + // Translate + while (*input) + copyFromArray(*(input++), out); + + // Make sure that we wrote the correct number of bytes + assert((out-&mOutput[0]) == (int)outlen); + + // And make extra sure the output is null terminated + assert(mOutput.size() > outlen); + assert(mOutput[outlen] == 0); + + // Return a string + return std::string(&mOutput[0], outlen); +} + +std::string Utf8Encoder::getLegacyEnc(const char *input, int size) +{ + // Double check that the input string stops at some point (it might + // contain zero terminators before this, inside its own data, which + // is also ok.) + assert(input[size] == 0); + + // TODO: The rest of this function is designed for single-character + // input encodings only. It also assumes that the input the input + // encoding shares its first 128 values (0-127) with ASCII. These + // conditions must be checked again if you add more input encodings + // later. + + // Compute output length, and check for pure ascii input at the same + // time. + bool ascii; + size_t outlen = getLength2(input, ascii); + + // If we're pure ascii, then don't bother converting anything. + if(ascii) + return std::string(input, outlen); + + // Make sure the output is large enough + resize(outlen); + char *out = &mOutput[0]; + + // Translate + while(*input) + copyFromArray2(input, out); + + // Make sure that we wrote the correct number of bytes + assert((out-&mOutput[0]) == (int)outlen); + + // And make extra sure the output is null terminated + assert(mOutput.size() > outlen); + assert(mOutput[outlen] == 0); + + // Return a string + return std::string(&mOutput[0], outlen); +} + +// Make sure the output vector is large enough for 'size' bytes, // including a terminating zero after it. +void Utf8Encoder::resize(size_t size) +{ + if (mOutput.size() <= size) + // Add some extra padding to reduce the chance of having to resize + // again later. + mOutput.resize(3*size); + + // And make sure the string is zero terminated + mOutput[size] = 0; +} + +/** Get the total length length needed to decode the given string with + the given translation array. The arrays are encoded with 6 bytes + per character, with the first giving the length and the next 5 the + actual data. + + The function serves a dual purpose for optimization reasons: it + checks if the input is pure ascii (all values are <= 127). If this + is the case, then the ascii parameter is set to true, and the + caller can optimize for this case. + */ +size_t Utf8Encoder::getLength(const char* input, bool &ascii) +{ + ascii = true; + size_t len = 0; + const char* ptr = input; + unsigned char inp = *ptr; + + // Do away with the ascii part of the string first (this is almost + // always the entire string.) + while (inp && inp < 128) + inp = *(++ptr); + len += (ptr-input); + + // If we're not at the null terminator at this point, then there + // were some non-ascii characters to deal with. Go to slow-mode for + // the rest of the string. + if (inp) + { + ascii = false; + while (inp) + { + // Find the translated length of this character in the + // lookup table. + len += translationArray[inp*6]; + inp = *(++ptr); + } + } + return len; +} + +// Translate one character 'ch' using the translation array 'arr', and +// advance the output pointer accordingly. +void Utf8Encoder::copyFromArray(unsigned char ch, char* &out) +{ + // Optimize for ASCII values + if (ch < 128) + { + *(out++) = ch; + return; + } + + const char *in = translationArray + ch*6; + int len = *(in++); + for (int i=0; i &buf, size_t size) { - if(buf.size() <= size) - // Add some extra padding to reduce the chance of having to resize - // again later. - buf.resize(3*size); + if(buf.size() <= size) + // Add some extra padding to reduce the chance of having to resize + // again later. + buf.resize(3*size); - // And make sure the string is zero terminated - buf[size] = 0; + // And make sure the string is zero terminated + buf[size] = 0; } // This is just used to spew out a reusable input buffer for the // conversion process. char *ToUTF8::getBuffer(int s) { - // Remember the requested size - size = s; - resize(buf, size); - return &buf[0]; + // Remember the requested size + size = s; + resize(buf, size); + return &buf[0]; } /** Get the total length length needed to decode the given string with - the given translation array. The arrays are encoded with 6 bytes - per character, with the first giving the length and the next 5 the - actual data. - - The function serves a dual purpose for optimization reasons: it - checks if the input is pure ascii (all values are <= 127). If this - is the case, then the ascii parameter is set to true, and the - caller can optimize for this case. + the given translation array. The arrays are encoded with 6 bytes + per character, with the first giving the length and the next 5 the + actual data. + + The function serves a dual purpose for optimization reasons: it + checks if the input is pure ascii (all values are <= 127). If this + is the case, then the ascii parameter is set to true, and the + caller can optimize for this case. */ static size_t getLength(const char *arr, const char* input, bool &ascii) { - ascii = true; - size_t len = 0; - const char* ptr = input; - unsigned char inp = *ptr; - - // Do away with the ascii part of the string first (this is almost - // always the entire string.) - while(inp && inp < 128) - inp = *(++ptr); - len += (ptr-input); - - // If we're not at the null terminator at this point, then there - // were some non-ascii characters to deal with. Go to slow-mode for - // the rest of the string. - if(inp) + ascii = true; + size_t len = 0; + const char* ptr = input; + unsigned char inp = *ptr; + + // Do away with the ascii part of the string first (this is almost + // always the entire string.) + while(inp && inp < 128) + inp = *(++ptr); + len += (ptr-input); + + // If we're not at the null terminator at this point, then there + // were some non-ascii characters to deal with. Go to slow-mode for + // the rest of the string. + if(inp) { - ascii = false; - while(inp) + ascii = false; + while(inp) { - // Find the translated length of this character in the - // lookup table. - len += arr[inp*6]; - inp = *(++ptr); + // Find the translated length of this character in the + // lookup table. + len += arr[inp*6]; + inp = *(++ptr); } } - return len; + return len; } // Translate one character 'ch' using the translation array 'arr', and // advance the output pointer accordingly. static void copyFromArray(const char *arr, unsigned char ch, char* &out) { - // Optimize for ASCII values - if(ch < 128) + // Optimize for ASCII values + if(ch < 128) { - *(out++) = ch; - return; + *(out++) = ch; + return; } - const char *in = arr + ch*6; - int len = *(in++); - for(int i=0; i outlen); - assert(output[outlen] == 0); - - // Return a string - return std::string(&output[0], outlen); + + // Double check that the input string stops at some point (it might + // contain zero terminators before this, inside its own data, which + // is also ok.) + const char* input = &buf[0]; + assert(input[size] == 0); + + // TODO: The rest of this function is designed for single-character + // input encodings only. It also assumes that the input the input + // encoding shares its first 128 values (0-127) with ASCII. These + // conditions must be checked again if you add more input encodings + // later. + + // Compute output length, and check for pure ascii input at the same + // time. + bool ascii; + size_t outlen = getLength(arr, input, ascii); + + // If we're pure ascii, then don't bother converting anything. + if(ascii) + return std::string(input, outlen); + + // Make sure the output is large enough + resize(output, outlen); + char *out = &output[0]; + + // Translate + while(*input) + copyFromArray(arr, *(input++), out); + + // Make sure that we wrote the correct number of bytes + assert((out-&output[0]) == (int)outlen); + + // And make extra sure the output is null terminated + assert(output.size() > outlen); + assert(output[outlen] == 0); + + // Return a string + return std::string(&output[0], outlen); } static size_t getLength2(const char *arr, const char* input, bool &ascii) { - ascii = true; - size_t len = 0; - const char* ptr = input; - unsigned char inp = *ptr; - - // Do away with the ascii part of the string first (this is almost - // always the entire string.) - while(inp && inp < 128) - inp = *(++ptr); - len += (ptr-input); - - // If we're not at the null terminator at this point, then there - // were some non-ascii characters to deal with. Go to slow-mode for - // the rest of the string. - if(inp) + ascii = true; + size_t len = 0; + const char* ptr = input; + unsigned char inp = *ptr; + + // Do away with the ascii part of the string first (this is almost + // always the entire string.) + while(inp && inp < 128) + inp = *(++ptr); + len += (ptr-input); + + // If we're not at the null terminator at this point, then there + // were some non-ascii characters to deal with. Go to slow-mode for + // the rest of the string. + if(inp) { - ascii = false; - while(inp) + ascii = false; + while(inp) { len += 1; - // Find the translated length of this character in the - // lookup table. + // Find the translated length of this character in the + // lookup table. switch(inp) { - case 0xe2: len -= 2; break; - case 0xc2: - case 0xcb: - case 0xc4: - case 0xc6: - case 0xc3: - case 0xd0: - case 0xd1: - case 0xd2: - case 0xc5: len -= 1; break; + case 0xe2: len -= 2; break; + case 0xc2: + case 0xcb: + case 0xc4: + case 0xc6: + case 0xc3: + case 0xd0: + case 0xd1: + case 0xd2: + case 0xc5: len -= 1; break; } - inp = *(++ptr); + inp = *(++ptr); } } - return len; + return len; } -#include -#include - static void copyFromArray2(const char *arr, char*& chp, char* &out) { unsigned char ch = *(chp++); - // Optimize for ASCII values - if(ch < 128) + // Optimize for ASCII values + if(ch < 128) { - *(out++) = ch; - return; + *(out++) = ch; + return; } - int len = 1; - switch (ch) - { - case 0xe2: len = 3; break; - case 0xc2: - case 0xcb: - case 0xc4: - case 0xc6: - case 0xc3: - case 0xd0: - case 0xd1: - case 0xd2: - case 0xc5: len = 2; break; - } - - if (len == 1) // There is no 1 length utf-8 glyph that is not 0x20 (empty space) - { - *(out++) = ch; - return; - } - - unsigned char ch2 = *(chp++); - unsigned char ch3 = '\0'; - if (len == 3) - ch3 = *(chp++); - - for (int i = 128; i < 256; i++) - { - unsigned char b1 = arr[i*6 + 1], b2 = arr[i*6 + 2], b3 = arr[i*6 + 3]; - if (b1 == ch && b2 == ch2 && (len != 3 || b3 == ch3)) - { - *(out++) = (char)i; - return; - } - } - - std::cout << "Could not find glyph " << std::hex << (int)ch << " " << (int)ch2 << " " << (int)ch3 << std::endl; - - *(out++) = ch; // Could not find glyph, just put whatever -} - -std::string ToUTF8::getLegacyEnc(ToUTF8::FromType to) -{ - // Pick translation array - const char *arr; - switch (to) - { - case ToUTF8::WINDOWS_1252: + int len = 1; + switch (ch) { - arr = ToUTF8::windows_1252; - break; + case 0xe2: len = 3; break; + case 0xc2: + case 0xcb: + case 0xc4: + case 0xc6: + case 0xc3: + case 0xd0: + case 0xd1: + case 0xd2: + case 0xc5: len = 2; break; } - case ToUTF8::WINDOWS_1250: + + if (len == 1) // There is no 1 length utf-8 glyph that is not 0x20 (empty space) { - arr = ToUTF8::windows_1250; - break; + *(out++) = ch; + return; } - case ToUTF8::WINDOWS_1251: + + unsigned char ch2 = *(chp++); + unsigned char ch3 = '\0'; + if (len == 3) + ch3 = *(chp++); + + for (int i = 128; i < 256; i++) { - arr = ToUTF8::windows_1251; - break; + unsigned char b1 = arr[i*6 + 1], b2 = arr[i*6 + 2], b3 = arr[i*6 + 3]; + if (b1 == ch && b2 == ch2 && (len != 3 || b3 == ch3)) + { + *(out++) = (char)i; + return; + } } - default: + + std::cout << "Could not find glyph " << std::hex << (int)ch << " " << (int)ch2 << " " << (int)ch3 << std::endl; + + *(out++) = ch; // Could not find glyph, just put whatever +} + +std::string ToUTF8::getLegacyEnc(ToUTF8::FromType to) +{ + // Pick translation array + const char *arr; + switch (to) { - assert(0); + case ToUTF8::WINDOWS_1252: + { + arr = ToUTF8::windows_1252; + break; + } + case ToUTF8::WINDOWS_1250: + { + arr = ToUTF8::windows_1250; + break; + } + case ToUTF8::WINDOWS_1251: + { + arr = ToUTF8::windows_1251; + break; + } + default: + { + assert(0); + } } - } - - // Double check that the input string stops at some point (it might - // contain zero terminators before this, inside its own data, which - // is also ok.) - char* input = &buf[0]; - assert(input[size] == 0); - - // TODO: The rest of this function is designed for single-character - // input encodings only. It also assumes that the input the input - // encoding shares its first 128 values (0-127) with ASCII. These - // conditions must be checked again if you add more input encodings - // later. - - // Compute output length, and check for pure ascii input at the same - // time. - bool ascii; - size_t outlen = getLength2(arr, input, ascii); - - // If we're pure ascii, then don't bother converting anything. - if(ascii) - return std::string(input, outlen); - - // Make sure the output is large enough - resize(output, outlen); - char *out = &output[0]; - - // Translate - while(*input) - copyFromArray2(arr, input, out); - - // Make sure that we wrote the correct number of bytes - assert((out-&output[0]) == (int)outlen); - - // And make extra sure the output is null terminated - assert(output.size() > outlen); - assert(output[outlen] == 0); - - // Return a string - return std::string(&output[0], outlen); + + // Double check that the input string stops at some point (it might + // contain zero terminators before this, inside its own data, which + // is also ok.) + char* input = &buf[0]; + assert(input[size] == 0); + + // TODO: The rest of this function is designed for single-character + // input encodings only. It also assumes that the input the input + // encoding shares its first 128 values (0-127) with ASCII. These + // conditions must be checked again if you add more input encodings + // later. + + // Compute output length, and check for pure ascii input at the same + // time. + bool ascii; + size_t outlen = getLength2(arr, input, ascii); + + // If we're pure ascii, then don't bother converting anything. + if(ascii) + return std::string(input, outlen); + + // Make sure the output is large enough + resize(output, outlen); + char *out = &output[0]; + + // Translate + while(*input) + copyFromArray2(arr, input, out); + + // Make sure that we wrote the correct number of bytes + assert((out-&output[0]) == (int)outlen); + + // And make extra sure the output is null terminated + assert(output.size() > outlen); + assert(output[outlen] == 0); + + // Return a string + return std::string(&output[0], outlen); } ToUTF8::FromType ToUTF8::calculateEncoding(const std::string& encodingName) { - if (encodingName == "win1250") - return ToUTF8::WINDOWS_1250; - else if (encodingName == "win1251") - return ToUTF8::WINDOWS_1251; - else - return ToUTF8::WINDOWS_1252; + if (encodingName == "win1250") + return ToUTF8::WINDOWS_1250; + else if (encodingName == "win1251") + return ToUTF8::WINDOWS_1251; + else + return ToUTF8::WINDOWS_1252; } std::string ToUTF8::encodingUsingMessage(const std::string& encodingName) { - if (encodingName == "win1250") - return "Using Central and Eastern European font encoding."; - else if (encodingName == "win1251") - return "Using Cyrillic font encoding."; - else - return "Using default (English) font encoding."; + if (encodingName == "win1250") + return "Using Central and Eastern European font encoding."; + else if (encodingName == "win1251") + return "Using Cyrillic font encoding."; + else + return "Using default (English) font encoding."; } diff --git a/components/to_utf8/to_utf8.hpp b/components/to_utf8/to_utf8.hpp index f52ae73bd..6877e2dc1 100644 --- a/components/to_utf8/to_utf8.hpp +++ b/components/to_utf8/to_utf8.hpp @@ -2,29 +2,66 @@ #define COMPONENTS_TOUTF8_H #include +#include +#include namespace ToUTF8 { - // These are all the currently supported code pages - enum FromType + // These are all the currently supported code pages + enum FromType { - WINDOWS_1250, // Central ane Eastern European languages - WINDOWS_1251, // Cyrillic languages - WINDOWS_1252 // Used by English version of Morrowind (and - // probably others) + WINDOWS_1250, // Central ane Eastern European languages + WINDOWS_1251, // Cyrillic languages + WINDOWS_1252 // Used by English version of Morrowind (and + // probably others) }; - // Return a writable buffer of at least 'size' bytes. The buffer - // does not have to be freed. - char* getBuffer(int size); + // Return a writable buffer of at least 'size' bytes. The buffer + // does not have to be freed. + char* getBuffer(int size); - // Convert the previously written buffer to UTF8 from the given code - // page. - std::string getUtf8(FromType from); - std::string getLegacyEnc(FromType to); + // Convert the previously written buffer to UTF8 from the given code + // page. + std::string getUtf8(FromType from); + std::string getLegacyEnc(FromType to); - FromType calculateEncoding(const std::string& encodingName); - std::string encodingUsingMessage(const std::string& encodingName); + FromType calculateEncoding(const std::string& encodingName); + std::string encodingUsingMessage(const std::string& encodingName); + + // class + + class Utf8Encoder + { + public: + Utf8Encoder(void); + + void setEncoding(const FromType sourceEncoding); + + // Convert to UTF8 from the previously given code page. + std::string getUtf8(const char *input, int size); + inline std::string getUtf8(const std::string &str) + { + return getUtf8(str.c_str(), str.size()); + } + + std::string getLegacyEnc(const char *input, int size); + inline std::string getLegacyEnc(const std::string &str) + { + return getLegacyEnc(str.c_str(), str.size()); + } + + private: + void resize(size_t size); + size_t getLength(const char* input, bool &ascii); + void copyFromArray(unsigned char chp, char* &out); + size_t getLength2(const char* input, bool &ascii); + void copyFromArray2(const char*& chp, char* &out); + + FromType mEncoding; + std::vector mOutput; + int mSize; + char* translationArray; + }; } #endif From 67273fc1777b45d9860fe114689cbdc9836c1f48 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Wed, 2 Jan 2013 23:39:21 +0100 Subject: [PATCH 111/136] mwiniimporter: use Utf8Encoder --- apps/mwiniimporter/importer.cpp | 12 +++--------- apps/mwiniimporter/importer.hpp | 2 +- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index def70615b..5c3dedd04 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -649,11 +649,13 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(std::string filename) { std::string section(""); MwIniImporter::multistrmap map; boost::iostreams::streamfile(filename.c_str()); + ToUTF8::Utf8Encoder encoder; + encoder.setEncoding(mEncoding); std::string line; while (std::getline(file, line)) { - line = toUTF8(line); + line = encoder.getUtf8(line); // unify Unix-style and Windows file ending if (!(line.empty()) && (line[line.length()-1]) == '\r') { @@ -829,14 +831,6 @@ void MwIniImporter::writeToFile(boost::iostreams::stream #include -#include "../../components/to_utf8/to_utf8.hpp" +#include class MwIniImporter { public: From 9906c3051dddaaf435d55841f5e9d0d392d575c5 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Thu, 3 Jan 2013 15:01:08 +0100 Subject: [PATCH 112/136] components/translation: use Utf8Encoder --- components/translation/translation.cpp | 6 ++---- components/translation/translation.hpp | 1 + 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/components/translation/translation.cpp b/components/translation/translation.cpp index fb5b03861..002446e4f 100644 --- a/components/translation/translation.cpp +++ b/components/translation/translation.cpp @@ -50,10 +50,7 @@ namespace Translation if (!line.empty()) { - char* buffer = ToUTF8::getBuffer(line.size() + 1); - //buffer has at least line.size() + 1 bytes, so it must be safe - strcpy(buffer, line.c_str()); - line = ToUTF8::getUtf8(mEncoding); + line = mEncoder.getUtf8(line); size_t tab_pos = line.find('\t'); if (tab_pos != std::string::npos && tab_pos > 0 && tab_pos < line.size() - 1) @@ -107,6 +104,7 @@ namespace Translation void Storage::setEncoding (const ToUTF8::FromType& encoding) { mEncoding = encoding; + mEncoder.setEncoding(encoding); } bool Storage::hasTranslation() const diff --git a/components/translation/translation.hpp b/components/translation/translation.hpp index 80d44d871..6c3e4df86 100644 --- a/components/translation/translation.hpp +++ b/components/translation/translation.hpp @@ -35,6 +35,7 @@ namespace Translation ToUTF8::FromType mEncoding; + ToUTF8::Utf8Encoder mEncoder; ContainerType mCellNamesTranslations, mTopicIDs, mPhraseForms; }; } From 02bf02f288c407ad639ad15c8bc3a72ae56597b4 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Thu, 3 Jan 2013 21:15:18 +0100 Subject: [PATCH 113/136] ESMReader, ESMWriter: use Utf8Encoder --- components/esm/esmreader.cpp | 22 +++++++++++++++++++--- components/esm/esmreader.hpp | 6 ++++++ components/esm/esmwriter.cpp | 8 +++----- components/esm/esmwriter.hpp | 1 + 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/components/esm/esmreader.cpp b/components/esm/esmreader.cpp index 580e006df..5cd99a64a 100644 --- a/components/esm/esmreader.cpp +++ b/components/esm/esmreader.cpp @@ -13,6 +13,11 @@ ESM_Context ESMReader::getContext() return mCtx; } +ESMReader::ESMReader(void): + mBuffer(50*1024) +{ +} + void ESMReader::restoreContext(const ESM_Context &rc) { // Reopen the file if necessary @@ -325,11 +330,21 @@ void ESMReader::getExact(void*x, int size) std::string ESMReader::getString(int size) { - char *ptr = ToUTF8::getBuffer(size); - mEsm->read(ptr, size); + size_t s = size; + if (mBuffer.size() <= s) + // Add some extra padding to reduce the chance of having to resize + // again later. + mBuffer.resize(3*s); + + // And make sure the string is zero terminated + mBuffer[s] = 0; + + // read ESM data + char *ptr = &mBuffer[0]; + getExact(ptr, size); // Convert to UTF8 and return - return ToUTF8::getUtf8(mEncoding); + return mEncoder.getUtf8(ptr, size); } void ESMReader::fail(const std::string &msg) @@ -350,6 +365,7 @@ void ESMReader::fail(const std::string &msg) void ESMReader::setEncoding(const ToUTF8::FromType& encoding) { mEncoding = encoding; + mEncoder.setEncoding(encoding); } } diff --git a/components/esm/esmreader.hpp b/components/esm/esmreader.hpp index 1d0f6f580..57503aea7 100644 --- a/components/esm/esmreader.hpp +++ b/components/esm/esmreader.hpp @@ -20,6 +20,8 @@ class ESMReader { public: + ESMReader(void); + /************************************************************************* * * Public type definitions @@ -244,9 +246,13 @@ private: // Special file signifier (see SpecialFile enum above) int mSpf; + // Buffer for ESM strings + std::vector mBuffer; + SaveData mSaveData; MasterList mMasters; ToUTF8::FromType mEncoding; + ToUTF8::Utf8Encoder mEncoder; }; } #endif diff --git a/components/esm/esmwriter.cpp b/components/esm/esmwriter.cpp index c1ae06490..a00c7971d 100644 --- a/components/esm/esmwriter.cpp +++ b/components/esm/esmwriter.cpp @@ -157,12 +157,8 @@ void ESMWriter::writeHString(const std::string& data) write("\0", 1); else { - char *ptr = ToUTF8::getBuffer(data.size()+1); - strncpy(ptr, &data[0], data.size()); - ptr[data.size()] = '\0'; - // Convert to UTF8 and return - std::string ascii = ToUTF8::getLegacyEnc(m_encoding); + std::string ascii = m_encoder.getLegacyEnc(data); write(ascii.c_str(), ascii.size()); } @@ -207,6 +203,8 @@ void ESMWriter::setEncoding(const std::string& encoding) // Default Latin encoding m_encoding = ToUTF8::WINDOWS_1252; } + + m_encoder.setEncoding(m_encoding); } } diff --git a/components/esm/esmwriter.hpp b/components/esm/esmwriter.hpp index d3777be81..20bc5da12 100644 --- a/components/esm/esmwriter.hpp +++ b/components/esm/esmwriter.hpp @@ -95,6 +95,7 @@ private: std::ostream* m_stream; std::streampos m_headerPos; ToUTF8::FromType m_encoding; + ToUTF8::Utf8Encoder m_encoder; int m_recordCount; HEDRstruct m_header; From 0bdf52a0719a756f3be97a988ff33784d02f7fcc Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Thu, 3 Jan 2013 23:21:14 +0100 Subject: [PATCH 114/136] components/to_utf8: keep only Utf8Encoder --- components/to_utf8/to_utf8.cpp | 314 --------------------------------- components/to_utf8/to_utf8.hpp | 9 - 2 files changed, 323 deletions(-) diff --git a/components/to_utf8/to_utf8.cpp b/components/to_utf8/to_utf8.cpp index 8ac582b81..5efec36a4 100644 --- a/components/to_utf8/to_utf8.cpp +++ b/components/to_utf8/to_utf8.cpp @@ -41,13 +41,6 @@ // Generated tables #include "tables_gen.hpp" -// Shared global buffers, we love you. These initial sizes are large -// enough to hold the largest books in Morrowind.esm, but we will -// resize automaticall if necessary. -static std::vector buf (50*1024); -static std::vector output (50*1024); -static int size; - using namespace ToUTF8; Utf8Encoder::Utf8Encoder(void): @@ -330,313 +323,6 @@ void Utf8Encoder::copyFromArray2(const char*& chp, char* &out) *(out++) = ch; // Could not find glyph, just put whatever } -static void resize(std::vector &buf, size_t size) -{ - if(buf.size() <= size) - // Add some extra padding to reduce the chance of having to resize - // again later. - buf.resize(3*size); - - // And make sure the string is zero terminated - buf[size] = 0; -} - -// This is just used to spew out a reusable input buffer for the -// conversion process. -char *ToUTF8::getBuffer(int s) -{ - // Remember the requested size - size = s; - resize(buf, size); - return &buf[0]; -} - -/** Get the total length length needed to decode the given string with - the given translation array. The arrays are encoded with 6 bytes - per character, with the first giving the length and the next 5 the - actual data. - - The function serves a dual purpose for optimization reasons: it - checks if the input is pure ascii (all values are <= 127). If this - is the case, then the ascii parameter is set to true, and the - caller can optimize for this case. - */ -static size_t getLength(const char *arr, const char* input, bool &ascii) -{ - ascii = true; - size_t len = 0; - const char* ptr = input; - unsigned char inp = *ptr; - - // Do away with the ascii part of the string first (this is almost - // always the entire string.) - while(inp && inp < 128) - inp = *(++ptr); - len += (ptr-input); - - // If we're not at the null terminator at this point, then there - // were some non-ascii characters to deal with. Go to slow-mode for - // the rest of the string. - if(inp) - { - ascii = false; - while(inp) - { - // Find the translated length of this character in the - // lookup table. - len += arr[inp*6]; - inp = *(++ptr); - } - } - return len; -} - -// Translate one character 'ch' using the translation array 'arr', and -// advance the output pointer accordingly. -static void copyFromArray(const char *arr, unsigned char ch, char* &out) -{ - // Optimize for ASCII values - if(ch < 128) - { - *(out++) = ch; - return; - } - - const char *in = arr + ch*6; - int len = *(in++); - for(int i=0; i outlen); - assert(output[outlen] == 0); - - // Return a string - return std::string(&output[0], outlen); -} - -static size_t getLength2(const char *arr, const char* input, bool &ascii) -{ - ascii = true; - size_t len = 0; - const char* ptr = input; - unsigned char inp = *ptr; - - // Do away with the ascii part of the string first (this is almost - // always the entire string.) - while(inp && inp < 128) - inp = *(++ptr); - len += (ptr-input); - - // If we're not at the null terminator at this point, then there - // were some non-ascii characters to deal with. Go to slow-mode for - // the rest of the string. - if(inp) - { - ascii = false; - while(inp) - { - len += 1; - // Find the translated length of this character in the - // lookup table. - switch(inp) - { - case 0xe2: len -= 2; break; - case 0xc2: - case 0xcb: - case 0xc4: - case 0xc6: - case 0xc3: - case 0xd0: - case 0xd1: - case 0xd2: - case 0xc5: len -= 1; break; - } - - inp = *(++ptr); - } - } - return len; -} - -static void copyFromArray2(const char *arr, char*& chp, char* &out) -{ - unsigned char ch = *(chp++); - // Optimize for ASCII values - if(ch < 128) - { - *(out++) = ch; - return; - } - - int len = 1; - switch (ch) - { - case 0xe2: len = 3; break; - case 0xc2: - case 0xcb: - case 0xc4: - case 0xc6: - case 0xc3: - case 0xd0: - case 0xd1: - case 0xd2: - case 0xc5: len = 2; break; - } - - if (len == 1) // There is no 1 length utf-8 glyph that is not 0x20 (empty space) - { - *(out++) = ch; - return; - } - - unsigned char ch2 = *(chp++); - unsigned char ch3 = '\0'; - if (len == 3) - ch3 = *(chp++); - - for (int i = 128; i < 256; i++) - { - unsigned char b1 = arr[i*6 + 1], b2 = arr[i*6 + 2], b3 = arr[i*6 + 3]; - if (b1 == ch && b2 == ch2 && (len != 3 || b3 == ch3)) - { - *(out++) = (char)i; - return; - } - } - - std::cout << "Could not find glyph " << std::hex << (int)ch << " " << (int)ch2 << " " << (int)ch3 << std::endl; - - *(out++) = ch; // Could not find glyph, just put whatever -} - -std::string ToUTF8::getLegacyEnc(ToUTF8::FromType to) -{ - // Pick translation array - const char *arr; - switch (to) - { - case ToUTF8::WINDOWS_1252: - { - arr = ToUTF8::windows_1252; - break; - } - case ToUTF8::WINDOWS_1250: - { - arr = ToUTF8::windows_1250; - break; - } - case ToUTF8::WINDOWS_1251: - { - arr = ToUTF8::windows_1251; - break; - } - default: - { - assert(0); - } - } - - // Double check that the input string stops at some point (it might - // contain zero terminators before this, inside its own data, which - // is also ok.) - char* input = &buf[0]; - assert(input[size] == 0); - - // TODO: The rest of this function is designed for single-character - // input encodings only. It also assumes that the input the input - // encoding shares its first 128 values (0-127) with ASCII. These - // conditions must be checked again if you add more input encodings - // later. - - // Compute output length, and check for pure ascii input at the same - // time. - bool ascii; - size_t outlen = getLength2(arr, input, ascii); - - // If we're pure ascii, then don't bother converting anything. - if(ascii) - return std::string(input, outlen); - - // Make sure the output is large enough - resize(output, outlen); - char *out = &output[0]; - - // Translate - while(*input) - copyFromArray2(arr, input, out); - - // Make sure that we wrote the correct number of bytes - assert((out-&output[0]) == (int)outlen); - - // And make extra sure the output is null terminated - assert(output.size() > outlen); - assert(output[outlen] == 0); - - // Return a string - return std::string(&output[0], outlen); -} - ToUTF8::FromType ToUTF8::calculateEncoding(const std::string& encodingName) { if (encodingName == "win1250") diff --git a/components/to_utf8/to_utf8.hpp b/components/to_utf8/to_utf8.hpp index 6877e2dc1..bfba8a1ac 100644 --- a/components/to_utf8/to_utf8.hpp +++ b/components/to_utf8/to_utf8.hpp @@ -16,15 +16,6 @@ namespace ToUTF8 // probably others) }; - // Return a writable buffer of at least 'size' bytes. The buffer - // does not have to be freed. - char* getBuffer(int size); - - // Convert the previously written buffer to UTF8 from the given code - // page. - std::string getUtf8(FromType from); - std::string getLegacyEnc(FromType to); - FromType calculateEncoding(const std::string& encodingName); std::string encodingUsingMessage(const std::string& encodingName); From 019893b5c677c1fd605e106cb22295805f2e019a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 3 Jan 2013 23:44:58 -0800 Subject: [PATCH 115/136] Get rid of some unnecessary case-insensitive compares --- components/nifogre/ogre_nif_loader.cpp | 21 ++++++++------------- components/nifogre/ogre_nif_loader.hpp | 17 ----------------- 2 files changed, 8 insertions(+), 30 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index ad51d50b9..b3ceb089e 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -43,6 +43,7 @@ #include +#include #include #include @@ -219,7 +220,7 @@ struct KeyTimeSort }; -typedef std::map LoaderMap; +typedef std::map LoaderMap; static LoaderMap sLoaders; public: @@ -918,7 +919,7 @@ class NIFMeshLoader : Ogre::ManualResourceLoader } - typedef std::map LoaderMap; + typedef std::map LoaderMap; static LoaderMap sLoaders; public: @@ -1101,13 +1102,6 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, TextKeyMap *textke return entitylist; } -struct checklow { - bool operator()(const char &a, const char &b) const - { - return ::tolower(a) == ::tolower(b); - } -}; - EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bonename, Ogre::SceneNode *parentNode, const std::string &name, @@ -1120,18 +1114,19 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo return entitylist; Ogre::SceneManager *sceneMgr = parentNode->getCreator(); - std::string filter = "Tri "+bonename; + std::string filter = "tri "+bonename; + std::transform(filter.begin()+4, filter.end(), filter.begin()+4, ::tolower); for(size_t i = 0;i < meshes.size();i++) { Ogre::Entity *ent = sceneMgr->createEntity(meshes[i].first->getName()); if(ent->hasSkeleton()) { + std::transform(meshes[i].second.begin(), meshes[i].second.end(), meshes[i].second.begin(), ::tolower); + if(meshes[i].second.length() < filter.length() || - std::mismatch(filter.begin(), filter.end(), meshes[i].second.begin(), checklow()).first != filter.end()) + meshes[i].second.compare(0, filter.length(), filter) != 0) { sceneMgr->destroyEntity(ent); - meshes.erase(meshes.begin()+i); - i--; continue; } if(!entitylist.mSkelBase) diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index a203112b5..08a233245 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -30,23 +30,6 @@ #include #include -#include -#include - -#include "../nif/node.hpp" - -#include - -class BoundsFinder; - -struct ciLessBoost : std::binary_function -{ - bool operator() (const std::string & s1, const std::string & s2) const - { - //case insensitive version of is_less - return boost::algorithm::lexicographical_compare(s1, s2, boost::algorithm::is_iless()); - } -}; namespace Nif { From 61ad8bb3ddcc1ec2a599a34a9a63d6707faaaae8 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 4 Jan 2013 00:14:41 -0800 Subject: [PATCH 116/136] Use a list of mesh names instead of mesh objects --- components/nifogre/ogre_nif_loader.cpp | 6 +++--- components/nifogre/ogre_nif_loader.hpp | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index b3ceb089e..9e17736ef 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -1005,7 +1005,7 @@ public: mesh->setAutoBuildEdgeLists(false); } - meshes.push_back(std::make_pair(mesh, shape->name)); + meshes.push_back(std::make_pair(mesh->getName(), shape->name)); } else if(node->recType != Nif::RC_NiNode && node->recType != Nif::RC_RootCollisionNode && node->recType != Nif::RC_NiRotatingParticles) @@ -1072,7 +1072,7 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, TextKeyMap *textke Ogre::SceneManager *sceneMgr = parent->getCreator(); for(size_t i = 0;i < meshes.size();i++) { - entitylist.mEntities.push_back(sceneMgr->createEntity(meshes[i].first->getName())); + entitylist.mEntities.push_back(sceneMgr->createEntity(meshes[i].first)); Ogre::Entity *entity = entitylist.mEntities.back(); if(!entitylist.mSkelBase && entity->hasSkeleton()) entitylist.mSkelBase = entity; @@ -1118,7 +1118,7 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo std::transform(filter.begin()+4, filter.end(), filter.begin()+4, ::tolower); for(size_t i = 0;i < meshes.size();i++) { - Ogre::Entity *ent = sceneMgr->createEntity(meshes[i].first->getName()); + Ogre::Entity *ent = sceneMgr->createEntity(meshes[i].first); if(ent->hasSkeleton()) { std::transform(meshes[i].second.begin(), meshes[i].second.end(), meshes[i].second.begin(), ::tolower); diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index 08a233245..74b6f44df 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -52,9 +52,8 @@ struct EntityList { }; -/** This holds a list of meshes along with the names of their parent nodes - */ -typedef std::vector< std::pair > MeshPairList; +/** This holds a list of mesh names along with the names of their parent nodes */ +typedef std::vector< std::pair > MeshPairList; /** Manual resource loader for NIF meshes. This is the main class responsible for translating the internal NIF mesh structure into From c947d87ab9e9510e322d8cb030f42b64f6f07dc4 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Fri, 4 Jan 2013 15:10:30 +0100 Subject: [PATCH 117/136] Add a test for to_utf8 component --- components/to_utf8/tests/.gitignore | 1 + .../to_utf8/tests/output/to_utf8_test.out | 4 ++ components/to_utf8/tests/test.sh | 18 ++++++ components/to_utf8/tests/to_utf8_test.cpp | 61 +++++++++++++++++++ 4 files changed, 84 insertions(+) create mode 100644 components/to_utf8/tests/.gitignore create mode 100644 components/to_utf8/tests/output/to_utf8_test.out create mode 100755 components/to_utf8/tests/test.sh create mode 100644 components/to_utf8/tests/to_utf8_test.cpp diff --git a/components/to_utf8/tests/.gitignore b/components/to_utf8/tests/.gitignore new file mode 100644 index 000000000..814490404 --- /dev/null +++ b/components/to_utf8/tests/.gitignore @@ -0,0 +1 @@ +*_test diff --git a/components/to_utf8/tests/output/to_utf8_test.out b/components/to_utf8/tests/output/to_utf8_test.out new file mode 100644 index 000000000..dcb32359a --- /dev/null +++ b/components/to_utf8/tests/output/to_utf8_test.out @@ -0,0 +1,4 @@ +original: Без вопроÑов отдаете ему рулет, знаÑ, что позже вы Ñможете привеÑти Ñ Ñобой Ñвоих друзей и тогда он получит по заÑлугам? +converted: Без вопроÑов отдаете ему рулет, знаÑ, что позже вы Ñможете привеÑти Ñ Ñобой Ñвоих друзей и тогда он получит по заÑлугам? +original: Vous lui donnez le gâteau sans protester avant d’aller chercher tous vos amis et de revenir vous venger. +converted: Vous lui donnez le gâteau sans protester avant d’aller chercher tous vos amis et de revenir vous venger. diff --git a/components/to_utf8/tests/test.sh b/components/to_utf8/tests/test.sh new file mode 100755 index 000000000..2d07708ad --- /dev/null +++ b/components/to_utf8/tests/test.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +make || exit + +mkdir -p output + +PROGS=*_test + +for a in $PROGS; do + if [ -f "output/$a.out" ]; then + echo "Running $a:" + ./$a | diff output/$a.out - + else + echo "Creating $a.out" + ./$a > "output/$a.out" + git add "output/$a.out" + fi +done diff --git a/components/to_utf8/tests/to_utf8_test.cpp b/components/to_utf8/tests/to_utf8_test.cpp new file mode 100644 index 000000000..8c25c483e --- /dev/null +++ b/components/to_utf8/tests/to_utf8_test.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include + +#include "../to_utf8.hpp" + +std::string getFirstLine(const std::string &filename); +void testEncoder(ToUTF8::FromType encoding, const std::string &legacyEncFile, + const std::string &utf8File); + +/// Test character encoding conversion to and from UTF-8 +void testEncoder(ToUTF8::FromType encoding, const std::string &legacyEncFile, + const std::string &utf8File) +{ + // get some test data + std::string legacyEncLine = getFirstLine(legacyEncFile); + std::string utf8Line = getFirstLine(utf8File); + + // create an encoder for specified character encoding + ToUTF8::Utf8Encoder encoder; + encoder.setEncoding(encoding); + + // convert text to UTF-8 + std::string convertedUtf8Line = encoder.getUtf8(legacyEncLine); + + std::cout << "original: " << utf8Line << std::endl; + std::cout << "converted: " << convertedUtf8Line << std::endl; + + // check correctness + assert(convertedUtf8Line == utf8Line); + + // convert UTF-8 text to legacy encoding + std::string convertedLegacyEncLine = encoder.getLegacyEnc(utf8Line); + // check correctness + assert(convertedLegacyEncLine == legacyEncLine); +} + +std::string getFirstLine(const std::string &filename) +{ + std::string line; + std::ifstream text (filename.c_str()); + + if (!text.is_open()) + { + throw std::runtime_error("Unable to open file " + filename); + } + + std::getline(text, line); + text.close(); + + return line; +} + +int main() +{ + testEncoder(ToUTF8::WINDOWS_1251, "data/russian-win1251.txt", "data/russian-utf8.txt"); + testEncoder(ToUTF8::WINDOWS_1252, "data/french-win1252.txt", "data/french-utf8.txt"); + return 0; +} From cc792da85895c85db8b76a5c9692bc260f35f649 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Fri, 4 Jan 2013 15:24:07 +0100 Subject: [PATCH 118/136] Fix to_utf8 test: add test data directory and remove unused include --- components/to_utf8/tests/test_data/french-utf8.txt | 1 + components/to_utf8/tests/test_data/french-win1252.txt | 1 + components/to_utf8/tests/test_data/russian-utf8.txt | 1 + components/to_utf8/tests/test_data/russian-win1251.txt | 1 + components/to_utf8/tests/to_utf8_test.cpp | 5 ++--- 5 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 components/to_utf8/tests/test_data/french-utf8.txt create mode 100644 components/to_utf8/tests/test_data/french-win1252.txt create mode 100644 components/to_utf8/tests/test_data/russian-utf8.txt create mode 100644 components/to_utf8/tests/test_data/russian-win1251.txt diff --git a/components/to_utf8/tests/test_data/french-utf8.txt b/components/to_utf8/tests/test_data/french-utf8.txt new file mode 100644 index 000000000..aaaccac73 --- /dev/null +++ b/components/to_utf8/tests/test_data/french-utf8.txt @@ -0,0 +1 @@ +Vous lui donnez le gâteau sans protester avant d’aller chercher tous vos amis et de revenir vous venger. \ No newline at end of file diff --git a/components/to_utf8/tests/test_data/french-win1252.txt b/components/to_utf8/tests/test_data/french-win1252.txt new file mode 100644 index 000000000..1de4593e9 --- /dev/null +++ b/components/to_utf8/tests/test_data/french-win1252.txt @@ -0,0 +1 @@ +Vous lui donnez le gâteau sans protester avant d’aller chercher tous vos amis et de revenir vous venger. \ No newline at end of file diff --git a/components/to_utf8/tests/test_data/russian-utf8.txt b/components/to_utf8/tests/test_data/russian-utf8.txt new file mode 100644 index 000000000..eb20b32dd --- /dev/null +++ b/components/to_utf8/tests/test_data/russian-utf8.txt @@ -0,0 +1 @@ +Без вопроÑов отдаете ему рулет, знаÑ, что позже вы Ñможете привеÑти Ñ Ñобой Ñвоих друзей и тогда он получит по заÑлугам? \ No newline at end of file diff --git a/components/to_utf8/tests/test_data/russian-win1251.txt b/components/to_utf8/tests/test_data/russian-win1251.txt new file mode 100644 index 000000000..086e57edd --- /dev/null +++ b/components/to_utf8/tests/test_data/russian-win1251.txt @@ -0,0 +1 @@ +Áåç âîïðîñîâ îòäàåòå åìó ðóëåò, çíàÿ, ÷òî ïîçæå âû ñìîæåòå ïðèâåñòè ñ ñîáîé ñâîèõ äðóçåé è òîãäà îí ïîëó÷èò ïî çàñëóãàì? \ No newline at end of file diff --git a/components/to_utf8/tests/to_utf8_test.cpp b/components/to_utf8/tests/to_utf8_test.cpp index 8c25c483e..4bba0cf90 100644 --- a/components/to_utf8/tests/to_utf8_test.cpp +++ b/components/to_utf8/tests/to_utf8_test.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include "../to_utf8.hpp" @@ -55,7 +54,7 @@ std::string getFirstLine(const std::string &filename) int main() { - testEncoder(ToUTF8::WINDOWS_1251, "data/russian-win1251.txt", "data/russian-utf8.txt"); - testEncoder(ToUTF8::WINDOWS_1252, "data/french-win1252.txt", "data/french-utf8.txt"); + testEncoder(ToUTF8::WINDOWS_1251, "test_data/russian-win1251.txt", "test_data/russian-utf8.txt"); + testEncoder(ToUTF8::WINDOWS_1252, "test_data/french-win1252.txt", "test_data/french-utf8.txt"); return 0; } From 3c91f7793b29d2c9479b3ca15e4b327cd87e08f2 Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Fri, 4 Jan 2013 08:40:33 -0800 Subject: [PATCH 119/136] overrode MyGUI::DataManager::isDataExist Created a override of MyGUI::DataManager::isDataExist to fix a performance issue with MyGUI startup. This required moving the functionality of MyGUI::OgrePlatform into OEngine::GUI::MyGUIManager so that a new version of the MyGUI::DataManager could be created. --- libs/openengine/gui/manager.cpp | 45 ++++++++++++++++++++++++++++----- libs/openengine/gui/manager.hpp | 11 +++++--- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/libs/openengine/gui/manager.cpp b/libs/openengine/gui/manager.cpp index acb4ed9df..925891e1b 100644 --- a/libs/openengine/gui/manager.cpp +++ b/libs/openengine/gui/manager.cpp @@ -6,6 +6,19 @@ using namespace OEngine::GUI; +/* + * As of MyGUI 3.2.0, MyGUI::OgreDataManager::isDataExist is unnecessarily complex + * this override fixes the resulting performance issue. + */ +class FixedOgreDataManager : public MyGUI::OgreDataManager +{ +public: + bool isDataExist(const std::string& _name) + { + return Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup (_name); + } +}; + void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging, const std::string& logDir) { assert(wnd); @@ -25,11 +38,18 @@ void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool if(!logDir.empty()) theLogFile.insert(0, logDir); - // Set up OGRE platform. We might make this more generic later. - mPlatform = new OgrePlatform(); + // Set up OGRE platform (bypassing OgrePlatform). We might make this more generic later. + mLogManager = new LogManager(); + mRenderManager = new OgreRenderManager(); + mDataManager = new FixedOgreDataManager(); + LogManager::getInstance().setSTDOutputEnabled(logging); - mPlatform->initialise(wnd, mgr, "General", theLogFile); + if (!theLogFile.empty()) + LogManager::getInstance().createDefaultSource(theLogFile); + + mRenderManager->initialise(wnd, mgr); + mDataManager->initialise("General"); // Create GUI mGui = new Gui(); @@ -40,11 +60,22 @@ void MyGUIManager::shutdown() { mGui->shutdown (); delete mGui; - if(mPlatform) + if(mRenderManager) + { + mRenderManager->shutdown(); + delete mRenderManager; + mRenderManager = NULL; + } + if(mDataManager) + { + mDataManager->shutdown(); + delete mDataManager; + mDataManager = NULL; + } + if (mLogManager) { - mPlatform->shutdown(); - delete mPlatform; + delete mLogManager; + mLogManager = NULL; } mGui = NULL; - mPlatform = NULL; } diff --git a/libs/openengine/gui/manager.hpp b/libs/openengine/gui/manager.hpp index 1ec2e2fcf..c0f98da88 100644 --- a/libs/openengine/gui/manager.hpp +++ b/libs/openengine/gui/manager.hpp @@ -3,8 +3,10 @@ namespace MyGUI { - class OgrePlatform; class Gui; + class LogManager; + class OgreDataManager; + class OgreRenderManager; } namespace Ogre @@ -18,12 +20,15 @@ namespace GUI { class MyGUIManager { - MyGUI::OgrePlatform *mPlatform; MyGUI::Gui *mGui; + MyGUI::LogManager* mLogManager; + MyGUI::OgreDataManager* mDataManager; + MyGUI::OgreRenderManager* mRenderManager; Ogre::SceneManager* mSceneMgr; + public: - MyGUIManager() : mPlatform(NULL), mGui(NULL) {} + MyGUIManager() : mLogManager(NULL), mDataManager(NULL), mRenderManager(NULL), mGui(NULL) {} MyGUIManager(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging=false, const std::string& logDir = std::string("")) { setup(wnd,mgr,logging, logDir); From 218139351830d00b3b564b13ab7d16276b99c6d3 Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Fri, 4 Jan 2013 11:36:22 -0800 Subject: [PATCH 120/136] change texture renaming logic to increase performance ResourceGroupManager::resourceExistsInAnyGroup is slow (at least on windows) if the tested path does not exist, but is fast if it does (due to finding it in the index). This change tries the '.dds' version of the name first, and reverts to the original if the '.dds' version was not found. --- components/nifogre/ogre_nif_loader.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index ad51d50b9..dca459119 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -536,11 +536,23 @@ static Ogre::String getMaterial(const NiTriShape *shape, const Ogre::String &nam * textures from tga to dds for increased load speed, but all * texture file name references were kept as .tga. */ - texName = "textures\\" + st->filename; - if(!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(texName)) + + static const char * path = "textures\\"; + + texName = path + st->filename; + + Ogre::String::size_type pos = texName.rfind('.'); + + if (texName.compare (pos, texName.size () - pos, ".dds") != 0) { - Ogre::String::size_type pos = texName.rfind('.'); + // since we know all (GOTY edition or less) textures end + // in .dds, we change the extension texName.replace(pos, texName.length(), ".dds"); + + // if it turns out that the above wasn't true in all cases (not for vanilla, but maybe mods) + // verify, and revert if false (this call succeeds quickly, but fails slowly) + if(!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(texName)) + texName = path + st->filename; } } else warn("Found internal texture, ignoring."); From dcfa902525ef76cfab2426c03965a6a0291b7c53 Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Fri, 4 Jan 2013 13:08:09 -0800 Subject: [PATCH 121/136] fixed error in cmake when disabling esmtool --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 36e45d78a..766167672 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -534,7 +534,9 @@ if (WIN32) set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS}) endif (BUILD_LAUNCHER) set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS}) - set_target_properties(esmtool PROPERTIES COMPILE_FLAGS ${WARNINGS}) + if (BUILD_ESMTOOL) + set_target_properties(esmtool PROPERTIES COMPILE_FLAGS ${WARNINGS}) + endif (BUILD_ESMTOOL) endif(MSVC) # Same for MinGW From 5c7f1bd497d620e1d219b485eebb6fb9f8c598ab Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Tue, 1 Jan 2013 12:55:39 -0800 Subject: [PATCH 122/136] moved ConstrainedDataStream into its own file moved the ConstrainedDataStream into its own source file and changed BSAFile to use it though the exposed factory function. This is in preperation foreimplementing it based on feedback from profiling that (at least on windows) the C++ iostreams library is quite slow. --- components/CMakeLists.txt | 2 +- components/bsa/bsa_file.cpp | 89 +------------- .../files/constrainedfiledatastream.cpp | 112 ++++++++++++++++++ .../files/constrainedfiledatastream.hpp | 8 ++ 4 files changed, 126 insertions(+), 85 deletions(-) create mode 100644 components/files/constrainedfiledatastream.cpp create mode 100644 components/files/constrainedfiledatastream.hpp diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index f3d5f4aee..f54efab22 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -48,7 +48,7 @@ add_component_dir (misc add_component_dir (files linuxpath windowspath macospath fixedpath multidircollection collections fileops configurationmanager - filelibrary ogreplugin + filelibrary ogreplugin constrainedfiledatastream ) add_component_dir (compiler diff --git a/components/bsa/bsa_file.cpp b/components/bsa/bsa_file.cpp index 1700e1aab..5e529e18e 100644 --- a/components/bsa/bsa_file.cpp +++ b/components/bsa/bsa_file.cpp @@ -23,94 +23,15 @@ #include "bsa_file.hpp" -#include -#include -#include +//#include +//#include +//#include -#include +#include "../files/constrainedfiledatastream.hpp" using namespace std; using namespace Bsa; -class ConstrainedDataStream : public Ogre::DataStream { - std::ifstream mStream; - const size_t mStart; - size_t mPos; - bool mIsEOF; - -public: - ConstrainedDataStream(const Ogre::String &fname, size_t start, size_t length) - : mStream(fname.c_str(), std::ios_base::binary), mStart(start), mPos(0), mIsEOF(false) - { - mSize = length; - if(!mStream.seekg(mStart, std::ios_base::beg)) - throw std::runtime_error("Error seeking to start of BSA entry"); - } - - ConstrainedDataStream(const Ogre::String &name, const Ogre::String &fname, - size_t start, size_t length) - : Ogre::DataStream(name), mStream(fname.c_str(), std::ios_base::binary), - mStart(start), mPos(0), mIsEOF(false) - { - mSize = length; - if(!mStream.seekg(mStart, std::ios_base::beg)) - throw std::runtime_error("Error seeking to start of BSA entry"); - } - - - virtual size_t read(void *buf, size_t count) - { - mStream.clear(); - - if(count > mSize-mPos) - { - count = mSize-mPos; - mIsEOF = true; - } - mStream.read(reinterpret_cast(buf), count); - - count = mStream.gcount(); - mPos += count; - return count; - } - - virtual void skip(long count) - { - if((count >= 0 && (size_t)count <= mSize-mPos) || - (count < 0 && (size_t)-count <= mPos)) - { - mStream.clear(); - if(mStream.seekg(count, std::ios_base::cur)) - { - mPos += count; - mIsEOF = false; - } - } - } - - virtual void seek(size_t pos) - { - if(pos < mSize) - { - mStream.clear(); - if(mStream.seekg(pos+mStart, std::ios_base::beg)) - { - mPos = pos; - mIsEOF = false; - } - } - } - - virtual size_t tell() const - { return mPos; } - - virtual bool eof() const - { return mIsEOF; } - - virtual void close() - { mStream.close(); } -}; - /// Error handling void BSAFile::fail(const string &msg) @@ -253,5 +174,5 @@ Ogre::DataStreamPtr BSAFile::getFile(const char *file) fail("File not found: " + string(file)); const FileStruct &fs = files[i]; - return Ogre::DataStreamPtr(new ConstrainedDataStream(filename, fs.offset, fs.fileSize)); + return openConstrainedFileDataStream (filename.c_str (), fs.offset, fs.fileSize); } diff --git a/components/files/constrainedfiledatastream.cpp b/components/files/constrainedfiledatastream.cpp new file mode 100644 index 000000000..037ffe6f0 --- /dev/null +++ b/components/files/constrainedfiledatastream.cpp @@ -0,0 +1,112 @@ +/* + OpenMW - The completely unofficial reimplementation of Morrowind + Copyright (C) 2008-2010 Nicolay Korslund + Email: < korslund@gmail.com > + WWW: http://openmw.sourceforge.net/ + + This file (bsa_file.cpp) is part of the OpenMW package. + + OpenMW is distributed as free software: you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 3, as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + version 3 along with this program. If not, see + http://www.gnu.org/licenses/ . + + */ + +#include "constrainedfiledatastream.hpp" + +#include + +class ConstrainedDataStream : public Ogre::DataStream { + std::ifstream mStream; + const size_t mStart; + size_t mPos; + bool mIsEOF; + +public: + ConstrainedDataStream(const Ogre::String &fname, size_t start, size_t length) + : mStream(fname.c_str(), std::ios_base::binary), mStart(start), mPos(0), mIsEOF(false) + { + mSize = length; + if(!mStream.seekg(mStart, std::ios_base::beg)) + throw std::runtime_error("Error seeking to start of BSA entry"); + } + + ConstrainedDataStream(const Ogre::String &name, const Ogre::String &fname, + size_t start, size_t length) + : Ogre::DataStream(name), mStream(fname.c_str(), std::ios_base::binary), + mStart(start), mPos(0), mIsEOF(false) + { + mSize = length; + if(!mStream.seekg(mStart, std::ios_base::beg)) + throw std::runtime_error("Error seeking to start of BSA entry"); + } + + + virtual size_t read(void *buf, size_t count) + { + mStream.clear(); + + if(count > mSize-mPos) + { + count = mSize-mPos; + mIsEOF = true; + } + mStream.read(reinterpret_cast(buf), count); + + count = mStream.gcount(); + mPos += count; + return count; + } + + virtual void skip(long count) + { + if((count >= 0 && (size_t)count <= mSize-mPos) || + (count < 0 && (size_t)-count <= mPos)) + { + mStream.clear(); + if(mStream.seekg(count, std::ios_base::cur)) + { + mPos += count; + mIsEOF = false; + } + } + } + + virtual void seek(size_t pos) + { + if(pos < mSize) + { + mStream.clear(); + if(mStream.seekg(pos+mStart, std::ios_base::beg)) + { + mPos = pos; + mIsEOF = false; + } + } + } + + virtual size_t tell() const + { return mPos; } + + virtual bool eof() const + { return mIsEOF; } + + virtual void close() + { mStream.close(); } +}; + +Ogre::DataStreamPtr openConstrainedFileDataStream (char const * filename, size_t offset, size_t length) +{ + assert (length != 0xFFFFFFFF); // reserved for future use... + + return Ogre::DataStreamPtr(new ConstrainedDataStream(filename, offset, length)); +} diff --git a/components/files/constrainedfiledatastream.hpp b/components/files/constrainedfiledatastream.hpp new file mode 100644 index 000000000..367defcbc --- /dev/null +++ b/components/files/constrainedfiledatastream.hpp @@ -0,0 +1,8 @@ +#ifndef COMPONENTS_FILES_CONSTRAINEDFILEDATASTREAM_HPP +#define COMPONENTS_FILES_CONSTRAINEDFILEDATASTREAM_HPP + +#include + +Ogre::DataStreamPtr openConstrainedFileDataStream (char const * filename, size_t offset = 0, size_t length = 0xFFFFFFFF); + +#endif // COMPONENTS_FILES_CONSTRAINEDFILEDATASTREAM_HPP From 278337116b93e62e7458e03463e83c2055eb15e7 Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Tue, 1 Jan 2013 15:07:33 -0800 Subject: [PATCH 123/136] increased performance of ConstrainedDataStream Reimplemented ConstrainedDataStream to use low-level IO calls and a custom buffering scheme to avoid using C++ iostreams. --- components/CMakeLists.txt | 2 +- .../files/constrainedfiledatastream.cpp | 218 ++++++++----- components/files/lowlevelfile.cpp | 299 ++++++++++++++++++ components/files/lowlevelfile.hpp | 54 ++++ 4 files changed, 492 insertions(+), 81 deletions(-) create mode 100644 components/files/lowlevelfile.cpp create mode 100644 components/files/lowlevelfile.hpp diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index f54efab22..3da09ecb8 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -48,7 +48,7 @@ add_component_dir (misc add_component_dir (files linuxpath windowspath macospath fixedpath multidircollection collections fileops configurationmanager - filelibrary ogreplugin constrainedfiledatastream + filelibrary ogreplugin constrainedfiledatastream lowlevelfile ) add_component_dir (compiler diff --git a/components/files/constrainedfiledatastream.cpp b/components/files/constrainedfiledatastream.cpp index 037ffe6f0..2f75ce41b 100644 --- a/components/files/constrainedfiledatastream.cpp +++ b/components/files/constrainedfiledatastream.cpp @@ -1,112 +1,170 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008-2010 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.sourceforge.net/ +#include "constrainedfiledatastream.hpp" +#include "lowlevelfile.hpp" - This file (bsa_file.cpp) is part of the OpenMW package. +#include +#include - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. +namespace { - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. +class ConstrainedDataStream : public Ogre::DataStream { +public: - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . + static const size_t sBufferSize = 4096; // somewhat arbitrary though 64KB buffers didn't seem to improve performance any + static const size_t sBufferThreshold = 1024; // reads larger than this bypass buffering as cost of memcpy outweighs cost of system call - */ + ConstrainedDataStream(const Ogre::String &fname, size_t start, size_t length) + { + mFile.open (fname.c_str ()); + mSize = length != 0xFFFFFFFF ? length : mFile.size () - start; -#include "constrainedfiledatastream.hpp" + mPos = 0; + mOrigin = start; + mExtent = start + mSize; -#include + mBufferOrigin = 0; + mBufferExtent = 0; + } + -class ConstrainedDataStream : public Ogre::DataStream { - std::ifstream mStream; - const size_t mStart; - size_t mPos; - bool mIsEOF; + size_t read(void* buf, size_t count) + { + assert (mPos <= mSize); -public: - ConstrainedDataStream(const Ogre::String &fname, size_t start, size_t length) - : mStream(fname.c_str(), std::ios_base::binary), mStart(start), mPos(0), mIsEOF(false) - { - mSize = length; - if(!mStream.seekg(mStart, std::ios_base::beg)) - throw std::runtime_error("Error seeking to start of BSA entry"); - } + uint8_t * out = reinterpret_cast (buf); - ConstrainedDataStream(const Ogre::String &name, const Ogre::String &fname, - size_t start, size_t length) - : Ogre::DataStream(name), mStream(fname.c_str(), std::ios_base::binary), - mStart(start), mPos(0), mIsEOF(false) - { - mSize = length; - if(!mStream.seekg(mStart, std::ios_base::beg)) - throw std::runtime_error("Error seeking to start of BSA entry"); - } + size_t posBeg = mOrigin + mPos; + size_t posEnd = posBeg + count; + if (posEnd > mExtent) + posEnd = mExtent; - virtual size_t read(void *buf, size_t count) - { - mStream.clear(); - - if(count > mSize-mPos) - { - count = mSize-mPos; - mIsEOF = true; - } - mStream.read(reinterpret_cast(buf), count); - - count = mStream.gcount(); - mPos += count; - return count; - } + size_t posCur = posBeg; + + while (posCur != posEnd) + { + size_t readLeft = posEnd - posCur; + + if (posCur < mBufferOrigin || posCur >= mBufferExtent) + { + if (readLeft >= sBufferThreshold || (posCur == mOrigin && posEnd == mExtent)) + { + assert (mFile.tell () == mBufferExtent); + + if (posCur != mBufferExtent) + mFile.seek (posCur); + + posCur += mFile.read (out, readLeft); + + mBufferOrigin = mBufferExtent = posCur; + + mPos = posCur - mOrigin; + + return posCur - posBeg; + } + else + { + size_t newBufferOrigin; + + if ((posCur < mBufferOrigin) && (mBufferOrigin - posCur < sBufferSize)) + newBufferOrigin = std::max (mOrigin, mBufferOrigin > sBufferSize ? mBufferOrigin - sBufferSize : 0); + else + newBufferOrigin = posCur; + + fill (newBufferOrigin); + } + } + + size_t xfer = std::min (readLeft, mBufferExtent - posCur); - virtual void skip(long count) + memcpy (out, mBuffer + (posCur - mBufferOrigin), xfer); + + posCur += xfer; + out += xfer; + } + + count = posEnd - posBeg; + mPos += count; + return count; + } + + void skip(long count) { + assert (mPos <= mSize); + if((count >= 0 && (size_t)count <= mSize-mPos) || (count < 0 && (size_t)-count <= mPos)) - { - mStream.clear(); - if(mStream.seekg(count, std::ios_base::cur)) - { - mPos += count; - mIsEOF = false; - } - } + mPos += count; } - virtual void seek(size_t pos) + void seek(size_t pos) { - if(pos < mSize) - { - mStream.clear(); - if(mStream.seekg(pos+mStart, std::ios_base::beg)) - { - mPos = pos; - mIsEOF = false; - } - } + assert (mPos <= mSize); + + if (pos < mSize) + mPos = pos; } virtual size_t tell() const - { return mPos; } + { + assert (mPos <= mSize); + + return mPos; + } virtual bool eof() const - { return mIsEOF; } + { + assert (mPos <= mSize); + + return mPos == mSize; + } virtual void close() - { mStream.close(); } + { + mFile.close(); + } + +private: + + void fill (size_t newOrigin) + { + assert (mFile.tell () == mBufferExtent); + + size_t newExtent = newOrigin + sBufferSize; + + if (newExtent > mExtent) + newExtent = mExtent; + + size_t oldExtent = mBufferExtent; + + if (newOrigin != oldExtent) + mFile.seek (newOrigin); + + mBufferOrigin = mBufferExtent = newOrigin; + + size_t amountRequested = newExtent - newOrigin; + + size_t amountRead = mFile.read (mBuffer, amountRequested); + + if (amountRead != amountRequested) + throw std::runtime_error ("An unexpected condition occurred while reading from a file."); + + mBufferExtent = newExtent; + } + + LowLevelFile mFile; + + size_t mOrigin; + size_t mExtent; + size_t mPos; + + uint8_t mBuffer [sBufferSize]; + size_t mBufferOrigin; + size_t mBufferExtent; }; +} // end of unnamed namespace + Ogre::DataStreamPtr openConstrainedFileDataStream (char const * filename, size_t offset, size_t length) { - assert (length != 0xFFFFFFFF); // reserved for future use... - return Ogre::DataStreamPtr(new ConstrainedDataStream(filename, offset, length)); } diff --git a/components/files/lowlevelfile.cpp b/components/files/lowlevelfile.cpp new file mode 100644 index 000000000..71fd1b523 --- /dev/null +++ b/components/files/lowlevelfile.cpp @@ -0,0 +1,299 @@ +#include "lowlevelfile.hpp" + +#include +#include +#include + +#if FILE_API == FILE_API_POSIX +#include +#include +#include +#endif + +#if FILE_API == FILE_API_STDIO +/* + * + * Implementation of LowLevelFile methods using c stdio + * + */ + +LowLevelFile::LowLevelFile () +{ + mHandle = NULL; +} + +LowLevelFile::~LowLevelFile () +{ + if (mHandle != NULL) + fclose (mHandle); +} + +void LowLevelFile::open (char const * filename) +{ + assert (mHandle == NULL); + + mHandle = fopen (filename, "rb"); + + if (mHandle == NULL) + { + std::ostringstream os; + os << "Failed to open '" << filename << "' for reading."; + throw std::runtime_error (os.str ()); + } +} + +void LowLevelFile::close () +{ + assert (mHandle != NULL); + + fclose (mHandle); + + mHandle = NULL; +} + +size_t LowLevelFile::size () +{ + assert (mHandle != NULL); + + long oldPosition = ftell (mHandle); + + if (oldPosition == -1) + throw std::runtime_error ("A query operation on a file failed."); + + if (fseek (mHandle, 0, SEEK_END) != 0) + throw std::runtime_error ("A query operation on a file failed."); + + long Size = ftell (mHandle); + + if (Size == -1) + throw std::runtime_error ("A query operation on a file failed."); + + if (fseek (mHandle, oldPosition, SEEK_SET) != 0) + throw std::runtime_error ("A query operation on a file failed."); + + return size_t (Size); +} + +void LowLevelFile::seek (size_t Position) +{ + assert (mHandle != NULL); + + if (fseek (mHandle, Position, SEEK_SET) != 0) + throw std::runtime_error ("A seek operation on a file failed."); +} + +size_t LowLevelFile::tell () +{ + assert (mHandle != NULL); + + long Position = ftell (mHandle); + + if (Position == -1) + throw std::runtime_error ("A query operation on a file failed."); + + return size_t (Position); +} + +size_t LowLevelFile::read (void * data, size_t size) +{ + assert (mHandle != NULL); + + int amount = fread (data, 1, size, mHandle); + + if (amount == 0 && ferror (mHandle)) + throw std::runtime_error ("A read operation on a file failed."); + + return amount; +} + +#elif FILE_API == FILE_API_POSIX +/* + * + * Implementation of LowLevelFile methods using posix IO calls + * + */ + +LowLevelFile::LowLevelFile () +{ + mHandle = -1; +} + +LowLevelFile::~LowLevelFile () +{ + if (mHandle != -1) + ::close (mHandle); +} + +void LowLevelFile::open (char const * filename) +{ + assert (mHandle == -1); + +#ifdef O_BINARY + static const int openFlags = O_RDONLY | O_BINARY; +#else + static const int openFlags = O_RDONLY; +#endif + + mHandle = ::open (filename, openFlags, 0); + + if (mHandle == -1) + { + std::ostringstream os; + os << "Failed to open '" << filename << "' for reading."; + throw std::runtime_error (os.str ()); + } +} + +void LowLevelFile::close () +{ + assert (mHandle != -1); + + ::close (mHandle); + + mHandle = -1; +} + +size_t LowLevelFile::size () +{ + assert (mHandle != -1); + + size_t oldPosition = ::lseek (mHandle, 0, SEEK_CUR); + + if (oldPosition == size_t (-1)) + throw std::runtime_error ("A query operation on a file failed."); + + size_t Size = ::lseek (mHandle, 0, SEEK_END); + + if (Size == size_t (-1)) + throw std::runtime_error ("A query operation on a file failed."); + + if (lseek (mHandle, oldPosition, SEEK_SET) == -1) + throw std::runtime_error ("A query operation on a file failed."); + + return Size; +} + +void LowLevelFile::seek (size_t Position) +{ + assert (mHandle != -1); + + if (::lseek (mHandle, Position, SEEK_SET) == -1) + throw std::runtime_error ("A seek operation on a file failed."); +} + +size_t LowLevelFile::tell () +{ + assert (mHandle != -1); + + size_t Position = ::lseek (mHandle, 0, SEEK_CUR); + + if (Position == size_t (-1)) + throw std::runtime_error ("A query operation on a file failed."); + + return Position; +} + +size_t LowLevelFile::read (void * data, size_t size) +{ + assert (mHandle != -1); + + int amount = ::read (mHandle, data, size); + + if (amount == -1) + throw std::runtime_error ("A read operation on a file failed."); + + return amount; +} + +#elif FILE_API == FILE_API_WIN32 +/* + * + * Implementation of LowLevelFile methods using Win32 API calls + * + */ + +LowLevelFile::LowLevelFile () +{ + mHandle = INVALID_HANDLE_VALUE; +} + +LowLevelFile::~LowLevelFile () +{ + if (mHandle == INVALID_HANDLE_VALUE) + CloseHandle (mHandle); +} + +void LowLevelFile::open (char const * filename) +{ + assert (mHandle == INVALID_HANDLE_VALUE); + + HANDLE handle = CreateFileA (filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + + if (handle == NULL) + { + std::ostringstream os; + os << "Failed to open '" << filename << "' for reading."; + throw std::runtime_error (os.str ()); + } + + mHandle = handle; +} + +void LowLevelFile::close () +{ + assert (mHandle != INVALID_HANDLE_VALUE); + + CloseHandle (mHandle); + + mHandle = INVALID_HANDLE_VALUE; +} + +size_t LowLevelFile::size () +{ + assert (mHandle != INVALID_HANDLE_VALUE); + + BY_HANDLE_FILE_INFORMATION info; + + if (!GetFileInformationByHandle (mHandle, &info)) + throw std::runtime_error ("A query operation on a file failed."); + + if (info.nFileSizeHigh != 0) + throw std::runtime_error ("Files greater that 4GB are not supported."); + + return info.nFileSizeLow; +} + +void LowLevelFile::seek (size_t Position) +{ + assert (mHandle != INVALID_HANDLE_VALUE); + + if (SetFilePointer (mHandle, Position, NULL, SEEK_SET) == INVALID_SET_FILE_POINTER) + if (GetLastError () != NO_ERROR) + throw std::runtime_error ("A seek operation on a file failed."); +} + +size_t LowLevelFile::tell () +{ + assert (mHandle != INVALID_HANDLE_VALUE); + + DWORD value = SetFilePointer (mHandle, 0, NULL, SEEK_CUR); + + if (value == INVALID_SET_FILE_POINTER && GetLastError () != NO_ERROR) + throw std::runtime_error ("A query operation on a file failed."); + + return value; +} + +size_t LowLevelFile::read (void * data, size_t size) +{ + assert (mHandle != INVALID_HANDLE_VALUE); + + DWORD read; + + if (!ReadFile (mHandle, data, size, &read, NULL)) + throw std::runtime_error ("A read operation on a file failed."); + + return read; +} + +#endif diff --git a/components/files/lowlevelfile.hpp b/components/files/lowlevelfile.hpp new file mode 100644 index 000000000..a6de6df76 --- /dev/null +++ b/components/files/lowlevelfile.hpp @@ -0,0 +1,54 @@ +#ifndef COMPONENTS_FILES_LOWLEVELFILE_HPP +#define COMPONENTS_FILES_LOWLEVELFILE_HPP + +#include + +#define FILE_API_STDIO 0 +#define FILE_API_POSIX 1 +#define FILE_API_WIN32 2 + +#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX +#define FILE_API FILE_API_POSIX +#elif OGRE_PLATFORM == OGRE_PLATFORM_WIN32 +#define FILE_API FILE_API_WIN32 +#else +#define FILE_API FILE_API_STDIO +#endif + +#if FILE_API == FILE_API_STDIO +#include +#elif FILE_API == FILE_API_POSIX +#elif FILE_API == FILE_API_WIN32 +#include +#else +#error Unsupported File API +#endif + +class LowLevelFile +{ +public: + + LowLevelFile (); + ~LowLevelFile (); + + void open (char const * filename); + void close (); + + size_t size (); + + void seek (size_t Position); + size_t tell (); + + size_t read (void * data, size_t size); + +private: +#if FILE_API == FILE_API_STDIO + FILE* mHandle; +#elif FILE_API == FILE_API_POSIX + int mHandle; +#elif FILE_API == FILE_API_WIN32 + HANDLE mHandle; +#endif +}; + +#endif From fec9a5923767747e9d845ac84cbadc60342e7da5 Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Tue, 1 Jan 2013 15:13:36 -0800 Subject: [PATCH 124/136] changed EMSLoader to use ConstrainedDataStream Changed the EMSLoader class to use the ConstrainedDataStream so that future changes may benifit from its increased performance. --- components/esm/esmreader.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/components/esm/esmreader.cpp b/components/esm/esmreader.cpp index 580e006df..62078977e 100644 --- a/components/esm/esmreader.cpp +++ b/components/esm/esmreader.cpp @@ -1,6 +1,8 @@ #include "esmreader.hpp" #include +#include "../files/constrainedfiledatastream.hpp" + namespace ESM { @@ -108,16 +110,12 @@ void ESMReader::open(Ogre::DataStreamPtr _esm, const std::string &name) void ESMReader::open(const std::string &file) { - std::ifstream *stream = OGRE_NEW_T(std::ifstream, Ogre::MEMCATEGORY_GENERAL)(file.c_str(), std::ios_base::binary); - // Ogre will delete the stream for us - open(Ogre::DataStreamPtr(new Ogre::FileStreamDataStream(stream)), file); + open (openConstrainedFileDataStream (file.c_str ()), file); } void ESMReader::openRaw(const std::string &file) { - std::ifstream *stream = OGRE_NEW_T(std::ifstream, Ogre::MEMCATEGORY_GENERAL)(file.c_str(), std::ios_base::binary); - // Ogre will delete the stream for us - openRaw(Ogre::DataStreamPtr(new Ogre::FileStreamDataStream(stream)), file); + openRaw (openConstrainedFileDataStream (file.c_str ()), file); } int64_t ESMReader::getHNLong(const char *name) From b4d63814cc13bcd0ef9d46682b73b0f36dad2d0f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 4 Jan 2013 23:12:56 +0100 Subject: [PATCH 125/136] post merge fix --- components/files/lowlevelfile.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/files/lowlevelfile.hpp b/components/files/lowlevelfile.hpp index a6de6df76..f49c466a5 100644 --- a/components/files/lowlevelfile.hpp +++ b/components/files/lowlevelfile.hpp @@ -3,6 +3,8 @@ #include +#include + #define FILE_API_STDIO 0 #define FILE_API_POSIX 1 #define FILE_API_WIN32 2 From 1d4d67f81153fc9a299158daa20b161bb9add69a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 4 Jan 2013 15:03:57 -0800 Subject: [PATCH 126/136] Avoid underflows if the texture name doesn't include a '.' --- components/nifogre/ogre_nif_loader.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index ae2a0ae15..93f00b178 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -537,14 +537,11 @@ static Ogre::String getMaterial(const NiTriShape *shape, const Ogre::String &nam * textures from tga to dds for increased load speed, but all * texture file name references were kept as .tga. */ - - static const char * path = "textures\\"; + static const char path[] = "textures\\"; texName = path + st->filename; - Ogre::String::size_type pos = texName.rfind('.'); - - if (texName.compare (pos, texName.size () - pos, ".dds") != 0) + if(pos != Ogre::String::npos && texName.compare(pos, texName.length() - pos, ".dds") != 0) { // since we know all (GOTY edition or less) textures end // in .dds, we change the extension From b52904a6ea4f9acd5f76a89a1eecabd27fc5562c Mon Sep 17 00:00:00 2001 From: Jordan Milne Date: Fri, 4 Jan 2013 19:47:24 -0400 Subject: [PATCH 127/136] Include headers necessary for compilation under VS2010 --- components/files/constrainedfiledatastream.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/components/files/constrainedfiledatastream.cpp b/components/files/constrainedfiledatastream.cpp index 2f75ce41b..9e36f9075 100644 --- a/components/files/constrainedfiledatastream.cpp +++ b/components/files/constrainedfiledatastream.cpp @@ -3,6 +3,7 @@ #include #include +#include namespace { From a3d33db4153c26f17dfc632551e09c2b62226f29 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 4 Jan 2013 15:55:47 -0800 Subject: [PATCH 128/136] Store a NiNode's NiTextKeyExtraData in a user object binding on Ogre::Bone --- components/nifogre/ogre_nif_loader.cpp | 78 +++++++++++++++++--------- 1 file changed, 51 insertions(+), 27 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 93f00b178..badadfe01 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -49,10 +49,21 @@ typedef unsigned char ubyte; -using namespace std; -using namespace Nif; -using namespace NifOgre; +namespace Nif +{ + +// These operators allow the Nif extra data types to be stored in an Ogre::Any +// object, which can then be stored in user object bindings on the nodes + +// TODO: Do something useful +std::ostream& operator<<(std::ostream &o, const Nif::NiTextKeyExtraData&) +{ return o; } +} // namespace Nif + + +namespace NifOgre +{ // Helper class that computes the bounding box and of a mesh class BoundsFinder @@ -63,7 +74,7 @@ class BoundsFinder MaxMinFinder() { - min = numeric_limits::infinity(); + min = std::numeric_limits::infinity(); max = -min; } @@ -198,6 +209,17 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, std::vectornext; } + Nif::ExtraPtr e = node->extra; + while(!e.empty()) + { + if(e->recType == Nif::RC_NiTextKeyExtraData) + { + const Nif::NiTextKeyExtraData *tk = static_cast(e.getPtr()); + bone->getUserObjectBindings().setUserAny(tk->recName, Ogre::Any(*tk)); + } + e = e->extra; + } + const Nif::NiNode *ninode = dynamic_cast(node); if(ninode) { @@ -270,16 +292,16 @@ void loadResource(Ogre::Resource *resource) Nif::NiKeyframeData *kf = kfc->data.getPtr(); /* Get the keyframes and make sure they're sorted first to last */ - QuaternionKeyList quatkeys = kf->mRotations; - Vector3KeyList trankeys = kf->mTranslations; - FloatKeyList scalekeys = kf->mScales; + Nif::QuaternionKeyList quatkeys = kf->mRotations; + Nif::Vector3KeyList trankeys = kf->mTranslations; + Nif::FloatKeyList scalekeys = kf->mScales; std::sort(quatkeys.mKeys.begin(), quatkeys.mKeys.end(), KeyTimeSort()); std::sort(trankeys.mKeys.begin(), trankeys.mKeys.end(), KeyTimeSort()); std::sort(scalekeys.mKeys.begin(), scalekeys.mKeys.end(), KeyTimeSort()); - QuaternionKeyList::VecType::const_iterator quatiter = quatkeys.mKeys.begin(); - Vector3KeyList::VecType::const_iterator traniter = trankeys.mKeys.begin(); - FloatKeyList::VecType::const_iterator scaleiter = scalekeys.mKeys.begin(); + Nif::QuaternionKeyList::VecType::const_iterator quatiter = quatkeys.mKeys.begin(); + Nif::Vector3KeyList::VecType::const_iterator traniter = trankeys.mKeys.begin(); + Nif::FloatKeyList::VecType::const_iterator scaleiter = scalekeys.mKeys.begin(); Ogre::Bone *bone = skel->getBone(targets[i]); const Ogre::Quaternion startquat = bone->getInitialOrientation(); @@ -347,7 +369,7 @@ void loadResource(Ogre::Resource *resource) kframe->setRotation(curquat); else { - QuaternionKeyList::VecType::const_iterator last = quatiter-1; + Nif::QuaternionKeyList::VecType::const_iterator last = quatiter-1; float diff = (curtime-last->mTime) / (quatiter->mTime-last->mTime); kframe->setRotation(Ogre::Quaternion::nlerp(diff, lastquat, curquat)); } @@ -355,7 +377,7 @@ void loadResource(Ogre::Resource *resource) kframe->setTranslate(curtrans); else { - Vector3KeyList::VecType::const_iterator last = traniter-1; + Nif::Vector3KeyList::VecType::const_iterator last = traniter-1; float diff = (curtime-last->mTime) / (traniter->mTime-last->mTime); kframe->setTranslate(lasttrans + ((curtrans-lasttrans)*diff)); } @@ -363,7 +385,7 @@ void loadResource(Ogre::Resource *resource) kframe->setScale(curscale); else { - FloatKeyList::VecType::const_iterator last = scaleiter-1; + Nif::FloatKeyList::VecType::const_iterator last = scaleiter-1; float diff = (curtime-last->mTime) / (scaleiter->mTime-last->mTime); kframe->setScale(lastscale + ((curscale-lastscale)*diff)); } @@ -485,7 +507,7 @@ static void fail(const std::string &msg) public: -static Ogre::String getMaterial(const NiTriShape *shape, const Ogre::String &name, const Ogre::String &group) +static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String &name, const Ogre::String &group) { Ogre::MaterialManager &matMgr = Ogre::MaterialManager::getSingleton(); Ogre::MaterialPtr material = matMgr.getByName(name); @@ -505,24 +527,24 @@ static Ogre::String getMaterial(const NiTriShape *shape, const Ogre::String &nam bool vertexColour = (shape->data->colors.size() != 0); // These are set below if present - const NiTexturingProperty *t = NULL; - const NiMaterialProperty *m = NULL; - const NiAlphaProperty *a = NULL; + const Nif::NiTexturingProperty *t = NULL; + const Nif::NiMaterialProperty *m = NULL; + const Nif::NiAlphaProperty *a = NULL; // Scan the property list for material information - const PropertyList &list = shape->props; + const Nif::PropertyList &list = shape->props; for (size_t i = 0;i < list.length();i++) { // Entries may be empty if (list[i].empty()) continue; - const Property *pr = list[i].getPtr(); - if (pr->recType == RC_NiTexturingProperty) - t = static_cast(pr); - else if (pr->recType == RC_NiMaterialProperty) - m = static_cast(pr); - else if (pr->recType == RC_NiAlphaProperty) - a = static_cast(pr); + const Nif::Property *pr = list[i].getPtr(); + if (pr->recType == Nif::RC_NiTexturingProperty) + t = static_cast(pr); + else if (pr->recType == Nif::RC_NiMaterialProperty) + m = static_cast(pr); + else if (pr->recType == Nif::RC_NiAlphaProperty) + a = static_cast(pr); else warn("Skipped property type: "+pr->recName); } @@ -530,7 +552,7 @@ static Ogre::String getMaterial(const NiTriShape *shape, const Ogre::String &nam // Texture if (t && t->textures[0].inUse) { - NiSourceTexture *st = t->textures[0].texture.getPtr(); + Nif::NiSourceTexture *st = t->textures[0].texture.getPtr(); if (st->external) { /* Bethesda at some at some point converted all their BSA @@ -991,7 +1013,7 @@ public: if(node->recType == Nif::RC_NiTriShape) { - const NiTriShape *shape = dynamic_cast(node); + const Nif::NiTriShape *shape = dynamic_cast(node); Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); std::string fullname = mName+"@shape="+shape->name; @@ -1220,3 +1242,5 @@ extern "C" void ogre_insertTexture(char* name, uint32_t width, uint32_t height, */ + +} // nsmaepace NifOgre From 683ced54a09eefd8dc38f8d64341a30d289f45a2 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 4 Jan 2013 19:41:37 -0800 Subject: [PATCH 129/136] Store and retrieve the node text keys in the bones' user object bindings --- components/nifogre/ogre_nif_loader.cpp | 67 +++++++++++++------------- components/nifogre/ogre_nif_loader.hpp | 2 +- 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index badadfe01..6ee02438a 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -49,22 +49,20 @@ typedef unsigned char ubyte; -namespace Nif +namespace std { -// These operators allow the Nif extra data types to be stored in an Ogre::Any +// These operators allow extra data types to be stored in an Ogre::Any // object, which can then be stored in user object bindings on the nodes // TODO: Do something useful -std::ostream& operator<<(std::ostream &o, const Nif::NiTextKeyExtraData&) +ostream& operator<<(ostream &o, const NifOgre::TextKeyMap&) { return o; } -} // namespace Nif - +} namespace NifOgre { - // Helper class that computes the bounding box and of a mesh class BoundsFinder { @@ -164,8 +162,9 @@ static void fail(const std::string &msg) } -static void insertTextKeys(const Nif::NiTextKeyExtraData *tk, TextKeyMap *textkeys) +static TextKeyMap extractTextKeys(const Nif::NiTextKeyExtraData *tk) { + TextKeyMap textkeys; for(size_t i = 0;i < tk->list.size();i++) { const std::string &str = tk->list[i].text; @@ -178,11 +177,12 @@ static void insertTextKeys(const Nif::NiTextKeyExtraData *tk, TextKeyMap *textke break; std::string::size_type nextpos = std::min(str.find('\r', pos), str.find('\n', pos)); - textkeys->insert(std::make_pair(tk->list[i].time, str.substr(pos, nextpos-pos))); + textkeys.insert(std::make_pair(tk->list[i].time, str.substr(pos, nextpos-pos))); pos = nextpos; } } + return textkeys; } @@ -215,7 +215,7 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, std::vectorrecType == Nif::RC_NiTextKeyExtraData) { const Nif::NiTextKeyExtraData *tk = static_cast(e.getPtr()); - bone->getUserObjectBindings().setUserAny(tk->recName, Ogre::Any(*tk)); + bone->getUserObjectBindings().setUserAny("TextKeyExtraData", Ogre::Any(extractTextKeys(tk))); } e = e->extra; } @@ -394,35 +394,18 @@ void loadResource(Ogre::Resource *resource) anim->optimise(); } -bool createSkeleton(const std::string &name, const std::string &group, TextKeyMap *textkeys, const Nif::Node *node) +bool createSkeleton(const std::string &name, const std::string &group, const Nif::Node *node) { - if(textkeys) - { - Nif::ExtraPtr e = node->extra; - while(!e.empty()) - { - if(e->recType == Nif::RC_NiTextKeyExtraData) - { - const Nif::NiTextKeyExtraData *tk = static_cast(e.getPtr()); - insertTextKeys(tk, textkeys); - } - e = e->extra; - } - } - if(node->boneTrafo != NULL) { Ogre::SkeletonManager &skelMgr = Ogre::SkeletonManager::getSingleton(); - Ogre::SkeletonPtr skel = skelMgr.getByName(name); if(skel.isNull()) { NIFSkeletonLoader *loader = &sLoaders[name]; skel = skelMgr.create(name, group, true, loader); } - - if(!textkeys || textkeys->size() > 0) - return true; + return true; } const Nif::NiNode *ninode = dynamic_cast(node); @@ -433,7 +416,7 @@ bool createSkeleton(const std::string &name, const std::string &group, TextKeyMa { if(!children[i].empty()) { - if(createSkeleton(name, group, textkeys, children[i].getPtr())) + if(createSkeleton(name, group, children[i].getPtr())) return true; } } @@ -1057,7 +1040,7 @@ public: NIFMeshLoader::LoaderMap NIFMeshLoader::sLoaders; -MeshPairList NIFLoader::load(std::string name, std::string skelName, TextKeyMap *textkeys, const std::string &group) +MeshPairList NIFLoader::load(std::string name, std::string skelName, const std::string &group) { MeshPairList meshes; @@ -1084,7 +1067,7 @@ MeshPairList NIFLoader::load(std::string name, std::string skelName, TextKeyMap } NIFSkeletonLoader skelldr; - bool hasSkel = skelldr.createSkeleton(skelName, group, textkeys, node); + bool hasSkel = skelldr.createSkeleton(skelName, group, node); NIFMeshLoader meshldr(name, group, (hasSkel ? skelName : std::string())); meshldr.createMeshes(node, meshes); @@ -1096,7 +1079,7 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, TextKeyMap *textke { EntityList entitylist; - MeshPairList meshes = load(name, name, textkeys, group); + MeshPairList meshes = load(name, name, group); if(meshes.size() == 0) return entitylist; @@ -1109,6 +1092,24 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, TextKeyMap *textke entitylist.mSkelBase = entity; } + if(entitylist.mSkelBase) + { + // Would be nice if Ogre::SkeletonInstance allowed access to the 'master' Ogre::SkeletonPtr. + Ogre::SkeletonManager &skelMgr = Ogre::SkeletonManager::getSingleton(); + Ogre::SkeletonPtr skel = skelMgr.getByName(entitylist.mSkelBase->getSkeleton()->getName()); + Ogre::Skeleton::BoneIterator iter = skel->getBoneIterator(); + while(iter.hasMoreElements()) + { + Ogre::Bone *bone = iter.getNext(); + const Ogre::Any &data = bone->getUserObjectBindings().getUserAny("TextKeyExtraData"); + if(!data.isEmpty()) + { + *textkeys = Ogre::any_cast(data); + break; + } + } + } + if(entitylist.mSkelBase) { parent->attachObject(entitylist.mSkelBase); @@ -1140,7 +1141,7 @@ EntityList NIFLoader::createEntities(Ogre::Entity *parent, const std::string &bo { EntityList entitylist; - MeshPairList meshes = load(name, parent->getMesh()->getSkeletonName(), NULL, group); + MeshPairList meshes = load(name, parent->getMesh()->getSkeletonName(), group); if(meshes.size() == 0) return entitylist; diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index 74b6f44df..3e05c5873 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -69,7 +69,7 @@ typedef std::vector< std::pair > MeshPairList; */ class NIFLoader { - static MeshPairList load(std::string name, std::string skelName, TextKeyMap *textkeys, const std::string &group); + static MeshPairList load(std::string name, std::string skelName, const std::string &group); public: static EntityList createEntities(Ogre::Entity *parent, const std::string &bonename, From 917bbc4e110672e8c0ef7bc8ea8d6282213fdeed Mon Sep 17 00:00:00 2001 From: Jordan Milne Date: Sat, 5 Jan 2013 00:26:33 -0400 Subject: [PATCH 130/136] Create static and non-discardable textures with the right parameters (should fix Issue 443) --- libs/openengine/ogre/imagerotate.cpp | 21 ++++++++++++++++++--- libs/openengine/ogre/renderer.cpp | 2 +- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/libs/openengine/ogre/imagerotate.cpp b/libs/openengine/ogre/imagerotate.cpp index 11fd5eea6..3dd584078 100644 --- a/libs/openengine/ogre/imagerotate.cpp +++ b/libs/openengine/ogre/imagerotate.cpp @@ -16,6 +16,8 @@ void ImageRotate::rotate(const std::string& sourceImage, const std::string& dest { Root* root = Ogre::Root::getSingletonPtr(); + std::string destImageRot = std::string(destImage) + std::string("_rot"); + SceneManager* sceneMgr = root->createSceneManager(ST_GENERIC); Camera* camera = sceneMgr->createCamera("ImageRotateCamera"); @@ -48,8 +50,8 @@ void ImageRotate::rotate(const std::string& sourceImage, const std::string& dest unsigned int width = sourceTexture->getWidth(); unsigned int height = sourceTexture->getHeight(); - TexturePtr destTexture = TextureManager::getSingleton().createManual( - destImage, + TexturePtr destTextureRot = TextureManager::getSingleton().createManual( + destImageRot, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, width, height, @@ -57,7 +59,7 @@ void ImageRotate::rotate(const std::string& sourceImage, const std::string& dest PF_FLOAT16_RGBA, TU_RENDERTARGET); - RenderTarget* rtt = destTexture->getBuffer()->getRenderTarget(); + RenderTarget* rtt = destTextureRot->getBuffer()->getRenderTarget(); rtt->setAutoUpdated(false); Viewport* vp = rtt->addViewport(camera); vp->setOverlaysEnabled(false); @@ -66,7 +68,20 @@ void ImageRotate::rotate(const std::string& sourceImage, const std::string& dest rtt->update(); + //copy the rotated image to a static texture + TexturePtr destTexture = TextureManager::getSingleton().createManual( + destImage, + ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + TEX_TYPE_2D, + width, height, + 0, + PF_FLOAT16_RGBA, + Ogre::TU_STATIC); + + destTexture->getBuffer()->blit(destTextureRot->getBuffer()); + // remove all the junk we've created + TextureManager::getSingleton().remove(destImageRot); MaterialManager::getSingleton().remove("ImageRotateMaterial"); root->destroySceneManager(sceneMgr); delete rect; diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 87ebe1139..3cdb00518 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -226,7 +226,7 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings& 1, 1, 0, Ogre::PF_A8R8G8B8, - Ogre::TU_DYNAMIC_WRITE_ONLY); + Ogre::TU_WRITE_ONLY); } void OgreRenderer::createScene(const std::string& camName, float fov, float nearClip) From 3131e8dae6de127c4d3c8ed95c773b56442da92f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 4 Jan 2013 20:33:26 -0800 Subject: [PATCH 131/136] Don't get the text keys if they're not being requested --- components/nifogre/ogre_nif_loader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 6ee02438a..27e4e7440 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -1092,7 +1092,7 @@ EntityList NIFLoader::createEntities(Ogre::SceneNode *parent, TextKeyMap *textke entitylist.mSkelBase = entity; } - if(entitylist.mSkelBase) + if(entitylist.mSkelBase && textkeys) { // Would be nice if Ogre::SkeletonInstance allowed access to the 'master' Ogre::SkeletonPtr. Ogre::SkeletonManager &skelMgr = Ogre::SkeletonManager::getSingleton(); From 8a086e3afbc510d70c66955c19a99d44b797bed7 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 4 Jan 2013 20:58:35 -0800 Subject: [PATCH 132/136] Cache the mesh names from the mesh/skeleton pairs --- components/nifogre/ogre_nif_loader.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 27e4e7440..31d873489 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -1040,13 +1040,19 @@ public: NIFMeshLoader::LoaderMap NIFMeshLoader::sLoaders; +typedef std::map MeshPairMap; +static MeshPairMap sMeshPairMap; + MeshPairList NIFLoader::load(std::string name, std::string skelName, const std::string &group) { - MeshPairList meshes; - std::transform(name.begin(), name.end(), name.begin(), ::tolower); std::transform(skelName.begin(), skelName.end(), skelName.begin(), ::tolower); + MeshPairMap::const_iterator meshiter = sMeshPairMap.find(name+"@skel="+skelName); + if(meshiter != sMeshPairMap.end()) + return meshiter->second; + + MeshPairList &meshes = sMeshPairMap[name+"@skel="+skelName]; Nif::NIFFile nif(name); if (nif.numRecords() < 1) { @@ -1067,7 +1073,7 @@ MeshPairList NIFLoader::load(std::string name, std::string skelName, const std:: } NIFSkeletonLoader skelldr; - bool hasSkel = skelldr.createSkeleton(skelName, group, node); + bool hasSkel = skelldr.createSkeleton(name, group, node); NIFMeshLoader meshldr(name, group, (hasSkel ? skelName : std::string())); meshldr.createMeshes(node, meshes); From 3ed77ca1890b90c9c1d9fe7a4cddbfea1e06933b Mon Sep 17 00:00:00 2001 From: Jordan Milne Date: Sat, 5 Jan 2013 01:17:07 -0400 Subject: [PATCH 133/136] Include C++ header instead --- components/files/constrainedfiledatastream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/files/constrainedfiledatastream.cpp b/components/files/constrainedfiledatastream.cpp index 9e36f9075..63bd3490f 100644 --- a/components/files/constrainedfiledatastream.cpp +++ b/components/files/constrainedfiledatastream.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include namespace { From 63f09462fd1395f1550df11eb400e0e81959c14b Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Sun, 6 Jan 2013 01:37:58 +0100 Subject: [PATCH 134/136] to_utf8, Utf8Encoder: pass encoding as constructor parameter Edit other files accordingly. --- apps/esmtool/esmtool.cpp | 25 ++++++++----------------- apps/launcher/model/datafilesmodel.cpp | 6 ++++-- apps/mwiniimporter/importer.cpp | 3 +-- apps/openmw/engine.cpp | 7 +++++-- apps/openmw/mwworld/worldimp.cpp | 4 ++-- apps/openmw/mwworld/worldimp.hpp | 2 +- components/esm/esmreader.cpp | 7 +++---- components/esm/esmreader.hpp | 7 +++---- components/esm/esmwriter.cpp | 20 +++----------------- components/esm/esmwriter.hpp | 8 +++----- components/to_utf8/to_utf8.cpp | 10 ++-------- components/to_utf8/to_utf8.hpp | 6 +----- components/translation/translation.cpp | 7 +++---- components/translation/translation.hpp | 5 ++--- 14 files changed, 41 insertions(+), 76 deletions(-) diff --git a/apps/esmtool/esmtool.cpp b/apps/esmtool/esmtool.cpp index 0cd6e3905..fbfc884d7 100644 --- a/apps/esmtool/esmtool.cpp +++ b/apps/esmtool/esmtool.cpp @@ -165,23 +165,12 @@ bool parseOptions (int argc, char** argv, Arguments &info) // Font encoding settings info.encoding = variables["encoding"].as(); - if (info.encoding == "win1250") + if(info.encoding != "win1250" && info.encoding != "win1251" && info.encoding != "win1252") { - std::cout << "Using Central and Eastern European font encoding." << std::endl; - } - else if (info.encoding == "win1251") - { - std::cout << "Using Cyrillic font encoding." << std::endl; - } - else - { - if(info.encoding != "win1252") - { - std::cout << info.encoding << " is not a valid encoding option." << std::endl; - info.encoding = "win1252"; - } - std::cout << "Using default (English) font encoding." << std::endl; + std::cout << info.encoding << " is not a valid encoding option." << std::endl; + info.encoding = "win1252"; } + std::cout << ToUTF8::encodingUsingMessage(info.encoding) << std::endl; return true; } @@ -262,7 +251,8 @@ void printRaw(ESM::ESMReader &esm) int load(Arguments& info) { ESM::ESMReader& esm = info.reader; - esm.setEncoding(ToUTF8::calculateEncoding(info.encoding)); + ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(info.encoding)); + esm.setEncoder(&encoder); std::string filename = info.filename; std::cout << "Loading file: " << filename << std::endl; @@ -432,7 +422,8 @@ int clone(Arguments& info) std::cout << std::endl << "Saving records to: " << info.outname << "..." << std::endl; ESM::ESMWriter& esm = info.writer; - esm.setEncoding(info.encoding); + ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(info.encoding)); + esm.setEncoder(&encoder); esm.setAuthor(info.data.author); esm.setDescription(info.data.description); esm.setVersion(info.data.version); diff --git a/apps/launcher/model/datafilesmodel.cpp b/apps/launcher/model/datafilesmodel.cpp index 716c9e902..e84dbe0ac 100644 --- a/apps/launcher/model/datafilesmodel.cpp +++ b/apps/launcher/model/datafilesmodel.cpp @@ -272,7 +272,8 @@ void DataFilesModel::addMasters(const QString &path) foreach (const QString &path, dir.entryList()) { try { ESM::ESMReader fileReader; - fileReader.setEncoding(ToUTF8::calculateEncoding(mEncoding.toStdString())); + ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(mEncoding.toStdString())); + fileReader.setEncoder(&encoder); fileReader.open(dir.absoluteFilePath(path).toStdString()); ESM::ESMReader::MasterList mlist = fileReader.getMasters(); @@ -335,7 +336,8 @@ void DataFilesModel::addPlugins(const QString &path) try { ESM::ESMReader fileReader; - fileReader.setEncoding(ToUTF8::calculateEncoding(mEncoding.toStdString())); + ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(mEncoding.toStdString())); + fileReader.setEncoder(&encoder); fileReader.open(dir.absoluteFilePath(path).toStdString()); ESM::ESMReader::MasterList mlist = fileReader.getMasters(); diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 5c3dedd04..6a7274e0a 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -649,8 +649,7 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(std::string filename) { std::string section(""); MwIniImporter::multistrmap map; boost::iostreams::streamfile(filename.c_str()); - ToUTF8::Utf8Encoder encoder; - encoder.setEncoding(mEncoding); + ToUTF8::Utf8Encoder encoder(mEncoding); std::string line; while (std::getline(file, line)) { diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index e2d28a808..aadeb7f3a 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -331,11 +331,15 @@ void OMW::Engine::go() // cursor replacer (converts the cursor from the bsa so they can be used by mygui) MWGui::CursorReplace replacer; + // Create encoder + ToUTF8::Utf8Encoder encoder (mEncoding); + // Create the world mEnvironment.setWorld (new MWWorld::World (*mOgre, mFileCollections, mMaster, - mResDir, mCfgMgr.getCachePath(), mNewGame, mEncoding, mFallbackMap)); + mResDir, mCfgMgr.getCachePath(), mNewGame, &encoder, mFallbackMap)); //Load translation data + mTranslationDataStorage.setEncoder(&encoder); mTranslationDataStorage.loadTranslationData(mFileCollections, mMaster); // Create window manager - this manages all the MW-specific GUI windows @@ -494,7 +498,6 @@ void OMW::Engine::showFPS(int level) void OMW::Engine::setEncoding(const ToUTF8::FromType& encoding) { mEncoding = encoding; - mTranslationDataStorage.setEncoding (encoding); } void OMW::Engine::setFallbackValues(std::map fallbackMap) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 3995123b0..4f60f6ef4 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -170,7 +170,7 @@ namespace MWWorld World::World (OEngine::Render::OgreRenderer& renderer, const Files::Collections& fileCollections, const std::string& master, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, - const ToUTF8::FromType& encoding, std::map fallbackMap) + ToUTF8::Utf8Encoder* encoder, std::map fallbackMap) : mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), mSky (true), mCells (mStore, mEsm), mNumFacing(0) @@ -187,7 +187,7 @@ namespace MWWorld std::cout << "Loading ESM " << masterPath.string() << "\n"; // This parses the ESM file and loads a sample cell - mEsm.setEncoding(encoding); + mEsm.setEncoder(encoder); mEsm.open (masterPath.string()); mStore.load (mEsm); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 71ae9597f..d29adebf4 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -95,7 +95,7 @@ namespace MWWorld World (OEngine::Render::OgreRenderer& renderer, const Files::Collections& fileCollections, const std::string& master, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, - const ToUTF8::FromType& encoding, std::map fallbackMap); + ToUTF8::Utf8Encoder* encoder, std::map fallbackMap); virtual ~World(); diff --git a/components/esm/esmreader.cpp b/components/esm/esmreader.cpp index 5cd99a64a..99f7971b1 100644 --- a/components/esm/esmreader.cpp +++ b/components/esm/esmreader.cpp @@ -344,7 +344,7 @@ std::string ESMReader::getString(int size) getExact(ptr, size); // Convert to UTF8 and return - return mEncoder.getUtf8(ptr, size); + return mEncoder->getUtf8(ptr, size); } void ESMReader::fail(const std::string &msg) @@ -362,10 +362,9 @@ void ESMReader::fail(const std::string &msg) throw std::runtime_error(ss.str()); } -void ESMReader::setEncoding(const ToUTF8::FromType& encoding) +void ESMReader::setEncoder(ToUTF8::Utf8Encoder* encoder) { - mEncoding = encoding; - mEncoder.setEncoding(encoding); + mEncoder = encoder; } } diff --git a/components/esm/esmreader.hpp b/components/esm/esmreader.hpp index 57503aea7..d52be25aa 100644 --- a/components/esm/esmreader.hpp +++ b/components/esm/esmreader.hpp @@ -235,8 +235,8 @@ public: /// Used for error handling void fail(const std::string &msg); - /// Sets font encoding for ESM strings - void setEncoding(const ToUTF8::FromType& encoding); + /// Sets font encoder for ESM strings + void setEncoder(ToUTF8::Utf8Encoder* encoder); private: Ogre::DataStreamPtr mEsm; @@ -251,8 +251,7 @@ private: SaveData mSaveData; MasterList mMasters; - ToUTF8::FromType mEncoding; - ToUTF8::Utf8Encoder mEncoder; + ToUTF8::Utf8Encoder* mEncoder; }; } #endif diff --git a/components/esm/esmwriter.cpp b/components/esm/esmwriter.cpp index a00c7971d..e2f878a25 100644 --- a/components/esm/esmwriter.cpp +++ b/components/esm/esmwriter.cpp @@ -158,7 +158,7 @@ void ESMWriter::writeHString(const std::string& data) else { // Convert to UTF8 and return - std::string ascii = m_encoder.getLegacyEnc(data); + std::string ascii = m_encoder->getLegacyEnc(data); write(ascii.c_str(), ascii.size()); } @@ -188,23 +188,9 @@ void ESMWriter::write(const char* data, int size) m_stream->write(data, size); } -void ESMWriter::setEncoding(const std::string& encoding) +void ESMWriter::setEncoder(ToUTF8::Utf8Encoder* encoder) { - if (encoding == "win1250") - { - m_encoding = ToUTF8::WINDOWS_1250; - } - else if (encoding == "win1251") - { - m_encoding = ToUTF8::WINDOWS_1251; - } - else - { - // Default Latin encoding - m_encoding = ToUTF8::WINDOWS_1252; - } - - m_encoder.setEncoding(m_encoding); + m_encoder = encoder; } } diff --git a/components/esm/esmwriter.hpp b/components/esm/esmwriter.hpp index 20bc5da12..b557a29ad 100644 --- a/components/esm/esmwriter.hpp +++ b/components/esm/esmwriter.hpp @@ -6,7 +6,7 @@ #include #include "esmcommon.hpp" -#include "../to_utf8/to_utf8.hpp" +#include namespace ESM { @@ -24,7 +24,7 @@ public: void setVersion(int ver); int getType(); void setType(int type); - void setEncoding(const std::string& encoding); // Write strings as UTF-8? + void setEncoder(ToUTF8::Utf8Encoder *encoding); // Write strings as UTF-8? void setAuthor(const std::string& author); void setDescription(const std::string& desc); @@ -94,12 +94,10 @@ private: std::list m_records; std::ostream* m_stream; std::streampos m_headerPos; - ToUTF8::FromType m_encoding; - ToUTF8::Utf8Encoder m_encoder; + ToUTF8::Utf8Encoder* m_encoder; int m_recordCount; HEDRstruct m_header; - SaveData m_saveData; }; } diff --git a/components/to_utf8/to_utf8.cpp b/components/to_utf8/to_utf8.cpp index 5efec36a4..275f5483f 100644 --- a/components/to_utf8/to_utf8.cpp +++ b/components/to_utf8/to_utf8.cpp @@ -43,16 +43,10 @@ using namespace ToUTF8; -Utf8Encoder::Utf8Encoder(void): +Utf8Encoder::Utf8Encoder(const FromType sourceEncoding): mOutput(50*1024) { -} - -void Utf8Encoder::setEncoding(const FromType sourceEncoding) -{ - mEncoding = sourceEncoding; - - switch (mEncoding) + switch (sourceEncoding) { case ToUTF8::WINDOWS_1252: { diff --git a/components/to_utf8/to_utf8.hpp b/components/to_utf8/to_utf8.hpp index bfba8a1ac..e150cf17b 100644 --- a/components/to_utf8/to_utf8.hpp +++ b/components/to_utf8/to_utf8.hpp @@ -24,9 +24,7 @@ namespace ToUTF8 class Utf8Encoder { public: - Utf8Encoder(void); - - void setEncoding(const FromType sourceEncoding); + Utf8Encoder(FromType sourceEncoding); // Convert to UTF8 from the previously given code page. std::string getUtf8(const char *input, int size); @@ -48,9 +46,7 @@ namespace ToUTF8 size_t getLength2(const char* input, bool &ascii); void copyFromArray2(const char*& chp, char* &out); - FromType mEncoding; std::vector mOutput; - int mSize; char* translationArray; }; } diff --git a/components/translation/translation.cpp b/components/translation/translation.cpp index 002446e4f..184cf399c 100644 --- a/components/translation/translation.cpp +++ b/components/translation/translation.cpp @@ -50,7 +50,7 @@ namespace Translation if (!line.empty()) { - line = mEncoder.getUtf8(line); + line = mEncoder->getUtf8(line); size_t tab_pos = line.find('\t'); if (tab_pos != std::string::npos && tab_pos > 0 && tab_pos < line.size() - 1) @@ -101,10 +101,9 @@ namespace Translation return phrase; } - void Storage::setEncoding (const ToUTF8::FromType& encoding) + void Storage::setEncoder(ToUTF8::Utf8Encoder* encoder) { - mEncoding = encoding; - mEncoder.setEncoding(encoding); + mEncoder = encoder; } bool Storage::hasTranslation() const diff --git a/components/translation/translation.hpp b/components/translation/translation.hpp index 6c3e4df86..bca9ea255 100644 --- a/components/translation/translation.hpp +++ b/components/translation/translation.hpp @@ -19,7 +19,7 @@ namespace Translation // Standard form usually means nominative case std::string topicStandardForm(const std::string& phrase) const; - void setEncoding (const ToUTF8::FromType& encoding); + void setEncoder(ToUTF8::Utf8Encoder* encoder); bool hasTranslation() const; @@ -34,8 +34,7 @@ namespace Translation void loadDataFromStream(ContainerType& container, std::istream& stream); - ToUTF8::FromType mEncoding; - ToUTF8::Utf8Encoder mEncoder; + ToUTF8::Utf8Encoder* mEncoder; ContainerType mCellNamesTranslations, mTopicIDs, mPhraseForms; }; } From 0b7d11d38d99033a09bed6b22c75378f692653a5 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Sun, 6 Jan 2013 11:39:18 +0100 Subject: [PATCH 135/136] to_utf8 test: fix Utf8Encoder constructor --- components/to_utf8/tests/to_utf8_test.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/to_utf8/tests/to_utf8_test.cpp b/components/to_utf8/tests/to_utf8_test.cpp index 4bba0cf90..3fcddd158 100644 --- a/components/to_utf8/tests/to_utf8_test.cpp +++ b/components/to_utf8/tests/to_utf8_test.cpp @@ -18,8 +18,7 @@ void testEncoder(ToUTF8::FromType encoding, const std::string &legacyEncFile, std::string utf8Line = getFirstLine(utf8File); // create an encoder for specified character encoding - ToUTF8::Utf8Encoder encoder; - encoder.setEncoding(encoding); + ToUTF8::Utf8Encoder encoder (encoding); // convert text to UTF-8 std::string convertedUtf8Line = encoder.getUtf8(legacyEncLine); From 1d3f3bcce30b211ba92b03fee3b7814042f0048c Mon Sep 17 00:00:00 2001 From: Nikolay Kasyanov Date: Sun, 6 Jan 2013 19:19:12 +0400 Subject: [PATCH 136/136] clang build fix --- components/files/constrainedfiledatastream.cpp | 4 ++++ components/translation/translation.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/components/files/constrainedfiledatastream.cpp b/components/files/constrainedfiledatastream.cpp index 63bd3490f..dd2985e56 100644 --- a/components/files/constrainedfiledatastream.cpp +++ b/components/files/constrainedfiledatastream.cpp @@ -3,7 +3,11 @@ #include #include +#ifndef __clang__ #include +#else +#include +#endif namespace { diff --git a/components/translation/translation.cpp b/components/translation/translation.cpp index fb5b03861..37bceafbf 100644 --- a/components/translation/translation.cpp +++ b/components/translation/translation.cpp @@ -30,7 +30,7 @@ namespace Translation { std::string path = dataFileCollections.getCollection (extension).getPath (fileName).string(); - std::ifstream stream (path); + std::ifstream stream (path.c_str()); if (!stream.is_open()) throw std::runtime_error ("failed to open translation file: " + fileName);