mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 01:26:39 +00:00 
			
		
		
		
	Merge branch 'master' of https://github.com/zinnschlag/openmw.git into AICombat
This commit is contained in:
		
						commit
						f9bfbc8764
					
				
					 150 changed files with 2025 additions and 2092 deletions
				
			
		| 
						 | 
				
			
			@ -19,7 +19,7 @@ include (OpenMWMacros)
 | 
			
		|||
# Version
 | 
			
		||||
 | 
			
		||||
set (OPENMW_VERSION_MAJOR 0)
 | 
			
		||||
set (OPENMW_VERSION_MINOR 25)
 | 
			
		||||
set (OPENMW_VERSION_MINOR 26)
 | 
			
		||||
set (OPENMW_VERSION_RELEASE 0)
 | 
			
		||||
 | 
			
		||||
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,7 +24,6 @@ set(LAUNCHER_HEADER
 | 
			
		|||
    graphicspage.hpp
 | 
			
		||||
    maindialog.hpp
 | 
			
		||||
    playpage.hpp
 | 
			
		||||
    unshieldthread.hpp
 | 
			
		||||
    textslotmsgbox.hpp
 | 
			
		||||
 | 
			
		||||
    settings/gamesettings.hpp
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +46,6 @@ set(LAUNCHER_HEADER_MOC
 | 
			
		|||
    graphicspage.hpp
 | 
			
		||||
    maindialog.hpp
 | 
			
		||||
    playpage.hpp
 | 
			
		||||
    unshieldthread.hpp
 | 
			
		||||
    textslotmsgbox.hpp
 | 
			
		||||
 | 
			
		||||
    utils/checkablemessagebox.hpp
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,11 @@
 | 
			
		|||
#include <QDesktopWidget>
 | 
			
		||||
#include <QMessageBox>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
 | 
			
		||||
#ifdef __APPLE__
 | 
			
		||||
// We need to do this because of Qt: https://bugreports.qt-project.org/browse/QTBUG-22154
 | 
			
		||||
#define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
 | 
			
		||||
#endif
 | 
			
		||||
#include <SDL.h>
 | 
			
		||||
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,10 @@
 | 
			
		|||
#include <QDir>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
 | 
			
		||||
#ifdef __APPLE__
 | 
			
		||||
// We need to do this because of Qt: https://bugreports.qt-project.org/browse/QTBUG-22154
 | 
			
		||||
#define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
 | 
			
		||||
#endif
 | 
			
		||||
#include <SDL.h>
 | 
			
		||||
 | 
			
		||||
#include "maindialog.hpp"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -216,7 +216,12 @@ namespace
 | 
			
		|||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if(copy)
 | 
			
		||||
                    bfs::copy_file(dir->path(), to / dir->path().filename());
 | 
			
		||||
                {
 | 
			
		||||
                    bfs::path dest = to / dir->path().filename();
 | 
			
		||||
                    if(bfs::exists(dest))
 | 
			
		||||
                        bfs::remove_all(dest);
 | 
			
		||||
                    bfs::copy_file(dir->path(), dest);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                    bfs::rename(dir->path(), to / dir->path().filename());
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -481,6 +486,7 @@ void UnshieldThread::run()
 | 
			
		|||
 | 
			
		||||
UnshieldThread::UnshieldThread()
 | 
			
		||||
{
 | 
			
		||||
    unshield_set_log_level(0);
 | 
			
		||||
    mMorrowindDone = false;
 | 
			
		||||
    mTribunalDone = false;
 | 
			
		||||
    mBloodmoonDone = false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,6 @@
 | 
			
		|||
 | 
			
		||||
#include <libunshield.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UnshieldThread : public QThread
 | 
			
		||||
{
 | 
			
		||||
   Q_OBJECT
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -135,7 +135,7 @@ if(WIN32)
 | 
			
		|||
    set(QT_USE_QTMAIN TRUE)
 | 
			
		||||
endif(WIN32)
 | 
			
		||||
 | 
			
		||||
find_package(Qt4 COMPONENTS QtCore QtGui QtXml QtXmlPatterns REQUIRED)
 | 
			
		||||
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork QtXml QtXmlPatterns REQUIRED)
 | 
			
		||||
include(${QT_USE_FILE})
 | 
			
		||||
 | 
			
		||||
qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,17 +2,24 @@
 | 
			
		|||
#include "editor.hpp"
 | 
			
		||||
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QLocalServer>
 | 
			
		||||
#include <QLocalSocket>
 | 
			
		||||
 | 
			
		||||
#include "model/doc/document.hpp"
 | 
			
		||||
#include "model/world/data.hpp"
 | 
			
		||||
 | 
			
		||||
CS::Editor::Editor() : mViewManager (mDocumentManager)
 | 
			
		||||
{
 | 
			
		||||
    mIpcServerName = "org.openmw.OpenCS";
 | 
			
		||||
 | 
			
		||||
    connect (&mViewManager, SIGNAL (newDocumentRequest ()), this, SLOT (createDocument ()));
 | 
			
		||||
    connect (&mViewManager, SIGNAL (loadDocumentRequest ()), this, SLOT (loadDocument ()));
 | 
			
		||||
    connect (&mViewManager, SIGNAL (editSettingsRequest()), this, SLOT (showSettings ()));
 | 
			
		||||
 | 
			
		||||
    connect (&mStartup, SIGNAL (createDocument()), this, SLOT (createDocument ()));
 | 
			
		||||
    connect (&mStartup, SIGNAL (createGame()), this, SLOT (createDocument ())); /// \todo split
 | 
			
		||||
    connect (&mStartup, SIGNAL (createAddon()), this, SLOT (createDocument ()));
 | 
			
		||||
    connect (&mStartup, SIGNAL (loadDocument()), this, SLOT (loadDocument ()));
 | 
			
		||||
    connect (&mStartup, SIGNAL (editConfig()), this, SLOT (showSettings ()));
 | 
			
		||||
 | 
			
		||||
    connect (&mFileDialog, SIGNAL(openFiles()), this, SLOT(openFiles()));
 | 
			
		||||
    connect (&mFileDialog, SIGNAL(createNewFile()), this, SLOT(createNewFile()));
 | 
			
		||||
| 
						 | 
				
			
			@ -65,7 +72,7 @@ void CS::Editor::setupDataFiles()
 | 
			
		|||
    //load the settings into the userSettings instance.
 | 
			
		||||
    const QString settingFileName = "opencs.cfg";
 | 
			
		||||
    CSMSettings::UserSettings::instance().loadSettings(settingFileName);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CS::Editor::createDocument()
 | 
			
		||||
| 
						 | 
				
			
			@ -114,6 +121,44 @@ void CS::Editor::createNewFile()
 | 
			
		|||
    mFileDialog.hide();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CS::Editor::showStartup()
 | 
			
		||||
{
 | 
			
		||||
    if(mStartup.isHidden())
 | 
			
		||||
        mStartup.show();
 | 
			
		||||
    mStartup.raise();
 | 
			
		||||
    mStartup.activateWindow();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CS::Editor::showSettings()
 | 
			
		||||
{
 | 
			
		||||
    if (mSettings.isHidden())
 | 
			
		||||
        mSettings.show();
 | 
			
		||||
 | 
			
		||||
    mSettings.raise();
 | 
			
		||||
    mSettings.activateWindow();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CS::Editor::makeIPCServer()
 | 
			
		||||
{
 | 
			
		||||
    mServer = new QLocalServer(this);
 | 
			
		||||
 | 
			
		||||
    if(mServer->listen(mIpcServerName))
 | 
			
		||||
    {
 | 
			
		||||
        connect(mServer, SIGNAL(newConnection()), this, SLOT(showStartup()));
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mServer->close();
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CS::Editor::connectToIPCServer()
 | 
			
		||||
{
 | 
			
		||||
    mClientSocket = new QLocalSocket(this);
 | 
			
		||||
    mClientSocket->connectToServer(mIpcServerName);
 | 
			
		||||
    mClientSocket->close();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int CS::Editor::run()
 | 
			
		||||
{
 | 
			
		||||
    mStartup.show();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,15 +2,22 @@
 | 
			
		|||
#define CS_EDITOR_H
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QLocalServer>
 | 
			
		||||
#include <QLocalSocket>
 | 
			
		||||
 | 
			
		||||
#ifndef Q_MOC_RUN
 | 
			
		||||
#include <components/files/configurationmanager.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "model/settings/usersettings.hpp"
 | 
			
		||||
#include "model/doc/documentmanager.hpp"
 | 
			
		||||
 | 
			
		||||
#include "view/doc/viewmanager.hpp"
 | 
			
		||||
#include "view/doc/startup.hpp"
 | 
			
		||||
#include "view/doc/filedialog.hpp"
 | 
			
		||||
#include "model/settings/usersettings.hpp"
 | 
			
		||||
 | 
			
		||||
#include "view/settings/usersettingsdialog.hpp"
 | 
			
		||||
 | 
			
		||||
namespace CS
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -22,6 +29,7 @@ namespace CS
 | 
			
		|||
            CSMDoc::DocumentManager mDocumentManager;
 | 
			
		||||
            CSVDoc::ViewManager mViewManager;
 | 
			
		||||
            CSVDoc::StartupDialogue mStartup;
 | 
			
		||||
            CSVSettings::UserSettingsDialog mSettings;
 | 
			
		||||
            FileDialog mFileDialog;
 | 
			
		||||
 | 
			
		||||
            Files::ConfigurationManager mCfgMgr;
 | 
			
		||||
| 
						 | 
				
			
			@ -35,6 +43,9 @@ namespace CS
 | 
			
		|||
 | 
			
		||||
            Editor();
 | 
			
		||||
 | 
			
		||||
            bool makeIPCServer();
 | 
			
		||||
            void connectToIPCServer();
 | 
			
		||||
 | 
			
		||||
            int run();
 | 
			
		||||
            ///< \return error status
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -45,6 +56,16 @@ namespace CS
 | 
			
		|||
            void loadDocument();
 | 
			
		||||
            void openFiles();
 | 
			
		||||
            void createNewFile();
 | 
			
		||||
 | 
			
		||||
            void showStartup();
 | 
			
		||||
 | 
			
		||||
            void showSettings();
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
 | 
			
		||||
            QString mIpcServerName;
 | 
			
		||||
            QLocalServer *mServer;
 | 
			
		||||
            QLocalSocket *mClientSocket;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,5 +39,11 @@ int main(int argc, char *argv[])
 | 
			
		|||
 | 
			
		||||
    CS::Editor editor;
 | 
			
		||||
 | 
			
		||||
    if(!editor.makeIPCServer())
 | 
			
		||||
    {
 | 
			
		||||
    	editor.connectToIPCServer();
 | 
			
		||||
    	return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return editor.run();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,8 @@
 | 
			
		|||
#include <components/misc/stringops.hpp>
 | 
			
		||||
 | 
			
		||||
#include "../world/columns.hpp"
 | 
			
		||||
#include "../world/data.hpp"
 | 
			
		||||
#include "../world/idcollection.hpp"
 | 
			
		||||
 | 
			
		||||
#include "booleannode.hpp"
 | 
			
		||||
#include "ornode.hpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -31,6 +33,7 @@ namespace CSMFilter
 | 
			
		|||
            Type_OpenSquare,
 | 
			
		||||
            Type_CloseSquare,
 | 
			
		||||
            Type_Comma,
 | 
			
		||||
            Type_OneShot,
 | 
			
		||||
            Type_Keyword_True, ///< \attention Keyword enums must be arranged continuously.
 | 
			
		||||
            Type_Keyword_False,
 | 
			
		||||
            Type_Keyword_And,
 | 
			
		||||
| 
						 | 
				
			
			@ -44,21 +47,33 @@ namespace CSMFilter
 | 
			
		|||
        std::string mString;
 | 
			
		||||
        double mNumber;
 | 
			
		||||
 | 
			
		||||
        Token (Type type);
 | 
			
		||||
        Token (Type type = Type_None);
 | 
			
		||||
 | 
			
		||||
        Token (Type type, const std::string& string);
 | 
			
		||||
        ///< Non-string type that can also be interpreted as a string.
 | 
			
		||||
 | 
			
		||||
        Token (const std::string& string);
 | 
			
		||||
 | 
			
		||||
        Token (double number);
 | 
			
		||||
 | 
			
		||||
        operator bool() const;
 | 
			
		||||
 | 
			
		||||
        bool isString() const;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Token::Token (Type type) : mType (type) {}
 | 
			
		||||
 | 
			
		||||
    Token::Token (Type type, const std::string& string) : mType (type), mString (string) {}
 | 
			
		||||
 | 
			
		||||
    Token::Token (const std::string& string) : mType (Type_String), mString (string) {}
 | 
			
		||||
 | 
			
		||||
    Token::Token (double number) : mType (Type_Number), mNumber (number) {}
 | 
			
		||||
 | 
			
		||||
    bool Token::isString() const
 | 
			
		||||
    {
 | 
			
		||||
        return mType==Type_String || mType>=Type_Keyword_True;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Token::operator bool() const
 | 
			
		||||
    {
 | 
			
		||||
        return mType!=Type_None;
 | 
			
		||||
| 
						 | 
				
			
			@ -89,7 +104,7 @@ CSMFilter::Token CSMFilter::Parser::getStringToken()
 | 
			
		|||
    {
 | 
			
		||||
        char c = mInput[mIndex];
 | 
			
		||||
 | 
			
		||||
        if (std::isalpha (c) || c=='_' || (!string.empty() && std::isdigit (c)) || c=='"' ||
 | 
			
		||||
        if (std::isalpha (c) || c==':' || c=='_' || (!string.empty() && std::isdigit (c)) || c=='"' ||
 | 
			
		||||
            (!string.empty() && string[0]=='"'))
 | 
			
		||||
            string += c;
 | 
			
		||||
        else
 | 
			
		||||
| 
						 | 
				
			
			@ -117,7 +132,7 @@ CSMFilter::Token CSMFilter::Parser::getStringToken()
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        if (string[0]=='"')
 | 
			
		||||
            string = string.substr (1, string.size()-2);
 | 
			
		||||
            return string.substr (1, string.size()-2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return checkKeywords (string);
 | 
			
		||||
| 
						 | 
				
			
			@ -171,15 +186,15 @@ CSMFilter::Token CSMFilter::Parser::checkKeywords (const Token& token)
 | 
			
		|||
    {
 | 
			
		||||
        "true", "false",
 | 
			
		||||
        "and", "or", "not",
 | 
			
		||||
        "text", "value",
 | 
			
		||||
        "string", "value",
 | 
			
		||||
        0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    std::string string = Misc::StringUtils::lowerCase (token.mString);
 | 
			
		||||
 | 
			
		||||
    for (int i=0; sKeywords[i]; ++i)
 | 
			
		||||
        if (sKeywords[i]==string)
 | 
			
		||||
            return Token (static_cast<Token::Type> (i+Token::Type_Keyword_True));
 | 
			
		||||
        if (sKeywords[i]==string || (string.size()==1 && sKeywords[i][0]==string[0]))
 | 
			
		||||
            return Token (static_cast<Token::Type> (i+Token::Type_Keyword_True), token.mString);
 | 
			
		||||
 | 
			
		||||
    return token;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -208,9 +223,10 @@ CSMFilter::Token CSMFilter::Parser::getNextToken()
 | 
			
		|||
        case '[': ++mIndex; return Token (Token::Type_OpenSquare);
 | 
			
		||||
        case ']': ++mIndex; return Token (Token::Type_CloseSquare);
 | 
			
		||||
        case ',': ++mIndex; return Token (Token::Type_Comma);
 | 
			
		||||
        case '!': ++mIndex; return Token (Token::Type_OneShot);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (c=='"' || c=='_' || std::isalpha (c))
 | 
			
		||||
    if (c=='"' || c=='_' || std::isalpha (c) || c==':')
 | 
			
		||||
        return getStringToken();
 | 
			
		||||
 | 
			
		||||
    if (c=='-' || c=='.' || std::isdigit (c))
 | 
			
		||||
| 
						 | 
				
			
			@ -220,54 +236,58 @@ CSMFilter::Token CSMFilter::Parser::getNextToken()
 | 
			
		|||
    return Token (Token::Type_None);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
boost::shared_ptr<CSMFilter::Node> CSMFilter::Parser::parseImp (bool allowEmpty)
 | 
			
		||||
boost::shared_ptr<CSMFilter::Node> CSMFilter::Parser::parseImp (bool allowEmpty, bool ignoreOneShot)
 | 
			
		||||
{
 | 
			
		||||
    if (Token token = getNextToken())
 | 
			
		||||
    {
 | 
			
		||||
        switch (token.mType)
 | 
			
		||||
        {
 | 
			
		||||
            case Token::Type_Keyword_True:
 | 
			
		||||
        if (token==Token (Token::Type_OneShot))
 | 
			
		||||
            token = getNextToken();
 | 
			
		||||
 | 
			
		||||
                return boost::shared_ptr<CSMFilter::Node> (new BooleanNode (true));
 | 
			
		||||
 | 
			
		||||
            case Token::Type_Keyword_False:
 | 
			
		||||
 | 
			
		||||
                return boost::shared_ptr<CSMFilter::Node> (new BooleanNode (false));
 | 
			
		||||
 | 
			
		||||
            case Token::Type_Keyword_And:
 | 
			
		||||
            case Token::Type_Keyword_Or:
 | 
			
		||||
 | 
			
		||||
                return parseNAry (token);
 | 
			
		||||
 | 
			
		||||
            case Token::Type_Keyword_Not:
 | 
			
		||||
        if (token)
 | 
			
		||||
            switch (token.mType)
 | 
			
		||||
            {
 | 
			
		||||
                boost::shared_ptr<CSMFilter::Node> node = parseImp();
 | 
			
		||||
                case Token::Type_Keyword_True:
 | 
			
		||||
 | 
			
		||||
                    return boost::shared_ptr<CSMFilter::Node> (new BooleanNode (true));
 | 
			
		||||
 | 
			
		||||
                case Token::Type_Keyword_False:
 | 
			
		||||
 | 
			
		||||
                    return boost::shared_ptr<CSMFilter::Node> (new BooleanNode (false));
 | 
			
		||||
 | 
			
		||||
                case Token::Type_Keyword_And:
 | 
			
		||||
                case Token::Type_Keyword_Or:
 | 
			
		||||
 | 
			
		||||
                    return parseNAry (token);
 | 
			
		||||
 | 
			
		||||
                case Token::Type_Keyword_Not:
 | 
			
		||||
                {
 | 
			
		||||
                    boost::shared_ptr<CSMFilter::Node> node = parseImp();
 | 
			
		||||
 | 
			
		||||
                    if (mError)
 | 
			
		||||
                        return boost::shared_ptr<Node>();
 | 
			
		||||
 | 
			
		||||
                    return boost::shared_ptr<CSMFilter::Node> (new NotNode (node));
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                case Token::Type_Keyword_Text:
 | 
			
		||||
 | 
			
		||||
                    return parseText();
 | 
			
		||||
 | 
			
		||||
                case Token::Type_Keyword_Value:
 | 
			
		||||
 | 
			
		||||
                    return parseValue();
 | 
			
		||||
 | 
			
		||||
                case Token::Type_EOS:
 | 
			
		||||
 | 
			
		||||
                    if (!allowEmpty)
 | 
			
		||||
                        error();
 | 
			
		||||
 | 
			
		||||
                if (mError)
 | 
			
		||||
                    return boost::shared_ptr<Node>();
 | 
			
		||||
 | 
			
		||||
                return boost::shared_ptr<CSMFilter::Node> (new NotNode (node));
 | 
			
		||||
            }
 | 
			
		||||
                default:
 | 
			
		||||
 | 
			
		||||
            case Token::Type_Keyword_Text:
 | 
			
		||||
 | 
			
		||||
                return parseText();
 | 
			
		||||
 | 
			
		||||
            case Token::Type_Keyword_Value:
 | 
			
		||||
 | 
			
		||||
                return parseValue();
 | 
			
		||||
 | 
			
		||||
            case Token::Type_EOS:
 | 
			
		||||
 | 
			
		||||
                if (!allowEmpty)
 | 
			
		||||
                    error();
 | 
			
		||||
 | 
			
		||||
                return boost::shared_ptr<Node>();
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
 | 
			
		||||
                error();
 | 
			
		||||
        }
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return boost::shared_ptr<Node>();
 | 
			
		||||
| 
						 | 
				
			
			@ -343,7 +363,7 @@ boost::shared_ptr<CSMFilter::Node> CSMFilter::Parser::parseText()
 | 
			
		|||
        if (static_cast<int> (token.mNumber)==token.mNumber)
 | 
			
		||||
            columnId = static_cast<int> (token.mNumber);
 | 
			
		||||
    }
 | 
			
		||||
    else if (token.mType==Token::Type_String)
 | 
			
		||||
    else if (token.isString())
 | 
			
		||||
    {
 | 
			
		||||
        columnId = CSMWorld::Columns::getId (token.mString);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -365,7 +385,7 @@ boost::shared_ptr<CSMFilter::Node> CSMFilter::Parser::parseText()
 | 
			
		|||
    // parse text pattern
 | 
			
		||||
    token = getNextToken();
 | 
			
		||||
 | 
			
		||||
    if (token.mType!=Token::Type_String)
 | 
			
		||||
    if (!token.isString())
 | 
			
		||||
    {
 | 
			
		||||
        error();
 | 
			
		||||
        return boost::shared_ptr<Node>();
 | 
			
		||||
| 
						 | 
				
			
			@ -407,7 +427,7 @@ boost::shared_ptr<CSMFilter::Node> CSMFilter::Parser::parseValue()
 | 
			
		|||
        if (static_cast<int> (token.mNumber)==token.mNumber)
 | 
			
		||||
            columnId = static_cast<int> (token.mNumber);
 | 
			
		||||
    }
 | 
			
		||||
    else if (token.mType==Token::Type_String)
 | 
			
		||||
    else if (token.isString())
 | 
			
		||||
    {
 | 
			
		||||
        columnId = CSMWorld::Columns::getId (token.mString);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -429,22 +449,22 @@ boost::shared_ptr<CSMFilter::Node> CSMFilter::Parser::parseValue()
 | 
			
		|||
    // parse value
 | 
			
		||||
    double lower = 0;
 | 
			
		||||
    double upper = 0;
 | 
			
		||||
    bool min = false;
 | 
			
		||||
    bool max = false;
 | 
			
		||||
    ValueNode::Type lowerType = ValueNode::Type_Open;
 | 
			
		||||
    ValueNode::Type upperType = ValueNode::Type_Open;
 | 
			
		||||
 | 
			
		||||
    token = getNextToken();
 | 
			
		||||
 | 
			
		||||
    if (token.mType==Token::Type_Number)
 | 
			
		||||
    {
 | 
			
		||||
        // single value
 | 
			
		||||
        min = max = true;
 | 
			
		||||
        lower = upper = token.mNumber;
 | 
			
		||||
        lowerType = upperType = ValueNode::Type_Closed;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        // interval
 | 
			
		||||
        if (token.mType==Token::Type_OpenSquare)
 | 
			
		||||
            min = true;
 | 
			
		||||
            lowerType = ValueNode::Type_Closed;
 | 
			
		||||
        else if (token.mType!=Token::Type_CloseSquare && token.mType!=Token::Type_Open)
 | 
			
		||||
        {
 | 
			
		||||
            error();
 | 
			
		||||
| 
						 | 
				
			
			@ -453,17 +473,23 @@ boost::shared_ptr<CSMFilter::Node> CSMFilter::Parser::parseValue()
 | 
			
		|||
 | 
			
		||||
        token = getNextToken();
 | 
			
		||||
 | 
			
		||||
        if (token.mType!=Token::Type_Number)
 | 
			
		||||
        if (token.mType==Token::Type_Number)
 | 
			
		||||
        {
 | 
			
		||||
            error();
 | 
			
		||||
            return boost::shared_ptr<Node>();
 | 
			
		||||
            lower = token.mNumber;
 | 
			
		||||
 | 
			
		||||
            token = getNextToken();
 | 
			
		||||
 | 
			
		||||
            if (token.mType!=Token::Type_Comma)
 | 
			
		||||
            {
 | 
			
		||||
                error();
 | 
			
		||||
                return boost::shared_ptr<Node>();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        lower = token.mNumber;
 | 
			
		||||
 | 
			
		||||
        token = getNextToken();
 | 
			
		||||
 | 
			
		||||
        if (token.mType!=Token::Type_Comma)
 | 
			
		||||
        else if (token.mType==Token::Type_Comma)
 | 
			
		||||
        {
 | 
			
		||||
            lowerType = ValueNode::Type_Infinite;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            error();
 | 
			
		||||
            return boost::shared_ptr<Node>();
 | 
			
		||||
| 
						 | 
				
			
			@ -471,18 +497,20 @@ boost::shared_ptr<CSMFilter::Node> CSMFilter::Parser::parseValue()
 | 
			
		|||
 | 
			
		||||
        token = getNextToken();
 | 
			
		||||
 | 
			
		||||
        if (token.mType!=Token::Type_Number)
 | 
			
		||||
        if (token.mType==Token::Type_Number)
 | 
			
		||||
        {
 | 
			
		||||
            error();
 | 
			
		||||
            return boost::shared_ptr<Node>();
 | 
			
		||||
            upper = token.mNumber;
 | 
			
		||||
 | 
			
		||||
            token = getNextToken();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        upper = token.mNumber;
 | 
			
		||||
 | 
			
		||||
        token = getNextToken();
 | 
			
		||||
        else
 | 
			
		||||
            upperType = ValueNode::Type_Infinite;
 | 
			
		||||
 | 
			
		||||
        if (token.mType==Token::Type_CloseSquare)
 | 
			
		||||
            max = true;
 | 
			
		||||
        {
 | 
			
		||||
            if (upperType!=ValueNode::Type_Infinite)
 | 
			
		||||
                upperType = ValueNode::Type_Closed;
 | 
			
		||||
        }
 | 
			
		||||
        else if (token.mType!=Token::Type_OpenSquare && token.mType!=Token::Type_Close)
 | 
			
		||||
        {
 | 
			
		||||
            error();
 | 
			
		||||
| 
						 | 
				
			
			@ -498,7 +526,7 @@ boost::shared_ptr<CSMFilter::Node> CSMFilter::Parser::parseValue()
 | 
			
		|||
        return boost::shared_ptr<Node>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return boost::shared_ptr<Node> (new ValueNode (columnId, lower, upper, min, max));
 | 
			
		||||
    return boost::shared_ptr<Node> (new ValueNode (columnId, lowerType, upperType, lower, upper));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CSMFilter::Parser::error()
 | 
			
		||||
| 
						 | 
				
			
			@ -506,9 +534,10 @@ void CSMFilter::Parser::error()
 | 
			
		|||
    mError = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CSMFilter::Parser::Parser() : mIndex (0), mError (false) {}
 | 
			
		||||
CSMFilter::Parser::Parser (const CSMWorld::Data& data)
 | 
			
		||||
: mIndex (0), mError (false), mData (data) {}
 | 
			
		||||
 | 
			
		||||
bool CSMFilter::Parser::parse (const std::string& filter)
 | 
			
		||||
bool CSMFilter::Parser::parse (const std::string& filter, bool allowPredefined)
 | 
			
		||||
{
 | 
			
		||||
    // reset
 | 
			
		||||
    mFilter.reset();
 | 
			
		||||
| 
						 | 
				
			
			@ -516,23 +545,67 @@ bool CSMFilter::Parser::parse (const std::string& filter)
 | 
			
		|||
    mInput = filter;
 | 
			
		||||
    mIndex = 0;
 | 
			
		||||
 | 
			
		||||
    boost::shared_ptr<Node> node = parseImp (true);
 | 
			
		||||
    Token token;
 | 
			
		||||
 | 
			
		||||
    if (mError)
 | 
			
		||||
        return false;
 | 
			
		||||
    if (allowPredefined)
 | 
			
		||||
        token = getNextToken();
 | 
			
		||||
 | 
			
		||||
    if (getNextToken()!=Token (Token::Type_EOS))
 | 
			
		||||
        return false;
 | 
			
		||||
    if (!allowPredefined || token==Token (Token::Type_OneShot))
 | 
			
		||||
    {
 | 
			
		||||
        boost::shared_ptr<Node> node = parseImp (true, token!=Token (Token::Type_OneShot));
 | 
			
		||||
 | 
			
		||||
    if (node)
 | 
			
		||||
        mFilter = node;
 | 
			
		||||
        if (mError)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (getNextToken()!=Token (Token::Type_EOS))
 | 
			
		||||
        {
 | 
			
		||||
            error();
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (node)
 | 
			
		||||
            mFilter = node;
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            // Empty filter string equals to filter "true".
 | 
			
		||||
            mFilter.reset (new BooleanNode (true));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    // We do not use isString() here, because there could be a pre-defined filter with an ID that is
 | 
			
		||||
    // equal a filter keyword.
 | 
			
		||||
    else if (token.mType==Token::Type_String && allowPredefined)
 | 
			
		||||
    {
 | 
			
		||||
        if (getNextToken()!=Token (Token::Type_EOS))
 | 
			
		||||
        {
 | 
			
		||||
            error();
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        int index = mData.getFilters().searchId (token.mString);
 | 
			
		||||
 | 
			
		||||
        if (index==-1)
 | 
			
		||||
        {
 | 
			
		||||
            error();
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const CSMWorld::Record<CSMFilter::Filter>& record = mData.getFilters().getRecord (index);
 | 
			
		||||
 | 
			
		||||
        if (record.isDeleted())
 | 
			
		||||
        {
 | 
			
		||||
            error();
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return parse (record.get().mFilter, false);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        // Empty filter string equals to filter "true".
 | 
			
		||||
        mFilter.reset (new BooleanNode (true));
 | 
			
		||||
        error();
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
boost::shared_ptr<CSMFilter::Node> CSMFilter::Parser::getFilter() const
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,11 @@
 | 
			
		|||
 | 
			
		||||
#include "node.hpp"
 | 
			
		||||
 | 
			
		||||
namespace CSMWorld
 | 
			
		||||
{
 | 
			
		||||
    class Data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace CSMFilter
 | 
			
		||||
{
 | 
			
		||||
    struct Token;
 | 
			
		||||
| 
						 | 
				
			
			@ -15,6 +20,7 @@ namespace CSMFilter
 | 
			
		|||
            std::string mInput;
 | 
			
		||||
            int mIndex;
 | 
			
		||||
            bool mError;
 | 
			
		||||
            const CSMWorld::Data& mData;
 | 
			
		||||
 | 
			
		||||
            Token getStringToken();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +31,7 @@ namespace CSMFilter
 | 
			
		|||
            Token checkKeywords (const Token& token);
 | 
			
		||||
            ///< Turn string token into keyword token, if possible.
 | 
			
		||||
 | 
			
		||||
            boost::shared_ptr<Node> parseImp (bool allowEmpty = false);
 | 
			
		||||
            boost::shared_ptr<Node> parseImp (bool allowEmpty = false, bool ignoreOneShot = false);
 | 
			
		||||
            ///< Will return a null-pointer, if there is nothing more to parse.
 | 
			
		||||
 | 
			
		||||
            boost::shared_ptr<Node> parseNAry (const Token& keyword);
 | 
			
		||||
| 
						 | 
				
			
			@ -38,9 +44,9 @@ namespace CSMFilter
 | 
			
		|||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            Parser();
 | 
			
		||||
            Parser (const CSMWorld::Data& data);
 | 
			
		||||
 | 
			
		||||
            bool parse (const std::string& filter);
 | 
			
		||||
            bool parse (const std::string& filter, bool allowPredefined = true);
 | 
			
		||||
            ///< Discards any previous calls to parse
 | 
			
		||||
            ///
 | 
			
		||||
            /// \return Success?
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,13 +28,34 @@ bool CSMFilter::TextNode::test (const CSMWorld::IdTable& table, int row,
 | 
			
		|||
 | 
			
		||||
    QVariant data = table.data (index);
 | 
			
		||||
 | 
			
		||||
    if (data.type()!=QVariant::String)
 | 
			
		||||
    QString string;
 | 
			
		||||
 | 
			
		||||
    if (data.type()==QVariant::String)
 | 
			
		||||
    {
 | 
			
		||||
        string = data.toString();
 | 
			
		||||
    }
 | 
			
		||||
    else if (data.type()==QVariant::Int || data.type()==QVariant::UInt ||
 | 
			
		||||
        CSMWorld::Columns::hasEnums (static_cast<CSMWorld::Columns::ColumnId> (mColumnId)))
 | 
			
		||||
    {
 | 
			
		||||
        int value = data.toInt();
 | 
			
		||||
 | 
			
		||||
        std::vector<std::string> enums =
 | 
			
		||||
            CSMWorld::Columns::getEnums (static_cast<CSMWorld::Columns::ColumnId> (mColumnId));
 | 
			
		||||
 | 
			
		||||
        if (value>=0 && value<static_cast<int> (enums.size()))
 | 
			
		||||
            string = QString::fromUtf8 (enums[value].c_str());
 | 
			
		||||
    }
 | 
			
		||||
    else if (data.type()==QVariant::Bool)
 | 
			
		||||
    {
 | 
			
		||||
        string = data.toBool() ? "true" : " false";
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    /// \todo make pattern syntax configurable
 | 
			
		||||
    QRegExp regExp (QString::fromUtf8 (mText.c_str()), Qt::CaseInsensitive);
 | 
			
		||||
 | 
			
		||||
    return regExp.exactMatch (data.toString());
 | 
			
		||||
    return regExp.exactMatch (string);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<int> CSMFilter::TextNode::getReferencedColumns() const
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,10 +7,9 @@
 | 
			
		|||
#include "../world/columns.hpp"
 | 
			
		||||
#include "../world/idtable.hpp"
 | 
			
		||||
 | 
			
		||||
CSMFilter::ValueNode::ValueNode (int columnId,
 | 
			
		||||
    double lower, double upper, bool min, bool max)
 | 
			
		||||
: mColumnId (columnId), mLower (lower), mUpper (upper), mMin (min), mMax (max)
 | 
			
		||||
{}
 | 
			
		||||
CSMFilter::ValueNode::ValueNode (int columnId, Type lowerType, Type upperType,
 | 
			
		||||
    double lower, double upper)
 | 
			
		||||
: mColumnId (columnId), mLowerType (lowerType), mUpperType (upperType), mLower (lower), mUpper (upper){}
 | 
			
		||||
 | 
			
		||||
bool CSMFilter::ValueNode::test (const CSMWorld::IdTable& table, int row,
 | 
			
		||||
    const std::map<int, int>& columns) const
 | 
			
		||||
| 
						 | 
				
			
			@ -33,10 +32,21 @@ bool CSMFilter::ValueNode::test (const CSMWorld::IdTable& table, int row,
 | 
			
		|||
 | 
			
		||||
    double value = data.toDouble();
 | 
			
		||||
 | 
			
		||||
    if (mLower==mUpper && mMin && mMax)
 | 
			
		||||
        return value==mLower;
 | 
			
		||||
    switch (mLowerType)
 | 
			
		||||
    {
 | 
			
		||||
        case Type_Closed: if (value<mLower) return false; break;
 | 
			
		||||
        case Type_Open: if (value<=mLower) return false; break;
 | 
			
		||||
        case Type_Infinite: break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (mMin ? value>=mLower : value>mLower) && (mMax ? value<=mUpper : value<mUpper);
 | 
			
		||||
    switch (mUpperType)
 | 
			
		||||
    {
 | 
			
		||||
        case Type_Closed: if (value>mUpper) return false; break;
 | 
			
		||||
        case Type_Open: if (value>=mUpper) return false; break;
 | 
			
		||||
        case Type_Infinite: break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<int> CSMFilter::ValueNode::getReferencedColumns() const
 | 
			
		||||
| 
						 | 
				
			
			@ -60,10 +70,26 @@ std::string CSMFilter::ValueNode::toString (bool numericColumns) const
 | 
			
		|||
 | 
			
		||||
    stream << ", \"";
 | 
			
		||||
 | 
			
		||||
    if (mLower==mUpper && mMin && mMax)
 | 
			
		||||
    if (mLower==mUpper && mLowerType!=Type_Infinite && mUpperType!=Type_Infinite)
 | 
			
		||||
        stream << mLower;
 | 
			
		||||
    else
 | 
			
		||||
        stream << (mMin ? "[" : "(") << mLower << ", " << mUpper << (mMax ? "]" : ")");
 | 
			
		||||
    {
 | 
			
		||||
        switch (mLowerType)
 | 
			
		||||
        {
 | 
			
		||||
            case Type_Closed: stream << "[" << mLower; break;
 | 
			
		||||
            case Type_Open: stream << "(" << mLower; break;
 | 
			
		||||
            case Type_Infinite: stream << "("; break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        stream << ", ";
 | 
			
		||||
 | 
			
		||||
        switch (mUpperType)
 | 
			
		||||
        {
 | 
			
		||||
            case Type_Closed: stream << mUpper << "]"; break;
 | 
			
		||||
            case Type_Open: stream << mUpper << ")"; break;
 | 
			
		||||
            case Type_Infinite: stream << ")"; break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    stream << ")";
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,16 +7,25 @@ namespace CSMFilter
 | 
			
		|||
{
 | 
			
		||||
    class ValueNode : public LeafNode
 | 
			
		||||
    {
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            enum Type
 | 
			
		||||
            {
 | 
			
		||||
                Type_Closed, Type_Open, Type_Infinite
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
 | 
			
		||||
            int mColumnId;
 | 
			
		||||
            std::string mText;
 | 
			
		||||
            double mLower;
 | 
			
		||||
            double mUpper;
 | 
			
		||||
            bool mMin;
 | 
			
		||||
            bool mMax;
 | 
			
		||||
            Type mLowerType;
 | 
			
		||||
            Type mUpperType;
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            ValueNode (int columnId, double lower, double upper, bool min, bool max);
 | 
			
		||||
            ValueNode (int columnId, Type lowerType, Type upperType, double lower, double upper);
 | 
			
		||||
 | 
			
		||||
            virtual bool test (const CSMWorld::IdTable& table, int row,
 | 
			
		||||
                const std::map<int, int>& columns) const;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@ void CSMWorld::Cell::load (ESM::ESMReader &esm)
 | 
			
		|||
{
 | 
			
		||||
    mName = mId;
 | 
			
		||||
 | 
			
		||||
    ESM::Cell::load (esm, true); /// \todo set this to false, once the bug in ESM::Cell::load is fixed
 | 
			
		||||
    ESM::Cell::load (esm, false);
 | 
			
		||||
 | 
			
		||||
    if (!(mData.mFlags & Interior))
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -236,14 +236,15 @@ namespace CSMWorld
 | 
			
		|||
                if (iter->second>=index+count)
 | 
			
		||||
                {
 | 
			
		||||
                    iter->second -= count;
 | 
			
		||||
                    ++iter;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    mIndex.erase (iter++);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            ++iter;
 | 
			
		||||
            else
 | 
			
		||||
                ++iter;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1191,6 +1191,31 @@ namespace CSMWorld
 | 
			
		|||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    template<typename ESXRecordT>
 | 
			
		||||
    struct FilterColumn : public Column<ESXRecordT>
 | 
			
		||||
    {
 | 
			
		||||
        FilterColumn() : Column<ESXRecordT> (Columns::ColumnId_Filter, ColumnBase::Display_String) {}
 | 
			
		||||
 | 
			
		||||
        virtual QVariant get (const Record<ESXRecordT>& record) const
 | 
			
		||||
        {
 | 
			
		||||
            return QString::fromUtf8 (record.get().mFilter.c_str());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void set (Record<ESXRecordT>& record, const QVariant& data)
 | 
			
		||||
        {
 | 
			
		||||
            ESXRecordT record2 = record.get();
 | 
			
		||||
 | 
			
		||||
            record2.mFilter = data.toString().toUtf8().constData();
 | 
			
		||||
 | 
			
		||||
            record.setModified (record2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual bool isEditable() const
 | 
			
		||||
        {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,8 @@
 | 
			
		|||
 | 
			
		||||
#include <components/misc/stringops.hpp>
 | 
			
		||||
 | 
			
		||||
#include "universalid.hpp"
 | 
			
		||||
 | 
			
		||||
namespace CSMWorld
 | 
			
		||||
{
 | 
			
		||||
    namespace Columns
 | 
			
		||||
| 
						 | 
				
			
			@ -144,6 +146,7 @@ namespace CSMWorld
 | 
			
		|||
            { ColumnId_MaxThrust, "Max Thrust" },
 | 
			
		||||
            { ColumnId_Magical, "Magical" },
 | 
			
		||||
            { ColumnId_Silver, "Silver" },
 | 
			
		||||
            { ColumnId_Filter, "Filter" },
 | 
			
		||||
 | 
			
		||||
            { ColumnId_UseValue1, "Use value 1" },
 | 
			
		||||
            { ColumnId_UseValue2, "Use value 2" },
 | 
			
		||||
| 
						 | 
				
			
			@ -195,4 +198,104 @@ int CSMWorld::Columns::getId (const std::string& name)
 | 
			
		|||
            return sNames[i].mId;
 | 
			
		||||
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
    static const char *sSpecialisations[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Combat", "Magic", "Stealth", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const char *sAttributes[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Strength", "Intelligence", "Willpower", "Agility", "Speed", "Endurance", "Personality",
 | 
			
		||||
        "Luck", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const char *sSpellTypes[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Spell", "Ability", "Blight", "Disease", "Curse", "Power", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const char *sApparatusTypes[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Mortar & Pestle", "Albemic", "Calcinator", "Retort", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const char *sArmorTypes[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Helmet", "Cuirass", "Left Pauldron", "Right Pauldron", "Greaves", "Boots", "Left Gauntlet",
 | 
			
		||||
        "Right Gauntlet", "Shield", "Left Bracer", "Right Bracer", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const char *sClothingTypes[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Pants", "Shoes", "Shirt", "Belt", "Robe", "Right Glove", "Left Glove", "Skirt", "Ring",
 | 
			
		||||
        "Amulet", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const char *sCreatureTypes[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Creature", "Deadra", "Undead", "Humanoid", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const char *sWeaponTypes[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Short Blade 1H", "Long Blade 1H", "Long Blade 2H", "Blunt 1H", "Blunt 2H Close",
 | 
			
		||||
        "Blunt 2H Wide", "Spear 2H", "Axe 1H", "Axe 2H", "Bow", "Crossbow", "Thrown", "Arrow",
 | 
			
		||||
        "Bolt", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const char *sModificationEnums[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Base", "Modified", "Added", "Deleted", "Deleted", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const char *sVarTypeEnums[] =
 | 
			
		||||
    {
 | 
			
		||||
        "unknown", "none", "short", "integer", "long", "float", "string", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const char **getEnumNames (CSMWorld::Columns::ColumnId column)
 | 
			
		||||
    {
 | 
			
		||||
        switch (column)
 | 
			
		||||
        {
 | 
			
		||||
            case CSMWorld::Columns::ColumnId_Specialisation: return sSpecialisations;
 | 
			
		||||
            case CSMWorld::Columns::ColumnId_Attribute: return sAttributes;
 | 
			
		||||
            case CSMWorld::Columns::ColumnId_SpellType: return sSpellTypes;
 | 
			
		||||
            case CSMWorld::Columns::ColumnId_ApparatusType: return sApparatusTypes;
 | 
			
		||||
            case CSMWorld::Columns::ColumnId_ArmorType: return sArmorTypes;
 | 
			
		||||
            case CSMWorld::Columns::ColumnId_ClothingType: return sClothingTypes;
 | 
			
		||||
            case CSMWorld::Columns::ColumnId_CreatureType: return sCreatureTypes;
 | 
			
		||||
            case CSMWorld::Columns::ColumnId_WeaponType: return sWeaponTypes;
 | 
			
		||||
            case CSMWorld::Columns::ColumnId_Modification: return sModificationEnums;
 | 
			
		||||
            case CSMWorld::Columns::ColumnId_ValueType: return sVarTypeEnums;
 | 
			
		||||
 | 
			
		||||
            default: return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CSMWorld::Columns::hasEnums (ColumnId column)
 | 
			
		||||
{
 | 
			
		||||
    return getEnumNames (column)!=0 || column==ColumnId_RecordType;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<std::string> CSMWorld::Columns::getEnums (ColumnId column)
 | 
			
		||||
{
 | 
			
		||||
    std::vector<std::string> enums;
 | 
			
		||||
 | 
			
		||||
    if (const char **table = getEnumNames (column))
 | 
			
		||||
        for (int i=0; table[i]; ++i)
 | 
			
		||||
            enums.push_back (table[i]);
 | 
			
		||||
    else if (column==ColumnId_RecordType)
 | 
			
		||||
    {
 | 
			
		||||
        enums.push_back (""); // none
 | 
			
		||||
 | 
			
		||||
        for (int i=UniversalId::Type_None+1; i<UniversalId::NumberOfTypes; ++i)
 | 
			
		||||
            enums.push_back (UniversalId (static_cast<UniversalId::Type> (i)).getTypeName());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return enums;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
#define CSM_WOLRD_COLUMNS_H
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace CSMWorld
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -138,6 +139,7 @@ namespace CSMWorld
 | 
			
		|||
            ColumnId_MaxThrust = 106,
 | 
			
		||||
            ColumnId_Magical = 107,
 | 
			
		||||
            ColumnId_Silver = 108,
 | 
			
		||||
            ColumnId_Filter = 109,
 | 
			
		||||
 | 
			
		||||
            // Allocated to a separate value range, so we don't get a collision should we ever need
 | 
			
		||||
            // to extend the number of use values.
 | 
			
		||||
| 
						 | 
				
			
			@ -179,6 +181,11 @@ namespace CSMWorld
 | 
			
		|||
 | 
			
		||||
        int getId (const std::string& name);
 | 
			
		||||
        ///< Will return -1 for an invalid name.
 | 
			
		||||
 | 
			
		||||
        bool hasEnums (ColumnId column);
 | 
			
		||||
 | 
			
		||||
        std::vector<std::string> getEnums (ColumnId column);
 | 
			
		||||
        ///< Returns an empty vector, if \æ column isn't an enum type column.
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,7 +69,9 @@ CSMWorld::RevertCommand::~RevertCommand()
 | 
			
		|||
 | 
			
		||||
void CSMWorld::RevertCommand::redo()
 | 
			
		||||
{
 | 
			
		||||
    QModelIndex index = mModel.getModelIndex (mId, 1);
 | 
			
		||||
    int column = mModel.findColumnIndex (Columns::ColumnId_Modification);
 | 
			
		||||
 | 
			
		||||
    QModelIndex index = mModel.getModelIndex (mId, column);
 | 
			
		||||
    RecordBase::State state = static_cast<RecordBase::State> (mModel.data (index).toInt());
 | 
			
		||||
 | 
			
		||||
    if (state==RecordBase::State_ModifiedOnly)
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +104,9 @@ CSMWorld::DeleteCommand::~DeleteCommand()
 | 
			
		|||
 | 
			
		||||
void CSMWorld::DeleteCommand::redo()
 | 
			
		||||
{
 | 
			
		||||
    QModelIndex index = mModel.getModelIndex (mId, 1);
 | 
			
		||||
    int column = mModel.findColumnIndex (Columns::ColumnId_Modification);
 | 
			
		||||
 | 
			
		||||
    QModelIndex index = mModel.getModelIndex (mId, column);
 | 
			
		||||
    RecordBase::State state = static_cast<RecordBase::State> (mModel.data (index).toInt());
 | 
			
		||||
 | 
			
		||||
    if (state==RecordBase::State_ModifiedOnly)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -150,6 +150,7 @@ CSMWorld::Data::Data() : mRefs (mCells)
 | 
			
		|||
 | 
			
		||||
    mFilters.addColumn (new StringIdColumn<CSMFilter::Filter>);
 | 
			
		||||
    mFilters.addColumn (new RecordStateColumn<CSMFilter::Filter>);
 | 
			
		||||
    mFilters.addColumn (new FilterColumn<CSMFilter::Filter>);
 | 
			
		||||
    mFilters.addColumn (new DescriptionColumn<CSMFilter::Filter>);
 | 
			
		||||
 | 
			
		||||
    addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
 | 
			
		||||
| 
						 | 
				
			
			@ -316,6 +317,16 @@ CSMWorld::RefCollection& CSMWorld::Data::getReferences()
 | 
			
		|||
    return mRefs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const CSMWorld::IdCollection<CSMFilter::Filter>& CSMWorld::Data::getFilters() const
 | 
			
		||||
{
 | 
			
		||||
    return mFilters;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CSMWorld::IdCollection<CSMFilter::Filter>& CSMWorld::Data::getFilters()
 | 
			
		||||
{
 | 
			
		||||
    return mFilters;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id)
 | 
			
		||||
{
 | 
			
		||||
    std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -119,6 +119,10 @@ namespace CSMWorld
 | 
			
		|||
 | 
			
		||||
            RefCollection& getReferences();
 | 
			
		||||
 | 
			
		||||
            const IdCollection<CSMFilter::Filter>& getFilters() const;
 | 
			
		||||
 | 
			
		||||
            IdCollection<CSMFilter::Filter>& getFilters();
 | 
			
		||||
 | 
			
		||||
            QAbstractItemModel *getTableModel (const UniversalId& id);
 | 
			
		||||
            ///< If no table model is available for \a id, an exception is thrown.
 | 
			
		||||
            ///
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,8 +8,6 @@ void CSMWorld::CellRef::load (ESM::ESMReader &esm, Cell& cell, const std::string
 | 
			
		|||
    mId = id;
 | 
			
		||||
    mCellId = cell.mId;
 | 
			
		||||
 | 
			
		||||
    cell.getNextRef (esm, *this);
 | 
			
		||||
 | 
			
		||||
    if (!mDeleted)
 | 
			
		||||
        cell.addRef (mId);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -6,10 +6,6 @@
 | 
			
		|||
#include "ref.hpp"
 | 
			
		||||
#include "cell.hpp"
 | 
			
		||||
 | 
			
		||||
CSMWorld::RefCollection::RefCollection (Collection<Cell>& cells)
 | 
			
		||||
: mCells (cells), mNextId (0)
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool base)
 | 
			
		||||
{
 | 
			
		||||
    Record<Cell> cell = mCells.getRecord (cellIndex);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,8 +16,10 @@ namespace CSMWorld
 | 
			
		|||
            int mNextId;
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            RefCollection (Collection<Cell>& cells);
 | 
			
		||||
            // MSVC needs the constructor for a class inheriting a template to be defined in header
 | 
			
		||||
            RefCollection (Collection<Cell>& cells)
 | 
			
		||||
              : mCells (cells), mNextId (0)
 | 
			
		||||
            {}
 | 
			
		||||
 | 
			
		||||
            void load (ESM::ESMReader& reader, int cellIndex, bool base);
 | 
			
		||||
            ///< Load a sequence of references.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,7 +80,7 @@ namespace
 | 
			
		|||
        { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" },
 | 
			
		||||
        { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" },
 | 
			
		||||
        { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Reference", 0 },
 | 
			
		||||
 | 
			
		||||
        { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Filter, "Filter", 0 },
 | 
			
		||||
        { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -90,8 +90,6 @@ namespace
 | 
			
		|||
 | 
			
		||||
        { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const unsigned int IDARG_SIZE = sizeof (sIdArg) / sizeof (TypeData);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CSMWorld::UniversalId::UniversalId (const std::string& universalId)
 | 
			
		||||
| 
						 | 
				
			
			@ -151,6 +149,22 @@ CSMWorld::UniversalId::UniversalId (Type type) : mArgumentType (ArgumentType_Non
 | 
			
		|||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    for (int i=0; sIdArg[i].mName; ++i)
 | 
			
		||||
        if (type==sIdArg[i].mType)
 | 
			
		||||
        {
 | 
			
		||||
            mArgumentType = ArgumentType_Id;
 | 
			
		||||
            mClass = sIdArg[i].mClass;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    for (int i=0; sIndexArg[i].mName; ++i)
 | 
			
		||||
        if (type==sIndexArg[i].mType)
 | 
			
		||||
        {
 | 
			
		||||
            mArgumentType = ArgumentType_Index;
 | 
			
		||||
            mClass = sIndexArg[i].mClass;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    throw std::logic_error ("invalid argument-less UniversalId type");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -293,25 +307,6 @@ std::vector<CSMWorld::UniversalId::Type> CSMWorld::UniversalId::listReferenceabl
 | 
			
		|||
    return list;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::pair<int, const char *> CSMWorld::UniversalId::getIdArgPair (unsigned int index)
 | 
			
		||||
{
 | 
			
		||||
    std::pair<int, const char *> retPair;
 | 
			
		||||
 | 
			
		||||
    if ( index < IDARG_SIZE )
 | 
			
		||||
    {
 | 
			
		||||
        retPair.first = sIdArg[index].mType;
 | 
			
		||||
        retPair.second = sIdArg[index].mName;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return retPair;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned int CSMWorld::UniversalId::getIdArgSize()
 | 
			
		||||
{
 | 
			
		||||
   return IDARG_SIZE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool CSMWorld::operator== (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right)
 | 
			
		||||
{
 | 
			
		||||
    return left.isEqual (right);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,7 +34,7 @@ namespace CSMWorld
 | 
			
		|||
 | 
			
		||||
            enum Type
 | 
			
		||||
            {
 | 
			
		||||
                Type_None,
 | 
			
		||||
                Type_None = 0,
 | 
			
		||||
                Type_Globals,
 | 
			
		||||
                Type_Global,
 | 
			
		||||
                Type_VerificationResults,
 | 
			
		||||
| 
						 | 
				
			
			@ -89,6 +89,8 @@ namespace CSMWorld
 | 
			
		|||
                Type_Filters
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            enum { NumberOfTypes = Type_Filters+1 };
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
 | 
			
		||||
            Class mClass;
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +104,6 @@ namespace CSMWorld
 | 
			
		|||
            UniversalId (const std::string& universalId);
 | 
			
		||||
 | 
			
		||||
            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.
 | 
			
		||||
| 
						 | 
				
			
			@ -134,9 +135,6 @@ namespace CSMWorld
 | 
			
		|||
            ///< Will return an empty string, if no icon is available.
 | 
			
		||||
 | 
			
		||||
            static std::vector<Type> listReferenceableTypes();
 | 
			
		||||
 | 
			
		||||
            static std::pair<int, const char *> getIdArgPair (unsigned int index);
 | 
			
		||||
            static unsigned int getIdArgSize ();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    bool operator== (const UniversalId& left, const UniversalId& right);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,21 +3,106 @@
 | 
			
		|||
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QDesktopWidget>
 | 
			
		||||
#include <QPushButton>
 | 
			
		||||
#include <QVBoxLayout>
 | 
			
		||||
#include <QHBoxLayout>
 | 
			
		||||
#include <QRect>
 | 
			
		||||
#include <QGridLayout>
 | 
			
		||||
#include <QLabel>
 | 
			
		||||
#include <QIcon>
 | 
			
		||||
#include <QPushButton>
 | 
			
		||||
 | 
			
		||||
CSVDoc::StartupDialogue::StartupDialogue()
 | 
			
		||||
QPushButton *CSVDoc::StartupDialogue::addButton (const QString& label, const QIcon& icon)
 | 
			
		||||
{
 | 
			
		||||
    QHBoxLayout *layout = new QHBoxLayout (this);
 | 
			
		||||
    int column = mColumn--;
 | 
			
		||||
 | 
			
		||||
    QPushButton *createDocument = new QPushButton ("new", this);
 | 
			
		||||
    connect (createDocument, SIGNAL (clicked()), this, SIGNAL (createDocument()));
 | 
			
		||||
    layout->addWidget (createDocument);
 | 
			
		||||
    QPushButton *button = new QPushButton (this);
 | 
			
		||||
 | 
			
		||||
    QPushButton *loadDocument = new QPushButton ("load", this);
 | 
			
		||||
    button->setIcon (QIcon (icon));
 | 
			
		||||
 | 
			
		||||
    button->setSizePolicy (QSizePolicy (QSizePolicy::Preferred, QSizePolicy::Preferred));
 | 
			
		||||
 | 
			
		||||
    mLayout->addWidget (button, 0, column);
 | 
			
		||||
 | 
			
		||||
    mLayout->addWidget (new QLabel (label, this), 1, column, Qt::AlignCenter);
 | 
			
		||||
 | 
			
		||||
    int width = mLayout->itemAtPosition (1, column)->widget()->sizeHint().width();
 | 
			
		||||
 | 
			
		||||
    if (width>mWidth)
 | 
			
		||||
        mWidth = width;
 | 
			
		||||
 | 
			
		||||
    return button;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
QWidget *CSVDoc::StartupDialogue::createButtons()
 | 
			
		||||
{
 | 
			
		||||
    QWidget *widget = new QWidget (this);
 | 
			
		||||
 | 
			
		||||
    mLayout = new QGridLayout (widget);
 | 
			
		||||
 | 
			
		||||
    /// \todo add icons
 | 
			
		||||
    QPushButton *loadDocument = addButton ("Edit A Content File", QIcon (":startup/edit-content"));
 | 
			
		||||
    connect (loadDocument, SIGNAL (clicked()), this, SIGNAL (loadDocument()));
 | 
			
		||||
    layout->addWidget (loadDocument);
 | 
			
		||||
 | 
			
		||||
    QPushButton *createAddon = addButton ("Create A New Addon", QIcon (":startup/create-addon"));
 | 
			
		||||
    connect (createAddon, SIGNAL (clicked()), this, SIGNAL (createAddon()));
 | 
			
		||||
 | 
			
		||||
    QPushButton *createGame = addButton ("Create A New Game", QIcon (":startup/create-game"));
 | 
			
		||||
    connect (createGame, SIGNAL (clicked()), this, SIGNAL (createGame()));
 | 
			
		||||
 | 
			
		||||
    for (int i=0; i<3; ++i)
 | 
			
		||||
        mLayout->setColumnMinimumWidth (i, mWidth);
 | 
			
		||||
 | 
			
		||||
    mLayout->setRowMinimumHeight (0, mWidth);
 | 
			
		||||
 | 
			
		||||
    mLayout->setSizeConstraint (QLayout::SetMinimumSize);
 | 
			
		||||
    mLayout->setHorizontalSpacing (32);
 | 
			
		||||
 | 
			
		||||
    mLayout->setContentsMargins (16, 16, 16, 8);
 | 
			
		||||
 | 
			
		||||
    loadDocument->setIconSize (QSize (mWidth, mWidth));
 | 
			
		||||
    createGame->setIconSize (QSize (mWidth, mWidth));
 | 
			
		||||
    createAddon->setIconSize (QSize (mWidth, mWidth));
 | 
			
		||||
 | 
			
		||||
    widget->setLayout (mLayout);
 | 
			
		||||
 | 
			
		||||
    return widget;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QWidget *CSVDoc::StartupDialogue::createTools()
 | 
			
		||||
{
 | 
			
		||||
    QWidget *widget = new QWidget (this);
 | 
			
		||||
 | 
			
		||||
    QHBoxLayout *layout = new QHBoxLayout (widget);
 | 
			
		||||
    layout->setDirection (QBoxLayout::RightToLeft);
 | 
			
		||||
    layout->setContentsMargins (4, 4, 4, 4);
 | 
			
		||||
 | 
			
		||||
    QPushButton *config = new QPushButton (widget);
 | 
			
		||||
 | 
			
		||||
    config->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
 | 
			
		||||
    config->setIcon (QIcon (":startup/configure"));
 | 
			
		||||
 | 
			
		||||
    layout->addWidget (config);
 | 
			
		||||
 | 
			
		||||
    layout->addWidget (new QWidget, 1); // dummy widget; stops buttons from taking all the space
 | 
			
		||||
 | 
			
		||||
    widget->setLayout (layout);
 | 
			
		||||
 | 
			
		||||
    connect (config, SIGNAL (clicked()), this, SIGNAL (editConfig()));
 | 
			
		||||
 | 
			
		||||
    return widget;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CSVDoc::StartupDialogue::StartupDialogue() : mWidth (0), mColumn (2)
 | 
			
		||||
{
 | 
			
		||||
    setWindowTitle ("Open CS");
 | 
			
		||||
 | 
			
		||||
    QVBoxLayout *layout = new QVBoxLayout (this);
 | 
			
		||||
 | 
			
		||||
    layout->setContentsMargins (0, 0, 0, 0);
 | 
			
		||||
 | 
			
		||||
    layout->addWidget (createButtons());
 | 
			
		||||
    layout->addWidget (createTools());
 | 
			
		||||
 | 
			
		||||
    setLayout (layout);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,21 +3,43 @@
 | 
			
		|||
 | 
			
		||||
#include <QWidget>
 | 
			
		||||
 | 
			
		||||
class QGridLayout;
 | 
			
		||||
class QString;
 | 
			
		||||
class QPushButton;
 | 
			
		||||
class QWidget;
 | 
			
		||||
class QIcon;
 | 
			
		||||
 | 
			
		||||
namespace CSVDoc
 | 
			
		||||
{
 | 
			
		||||
    class StartupDialogue : public QWidget
 | 
			
		||||
    {
 | 
			
		||||
        Q_OBJECT
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
 | 
			
		||||
            int mWidth;
 | 
			
		||||
            int mColumn;
 | 
			
		||||
            QGridLayout *mLayout;
 | 
			
		||||
 | 
			
		||||
            QPushButton *addButton (const QString& label, const QIcon& icon);
 | 
			
		||||
 | 
			
		||||
            QWidget *createButtons();
 | 
			
		||||
 | 
			
		||||
            QWidget *createTools();
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            StartupDialogue();
 | 
			
		||||
 | 
			
		||||
        signals:
 | 
			
		||||
 | 
			
		||||
            void createDocument();
 | 
			
		||||
            void createGame();
 | 
			
		||||
 | 
			
		||||
            void createAddon();
 | 
			
		||||
 | 
			
		||||
            void loadDocument();
 | 
			
		||||
 | 
			
		||||
            void editConfig();
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,7 +67,7 @@ void CSVDoc::View::setupEditMenu()
 | 
			
		|||
    edit->addAction (mRedo);
 | 
			
		||||
 | 
			
		||||
    QAction *userSettings = new QAction (tr ("&Preferences"), this);
 | 
			
		||||
    connect (userSettings, SIGNAL (triggered()), this, SLOT (showUserSettings()));
 | 
			
		||||
    connect (userSettings, SIGNAL (triggered()), this, SIGNAL (editSettingsRequest()));
 | 
			
		||||
    edit->addAction (userSettings);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -415,13 +415,6 @@ void CSVDoc::View::exit()
 | 
			
		|||
    emit exitApplicationRequest (this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CSVDoc::View::showUserSettings()
 | 
			
		||||
{
 | 
			
		||||
    CSVSettings::UserSettingsDialog *settingsDialog = new CSVSettings::UserSettingsDialog(this);
 | 
			
		||||
 | 
			
		||||
    settingsDialog->show();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CSVDoc::View::resizeViewWidth (int width)
 | 
			
		||||
{
 | 
			
		||||
    if (width >= 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -112,6 +112,8 @@ namespace CSVDoc
 | 
			
		|||
 | 
			
		||||
            void exitApplicationRequest (CSVDoc::View *view);
 | 
			
		||||
 | 
			
		||||
            void editSettingsRequest();
 | 
			
		||||
 | 
			
		||||
        public slots:
 | 
			
		||||
 | 
			
		||||
            void addSubView (const CSMWorld::UniversalId& id);
 | 
			
		||||
| 
						 | 
				
			
			@ -160,8 +162,6 @@ namespace CSVDoc
 | 
			
		|||
 | 
			
		||||
            void addFiltersSubView();
 | 
			
		||||
 | 
			
		||||
            void showUserSettings();
 | 
			
		||||
 | 
			
		||||
            void toggleShowStatusBar (bool show);
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@
 | 
			
		|||
 | 
			
		||||
#include "../../model/doc/documentmanager.hpp"
 | 
			
		||||
#include "../../model/doc/document.hpp"
 | 
			
		||||
#include "../../model/world/columns.hpp"
 | 
			
		||||
 | 
			
		||||
#include "../world/util.hpp"
 | 
			
		||||
#include "../world/enumdelegate.hpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -43,51 +44,6 @@ void CSVDoc::ViewManager::updateIndices()
 | 
			
		|||
CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
 | 
			
		||||
    : mDocumentManager (documentManager), mExitOnSaveStateChange(false), mUserWarned(false)
 | 
			
		||||
{
 | 
			
		||||
    static const char *sSpecialisations[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Combat", "Magic", "Stealth", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const char *sAttributes[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Strength", "Intelligence", "Willpower", "Agility", "Speed", "Endurance", "Personality",
 | 
			
		||||
        "Luck", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const char *sSpellTypes[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Spell", "Ability", "Blight", "Disease", "Curse", "Power", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const char *sApparatusTypes[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Mortar & Pestle", "Albemic", "Calcinator", "Retort", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const char *sArmorTypes[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Helmet", "Cuirass", "Left Pauldron", "Right Pauldron", "Greaves", "Boots", "Left Gauntlet",
 | 
			
		||||
        "Right Gauntlet", "Shield", "Left Bracer", "Right Bracer", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const char *sClothingTypes[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Pants", "Shoes", "Shirt", "Belt", "Robe", "Right Glove", "Left Glove", "Skirt", "Ring",
 | 
			
		||||
        "Amulet", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const char *sCreatureTypes[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Creature", "Deadra", "Undead", "Humanoid", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const char *sWeaponTypes[] =
 | 
			
		||||
    {
 | 
			
		||||
        "Short Blade 1H", "Long Blade 1H", "Long Blade 2H", "Blunt 1H", "Blunt 2H Close",
 | 
			
		||||
        "Blunt 2H Wide", "Spear 2H", "Axe 1H", "Axe 2H", "Bow", "Crossbow", "Thrown", "Arrow",
 | 
			
		||||
        "Bolt", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection;
 | 
			
		||||
 | 
			
		||||
    mDelegateFactories->add (CSMWorld::ColumnBase::Display_GmstVarType,
 | 
			
		||||
| 
						 | 
				
			
			@ -96,38 +52,37 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
 | 
			
		|||
    mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType,
 | 
			
		||||
        new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float));
 | 
			
		||||
 | 
			
		||||
    mDelegateFactories->add (CSMWorld::ColumnBase::Display_Specialisation,
 | 
			
		||||
        new CSVWorld::EnumDelegateFactory (sSpecialisations));
 | 
			
		||||
 | 
			
		||||
    mDelegateFactories->add (CSMWorld::ColumnBase::Display_Attribute,
 | 
			
		||||
        new CSVWorld::EnumDelegateFactory (sAttributes, true));
 | 
			
		||||
 | 
			
		||||
    mDelegateFactories->add (CSMWorld::ColumnBase::Display_SpellType,
 | 
			
		||||
        new CSVWorld::EnumDelegateFactory (sSpellTypes));
 | 
			
		||||
 | 
			
		||||
    mDelegateFactories->add (CSMWorld::ColumnBase::Display_ApparatusType,
 | 
			
		||||
        new CSVWorld::EnumDelegateFactory (sApparatusTypes));
 | 
			
		||||
 | 
			
		||||
    mDelegateFactories->add (CSMWorld::ColumnBase::Display_ArmorType,
 | 
			
		||||
        new CSVWorld::EnumDelegateFactory (sArmorTypes));
 | 
			
		||||
 | 
			
		||||
    mDelegateFactories->add (CSMWorld::ColumnBase::Display_ClothingType,
 | 
			
		||||
        new CSVWorld::EnumDelegateFactory (sClothingTypes));
 | 
			
		||||
 | 
			
		||||
    mDelegateFactories->add (CSMWorld::ColumnBase::Display_CreatureType,
 | 
			
		||||
        new CSVWorld::EnumDelegateFactory (sCreatureTypes));
 | 
			
		||||
 | 
			
		||||
    mDelegateFactories->add (CSMWorld::ColumnBase::Display_WeaponType,
 | 
			
		||||
        new CSVWorld::EnumDelegateFactory (sWeaponTypes));
 | 
			
		||||
 | 
			
		||||
    mDelegateFactories->add (CSMWorld::ColumnBase::Display_RecordState,
 | 
			
		||||
        new CSVWorld::RecordStatusDelegateFactory() );
 | 
			
		||||
        new CSVWorld::RecordStatusDelegateFactory());
 | 
			
		||||
 | 
			
		||||
    mDelegateFactories->add (CSMWorld::ColumnBase::Display_RefRecordType,
 | 
			
		||||
        new CSVWorld::RefIdTypeDelegateFactory() );
 | 
			
		||||
        new CSVWorld::RefIdTypeDelegateFactory());
 | 
			
		||||
 | 
			
		||||
    struct Mapping
 | 
			
		||||
    {
 | 
			
		||||
        CSMWorld::ColumnBase::Display mDisplay;
 | 
			
		||||
        CSMWorld::Columns::ColumnId mColumnId;
 | 
			
		||||
        bool mAllowNone;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const Mapping sMapping[] =
 | 
			
		||||
    {
 | 
			
		||||
        { CSMWorld::ColumnBase::Display_Specialisation, CSMWorld::Columns::ColumnId_Specialisation, false },
 | 
			
		||||
        { CSMWorld::ColumnBase::Display_Attribute, CSMWorld::Columns::ColumnId_Attribute, true },
 | 
			
		||||
        { CSMWorld::ColumnBase::Display_SpellType, CSMWorld::Columns::ColumnId_SpellType, false },
 | 
			
		||||
        { CSMWorld::ColumnBase::Display_ApparatusType, CSMWorld::Columns::ColumnId_ApparatusType, false },
 | 
			
		||||
        { CSMWorld::ColumnBase::Display_ArmorType, CSMWorld::Columns::ColumnId_ArmorType, false },
 | 
			
		||||
        { CSMWorld::ColumnBase::Display_ClothingType, CSMWorld::Columns::ColumnId_ClothingType, false },
 | 
			
		||||
        { CSMWorld::ColumnBase::Display_CreatureType, CSMWorld::Columns::ColumnId_CreatureType, false },
 | 
			
		||||
        { CSMWorld::ColumnBase::Display_WeaponType, CSMWorld::Columns::ColumnId_WeaponType, false }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    for (std::size_t i=0; i<sizeof (sMapping)/sizeof (Mapping); ++i)
 | 
			
		||||
        mDelegateFactories->add (sMapping[i].mDisplay, new CSVWorld::EnumDelegateFactory (
 | 
			
		||||
            CSMWorld::Columns::getEnums (sMapping[i].mColumnId), sMapping[i].mAllowNone));
 | 
			
		||||
 | 
			
		||||
    connect (&CSMSettings::UserSettings::instance(), SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)),
 | 
			
		||||
             this, SLOT (slotUpdateEditorSetting (const QString &, const QString &)));
 | 
			
		||||
        this, SLOT (slotUpdateEditorSetting (const QString &, const QString &)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CSVDoc::ViewManager::~ViewManager()
 | 
			
		||||
| 
						 | 
				
			
			@ -159,6 +114,7 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document)
 | 
			
		|||
 | 
			
		||||
    connect (view, SIGNAL (newDocumentRequest ()), this, SIGNAL (newDocumentRequest()));
 | 
			
		||||
    connect (view, SIGNAL (loadDocumentRequest ()), this, SIGNAL (loadDocumentRequest()));
 | 
			
		||||
    connect (view, SIGNAL (editSettingsRequest()), this, SIGNAL (editSettingsRequest()));
 | 
			
		||||
 | 
			
		||||
    updateIndices();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,6 +61,8 @@ namespace CSVDoc
 | 
			
		|||
 | 
			
		||||
            void closeMessageBox();
 | 
			
		||||
 | 
			
		||||
            void editSettingsRequest();
 | 
			
		||||
 | 
			
		||||
        public slots:
 | 
			
		||||
 | 
			
		||||
            void exitApplication (CSVDoc::View *view);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,11 +1,27 @@
 | 
			
		|||
 | 
			
		||||
#include "editwidget.hpp"
 | 
			
		||||
 | 
			
		||||
CSVFilter::EditWidget::EditWidget (QWidget *parent)
 | 
			
		||||
: QLineEdit (parent)
 | 
			
		||||
#include <QAbstractItemModel>
 | 
			
		||||
 | 
			
		||||
#include "../../model/world/data.hpp"
 | 
			
		||||
 | 
			
		||||
CSVFilter::EditWidget::EditWidget (CSMWorld::Data& data, QWidget *parent)
 | 
			
		||||
: QLineEdit (parent), mParser (data)
 | 
			
		||||
{
 | 
			
		||||
    mPalette = palette();
 | 
			
		||||
    connect (this, SIGNAL (textChanged (const QString&)), this, SLOT (textChanged (const QString&)));
 | 
			
		||||
 | 
			
		||||
    QAbstractItemModel *model = data.getTableModel (CSMWorld::UniversalId::Type_Filters);
 | 
			
		||||
 | 
			
		||||
    connect (model, SIGNAL (dataChanged (const QModelIndex &, const QModelIndex&)),
 | 
			
		||||
        this, SLOT (filterDataChanged (const QModelIndex &, const QModelIndex&)),
 | 
			
		||||
        Qt::QueuedConnection);
 | 
			
		||||
    connect (model, SIGNAL (rowsRemoved (const QModelIndex&, int, int)),
 | 
			
		||||
        this, SLOT (filterRowsRemoved (const QModelIndex&, int, int)),
 | 
			
		||||
        Qt::QueuedConnection);
 | 
			
		||||
    connect (model, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
 | 
			
		||||
        this, SLOT (filterRowsInserted (const QModelIndex&, int, int)),
 | 
			
		||||
        Qt::QueuedConnection);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CSVFilter::EditWidget::textChanged (const QString& text)
 | 
			
		||||
| 
						 | 
				
			
			@ -23,4 +39,20 @@ void CSVFilter::EditWidget::textChanged (const QString& text)
 | 
			
		|||
 | 
			
		||||
        /// \todo improve error reporting; mark only the faulty part
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CSVFilter::EditWidget::filterDataChanged (const QModelIndex& topLeft,
 | 
			
		||||
    const QModelIndex& bottomRight)
 | 
			
		||||
{
 | 
			
		||||
    textChanged (text());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CSVFilter::EditWidget::filterRowsRemoved (const QModelIndex& parent, int start, int end)
 | 
			
		||||
{
 | 
			
		||||
    textChanged (text());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CSVFilter::EditWidget::filterRowsInserted (const QModelIndex& parent, int start, int end)
 | 
			
		||||
{
 | 
			
		||||
    textChanged (text());
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,13 @@
 | 
			
		|||
#include "../../model/filter/parser.hpp"
 | 
			
		||||
#include "../../model/filter/node.hpp"
 | 
			
		||||
 | 
			
		||||
class QModelIndex;
 | 
			
		||||
 | 
			
		||||
namespace CSMWorld
 | 
			
		||||
{
 | 
			
		||||
    class Data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace CSVFilter
 | 
			
		||||
{
 | 
			
		||||
    class EditWidget : public QLineEdit
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +27,7 @@ namespace CSVFilter
 | 
			
		|||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            EditWidget (QWidget *parent = 0);
 | 
			
		||||
            EditWidget (CSMWorld::Data& data, QWidget *parent = 0);
 | 
			
		||||
 | 
			
		||||
        signals:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -29,6 +36,12 @@ namespace CSVFilter
 | 
			
		|||
        private slots:
 | 
			
		||||
 | 
			
		||||
            void textChanged (const QString& text);
 | 
			
		||||
 | 
			
		||||
            void filterDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
 | 
			
		||||
 | 
			
		||||
            void filterRowsRemoved (const QModelIndex& parent, int start, int end);
 | 
			
		||||
 | 
			
		||||
            void filterRowsInserted (const QModelIndex& parent, int start, int end);
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,14 +5,14 @@
 | 
			
		|||
 | 
			
		||||
#include "recordfilterbox.hpp"
 | 
			
		||||
 | 
			
		||||
CSVFilter::FilterBox::FilterBox (QWidget *parent)
 | 
			
		||||
CSVFilter::FilterBox::FilterBox (CSMWorld::Data& data, QWidget *parent)
 | 
			
		||||
: QWidget (parent)
 | 
			
		||||
{
 | 
			
		||||
    QHBoxLayout *layout = new QHBoxLayout (this);
 | 
			
		||||
 | 
			
		||||
    layout->setContentsMargins (0, 0, 0, 0);
 | 
			
		||||
 | 
			
		||||
    RecordFilterBox *recordFilterBox = new RecordFilterBox (this);
 | 
			
		||||
    RecordFilterBox *recordFilterBox = new RecordFilterBox (data, this);
 | 
			
		||||
 | 
			
		||||
    layout->addWidget (recordFilterBox);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,11 @@
 | 
			
		|||
 | 
			
		||||
#include "../../model/filter/node.hpp"
 | 
			
		||||
 | 
			
		||||
namespace CSMWorld
 | 
			
		||||
{
 | 
			
		||||
    class Data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace CSVFilter
 | 
			
		||||
{
 | 
			
		||||
    class FilterBox : public QWidget
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +18,7 @@ namespace CSVFilter
 | 
			
		|||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            FilterBox (QWidget *parent = 0);
 | 
			
		||||
            FilterBox (CSMWorld::Data& data, QWidget *parent = 0);
 | 
			
		||||
 | 
			
		||||
        signals:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
 | 
			
		||||
#include "editwidget.hpp"
 | 
			
		||||
 | 
			
		||||
CSVFilter::RecordFilterBox::RecordFilterBox (QWidget *parent)
 | 
			
		||||
CSVFilter::RecordFilterBox::RecordFilterBox (CSMWorld::Data& data, QWidget *parent)
 | 
			
		||||
: QWidget (parent)
 | 
			
		||||
{
 | 
			
		||||
    QHBoxLayout *layout = new QHBoxLayout (this);
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ CSVFilter::RecordFilterBox::RecordFilterBox (QWidget *parent)
 | 
			
		|||
 | 
			
		||||
    layout->addWidget (new QLabel ("Record Filter", this));
 | 
			
		||||
 | 
			
		||||
    EditWidget *editWidget = new EditWidget (this);
 | 
			
		||||
    EditWidget *editWidget = new EditWidget (data, this);
 | 
			
		||||
 | 
			
		||||
    layout->addWidget (editWidget);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,11 @@
 | 
			
		|||
 | 
			
		||||
#include "../../model/filter/node.hpp"
 | 
			
		||||
 | 
			
		||||
namespace CSMWorld
 | 
			
		||||
{
 | 
			
		||||
    class Data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace CSVFilter
 | 
			
		||||
{
 | 
			
		||||
    class RecordFilterBox : public QWidget
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +22,7 @@ namespace CSVFilter
 | 
			
		|||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            RecordFilterBox (QWidget *parent = 0);
 | 
			
		||||
            RecordFilterBox (CSMWorld::Data& data, QWidget *parent = 0);
 | 
			
		||||
 | 
			
		||||
        signals:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
#include "usersettingsdialog.hpp"
 | 
			
		||||
 | 
			
		||||
#include <boost/filesystem/path.hpp>
 | 
			
		||||
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QDesktopWidget>
 | 
			
		||||
#include <QWidget>
 | 
			
		||||
| 
						 | 
				
			
			@ -9,14 +11,14 @@
 | 
			
		|||
#include <QFile>
 | 
			
		||||
#include <QPushButton>
 | 
			
		||||
#include <QDockWidget>
 | 
			
		||||
 | 
			
		||||
#include <QGridLayout>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QDesktopWidget>
 | 
			
		||||
 | 
			
		||||
#include "../../model/settings/support.hpp"
 | 
			
		||||
 | 
			
		||||
#include "datadisplayformatpage.hpp"
 | 
			
		||||
#include "windowpage.hpp"
 | 
			
		||||
 | 
			
		||||
#include "../../model/settings/support.hpp"
 | 
			
		||||
#include <boost/filesystem/path.hpp>
 | 
			
		||||
#include "settingwidget.hpp"
 | 
			
		||||
 | 
			
		||||
CSVSettings::UserSettingsDialog::UserSettingsDialog(QMainWindow *parent) :
 | 
			
		||||
| 
						 | 
				
			
			@ -29,7 +31,11 @@ CSVSettings::UserSettingsDialog::UserSettingsDialog(QMainWindow *parent) :
 | 
			
		|||
    connect (mListWidget,
 | 
			
		||||
             SIGNAL (currentItemChanged(QListWidgetItem*, QListWidgetItem*)),
 | 
			
		||||
             this,
 | 
			
		||||
             SLOT (slotChangePage (QListWidgetItem*, QListWidgetItem*)));    
 | 
			
		||||
             SLOT (slotChangePage (QListWidgetItem*, QListWidgetItem*)));
 | 
			
		||||
 | 
			
		||||
    QRect scr = QApplication::desktop()->screenGeometry();
 | 
			
		||||
    QRect rect = geometry();
 | 
			
		||||
    move (scr.center().x() - rect.center().x(), scr.center().y() - rect.center().y());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CSVSettings::UserSettingsDialog::~UserSettingsDialog()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -109,6 +109,18 @@ CSVWorld::EnumDelegateFactory::EnumDelegateFactory (const char **names, bool all
 | 
			
		|||
        add (i, names[i]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CSVWorld::EnumDelegateFactory::EnumDelegateFactory (const std::vector<std::string>& names,
 | 
			
		||||
    bool allowNone)
 | 
			
		||||
{
 | 
			
		||||
    if (allowNone)
 | 
			
		||||
        add (-1, "");
 | 
			
		||||
 | 
			
		||||
    int size = static_cast<int> (names.size());
 | 
			
		||||
 | 
			
		||||
    for (int i=0; i<size; ++i)
 | 
			
		||||
        add (i, names[i].c_str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CSVWorld::CommandDelegate *CSVWorld::EnumDelegateFactory::makeDelegate (QUndoStack& undoStack,
 | 
			
		||||
    QObject *parent) const
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,6 +54,9 @@ namespace CSVWorld
 | 
			
		|||
            ///< \param names Array of char pointer with a 0-pointer as end mark
 | 
			
		||||
            /// \param allowNone Use value of -1 for "none selected" (empty string)
 | 
			
		||||
 | 
			
		||||
            EnumDelegateFactory (const std::vector<std::string>& names, bool allowNone = false);
 | 
			
		||||
            /// \param allowNone Use value of -1 for "none selected" (empty string)
 | 
			
		||||
 | 
			
		||||
            virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
 | 
			
		||||
            ///< The ownership of the returned CommandDelegate is transferred to the caller.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,11 @@
 | 
			
		|||
#include "recordstatusdelegate.hpp"
 | 
			
		||||
 | 
			
		||||
#include <QPainter>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QUndoStack>
 | 
			
		||||
 | 
			
		||||
#include "../../model/settings/usersettings.hpp"
 | 
			
		||||
#include "../../model/world/columns.hpp"
 | 
			
		||||
 | 
			
		||||
CSVWorld::RecordStatusDelegate::RecordStatusDelegate(const ValueList& values,
 | 
			
		||||
                                                     const IconList & icons,
 | 
			
		||||
| 
						 | 
				
			
			@ -37,9 +40,14 @@ bool CSVWorld::RecordStatusDelegate::updateEditorSetting (const QString &setting
 | 
			
		|||
 | 
			
		||||
CSVWorld::RecordStatusDelegateFactory::RecordStatusDelegateFactory()
 | 
			
		||||
{
 | 
			
		||||
    DataDisplayDelegateFactory::add ( CSMWorld::RecordBase::State_BaseOnly,     "Base",     ":./base.png");
 | 
			
		||||
    DataDisplayDelegateFactory::add ( CSMWorld::RecordBase::State_Deleted,      "Deleted",  ":./removed.png");
 | 
			
		||||
    DataDisplayDelegateFactory::add ( CSMWorld::RecordBase::State_Erased,       "Deleted",  ":./removed.png");
 | 
			
		||||
    DataDisplayDelegateFactory::add ( CSMWorld::RecordBase::State_Modified,     "Modified", ":./modified.png");
 | 
			
		||||
    DataDisplayDelegateFactory::add ( CSMWorld::RecordBase::State_ModifiedOnly, "Added",    ":./added.png");
 | 
			
		||||
    std::vector<std::string> enums =
 | 
			
		||||
        CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_Modification);
 | 
			
		||||
 | 
			
		||||
    static const char *sIcons[] =
 | 
			
		||||
    {
 | 
			
		||||
        ":./base.png", ":./modified.png", ":./added.png", ":./removed.png", ":./removed.png", 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    for (int i=0; sIcons[i]; ++i)
 | 
			
		||||
        add (i, enums.at (i).c_str(), sIcons[i]);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
#include "refidtypedelegate.hpp"
 | 
			
		||||
 | 
			
		||||
#include "../../model/world/universalid.hpp"
 | 
			
		||||
 | 
			
		||||
CSVWorld::RefIdTypeDelegate::RefIdTypeDelegate
 | 
			
		||||
| 
						 | 
				
			
			@ -6,6 +7,26 @@ CSVWorld::RefIdTypeDelegate::RefIdTypeDelegate
 | 
			
		|||
    : DataDisplayDelegate (values, icons, undoStack, parent)
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
bool CSVWorld::RefIdTypeDelegate::updateEditorSetting (const QString &settingName, const QString &settingValue)
 | 
			
		||||
{
 | 
			
		||||
    if (settingName == "Referenceable ID Type Display")
 | 
			
		||||
    {
 | 
			
		||||
        if (settingValue == "Icon and Text")
 | 
			
		||||
            mDisplayMode = Mode_IconAndText;
 | 
			
		||||
 | 
			
		||||
        else if (settingValue == "Icon Only")
 | 
			
		||||
            mDisplayMode = Mode_IconOnly;
 | 
			
		||||
 | 
			
		||||
        else if (settingValue == "Text Only")
 | 
			
		||||
            mDisplayMode = Mode_TextOnly;
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
CSVWorld::RefIdTypeDelegateFactory::RefIdTypeDelegateFactory()
 | 
			
		||||
{
 | 
			
		||||
    UidTypeList uIdList = buildUidTypeList();
 | 
			
		||||
| 
						 | 
				
			
			@ -39,22 +60,3 @@ CSVWorld::RefIdTypeDelegateFactory::UidTypeList CSVWorld::RefIdTypeDelegateFacto
 | 
			
		|||
 | 
			
		||||
    return list;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CSVWorld::RefIdTypeDelegate::updateEditorSetting (const QString &settingName, const QString &settingValue)
 | 
			
		||||
{
 | 
			
		||||
    if (settingName == "Referenceable ID Type Display")
 | 
			
		||||
    {
 | 
			
		||||
        if (settingValue == "Icon and Text")
 | 
			
		||||
            mDisplayMode = Mode_IconAndText;
 | 
			
		||||
 | 
			
		||||
        else if (settingValue == "Icon Only")
 | 
			
		||||
            mDisplayMode = Mode_IconOnly;
 | 
			
		||||
 | 
			
		||||
        else if (settingValue == "Text Only")
 | 
			
		||||
            mDisplayMode = Mode_TextOnly;
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,25 +0,0 @@
 | 
			
		|||
#include "refrecordtypedelegate.hpp"
 | 
			
		||||
#include "../../model/world/universalid.hpp"
 | 
			
		||||
 | 
			
		||||
CSVWorld::RefRecordTypeDelegate::RefRecordTypeDelegate
 | 
			
		||||
    (const std::vector<std::pair<int, QString> > &values, QUndoStack& undoStack, QObject *parent)
 | 
			
		||||
        : EnumDelegate (values, undoStack, parent)
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
CSVWorld::RefRecordTypeDelegateFactory::RefRecordTypeDelegateFactory()
 | 
			
		||||
{
 | 
			
		||||
    unsigned int argSize = CSMWorld::UniversalId::getIdArgSize();
 | 
			
		||||
 | 
			
		||||
    for (unsigned int i = 0; i < argSize; i++)
 | 
			
		||||
    {
 | 
			
		||||
        std::pair<int, const char *> idPair = CSMWorld::UniversalId::getIdArgPair(i);
 | 
			
		||||
 | 
			
		||||
        mValues.push_back (std::pair<int, QString>(idPair.first, QString::fromUtf8(idPair.second)));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CSVWorld::CommandDelegate *CSVWorld::RefRecordTypeDelegateFactory::makeDelegate (QUndoStack& undoStack,
 | 
			
		||||
    QObject *parent) const
 | 
			
		||||
{
 | 
			
		||||
    return new RefRecordTypeDelegate (mValues, undoStack, parent);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,58 +0,0 @@
 | 
			
		|||
#ifndef REFRECORDTYPEDELEGATE_HPP
 | 
			
		||||
#define REFRECORDTYPEDELEGATE_HPP
 | 
			
		||||
 | 
			
		||||
#include "enumdelegate.hpp"
 | 
			
		||||
#include "util.hpp"
 | 
			
		||||
 | 
			
		||||
namespace CSVWorld
 | 
			
		||||
{
 | 
			
		||||
    class RefRecordTypeDelegate : public EnumDelegate
 | 
			
		||||
    {
 | 
			
		||||
        public:
 | 
			
		||||
            RefRecordTypeDelegate (const std::vector<std::pair<int, QString> > &mValues, QUndoStack& undoStack, QObject *parent);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class RefRecordTypeDelegateFactory : public CommandDelegateFactory
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        std::vector<std::pair<int, QString> > mValues;
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
            RefRecordTypeDelegateFactory();
 | 
			
		||||
 | 
			
		||||
            virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
 | 
			
		||||
            ///< The ownership of the returned CommandDelegate is transferred to the caller.
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
    class VarTypeDelegate : public EnumDelegate
 | 
			
		||||
    {
 | 
			
		||||
        private:
 | 
			
		||||
 | 
			
		||||
            virtual void addCommands (QAbstractItemModel *model,
 | 
			
		||||
                const QModelIndex& index, int type) const;
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            VarTypeDelegate (const std::vector<std::pair<int, QString> >& values,
 | 
			
		||||
                QUndoStack& undoStack, QObject *parent);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class VarTypeDelegateFactory : public CommandDelegateFactory
 | 
			
		||||
    {
 | 
			
		||||
            std::vector<std::pair<int, QString> > mValues;
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
            VarTypeDelegateFactory (ESM::VarType type0 = ESM::VT_Unknown,
 | 
			
		||||
                ESM::VarType type1 = ESM::VT_Unknown, ESM::VarType type2 = ESM::VT_Unknown,
 | 
			
		||||
                ESM::VarType type3 = ESM::VT_Unknown);
 | 
			
		||||
 | 
			
		||||
            virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
 | 
			
		||||
            ///< The ownership of the returned CommandDelegate is transferred to the caller.
 | 
			
		||||
 | 
			
		||||
            void add (ESM::VarType type);
 | 
			
		||||
    };
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#endif // REFRECORDTYPEDELEGATE_HPP
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D
 | 
			
		|||
    layout->insertWidget (0, mTable =
 | 
			
		||||
        new Table (id, document.getData(), document.getUndoStack(), mBottom->canCreateAndDelete()), 2);
 | 
			
		||||
 | 
			
		||||
    CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (this);
 | 
			
		||||
    CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this);
 | 
			
		||||
 | 
			
		||||
    layout->insertWidget (0, filterBox);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,7 @@
 | 
			
		|||
#include <QUndoStack>
 | 
			
		||||
 | 
			
		||||
#include "../../model/world/commands.hpp"
 | 
			
		||||
#include "../../model/world/columns.hpp"
 | 
			
		||||
 | 
			
		||||
void CSVWorld::VarTypeDelegate::addCommands (QAbstractItemModel *model, const QModelIndex& index, int type)
 | 
			
		||||
    const
 | 
			
		||||
| 
						 | 
				
			
			@ -75,29 +76,11 @@ CSVWorld::CommandDelegate *CSVWorld::VarTypeDelegateFactory::makeDelegate (QUndo
 | 
			
		|||
 | 
			
		||||
void CSVWorld::VarTypeDelegateFactory::add (ESM::VarType type)
 | 
			
		||||
{
 | 
			
		||||
    struct Name
 | 
			
		||||
    {
 | 
			
		||||
        ESM::VarType mType;
 | 
			
		||||
        const char *mName;
 | 
			
		||||
    };
 | 
			
		||||
    std::vector<std::string> enums =
 | 
			
		||||
        CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_ValueType);
 | 
			
		||||
 | 
			
		||||
    static const Name sNames[] =
 | 
			
		||||
    {
 | 
			
		||||
        { ESM::VT_None, "empty" },
 | 
			
		||||
        { ESM::VT_Short, "short" },
 | 
			
		||||
        { ESM::VT_Int, "integer" },
 | 
			
		||||
        { ESM::VT_Long, "long" },
 | 
			
		||||
        { ESM::VT_Float, "float" },
 | 
			
		||||
        { ESM::VT_String, "string" },
 | 
			
		||||
        { ESM::VT_Unknown, 0 } // end marker
 | 
			
		||||
    };
 | 
			
		||||
    if (type<0 && type>=enums.size())
 | 
			
		||||
        throw std::logic_error ("Unsupported variable type");
 | 
			
		||||
 | 
			
		||||
    for (int i=0; sNames[i].mName; ++i)
 | 
			
		||||
        if (sNames[i].mType==type)
 | 
			
		||||
        {
 | 
			
		||||
            mValues.push_back (std::make_pair (type, sNames[i].mName));
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    throw std::logic_error ("Unsupported variable type");
 | 
			
		||||
    mValues.push_back (std::make_pair (type, QString::fromUtf8 (enums[type].c_str())));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -123,6 +123,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
 | 
			
		|||
        MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(), tri, batch);
 | 
			
		||||
 | 
			
		||||
        MWBase::Environment::get().getWindowManager()->onFrame(frametime);
 | 
			
		||||
        MWBase::Environment::get().getWindowManager()->update();
 | 
			
		||||
    }
 | 
			
		||||
    catch (const std::exception& e)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -385,26 +386,39 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
 | 
			
		|||
 | 
			
		||||
    loadBSA();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Create input and UI first to set up a bootstrapping environment for
 | 
			
		||||
    // showing a loading screen and keeping the window responsive while doing so
 | 
			
		||||
 | 
			
		||||
    std::string keybinderUser = (mCfgMgr.getUserPath() / "input.xml").string();
 | 
			
		||||
    bool keybinderUserExists = boost::filesystem::exists(keybinderUser);
 | 
			
		||||
    MWInput::InputManager* input = new MWInput::InputManager (*mOgre, *this, keybinderUser, keybinderUserExists);
 | 
			
		||||
    mEnvironment.setInputManager (input);
 | 
			
		||||
 | 
			
		||||
    MWGui::WindowManager* window = new MWGui::WindowManager(
 | 
			
		||||
                mExtensions, mFpsLevel, mOgre, mCfgMgr.getLogPath().string() + std::string("/"),
 | 
			
		||||
                mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding);
 | 
			
		||||
    mEnvironment.setWindowManager (window);
 | 
			
		||||
    if (mNewGame)
 | 
			
		||||
        mEnvironment.getWindowManager()->setNewGame(true);
 | 
			
		||||
 | 
			
		||||
    // Create the world
 | 
			
		||||
    mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mMaster, mPlugins,
 | 
			
		||||
        mResDir, mCfgMgr.getCachePath(), mEncoder, mFallbackMap,
 | 
			
		||||
        mActivationDistanceOverride));
 | 
			
		||||
    MWBase::Environment::get().getWorld()->setupPlayer();
 | 
			
		||||
    input->setPlayer(&mEnvironment.getWorld()->getPlayer());
 | 
			
		||||
 | 
			
		||||
    window->initUI();
 | 
			
		||||
    window->renderWorldMap();
 | 
			
		||||
 | 
			
		||||
    //Load translation data
 | 
			
		||||
    mTranslationDataStorage.setEncoder(mEncoder);
 | 
			
		||||
    for (size_t i = 0; i < mMaster.size(); i++)
 | 
			
		||||
      mTranslationDataStorage.loadTranslationData(mFileCollections, mMaster[i]);
 | 
			
		||||
 | 
			
		||||
    // Create window manager - this manages all the MW-specific GUI windows
 | 
			
		||||
    Compiler::registerExtensions (mExtensions); 
 | 
			
		||||
 | 
			
		||||
    mEnvironment.setWindowManager (new MWGui::WindowManager(
 | 
			
		||||
        mExtensions, mFpsLevel, mOgre, mCfgMgr.getLogPath().string() + std::string("/"),
 | 
			
		||||
        mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding));
 | 
			
		||||
    if (mNewGame)
 | 
			
		||||
        mEnvironment.getWindowManager()->setNewGame(true);
 | 
			
		||||
 | 
			
		||||
    // Create sound system
 | 
			
		||||
    mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -422,16 +436,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
 | 
			
		|||
    mEnvironment.setJournal (new MWDialogue::Journal);
 | 
			
		||||
    mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts, mTranslationDataStorage));
 | 
			
		||||
 | 
			
		||||
    // Sets up the input system
 | 
			
		||||
 | 
			
		||||
    // Get the path for the keybinder xml file
 | 
			
		||||
    std::string keybinderUser = (mCfgMgr.getUserPath() / "input.xml").string();
 | 
			
		||||
    bool keybinderUserExists = boost::filesystem::exists(keybinderUser);
 | 
			
		||||
 | 
			
		||||
    mEnvironment.setInputManager (new MWInput::InputManager (*mOgre,
 | 
			
		||||
        MWBase::Environment::get().getWorld()->getPlayer(),
 | 
			
		||||
         *MWBase::Environment::get().getWindowManager(), *this, keybinderUser, keybinderUserExists));
 | 
			
		||||
 | 
			
		||||
    mEnvironment.getWorld()->renderPlayer();
 | 
			
		||||
 | 
			
		||||
    if (!mNewGame)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,9 +39,11 @@ namespace MWBase
 | 
			
		|||
                Play_Normal  = 0, /* tracked, non-looping, multi-instance, environment */
 | 
			
		||||
                Play_Loop    = 1<<0, /* Sound will continually loop until explicitly stopped */
 | 
			
		||||
                Play_NoEnv   = 1<<1, /* Do not apply environment effects (eg, underwater filters) */
 | 
			
		||||
                Play_NoTrack = 1<<2  /* (3D only) Play the sound at the given object's position
 | 
			
		||||
                Play_NoTrack = 1<<2, /* (3D only) Play the sound at the given object's position
 | 
			
		||||
                                      * but do not keep it updated (the sound will not move with
 | 
			
		||||
                                      * the object and will not stop when the object is deleted. */
 | 
			
		||||
 | 
			
		||||
                Play_LoopNoEnv = Play_Loop | Play_NoEnv
 | 
			
		||||
            };
 | 
			
		||||
            enum PlayType {
 | 
			
		||||
                Play_TypeSfx   = 1<<3, /* Normal SFX sound */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,8 @@
 | 
			
		|||
 | 
			
		||||
#include <components/translation/translation.hpp>
 | 
			
		||||
 | 
			
		||||
#include <components/loadinglistener/loadinglistener.hpp>
 | 
			
		||||
 | 
			
		||||
#include "../mwmechanics/stat.hpp"
 | 
			
		||||
 | 
			
		||||
#include "../mwgui/mode.hpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -253,9 +255,6 @@ namespace MWBase
 | 
			
		|||
 | 
			
		||||
            virtual void executeInConsole (const std::string& path) = 0;
 | 
			
		||||
 | 
			
		||||
            virtual void setLoadingProgress (const std::string& stage, int depth, int current, int total) = 0;
 | 
			
		||||
            virtual void loadingDone() = 0;
 | 
			
		||||
 | 
			
		||||
            virtual void enableRest() = 0;
 | 
			
		||||
            virtual bool getRestEnabled() = 0;
 | 
			
		||||
            virtual bool getJournalAllowed() = 0; 
 | 
			
		||||
| 
						 | 
				
			
			@ -282,6 +281,8 @@ namespace MWBase
 | 
			
		|||
            virtual const Translation::Storage& getTranslationDataStorage() const = 0;
 | 
			
		||||
 | 
			
		||||
            virtual void setKeyFocusWidget (MyGUI::Widget* widget) = 0;
 | 
			
		||||
 | 
			
		||||
            virtual Loading::Listener* getLoadingScreen() = 0;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,19 +6,26 @@
 | 
			
		|||
#include "../mwbase/environment.hpp"
 | 
			
		||||
#include "../mwbase/windowmanager.hpp"
 | 
			
		||||
#include "../mwbase/mechanicsmanager.hpp"
 | 
			
		||||
#include "../mwbase/world.hpp"
 | 
			
		||||
 | 
			
		||||
#include "../mwworld//cellstore.hpp"
 | 
			
		||||
#include "../mwworld/ptr.hpp"
 | 
			
		||||
#include "../mwworld/physicssystem.hpp"
 | 
			
		||||
#include "../mwworld/action.hpp"
 | 
			
		||||
#include "../mwworld/failedaction.hpp"
 | 
			
		||||
#include "../mwworld/nullaction.hpp"
 | 
			
		||||
 | 
			
		||||
#include "../mwrender/actors.hpp"
 | 
			
		||||
#include "../mwrender/renderinginterface.hpp"
 | 
			
		||||
 | 
			
		||||
#include "../mwgui/tooltips.hpp"
 | 
			
		||||
 | 
			
		||||
#include "../mwmechanics/npcstats.hpp"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace MWClass
 | 
			
		||||
{
 | 
			
		||||
   void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
 | 
			
		||||
    void Activator::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
 | 
			
		||||
    {
 | 
			
		||||
        const std::string model = getModel(ptr);
 | 
			
		||||
        if (!model.empty()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -94,7 +101,23 @@ namespace MWClass
 | 
			
		|||
 | 
			
		||||
        return info;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    boost::shared_ptr<MWWorld::Action> Activator::activate(const MWWorld::Ptr &ptr, const MWWorld::Ptr &actor) const
 | 
			
		||||
    {
 | 
			
		||||
        if(get(actor).isNpc() && get(actor).getNpcStats(actor).isWerewolf())
 | 
			
		||||
        {
 | 
			
		||||
            const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
 | 
			
		||||
            const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfActivator");
 | 
			
		||||
 | 
			
		||||
            boost::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction("#{sWerewolfRefusal}"));
 | 
			
		||||
            if(sound) action->setSound(sound->mId);
 | 
			
		||||
 | 
			
		||||
            return action;
 | 
			
		||||
        }
 | 
			
		||||
        return boost::shared_ptr<MWWorld::Action>(new MWWorld::NullAction);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    MWWorld::Ptr
 | 
			
		||||
    Activator::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,9 @@ namespace MWClass
 | 
			
		|||
            virtual std::string getScript (const MWWorld::Ptr& ptr) const;
 | 
			
		||||
            ///< Return name of the script attached to ptr
 | 
			
		||||
 | 
			
		||||
            virtual boost::shared_ptr<MWWorld::Action> activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const;
 | 
			
		||||
            ///< Generate action for activation
 | 
			
		||||
 | 
			
		||||
            static void registerSelf();
 | 
			
		||||
 | 
			
		||||
            virtual std::string getModel(const MWWorld::Ptr &ptr) const;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,20 +19,16 @@ namespace MWGui
 | 
			
		|||
        : mSceneMgr(sceneMgr)
 | 
			
		||||
        , mWindow(rw)
 | 
			
		||||
        , WindowBase("openmw_loading_screen.layout")
 | 
			
		||||
        , mLoadingOn(false)
 | 
			
		||||
        , mLastRenderTime(0.f)
 | 
			
		||||
        , mLastWallpaperChangeTime(0.f)
 | 
			
		||||
        , mFirstLoad(true)
 | 
			
		||||
        , mTotalRefsLoading(0)
 | 
			
		||||
        , mCurrentCellLoading(0)
 | 
			
		||||
        , mTotalCellsLoading(0)
 | 
			
		||||
        , mCurrentRefLoading(0)
 | 
			
		||||
        , mCurrentRefList(0)
 | 
			
		||||
        , mProgress(0)
 | 
			
		||||
    {
 | 
			
		||||
        getWidget(mLoadingText, "LoadingText");
 | 
			
		||||
        getWidget(mProgressBar, "ProgressBar");
 | 
			
		||||
        getWidget(mBackgroundImage, "BackgroundImage");
 | 
			
		||||
 | 
			
		||||
        mProgressBar->setScrollViewPage(1);
 | 
			
		||||
 | 
			
		||||
        mBackgroundMaterial = Ogre::MaterialManager::getSingleton().create("BackgroundMaterial", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
 | 
			
		||||
        mBackgroundMaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false);
 | 
			
		||||
| 
						 | 
				
			
			@ -54,6 +50,11 @@ namespace MWGui
 | 
			
		|||
        mRectangle->setVisible(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadingScreen::setLabel(const std::string &label)
 | 
			
		||||
    {
 | 
			
		||||
        mLoadingText->setCaptionWithReplacing(label);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    LoadingScreen::~LoadingScreen()
 | 
			
		||||
    {
 | 
			
		||||
        delete mRectangle;
 | 
			
		||||
| 
						 | 
				
			
			@ -64,149 +65,25 @@ namespace MWGui
 | 
			
		|||
        setCoord(0,0,w,h);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadingScreen::setLoadingProgress (const std::string& stage, int depth, int current, int total)
 | 
			
		||||
    {
 | 
			
		||||
        if (!mLoadingOn)
 | 
			
		||||
            loadingOn();
 | 
			
		||||
 | 
			
		||||
        const int numRefLists = 20;
 | 
			
		||||
 | 
			
		||||
        if (depth == 0)
 | 
			
		||||
        {
 | 
			
		||||
            mCurrentCellLoading = current;
 | 
			
		||||
            mTotalCellsLoading = total;
 | 
			
		||||
 | 
			
		||||
            mCurrentRefLoading = 0;
 | 
			
		||||
            mCurrentRefList = 0;
 | 
			
		||||
        }
 | 
			
		||||
        else if (depth == 1)
 | 
			
		||||
        {
 | 
			
		||||
            mCurrentRefLoading = current;
 | 
			
		||||
            mTotalRefsLoading = total;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        assert (mTotalCellsLoading != 0);
 | 
			
		||||
 | 
			
		||||
        float refProgress;
 | 
			
		||||
        if (mTotalRefsLoading <= 1)
 | 
			
		||||
            refProgress = 1;
 | 
			
		||||
        else
 | 
			
		||||
            refProgress = float(mCurrentRefLoading) / float(mTotalRefsLoading-1);
 | 
			
		||||
        refProgress += mCurrentRefList;
 | 
			
		||||
        refProgress /= numRefLists;
 | 
			
		||||
 | 
			
		||||
        assert(refProgress <= 1 && refProgress >= 0);
 | 
			
		||||
 | 
			
		||||
        if (depth == 1 && mCurrentRefLoading == mTotalRefsLoading-1)
 | 
			
		||||
            ++mCurrentRefList;
 | 
			
		||||
 | 
			
		||||
        float progress = (float(mCurrentCellLoading)+refProgress) / float(mTotalCellsLoading);
 | 
			
		||||
        assert(progress <= 1 && progress >= 0);
 | 
			
		||||
 | 
			
		||||
        mLoadingText->setCaption(stage);
 | 
			
		||||
        mProgressBar->setProgressPosition (static_cast<size_t>(progress * 1000));
 | 
			
		||||
 | 
			
		||||
        static float loadingScreenFps = 30.f;
 | 
			
		||||
 | 
			
		||||
        if (mTimer.getMilliseconds () > mLastRenderTime + (1.f/loadingScreenFps) * 1000.f)
 | 
			
		||||
        {
 | 
			
		||||
            float dt = mTimer.getMilliseconds () - mLastRenderTime;
 | 
			
		||||
            mLastRenderTime = mTimer.getMilliseconds ();
 | 
			
		||||
 | 
			
		||||
            if (mFirstLoad && mTimer.getMilliseconds () > mLastWallpaperChangeTime + 3000*1)
 | 
			
		||||
            {
 | 
			
		||||
                mLastWallpaperChangeTime = mTimer.getMilliseconds ();
 | 
			
		||||
                changeWallpaper();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Turn off rendering except the GUI
 | 
			
		||||
            mSceneMgr->clearSpecialCaseRenderQueues();
 | 
			
		||||
            // SCRQM_INCLUDE with RENDER_QUEUE_OVERLAY does not work.
 | 
			
		||||
            for (int i = 0; i < Ogre::RENDER_QUEUE_MAX; ++i)
 | 
			
		||||
            {
 | 
			
		||||
                if (i > 0 && i < 96)
 | 
			
		||||
                    mSceneMgr->addSpecialCaseRenderQueue(i);
 | 
			
		||||
            }
 | 
			
		||||
            mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE);
 | 
			
		||||
 | 
			
		||||
            // always update input before rendering something, otherwise mygui goes crazy when something was entered in the frame before
 | 
			
		||||
            // (e.g. when using "coc" console command, it would enter an infinite loop and crash due to overflow)
 | 
			
		||||
            MWBase::Environment::get().getInputManager()->update(0, true);
 | 
			
		||||
 | 
			
		||||
            Ogre::CompositorChain* chain = Ogre::CompositorManager::getSingleton().getCompositorChain(mWindow->getViewport(0));
 | 
			
		||||
 | 
			
		||||
            bool hasCompositor = chain->getCompositor ("gbufferFinalizer");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            if (!hasCompositor)
 | 
			
		||||
            {
 | 
			
		||||
                mWindow->getViewport(0)->setClearEveryFrame(false);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (!mFirstLoad)
 | 
			
		||||
                {
 | 
			
		||||
                    mBackgroundMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(chain->getCompositor ("gbufferFinalizer")->getTextureInstance ("no_mrt_output", 0)->getName());
 | 
			
		||||
                    mRectangle->setVisible(true);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                for (unsigned int i = 0; i<chain->getNumCompositors(); ++i)
 | 
			
		||||
                {
 | 
			
		||||
                    Ogre::CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), chain->getCompositor(i)->getCompositor()->getName(), false);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            MWBase::Environment::get().getWorld ()->getFader ()->update (dt);
 | 
			
		||||
 | 
			
		||||
            mWindow->update();
 | 
			
		||||
 | 
			
		||||
            if (!hasCompositor)
 | 
			
		||||
                mWindow->getViewport(0)->setClearEveryFrame(true);
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                for (unsigned int i = 0; i<chain->getNumCompositors(); ++i)
 | 
			
		||||
                {
 | 
			
		||||
                    Ogre::CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), chain->getCompositor(i)->getCompositor()->getName(), true);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            mRectangle->setVisible(false);
 | 
			
		||||
 | 
			
		||||
            // resume 3d rendering
 | 
			
		||||
            mSceneMgr->clearSpecialCaseRenderQueues();
 | 
			
		||||
            mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadingScreen::loadingDone()
 | 
			
		||||
    {
 | 
			
		||||
        loadingOff();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadingScreen::loadingOn()
 | 
			
		||||
    {
 | 
			
		||||
        setVisible(true);
 | 
			
		||||
        mLoadingOn = true;
 | 
			
		||||
 | 
			
		||||
        if (mFirstLoad)
 | 
			
		||||
        {
 | 
			
		||||
            changeWallpaper();
 | 
			
		||||
 | 
			
		||||
            MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_LoadingWallpaper);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            mBackgroundImage->setImageTexture("");
 | 
			
		||||
            MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Loading);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        MWBase::Environment::get().getWindowManager()->pushGuiMode(mFirstLoad ? GM_LoadingWallpaper : GM_Loading);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadingScreen::loadingOff()
 | 
			
		||||
    {
 | 
			
		||||
        setVisible(false);
 | 
			
		||||
        mLoadingOn = false;
 | 
			
		||||
        mFirstLoad = false;
 | 
			
		||||
 | 
			
		||||
        MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Loading);
 | 
			
		||||
        MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_LoadingWallpaper);
 | 
			
		||||
| 
						 | 
				
			
			@ -235,4 +112,124 @@ namespace MWGui
 | 
			
		|||
        else
 | 
			
		||||
            std::cerr << "No loading screens found!" << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadingScreen::setProgressRange (size_t range)
 | 
			
		||||
    {
 | 
			
		||||
        mProgressBar->setScrollRange(range+1);
 | 
			
		||||
        mProgressBar->setScrollPosition(0);
 | 
			
		||||
        mProgressBar->setTrackSize(0);
 | 
			
		||||
        mProgress = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadingScreen::setProgress (size_t value)
 | 
			
		||||
    {
 | 
			
		||||
        assert(value < mProgressBar->getScrollRange());
 | 
			
		||||
        if (value - mProgress < mProgressBar->getScrollRange()/100.f)
 | 
			
		||||
            return;
 | 
			
		||||
        mProgress = value;
 | 
			
		||||
        mProgressBar->setScrollPosition(0);
 | 
			
		||||
        mProgressBar->setTrackSize(value / (float)(mProgressBar->getScrollRange()) * mProgressBar->getLineSize());
 | 
			
		||||
        draw();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadingScreen::increaseProgress (size_t increase)
 | 
			
		||||
    {
 | 
			
		||||
        mProgressBar->setScrollPosition(0);
 | 
			
		||||
        size_t value = mProgress + increase;
 | 
			
		||||
        mProgress = value;
 | 
			
		||||
        assert(mProgress < mProgressBar->getScrollRange());
 | 
			
		||||
        mProgressBar->setTrackSize(value / (float)(mProgressBar->getScrollRange()) * mProgressBar->getLineSize());
 | 
			
		||||
        draw();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadingScreen::indicateProgress()
 | 
			
		||||
    {
 | 
			
		||||
        float time = (mTimer.getMilliseconds() % 2001) / 1000.f;
 | 
			
		||||
        if (time > 1)
 | 
			
		||||
            time = (time-2)*-1;
 | 
			
		||||
 | 
			
		||||
        mProgressBar->setTrackSize(50);
 | 
			
		||||
        mProgressBar->setScrollPosition(time * (mProgressBar->getScrollRange()-1));
 | 
			
		||||
        draw();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadingScreen::removeWallpaper()
 | 
			
		||||
    {
 | 
			
		||||
        mFirstLoad = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadingScreen::draw()
 | 
			
		||||
    {
 | 
			
		||||
        const float loadingScreenFps = 20.f;
 | 
			
		||||
 | 
			
		||||
        if (mTimer.getMilliseconds () > mLastRenderTime + (1.f/loadingScreenFps) * 1000.f)
 | 
			
		||||
        {
 | 
			
		||||
            mLastRenderTime = mTimer.getMilliseconds ();
 | 
			
		||||
 | 
			
		||||
            if (mFirstLoad && mTimer.getMilliseconds () > mLastWallpaperChangeTime + 5000*1)
 | 
			
		||||
            {
 | 
			
		||||
                mLastWallpaperChangeTime = mTimer.getMilliseconds ();
 | 
			
		||||
                changeWallpaper();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Turn off rendering except the GUI
 | 
			
		||||
            mSceneMgr->clearSpecialCaseRenderQueues();
 | 
			
		||||
            // SCRQM_INCLUDE with RENDER_QUEUE_OVERLAY does not work.
 | 
			
		||||
            for (int i = 0; i < Ogre::RENDER_QUEUE_MAX; ++i)
 | 
			
		||||
            {
 | 
			
		||||
                if (i > 0 && i < 96)
 | 
			
		||||
                    mSceneMgr->addSpecialCaseRenderQueue(i);
 | 
			
		||||
            }
 | 
			
		||||
            mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE);
 | 
			
		||||
 | 
			
		||||
            MWBase::Environment::get().getInputManager()->update(0, true);
 | 
			
		||||
 | 
			
		||||
            Ogre::CompositorChain* chain = Ogre::CompositorManager::getSingleton().getCompositorChain(mWindow->getViewport(0));
 | 
			
		||||
 | 
			
		||||
            bool hasCompositor = chain->getCompositor ("gbufferFinalizer");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            if (!hasCompositor)
 | 
			
		||||
            {
 | 
			
		||||
                mWindow->getViewport(0)->setClearEveryFrame(false);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (!mFirstLoad)
 | 
			
		||||
                {
 | 
			
		||||
                    mBackgroundMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(chain->getCompositor ("gbufferFinalizer")->getTextureInstance ("no_mrt_output", 0)->getName());
 | 
			
		||||
                    mRectangle->setVisible(true);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                for (unsigned int i = 0; i<chain->getNumCompositors(); ++i)
 | 
			
		||||
                {
 | 
			
		||||
                    Ogre::CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), chain->getCompositor(i)->getCompositor()->getName(), false);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // First, swap buffers from last draw, then, queue an update of the
 | 
			
		||||
            // window contents, but don't swap buffers (which would have
 | 
			
		||||
            // caused a sync / flush and would be expensive).
 | 
			
		||||
            // We're doing this so we can do some actual loading while the GPU is busy with the render.
 | 
			
		||||
            // This means the render is lagging a frame behind, but this is hardly noticable.
 | 
			
		||||
            mWindow->swapBuffers(false); // never Vsync, makes no sense here
 | 
			
		||||
            mWindow->update(false);
 | 
			
		||||
 | 
			
		||||
            if (!hasCompositor)
 | 
			
		||||
                mWindow->getViewport(0)->setClearEveryFrame(true);
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                for (unsigned int i = 0; i<chain->getNumCompositors(); ++i)
 | 
			
		||||
                {
 | 
			
		||||
                    Ogre::CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), chain->getCompositor(i)->getCompositor()->getName(), true);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            mRectangle->setVisible(false);
 | 
			
		||||
 | 
			
		||||
            // resume 3d rendering
 | 
			
		||||
            mSceneMgr->clearSpecialCaseRenderQueues();
 | 
			
		||||
            mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,11 +5,27 @@
 | 
			
		|||
 | 
			
		||||
#include "windowbase.hpp"
 | 
			
		||||
 | 
			
		||||
#include <components/loadinglistener/loadinglistener.hpp>
 | 
			
		||||
 | 
			
		||||
namespace MWGui
 | 
			
		||||
{
 | 
			
		||||
    class LoadingScreen : public WindowBase
 | 
			
		||||
    class LoadingScreen : public WindowBase, public Loading::Listener
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        virtual void setLabel (const std::string& label);
 | 
			
		||||
 | 
			
		||||
        /// Indicate that some progress has been made, without specifying how much
 | 
			
		||||
        virtual void indicateProgress ();
 | 
			
		||||
 | 
			
		||||
        virtual void loadingOn();
 | 
			
		||||
        virtual void loadingOff();
 | 
			
		||||
 | 
			
		||||
        virtual void setProgressRange (size_t range);
 | 
			
		||||
        virtual void setProgress (size_t value);
 | 
			
		||||
        virtual void increaseProgress (size_t increase);
 | 
			
		||||
 | 
			
		||||
        virtual void removeWallpaper();
 | 
			
		||||
 | 
			
		||||
        LoadingScreen(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* rw);
 | 
			
		||||
        virtual ~LoadingScreen();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -30,27 +46,20 @@ namespace MWGui
 | 
			
		|||
        unsigned long mLastRenderTime;
 | 
			
		||||
        Ogre::Timer mTimer;
 | 
			
		||||
 | 
			
		||||
        MyGUI::TextBox* mLoadingText;
 | 
			
		||||
        MyGUI::ProgressBar* mProgressBar;
 | 
			
		||||
        MyGUI::ImageBox* mBackgroundImage;
 | 
			
		||||
        size_t mProgress;
 | 
			
		||||
 | 
			
		||||
        int mCurrentCellLoading;
 | 
			
		||||
        int mTotalCellsLoading;
 | 
			
		||||
        int mCurrentRefLoading;
 | 
			
		||||
        int mTotalRefsLoading;
 | 
			
		||||
        int mCurrentRefList;
 | 
			
		||||
        MyGUI::TextBox* mLoadingText;
 | 
			
		||||
        MyGUI::ScrollBar* mProgressBar;
 | 
			
		||||
        MyGUI::ImageBox* mBackgroundImage;
 | 
			
		||||
 | 
			
		||||
        Ogre::Rectangle2D* mRectangle;
 | 
			
		||||
        Ogre::MaterialPtr mBackgroundMaterial;
 | 
			
		||||
 | 
			
		||||
        Ogre::StringVector mResources;
 | 
			
		||||
 | 
			
		||||
        bool mLoadingOn;
 | 
			
		||||
 | 
			
		||||
        void loadingOn();
 | 
			
		||||
        void loadingOff();
 | 
			
		||||
 | 
			
		||||
        void changeWallpaper();
 | 
			
		||||
 | 
			
		||||
        void draw();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -260,12 +260,10 @@ namespace MWGui
 | 
			
		|||
    MapWindow::MapWindow(const std::string& cacheDir)
 | 
			
		||||
        : MWGui::WindowPinnableBase("openmw_map_window.layout")
 | 
			
		||||
        , mGlobal(false)
 | 
			
		||||
        , mGlobalMap(0)
 | 
			
		||||
    {
 | 
			
		||||
        setCoord(500,0,320,300);
 | 
			
		||||
 | 
			
		||||
        mGlobalMapRender = new MWRender::GlobalMap(cacheDir);
 | 
			
		||||
        mGlobalMapRender->render();
 | 
			
		||||
 | 
			
		||||
        getWidget(mLocalMap, "LocalMap");
 | 
			
		||||
        getWidget(mGlobalMap, "GlobalMap");
 | 
			
		||||
        getWidget(mGlobalMapImage, "GlobalMapImage");
 | 
			
		||||
| 
						 | 
				
			
			@ -273,9 +271,6 @@ namespace MWGui
 | 
			
		|||
        getWidget(mPlayerArrowLocal, "CompassLocal");
 | 
			
		||||
        getWidget(mPlayerArrowGlobal, "CompassGlobal");
 | 
			
		||||
 | 
			
		||||
        mGlobalMapImage->setImageTexture("GlobalMap.png");
 | 
			
		||||
        mGlobalMapOverlay->setImageTexture("GlobalMapOverlay");
 | 
			
		||||
 | 
			
		||||
        mGlobalMap->setVisible (false);
 | 
			
		||||
 | 
			
		||||
        getWidget(mButton, "WorldButton");
 | 
			
		||||
| 
						 | 
				
			
			@ -292,6 +287,14 @@ namespace MWGui
 | 
			
		|||
        LocalMapBase::init(mLocalMap, mPlayerArrowLocal, this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void MapWindow::renderGlobalMap(Loading::Listener* loadingListener)
 | 
			
		||||
    {
 | 
			
		||||
        mGlobalMapRender = new MWRender::GlobalMap("");
 | 
			
		||||
        mGlobalMapRender->render(loadingListener);
 | 
			
		||||
        mGlobalMapImage->setImageTexture("GlobalMap.png");
 | 
			
		||||
        mGlobalMapOverlay->setImageTexture("GlobalMapOverlay");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    MapWindow::~MapWindow()
 | 
			
		||||
    {
 | 
			
		||||
        delete mGlobalMapRender;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,11 @@ namespace MWRender
 | 
			
		|||
    class GlobalMap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Loading
 | 
			
		||||
{
 | 
			
		||||
    class Listener;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace MWGui
 | 
			
		||||
{
 | 
			
		||||
    class LocalMapBase
 | 
			
		||||
| 
						 | 
				
			
			@ -71,6 +76,8 @@ namespace MWGui
 | 
			
		|||
 | 
			
		||||
        void setCellName(const std::string& cellName);
 | 
			
		||||
 | 
			
		||||
        void renderGlobalMap(Loading::Listener* loadingListener);
 | 
			
		||||
 | 
			
		||||
        void addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map
 | 
			
		||||
        void cellExplored(int x, int y);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,6 +62,7 @@ namespace MWGui
 | 
			
		|||
            const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts,
 | 
			
		||||
            Translation::Storage& translationDataStorage, ToUTF8::FromType encoding)
 | 
			
		||||
      : mGuiManager(NULL)
 | 
			
		||||
      , mConsoleOnlyScripts(consoleOnlyScripts)
 | 
			
		||||
      , mRendering(ogre)
 | 
			
		||||
      , mHud(NULL)
 | 
			
		||||
      , mMap(NULL)
 | 
			
		||||
| 
						 | 
				
			
			@ -156,7 +157,28 @@ namespace MWGui
 | 
			
		|||
        MyGUI::LanguageManager::getInstance().eventRequestTag = MyGUI::newDelegate(this, &WindowManager::onRetrieveTag);
 | 
			
		||||
 | 
			
		||||
        // Get size info from the Gui object
 | 
			
		||||
        assert(mGui);
 | 
			
		||||
        int w = MyGUI::RenderManager::getInstance().getViewSize().width;
 | 
			
		||||
        int h = MyGUI::RenderManager::getInstance().getViewSize().height;
 | 
			
		||||
 | 
			
		||||
        mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow ());
 | 
			
		||||
        mLoadingScreen->onResChange (w,h);
 | 
			
		||||
 | 
			
		||||
        //set up the hardware cursor manager
 | 
			
		||||
        mSoftwareCursor = new Cursor();
 | 
			
		||||
        mCursorManager = new SFO::SDLCursorManager();
 | 
			
		||||
 | 
			
		||||
        MyGUI::PointerManager::getInstance().eventChangeMousePointer += MyGUI::newDelegate(this, &WindowManager::onCursorChange);
 | 
			
		||||
 | 
			
		||||
        MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged);
 | 
			
		||||
 | 
			
		||||
        setUseHardwareCursors(mUseHardwareCursors);
 | 
			
		||||
        onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer());
 | 
			
		||||
        mCursorManager->cursorVisibilityChange(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WindowManager::initUI()
 | 
			
		||||
    {
 | 
			
		||||
        // Get size info from the Gui object
 | 
			
		||||
        int w = MyGUI::RenderManager::getInstance().getViewSize().width;
 | 
			
		||||
        int h = MyGUI::RenderManager::getInstance().getViewSize().height;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -169,9 +191,9 @@ namespace MWGui
 | 
			
		|||
        mDragAndDrop->mDragAndDropWidget = dragAndDropWidget;
 | 
			
		||||
 | 
			
		||||
        mMenu = new MainMenu(w,h);
 | 
			
		||||
        mMap = new MapWindow(cacheDir);
 | 
			
		||||
        mMap = new MapWindow("");
 | 
			
		||||
        mStatsWindow = new StatsWindow();
 | 
			
		||||
        mConsole = new Console(w,h, consoleOnlyScripts);
 | 
			
		||||
        mConsole = new Console(w,h, mConsoleOnlyScripts);
 | 
			
		||||
        mJournal = JournalWindow::create(JournalViewModel::create ());
 | 
			
		||||
        mMessageBoxManager = new MessageBoxManager();
 | 
			
		||||
        mInventoryWindow = new InventoryWindow(mDragAndDrop);
 | 
			
		||||
| 
						 | 
				
			
			@ -200,13 +222,8 @@ namespace MWGui
 | 
			
		|||
        mSoulgemDialog = new SoulgemDialog(mMessageBoxManager);
 | 
			
		||||
        mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager);
 | 
			
		||||
 | 
			
		||||
        mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow ());
 | 
			
		||||
        mLoadingScreen->onResChange (w,h);
 | 
			
		||||
 | 
			
		||||
        mInputBlocker = mGui->createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Default,"Windows","");
 | 
			
		||||
 | 
			
		||||
        mSoftwareCursor = new Cursor();
 | 
			
		||||
 | 
			
		||||
        mHud->setVisible(mHudEnabled);
 | 
			
		||||
 | 
			
		||||
        mCharGen = new CharacterCreation();
 | 
			
		||||
| 
						 | 
				
			
			@ -225,19 +242,15 @@ namespace MWGui
 | 
			
		|||
        unsetSelectedSpell();
 | 
			
		||||
        unsetSelectedWeapon();
 | 
			
		||||
 | 
			
		||||
        //set up the hardware cursor manager
 | 
			
		||||
        mCursorManager = new SFO::SDLCursorManager();
 | 
			
		||||
 | 
			
		||||
        MyGUI::PointerManager::getInstance().eventChangeMousePointer += MyGUI::newDelegate(this, &WindowManager::onCursorChange);
 | 
			
		||||
 | 
			
		||||
        MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged);
 | 
			
		||||
 | 
			
		||||
        setUseHardwareCursors(mUseHardwareCursors);
 | 
			
		||||
        onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer());
 | 
			
		||||
        mCursorManager->cursorVisibilityChange(false);
 | 
			
		||||
 | 
			
		||||
        // Set up visibility
 | 
			
		||||
        updateVisible();
 | 
			
		||||
 | 
			
		||||
        MWBase::Environment::get().getInputManager()->changeInputMode(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WindowManager::renderWorldMap()
 | 
			
		||||
    {
 | 
			
		||||
        mMap->renderGlobalMap(mLoadingScreen);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WindowManager::setNewGame(bool newgame)
 | 
			
		||||
| 
						 | 
				
			
			@ -329,6 +342,8 @@ namespace MWGui
 | 
			
		|||
 | 
			
		||||
    void WindowManager::updateVisible()
 | 
			
		||||
    {
 | 
			
		||||
        if (!mMap)
 | 
			
		||||
            return; // UI not created yet
 | 
			
		||||
        // Start out by hiding everything except the HUD
 | 
			
		||||
        mMap->setVisible(false);
 | 
			
		||||
        mMenu->setVisible(false);
 | 
			
		||||
| 
						 | 
				
			
			@ -914,6 +929,10 @@ namespace MWGui
 | 
			
		|||
 | 
			
		||||
    void WindowManager::windowResized(int x, int y)
 | 
			
		||||
    {
 | 
			
		||||
        mGuiManager->windowResized();
 | 
			
		||||
        mLoadingScreen->onResChange (x,y);
 | 
			
		||||
        if (!mHud)
 | 
			
		||||
            return; // UI not initialized yet
 | 
			
		||||
        mHud->onResChange(x, y);
 | 
			
		||||
        mConsole->onResChange(x, y);
 | 
			
		||||
        mMenu->onResChange(x, y);
 | 
			
		||||
| 
						 | 
				
			
			@ -923,10 +942,8 @@ namespace MWGui
 | 
			
		|||
        mBookWindow->center();
 | 
			
		||||
        mQuickKeysMenu->center();
 | 
			
		||||
        mSpellBuyingWindow->center();
 | 
			
		||||
        mLoadingScreen->onResChange (x,y);
 | 
			
		||||
        mDragAndDrop->mDragAndDropWidget->setSize(MyGUI::IntSize(x, y));
 | 
			
		||||
        mInputBlocker->setSize(MyGUI::IntSize(x,y));
 | 
			
		||||
        mGuiManager->windowResized();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WindowManager::pushGuiMode(GuiMode mode)
 | 
			
		||||
| 
						 | 
				
			
			@ -1148,7 +1165,7 @@ namespace MWGui
 | 
			
		|||
 | 
			
		||||
    bool WindowManager::isGuiMode() const
 | 
			
		||||
    {
 | 
			
		||||
        return !mGuiModes.empty() || mMessageBoxManager->isInteractiveMessageBox();
 | 
			
		||||
        return !mGuiModes.empty() || (mMessageBoxManager && mMessageBoxManager->isInteractiveMessageBox());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool WindowManager::isConsoleMode() const
 | 
			
		||||
| 
						 | 
				
			
			@ -1211,7 +1228,8 @@ namespace MWGui
 | 
			
		|||
 | 
			
		||||
    void WindowManager::showCrosshair (bool show)
 | 
			
		||||
    {
 | 
			
		||||
        mHud->setCrosshairVisible (show && mCrosshairEnabled);
 | 
			
		||||
        if (mHud)
 | 
			
		||||
            mHud->setCrosshairVisible (show && mCrosshairEnabled);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WindowManager::activateQuickKey (int index)
 | 
			
		||||
| 
						 | 
				
			
			@ -1230,15 +1248,6 @@ namespace MWGui
 | 
			
		|||
        mHud->setVisible (mHudEnabled);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WindowManager::setLoadingProgress (const std::string& stage, int depth, int current, int total)
 | 
			
		||||
    {
 | 
			
		||||
        mLoadingScreen->setLoadingProgress (stage, depth, current, total);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WindowManager::loadingDone ()
 | 
			
		||||
    {
 | 
			
		||||
        mLoadingScreen->loadingDone ();
 | 
			
		||||
    }
 | 
			
		||||
    bool WindowManager::getRestEnabled()
 | 
			
		||||
    {
 | 
			
		||||
        //Enable rest dialogue if character creation finished
 | 
			
		||||
| 
						 | 
				
			
			@ -1345,4 +1354,9 @@ namespace MWGui
 | 
			
		|||
        mHud->setEnemy(enemy);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Loading::Listener* WindowManager::getLoadingScreen()
 | 
			
		||||
    {
 | 
			
		||||
        return mLoadingScreen;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -91,6 +91,11 @@ namespace MWGui
 | 
			
		|||
                  Translation::Storage& translationDataStorage, ToUTF8::FromType encoding);
 | 
			
		||||
    virtual ~WindowManager();
 | 
			
		||||
 | 
			
		||||
    void initUI();
 | 
			
		||||
    void renderWorldMap();
 | 
			
		||||
 | 
			
		||||
    virtual Loading::Listener* getLoadingScreen();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Should be called each frame to update windows/gui elements.
 | 
			
		||||
     * This could mean updating sizes of gui elements or opening
 | 
			
		||||
| 
						 | 
				
			
			@ -241,9 +246,6 @@ namespace MWGui
 | 
			
		|||
 | 
			
		||||
    virtual void executeInConsole (const std::string& path);
 | 
			
		||||
 | 
			
		||||
    virtual void setLoadingProgress (const std::string& stage, int depth, int current, int total);
 | 
			
		||||
    virtual void loadingDone();
 | 
			
		||||
 | 
			
		||||
    virtual void enableRest() { mRestAllowed = true; }
 | 
			
		||||
    virtual bool getRestEnabled();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -275,6 +277,8 @@ namespace MWGui
 | 
			
		|||
    void onSoulgemDialogButtonPressed (int button);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    bool mConsoleOnlyScripts;
 | 
			
		||||
 | 
			
		||||
    OEngine::GUI::MyGUIManager *mGuiManager;
 | 
			
		||||
    OEngine::Render::OgreRenderer *mRendering;
 | 
			
		||||
    HUD *mHud;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -86,13 +86,10 @@ namespace
 | 
			
		|||
namespace MWInput
 | 
			
		||||
{
 | 
			
		||||
    InputManager::InputManager(OEngine::Render::OgreRenderer &ogre,
 | 
			
		||||
            MWWorld::Player& player,
 | 
			
		||||
            MWBase::WindowManager &windows,
 | 
			
		||||
            OMW::Engine& engine,
 | 
			
		||||
            const std::string& userFile, bool userFileExists)
 | 
			
		||||
        : mOgre(ogre)
 | 
			
		||||
        , mPlayer(player)
 | 
			
		||||
        , mWindows(windows)
 | 
			
		||||
        , mPlayer(NULL)
 | 
			
		||||
        , mEngine(engine)
 | 
			
		||||
        , mMouseLookEnabled(true)
 | 
			
		||||
        , mMouseX(ogre.getWindow()->getWidth ()/2.f)
 | 
			
		||||
| 
						 | 
				
			
			@ -124,8 +121,6 @@ namespace MWInput
 | 
			
		|||
 | 
			
		||||
        adjustMouseRegion (window->getWidth(), window->getHeight());
 | 
			
		||||
 | 
			
		||||
        MyGUI::InputManager::getInstance().injectMouseMove(mMouseX, mMouseY, 0);
 | 
			
		||||
 | 
			
		||||
        loadKeyDefaults();
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < A_Last; ++i)
 | 
			
		||||
| 
						 | 
				
			
			@ -140,8 +135,6 @@ namespace MWInput
 | 
			
		|||
        mControlSwitch["playermagic"]         = true;
 | 
			
		||||
        mControlSwitch["playerviewswitch"]    = true;
 | 
			
		||||
        mControlSwitch["vanitymode"]          = true;
 | 
			
		||||
 | 
			
		||||
        changeInputMode(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    InputManager::~InputManager()
 | 
			
		||||
| 
						 | 
				
			
			@ -164,7 +157,7 @@ namespace MWInput
 | 
			
		|||
 | 
			
		||||
        if (action == A_Use)
 | 
			
		||||
        {
 | 
			
		||||
            MWWorld::Class::get(mPlayer.getPlayer()).getCreatureStats(mPlayer.getPlayer()).setAttackingOrSpell(currentValue);
 | 
			
		||||
            MWWorld::Class::get(mPlayer->getPlayer()).getCreatureStats(mPlayer->getPlayer()).setAttackingOrSpell(currentValue);
 | 
			
		||||
            if (currentValue == 1)
 | 
			
		||||
            {
 | 
			
		||||
                int type = MWMechanics::CreatureStats::AT_Chop;
 | 
			
		||||
| 
						 | 
				
			
			@ -177,7 +170,7 @@ namespace MWInput
 | 
			
		|||
                if (forward && !side)
 | 
			
		||||
                    type = MWMechanics::CreatureStats::AT_Thrust;
 | 
			
		||||
 | 
			
		||||
                MWWorld::Class::get(mPlayer.getPlayer()).getCreatureStats(mPlayer.getPlayer()).setAttackType(type);
 | 
			
		||||
                MWWorld::Class::get(mPlayer->getPlayer()).getCreatureStats(mPlayer->getPlayer()).setAttackType(type);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -204,9 +197,9 @@ namespace MWInput
 | 
			
		|||
            case A_Activate:
 | 
			
		||||
                resetIdleTime();
 | 
			
		||||
 | 
			
		||||
                if (mWindows.isGuiMode())
 | 
			
		||||
                if (MWBase::Environment::get().getWindowManager()->isGuiMode())
 | 
			
		||||
                {
 | 
			
		||||
                    if (mWindows.getMode() == MWGui::GM_Container)
 | 
			
		||||
                    if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Container)
 | 
			
		||||
                        toggleContainer ();
 | 
			
		||||
                    else
 | 
			
		||||
                        MWBase::Environment::get().getWindowManager()->activateKeyPressed();
 | 
			
		||||
| 
						 | 
				
			
			@ -266,7 +259,7 @@ namespace MWInput
 | 
			
		|||
                showQuickKeysMenu();
 | 
			
		||||
                break;
 | 
			
		||||
            case A_ToggleHUD:
 | 
			
		||||
                mWindows.toggleHud();
 | 
			
		||||
                MWBase::Environment::get().getWindowManager()->toggleHud();
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -274,8 +267,7 @@ namespace MWInput
 | 
			
		|||
 | 
			
		||||
    void InputManager::update(float dt, bool loading)
 | 
			
		||||
    {
 | 
			
		||||
        // Tell OIS to handle all input events
 | 
			
		||||
        mInputManager->capture();
 | 
			
		||||
        mInputManager->capture(loading);
 | 
			
		||||
        // 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);
 | 
			
		||||
| 
						 | 
				
			
			@ -285,18 +277,10 @@ namespace MWInput
 | 
			
		|||
        if (!loading)
 | 
			
		||||
            mInputBinder->update(dt);
 | 
			
		||||
 | 
			
		||||
        // Update windows/gui as a result of input events
 | 
			
		||||
        // For instance this could mean opening a new window/dialog,
 | 
			
		||||
        // by doing this after the input events are handled we
 | 
			
		||||
        // ensure that window/gui changes appear quickly while
 | 
			
		||||
        // avoiding that window/gui changes does not happen in
 | 
			
		||||
        // event callbacks (which may crash)
 | 
			
		||||
        mWindows.update();
 | 
			
		||||
 | 
			
		||||
        bool main_menu = mWindows.containsMode(MWGui::GM_MainMenu);
 | 
			
		||||
        bool main_menu = MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu);
 | 
			
		||||
 | 
			
		||||
        bool was_relative = mInputManager->getMouseRelative();
 | 
			
		||||
        bool is_relative = !mWindows.isGuiMode();
 | 
			
		||||
        bool is_relative = !MWBase::Environment::get().getWindowManager()->isGuiMode();
 | 
			
		||||
 | 
			
		||||
        // don't keep the pointer away from the window edge in gui mode
 | 
			
		||||
        // stop using raw mouse motions and switch to system cursor movements
 | 
			
		||||
| 
						 | 
				
			
			@ -312,8 +296,11 @@ namespace MWInput
 | 
			
		|||
            mInputManager->warpMouse(mMouseX, mMouseY);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (loading)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        // Disable movement in Gui mode
 | 
			
		||||
        if (mWindows.isGuiMode()) return;
 | 
			
		||||
        if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // Configure player movement according to keyboard input. Actual movement will
 | 
			
		||||
| 
						 | 
				
			
			@ -324,45 +311,45 @@ namespace MWInput
 | 
			
		|||
            if (actionIsActive(A_MoveLeft))
 | 
			
		||||
            {
 | 
			
		||||
                triedToMove = true;
 | 
			
		||||
                mPlayer.setLeftRight (-1);
 | 
			
		||||
                mPlayer->setLeftRight (-1);
 | 
			
		||||
            }
 | 
			
		||||
            else if (actionIsActive(A_MoveRight))
 | 
			
		||||
            {
 | 
			
		||||
                triedToMove = true;
 | 
			
		||||
                mPlayer.setLeftRight (1);
 | 
			
		||||
                mPlayer->setLeftRight (1);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (actionIsActive(A_MoveForward))
 | 
			
		||||
            {
 | 
			
		||||
                triedToMove = true;
 | 
			
		||||
                mPlayer.setAutoMove (false);
 | 
			
		||||
                mPlayer.setForwardBackward (1);
 | 
			
		||||
                mPlayer->setAutoMove (false);
 | 
			
		||||
                mPlayer->setForwardBackward (1);
 | 
			
		||||
            }
 | 
			
		||||
            else if (actionIsActive(A_MoveBackward))
 | 
			
		||||
            {
 | 
			
		||||
                triedToMove = true;
 | 
			
		||||
                mPlayer.setAutoMove (false);
 | 
			
		||||
                mPlayer.setForwardBackward (-1);
 | 
			
		||||
                mPlayer->setAutoMove (false);
 | 
			
		||||
                mPlayer->setForwardBackward (-1);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            else if(mPlayer.getAutoMove())
 | 
			
		||||
            else if(mPlayer->getAutoMove())
 | 
			
		||||
            {
 | 
			
		||||
                triedToMove = true;
 | 
			
		||||
                mPlayer.setForwardBackward (1);
 | 
			
		||||
                mPlayer->setForwardBackward (1);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            mPlayer.setSneak(actionIsActive(A_Sneak));
 | 
			
		||||
            mPlayer->setSneak(actionIsActive(A_Sneak));
 | 
			
		||||
 | 
			
		||||
            if (actionIsActive(A_Jump) && mControlSwitch["playerjumping"])
 | 
			
		||||
            {
 | 
			
		||||
                mPlayer.setUpDown (1);
 | 
			
		||||
                mPlayer->setUpDown (1);
 | 
			
		||||
                triedToMove = true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (mAlwaysRunActive)
 | 
			
		||||
                mPlayer.setRunState(!actionIsActive(A_Run));
 | 
			
		||||
                mPlayer->setRunState(!actionIsActive(A_Run));
 | 
			
		||||
            else
 | 
			
		||||
                mPlayer.setRunState(actionIsActive(A_Run));
 | 
			
		||||
                mPlayer->setRunState(actionIsActive(A_Run));
 | 
			
		||||
 | 
			
		||||
            // if player tried to start moving, but can't (due to being overencumbered), display a notification.
 | 
			
		||||
            if (triedToMove)
 | 
			
		||||
| 
						 | 
				
			
			@ -371,7 +358,7 @@ namespace MWInput
 | 
			
		|||
                mOverencumberedMessageDelay -= dt;
 | 
			
		||||
                if (MWWorld::Class::get(player).getEncumbrance(player) >= MWWorld::Class::get(player).getCapacity(player))
 | 
			
		||||
                {
 | 
			
		||||
                    mPlayer.setAutoMove (false);
 | 
			
		||||
                    mPlayer->setAutoMove (false);
 | 
			
		||||
                    if (mOverencumberedMessageDelay <= 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        MWBase::Environment::get().getWindowManager ()->messageBox("#{sNotifyMessage59}");
 | 
			
		||||
| 
						 | 
				
			
			@ -425,8 +412,8 @@ namespace MWInput
 | 
			
		|||
        mGuiCursorEnabled = guiMode;
 | 
			
		||||
        mMouseLookEnabled = !guiMode;
 | 
			
		||||
        if (guiMode)
 | 
			
		||||
            mWindows.showCrosshair(false);
 | 
			
		||||
        mWindows.setCursorVisible(guiMode);
 | 
			
		||||
            MWBase::Environment::get().getWindowManager()->showCrosshair(false);
 | 
			
		||||
        MWBase::Environment::get().getWindowManager()->setCursorVisible(guiMode);
 | 
			
		||||
        // if not in gui mode, the camera decides whether to show crosshair or not.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -459,13 +446,13 @@ namespace MWInput
 | 
			
		|||
        }
 | 
			
		||||
        /// \note 7 switches at all, if-else is relevant
 | 
			
		||||
        if (sw == "playercontrols" && !value) {
 | 
			
		||||
            mPlayer.setLeftRight(0);
 | 
			
		||||
            mPlayer.setForwardBackward(0);
 | 
			
		||||
            mPlayer.setAutoMove(false);
 | 
			
		||||
            mPlayer.setUpDown(0);
 | 
			
		||||
            mPlayer->setLeftRight(0);
 | 
			
		||||
            mPlayer->setForwardBackward(0);
 | 
			
		||||
            mPlayer->setAutoMove(false);
 | 
			
		||||
            mPlayer->setUpDown(0);
 | 
			
		||||
        } else if (sw == "playerjumping" && !value) {
 | 
			
		||||
            /// \fixme maybe crouching at this time
 | 
			
		||||
            mPlayer.setUpDown(0);
 | 
			
		||||
            mPlayer->setUpDown(0);
 | 
			
		||||
        } else if (sw == "vanitymode") {
 | 
			
		||||
            MWBase::Environment::get().getWorld()->allowVanityMode(value);
 | 
			
		||||
        } else if (sw == "playerlooking") {
 | 
			
		||||
| 
						 | 
				
			
			@ -594,8 +581,8 @@ namespace MWInput
 | 
			
		|||
            // Only actually turn player when we're not in vanity mode 
 | 
			
		||||
            if(!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot))
 | 
			
		||||
            {
 | 
			
		||||
                mPlayer.yaw(x/scale);
 | 
			
		||||
                mPlayer.pitch(-y/scale);
 | 
			
		||||
                mPlayer->yaw(x/scale);
 | 
			
		||||
                mPlayer->pitch(-y/scale);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (arg.zrel)
 | 
			
		||||
| 
						 | 
				
			
			@ -627,51 +614,51 @@ namespace MWInput
 | 
			
		|||
        if (MyGUI::InputManager::getInstance ().isModalAny())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (mWindows.isGuiMode () && mWindows.getMode () == MWGui::GM_Video)
 | 
			
		||||
        if (MWBase::Environment::get().getWindowManager()->isGuiMode () && MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_Video)
 | 
			
		||||
            MWBase::Environment::get().getWorld ()->stopVideo ();
 | 
			
		||||
        else if (mWindows.containsMode(MWGui::GM_MainMenu))
 | 
			
		||||
            mWindows.popGuiMode();
 | 
			
		||||
        else if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu))
 | 
			
		||||
            MWBase::Environment::get().getWindowManager()->popGuiMode();
 | 
			
		||||
        else
 | 
			
		||||
            mWindows.pushGuiMode (MWGui::GM_MainMenu);
 | 
			
		||||
            MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void InputManager::toggleSpell()
 | 
			
		||||
    {
 | 
			
		||||
        if (mWindows.isGuiMode()) return;
 | 
			
		||||
        if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
 | 
			
		||||
 | 
			
		||||
        // Not allowed before the magic window is accessible
 | 
			
		||||
        if (!mWindows.isAllowed(MWGui::GW_Magic))
 | 
			
		||||
        if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Magic))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        MWMechanics::DrawState_ state = mPlayer.getDrawState();
 | 
			
		||||
        MWMechanics::DrawState_ state = mPlayer->getDrawState();
 | 
			
		||||
        if (state == MWMechanics::DrawState_Weapon || state == MWMechanics::DrawState_Nothing)
 | 
			
		||||
            mPlayer.setDrawState(MWMechanics::DrawState_Spell);
 | 
			
		||||
            mPlayer->setDrawState(MWMechanics::DrawState_Spell);
 | 
			
		||||
        else
 | 
			
		||||
            mPlayer.setDrawState(MWMechanics::DrawState_Nothing);
 | 
			
		||||
            mPlayer->setDrawState(MWMechanics::DrawState_Nothing);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void InputManager::toggleWeapon()
 | 
			
		||||
    {
 | 
			
		||||
        if (mWindows.isGuiMode()) return;
 | 
			
		||||
        if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
 | 
			
		||||
 | 
			
		||||
        // Not allowed before the inventory window is accessible
 | 
			
		||||
        if (!mWindows.isAllowed(MWGui::GW_Inventory))
 | 
			
		||||
        if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        MWMechanics::DrawState_ state = mPlayer.getDrawState();
 | 
			
		||||
        MWMechanics::DrawState_ state = mPlayer->getDrawState();
 | 
			
		||||
        if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing)
 | 
			
		||||
            mPlayer.setDrawState(MWMechanics::DrawState_Weapon);
 | 
			
		||||
            mPlayer->setDrawState(MWMechanics::DrawState_Weapon);
 | 
			
		||||
        else
 | 
			
		||||
            mPlayer.setDrawState(MWMechanics::DrawState_Nothing);
 | 
			
		||||
            mPlayer->setDrawState(MWMechanics::DrawState_Nothing);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void InputManager::rest()
 | 
			
		||||
    {
 | 
			
		||||
        if (!mWindows.getRestEnabled () || mWindows.isGuiMode ())
 | 
			
		||||
        if (!MWBase::Environment::get().getWindowManager()->getRestEnabled () || MWBase::Environment::get().getWindowManager()->isGuiMode ())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        /// \todo check if resting is currently allowed (enemies nearby?)
 | 
			
		||||
        mWindows.pushGuiMode (MWGui::GM_Rest);
 | 
			
		||||
        MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_Rest);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void InputManager::screenshot()
 | 
			
		||||
| 
						 | 
				
			
			@ -679,7 +666,7 @@ namespace MWInput
 | 
			
		|||
        mEngine.screenshot();
 | 
			
		||||
 | 
			
		||||
        std::vector<std::string> empty;
 | 
			
		||||
        mWindows.messageBox ("Screenshot saved", empty);
 | 
			
		||||
        MWBase::Environment::get().getWindowManager()->messageBox ("Screenshot saved", empty);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void InputManager::toggleInventory()
 | 
			
		||||
| 
						 | 
				
			
			@ -688,13 +675,13 @@ namespace MWInput
 | 
			
		|||
            return;
 | 
			
		||||
 | 
			
		||||
        // Toggle between game mode and inventory mode
 | 
			
		||||
        if(!mWindows.isGuiMode())
 | 
			
		||||
            mWindows.pushGuiMode(MWGui::GM_Inventory);
 | 
			
		||||
        if(!MWBase::Environment::get().getWindowManager()->isGuiMode())
 | 
			
		||||
            MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Inventory);
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            MWGui::GuiMode mode = mWindows.getMode();
 | 
			
		||||
            MWGui::GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode();
 | 
			
		||||
            if(mode == MWGui::GM_Inventory || mode == MWGui::GM_Container)
 | 
			
		||||
                mWindows.popGuiMode();
 | 
			
		||||
                MWBase::Environment::get().getWindowManager()->popGuiMode();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // .. but don't touch any other mode, except container.
 | 
			
		||||
| 
						 | 
				
			
			@ -705,12 +692,12 @@ namespace MWInput
 | 
			
		|||
        if (MyGUI::InputManager::getInstance ().isModalAny())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if(mWindows.isGuiMode())
 | 
			
		||||
        if(MWBase::Environment::get().getWindowManager()->isGuiMode())
 | 
			
		||||
        {
 | 
			
		||||
            if (mWindows.getMode() == MWGui::GM_Container)
 | 
			
		||||
                mWindows.popGuiMode();
 | 
			
		||||
            if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Container)
 | 
			
		||||
                MWBase::Environment::get().getWindowManager()->popGuiMode();
 | 
			
		||||
            else
 | 
			
		||||
                mWindows.pushGuiMode(MWGui::GM_Container);
 | 
			
		||||
                MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Container);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -722,15 +709,15 @@ namespace MWInput
 | 
			
		|||
 | 
			
		||||
        // Switch to console mode no matter what mode we are currently
 | 
			
		||||
        // in, except of course if we are already in console mode
 | 
			
		||||
        if (mWindows.isGuiMode())
 | 
			
		||||
        if (MWBase::Environment::get().getWindowManager()->isGuiMode())
 | 
			
		||||
        {
 | 
			
		||||
            if (mWindows.getMode() == MWGui::GM_Console)
 | 
			
		||||
                mWindows.popGuiMode();
 | 
			
		||||
            if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Console)
 | 
			
		||||
                MWBase::Environment::get().getWindowManager()->popGuiMode();
 | 
			
		||||
            else
 | 
			
		||||
                mWindows.pushGuiMode(MWGui::GM_Console);
 | 
			
		||||
                MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Console);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            mWindows.pushGuiMode(MWGui::GM_Console);
 | 
			
		||||
            MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Console);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void InputManager::toggleJournal()
 | 
			
		||||
| 
						 | 
				
			
			@ -739,31 +726,31 @@ namespace MWInput
 | 
			
		|||
            return;
 | 
			
		||||
 | 
			
		||||
        // Toggle between game mode and journal mode
 | 
			
		||||
        if(!mWindows.isGuiMode() && MWBase::Environment::get().getWindowManager ()->getJournalAllowed())
 | 
			
		||||
        if(!MWBase::Environment::get().getWindowManager()->isGuiMode() && MWBase::Environment::get().getWindowManager ()->getJournalAllowed())
 | 
			
		||||
        {
 | 
			
		||||
            MWBase::Environment::get().getSoundManager()->playSound ("book open", 1.0, 1.0);
 | 
			
		||||
            mWindows.pushGuiMode(MWGui::GM_Journal);
 | 
			
		||||
            MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Journal);
 | 
			
		||||
        }
 | 
			
		||||
        else if(mWindows.getMode() == MWGui::GM_Journal)
 | 
			
		||||
        else if(MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Journal)
 | 
			
		||||
        {
 | 
			
		||||
            MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0);
 | 
			
		||||
            mWindows.popGuiMode();
 | 
			
		||||
            MWBase::Environment::get().getWindowManager()->popGuiMode();
 | 
			
		||||
        }
 | 
			
		||||
        // .. but don't touch any other mode.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void InputManager::quickKey (int index)
 | 
			
		||||
    {
 | 
			
		||||
        if (!mWindows.isGuiMode())
 | 
			
		||||
            mWindows.activateQuickKey (index);
 | 
			
		||||
        if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
 | 
			
		||||
            MWBase::Environment::get().getWindowManager()->activateQuickKey (index);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void InputManager::showQuickKeysMenu()
 | 
			
		||||
    {
 | 
			
		||||
        if (!mWindows.isGuiMode ())
 | 
			
		||||
            mWindows.pushGuiMode (MWGui::GM_QuickKeysMenu);
 | 
			
		||||
        else if (mWindows.getMode () == MWGui::GM_QuickKeysMenu)
 | 
			
		||||
            mWindows.removeGuiMode (MWGui::GM_QuickKeysMenu);
 | 
			
		||||
        if (!MWBase::Environment::get().getWindowManager()->isGuiMode ())
 | 
			
		||||
            MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_QuickKeysMenu);
 | 
			
		||||
        else if (MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_QuickKeysMenu)
 | 
			
		||||
            MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_QuickKeysMenu);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void InputManager::activate()
 | 
			
		||||
| 
						 | 
				
			
			@ -774,22 +761,22 @@ namespace MWInput
 | 
			
		|||
 | 
			
		||||
    void InputManager::toggleAutoMove()
 | 
			
		||||
    {
 | 
			
		||||
        if (mWindows.isGuiMode()) return;
 | 
			
		||||
        if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
 | 
			
		||||
 | 
			
		||||
        if (mControlSwitch["playercontrols"])
 | 
			
		||||
            mPlayer.setAutoMove (!mPlayer.getAutoMove());
 | 
			
		||||
            mPlayer->setAutoMove (!mPlayer->getAutoMove());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void InputManager::toggleWalking()
 | 
			
		||||
    {
 | 
			
		||||
        if (mWindows.isGuiMode()) return;
 | 
			
		||||
        if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
 | 
			
		||||
        mAlwaysRunActive = !mAlwaysRunActive;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Exit program now button (which is disabled in GUI mode)
 | 
			
		||||
    void InputManager::exitNow()
 | 
			
		||||
    {
 | 
			
		||||
        if(!mWindows.isGuiMode())
 | 
			
		||||
        if(!MWBase::Environment::get().getWindowManager()->isGuiMode())
 | 
			
		||||
            Ogre::Root::getSingleton().queueEndRendering ();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,8 +60,6 @@ namespace MWInput
 | 
			
		|||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        InputManager(OEngine::Render::OgreRenderer &_ogre,
 | 
			
		||||
            MWWorld::Player&_player,
 | 
			
		||||
            MWBase::WindowManager &_windows,
 | 
			
		||||
            OMW::Engine& engine,
 | 
			
		||||
            const std::string& userFile, bool userFileExists);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -69,6 +67,8 @@ namespace MWInput
 | 
			
		|||
 | 
			
		||||
        virtual void update(float dt, bool loading);
 | 
			
		||||
 | 
			
		||||
        void setPlayer (MWWorld::Player* player) { mPlayer = player; }
 | 
			
		||||
 | 
			
		||||
        virtual void changeInputMode(bool guiMode);
 | 
			
		||||
 | 
			
		||||
        virtual void processChangedSettings(const Settings::CategorySettingVector& changed);
 | 
			
		||||
| 
						 | 
				
			
			@ -125,8 +125,7 @@ namespace MWInput
 | 
			
		|||
 | 
			
		||||
    private:
 | 
			
		||||
        OEngine::Render::OgreRenderer &mOgre;
 | 
			
		||||
        MWWorld::Player& mPlayer;
 | 
			
		||||
        MWBase::WindowManager &mWindows;
 | 
			
		||||
        MWWorld::Player* mPlayer;
 | 
			
		||||
        OMW::Engine& mEngine;
 | 
			
		||||
 | 
			
		||||
        ICS::InputControlSystem* mInputBinder;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,10 +11,12 @@
 | 
			
		|||
 | 
			
		||||
#include "../mwworld/class.hpp"
 | 
			
		||||
#include "../mwworld/inventorystore.hpp"
 | 
			
		||||
#include "../mwworld/player.hpp"
 | 
			
		||||
 | 
			
		||||
#include "../mwbase/world.hpp"
 | 
			
		||||
#include "../mwbase/environment.hpp"
 | 
			
		||||
#include "../mwbase/windowmanager.hpp"
 | 
			
		||||
#include "../mwbase/soundmanager.hpp"
 | 
			
		||||
 | 
			
		||||
#include "npcstats.hpp"
 | 
			
		||||
#include "creaturestats.hpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -68,22 +70,24 @@ namespace MWMechanics
 | 
			
		|||
    {
 | 
			
		||||
        CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
 | 
			
		||||
 | 
			
		||||
        int strength        = creatureStats.getAttribute(0).getBase();
 | 
			
		||||
        int intelligence    = creatureStats.getAttribute(1).getBase();
 | 
			
		||||
        int willpower       = creatureStats.getAttribute(2).getBase();
 | 
			
		||||
        int agility         = creatureStats.getAttribute(3).getBase();
 | 
			
		||||
        int endurance       = creatureStats.getAttribute(5).getBase();
 | 
			
		||||
        int strength     = creatureStats.getAttribute(ESM::Attribute::Strength).getBase();
 | 
			
		||||
        int intelligence = creatureStats.getAttribute(ESM::Attribute::Intelligence).getBase();
 | 
			
		||||
        int willpower    = creatureStats.getAttribute(ESM::Attribute::Willpower).getBase();
 | 
			
		||||
        int agility      = creatureStats.getAttribute(ESM::Attribute::Agility).getBase();
 | 
			
		||||
        int endurance    = creatureStats.getAttribute(ESM::Attribute::Endurance).getBase();
 | 
			
		||||
 | 
			
		||||
        double magickaFactor =
 | 
			
		||||
            creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::FortifyMaximumMagicka)).mMagnitude * 0.1 + 0.5;
 | 
			
		||||
 | 
			
		||||
        DynamicStat<float> magicka = creatureStats.getMagicka();
 | 
			
		||||
        magicka.setBase (static_cast<int> (intelligence + magickaFactor * intelligence));
 | 
			
		||||
        creatureStats.setMagicka (magicka);
 | 
			
		||||
        float diff = (static_cast<int>(intelligence + magickaFactor*intelligence)) - magicka.getBase();
 | 
			
		||||
        magicka.modify(diff);
 | 
			
		||||
        creatureStats.setMagicka(magicka);
 | 
			
		||||
 | 
			
		||||
        DynamicStat<float> fatigue = creatureStats.getFatigue();
 | 
			
		||||
        fatigue.setBase (strength+willpower+agility+endurance);
 | 
			
		||||
        creatureStats.setFatigue (fatigue);
 | 
			
		||||
        diff = (strength+willpower+agility+endurance) - fatigue.getBase();
 | 
			
		||||
        fatigue.modify(diff);
 | 
			
		||||
        creatureStats.setFatigue(fatigue);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Actors::calculateRestoration (const MWWorld::Ptr& ptr, float duration)
 | 
			
		||||
| 
						 | 
				
			
			@ -133,62 +137,63 @@ namespace MWMechanics
 | 
			
		|||
 | 
			
		||||
    void Actors::calculateCreatureStatModifiers (const MWWorld::Ptr& ptr)
 | 
			
		||||
    {
 | 
			
		||||
        CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
 | 
			
		||||
        CreatureStats &creatureStats = MWWorld::Class::get(ptr).getCreatureStats(ptr);
 | 
			
		||||
        const MagicEffects &effects = creatureStats.getMagicEffects();
 | 
			
		||||
 | 
			
		||||
        // attributes
 | 
			
		||||
        for (int i=0; i<8; ++i)
 | 
			
		||||
        for(int i = 0;i < ESM::Attribute::Length;++i)
 | 
			
		||||
        {
 | 
			
		||||
            int modifier =
 | 
			
		||||
                creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::FortifyAttribute, i)).mMagnitude;
 | 
			
		||||
            Stat<int> stat = creatureStats.getAttribute(i);
 | 
			
		||||
            stat.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifyAttribute, i)).mMagnitude -
 | 
			
		||||
                             effects.get(EffectKey(ESM::MagicEffect::DrainAttribute, i)).mMagnitude);
 | 
			
		||||
 | 
			
		||||
            modifier -= creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::DrainAttribute, i)).mMagnitude;
 | 
			
		||||
 | 
			
		||||
            creatureStats.getAttribute(i).setModifier (modifier);
 | 
			
		||||
            creatureStats.setAttribute(i, stat);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // dynamic stats
 | 
			
		||||
        MagicEffects effects = creatureStats.getMagicEffects();
 | 
			
		||||
 | 
			
		||||
        for (int i=0; i<3; ++i)
 | 
			
		||||
        for(int i = 0;i < 3;++i)
 | 
			
		||||
        {
 | 
			
		||||
            DynamicStat<float> stat = creatureStats.getDynamic (i);
 | 
			
		||||
            DynamicStat<float> stat = creatureStats.getDynamic(i);
 | 
			
		||||
            stat.setModifier(effects.get(EffectKey(80+i)).mMagnitude -
 | 
			
		||||
                             effects.get(EffectKey(18+i)).mMagnitude);
 | 
			
		||||
 | 
			
		||||
            stat.setModifier (
 | 
			
		||||
                effects.get (EffectKey(80+i)).mMagnitude - effects.get (EffectKey(18+i)).mMagnitude);
 | 
			
		||||
 | 
			
		||||
            creatureStats.setDynamic (i, stat);
 | 
			
		||||
            creatureStats.setDynamic(i, stat);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Actors::updateDrowning(const MWWorld::Ptr& ptr, float duration)
 | 
			
		||||
    {
 | 
			
		||||
        NpcStats &stats = MWWorld::Class::get(ptr).getNpcStats(ptr);
 | 
			
		||||
        if(MWBase::Environment::get().getWorld()->isSubmerged(ptr) && 
 | 
			
		||||
        MWBase::World *world = MWBase::Environment::get().getWorld();
 | 
			
		||||
        NpcStats &stats = ptr.getClass().getNpcStats(ptr);
 | 
			
		||||
        if(world->isSubmerged(ptr) &&
 | 
			
		||||
           stats.getMagicEffects().get(ESM::MagicEffect::WaterBreathing).mMagnitude == 0)
 | 
			
		||||
        {
 | 
			
		||||
            float timeLeft = 0.0f;
 | 
			
		||||
            if(stats.getFatigue().getCurrent() == 0)
 | 
			
		||||
                stats.setTimeToStartDrowning(0);
 | 
			
		||||
 | 
			
		||||
            float timeLeft = stats.getTimeToStartDrowning()-duration;
 | 
			
		||||
            if(timeLeft < 0.0f)
 | 
			
		||||
                timeLeft = 0.0f;
 | 
			
		||||
 | 
			
		||||
            stats.setTimeToStartDrowning(timeLeft);
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                timeLeft = stats.getTimeToStartDrowning() - duration;
 | 
			
		||||
                if(timeLeft < 0.0f)
 | 
			
		||||
                    timeLeft = 0.0f;
 | 
			
		||||
                stats.setTimeToStartDrowning(timeLeft);
 | 
			
		||||
            }
 | 
			
		||||
            if(timeLeft == 0.0f)
 | 
			
		||||
                stats.setLastDrowningHitTime(stats.getLastDrowningHitTime()+duration);
 | 
			
		||||
            {
 | 
			
		||||
                // If drowning, apply 3 points of damage per second
 | 
			
		||||
                ptr.getClass().setActorHealth(ptr, stats.getHealth().getCurrent() - 3.0f*duration);
 | 
			
		||||
 | 
			
		||||
                // Play a drowning sound as necessary for the player
 | 
			
		||||
                if(ptr == world->getPlayer().getPlayer())
 | 
			
		||||
                {
 | 
			
		||||
                    MWBase::SoundManager *sndmgr = MWBase::Environment::get().getSoundManager();
 | 
			
		||||
                    if(!sndmgr->getSoundPlaying(MWWorld::Ptr(), "drown"))
 | 
			
		||||
                        sndmgr->playSound("drown", 1.0f, 1.0f);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            stats.setTimeToStartDrowning(20);
 | 
			
		||||
            stats.setLastDrowningHitTime(0);
 | 
			
		||||
        }
 | 
			
		||||
        //if npc is drowning and it's time to hit, then hit
 | 
			
		||||
        while(stats.getTimeToStartDrowning() == 0.0f && stats.getLastDrowningHitTime() > 0.33f)
 | 
			
		||||
        {
 | 
			
		||||
            stats.setLastDrowningHitTime(stats.getLastDrowningHitTime()-0.33f);
 | 
			
		||||
            //fixme: replace it with something different once screen hit effects are implemented (blood on screen)
 | 
			
		||||
            MWWorld::Class::get(ptr).setActorHealth(ptr, stats.getHealth().getCurrent()-1.0f);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Actors::Actors() : mDuration (0) {}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,46 +33,48 @@ namespace MWMechanics
 | 
			
		|||
 | 
			
		||||
    bool AiTravel::execute (const MWWorld::Ptr& actor)
 | 
			
		||||
    {
 | 
			
		||||
        MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
 | 
			
		||||
        MWBase::World *world = MWBase::Environment::get().getWorld();
 | 
			
		||||
        ESM::Position pos = actor.getRefData().getPosition();
 | 
			
		||||
        bool cellChange = actor.getCell()->mCell->mData.mX != cellX || actor.getCell()->mCell->mData.mY != cellY;
 | 
			
		||||
        const ESM::Pathgrid *pathgrid =
 | 
			
		||||
            MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*actor.getCell()->mCell);
 | 
			
		||||
        Movement &movement = actor.getClass().getMovementSettings(actor);
 | 
			
		||||
        const ESM::Cell *cell = actor.getCell()->mCell;
 | 
			
		||||
 | 
			
		||||
        if(actor.getCell()->mCell->mData.mX != player.getCell()->mCell->mData.mX)
 | 
			
		||||
        MWWorld::Ptr player = world->getPlayer().getPlayer();
 | 
			
		||||
        if(cell->mData.mX != player.getCell()->mCell->mData.mX)
 | 
			
		||||
        {
 | 
			
		||||
            int sideX = sgn(actor.getCell()->mCell->mData.mX - player.getCell()->mCell->mData.mX);
 | 
			
		||||
            //check if actor is near the border of an inactive cell. If so, disable aitravel.
 | 
			
		||||
            if(sideX * (pos.pos[0] - actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE /
 | 
			
		||||
                2.0 - 200)) 
 | 
			
		||||
            int sideX = sgn(cell->mData.mX - player.getCell()->mCell->mData.mX);
 | 
			
		||||
            //check if actor is near the border of an inactive cell. If so, stop walking.
 | 
			
		||||
            if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) >
 | 
			
		||||
               sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f))
 | 
			
		||||
            {
 | 
			
		||||
                MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
 | 
			
		||||
                return true;
 | 
			
		||||
                movement.mPosition[1] = 0;
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if(actor.getCell()->mCell->mData.mY != player.getCell()->mCell->mData.mY)
 | 
			
		||||
        if(cell->mData.mY != player.getCell()->mCell->mData.mY)
 | 
			
		||||
        {
 | 
			
		||||
            int sideY = sgn(actor.getCell()->mCell->mData.mY - player.getCell()->mCell->mData.mY);
 | 
			
		||||
            //check if actor is near the border of an inactive cell. If so, disable aitravel.
 | 
			
		||||
            if(sideY * (pos.pos[1] - actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE /
 | 
			
		||||
                2.0 - 200)) 
 | 
			
		||||
            int sideY = sgn(cell->mData.mY - player.getCell()->mCell->mData.mY);
 | 
			
		||||
            //check if actor is near the border of an inactive cell. If so, stop walking.
 | 
			
		||||
            if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) >
 | 
			
		||||
               sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f))
 | 
			
		||||
            {
 | 
			
		||||
                MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
 | 
			
		||||
                return true;
 | 
			
		||||
                movement.mPosition[1] = 0;
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const ESM::Pathgrid *pathgrid = world->getStore().get<ESM::Pathgrid>().search(*cell);
 | 
			
		||||
        bool cellChange = cell->mData.mX != cellX || cell->mData.mY != cellY;
 | 
			
		||||
        if(!mPathFinder.isPathConstructed() || cellChange)
 | 
			
		||||
        {
 | 
			
		||||
            cellX = actor.getCell()->mCell->mData.mX;
 | 
			
		||||
            cellY = actor.getCell()->mCell->mData.mY;
 | 
			
		||||
            cellX = cell->mData.mX;
 | 
			
		||||
            cellY = cell->mData.mY;
 | 
			
		||||
            float xCell = 0;
 | 
			
		||||
            float yCell = 0;
 | 
			
		||||
 | 
			
		||||
            if (actor.getCell()->mCell->isExterior())
 | 
			
		||||
            if(cell->isExterior())
 | 
			
		||||
            {
 | 
			
		||||
                xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE;
 | 
			
		||||
                yCell = actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE;
 | 
			
		||||
                xCell = cell->mData.mX * ESM::Land::REAL_SIZE;
 | 
			
		||||
                yCell = cell->mData.mY * ESM::Land::REAL_SIZE;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            ESM::Pathgrid::Point dest;
 | 
			
		||||
| 
						 | 
				
			
			@ -90,13 +92,13 @@ namespace MWMechanics
 | 
			
		|||
 | 
			
		||||
        if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2]))
 | 
			
		||||
        {
 | 
			
		||||
            MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
 | 
			
		||||
            movement.mPosition[1] = 0;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
 | 
			
		||||
        MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false);
 | 
			
		||||
        MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
 | 
			
		||||
        world->rotateObject(actor, 0, 0, zAngle, false);
 | 
			
		||||
        movement.mPosition[1] = 1;
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -65,10 +65,11 @@ namespace MWMechanics
 | 
			
		|||
 | 
			
		||||
    bool AiWander::execute (const MWWorld::Ptr& actor)
 | 
			
		||||
    {
 | 
			
		||||
        MWBase::World *world = MWBase::Environment::get().getWorld();
 | 
			
		||||
        if(mDuration)
 | 
			
		||||
        {
 | 
			
		||||
            // End package if duration is complete or mid-night hits:
 | 
			
		||||
            MWWorld::TimeStamp currentTime = MWBase::Environment::get().getWorld()->getTimeStamp();
 | 
			
		||||
            MWWorld::TimeStamp currentTime = world->getTimeStamp();
 | 
			
		||||
            if(currentTime.getHour() >= mStartTime.getHour() + mDuration)
 | 
			
		||||
            {
 | 
			
		||||
                if(!mRepeat)
 | 
			
		||||
| 
						 | 
				
			
			@ -96,8 +97,7 @@ namespace MWMechanics
 | 
			
		|||
        if(!mStoredAvailableNodes)
 | 
			
		||||
        {
 | 
			
		||||
            mStoredAvailableNodes = true;
 | 
			
		||||
            mPathgrid =
 | 
			
		||||
                MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*actor.getCell()->mCell);
 | 
			
		||||
            mPathgrid = world->getStore().get<ESM::Pathgrid>().search(*actor.getCell()->mCell);
 | 
			
		||||
 | 
			
		||||
            mCellX = actor.getCell()->mCell->mData.mX;
 | 
			
		||||
            mCellY = actor.getCell()->mCell->mData.mY;
 | 
			
		||||
| 
						 | 
				
			
			@ -150,37 +150,8 @@ namespace MWMechanics
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
 | 
			
		||||
        bool cellChange = actor.getCell()->mCell->mData.mX != mCellX || actor.getCell()->mCell->mData.mY != mCellY;
 | 
			
		||||
 | 
			
		||||
        if(actor.getCell()->mCell->mData.mX != player.getCell()->mCell->mData.mX)
 | 
			
		||||
        {
 | 
			
		||||
            int sideX = sgn(actor.getCell()->mCell->mData.mX - player.getCell()->mCell->mData.mX);
 | 
			
		||||
            // Check if actor is near the border of an inactive cell. If so, disable AiWander.
 | 
			
		||||
            // FIXME: This *should* pause the AiWander package instead of terminating it.
 | 
			
		||||
            if(sideX * (pos.pos[0] - actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE /
 | 
			
		||||
                2.0 - 200)) 
 | 
			
		||||
            {
 | 
			
		||||
                stopWalking(actor);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(actor.getCell()->mCell->mData.mY != player.getCell()->mCell->mData.mY)
 | 
			
		||||
        {
 | 
			
		||||
            int sideY = sgn(actor.getCell()->mCell->mData.mY - player.getCell()->mCell->mData.mY);
 | 
			
		||||
            // Check if actor is near the border of an inactive cell. If so, disable AiWander.
 | 
			
		||||
            // FIXME: This *should* pause the AiWander package instead of terminating it.
 | 
			
		||||
            if(sideY * (pos.pos[1] - actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE /
 | 
			
		||||
                2.0 - 200)) 
 | 
			
		||||
            {
 | 
			
		||||
                stopWalking(actor);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Don't try to move if you are in a new cell (ie: positioncell command called) but still play idles.
 | 
			
		||||
        if(mDistance && (cellChange || (mCellX != actor.getCell()->mCell->mData.mX || mCellY != actor.getCell()->mCell->mData.mY)))
 | 
			
		||||
        if(mDistance && (mCellX != actor.getCell()->mCell->mData.mX || mCellY != actor.getCell()->mCell->mData.mY))
 | 
			
		||||
            mDistance = 0;
 | 
			
		||||
 | 
			
		||||
        if(mChooseAction)
 | 
			
		||||
| 
						 | 
				
			
			@ -207,7 +178,7 @@ namespace MWMechanics
 | 
			
		|||
            else
 | 
			
		||||
            {
 | 
			
		||||
                // Play idle animation and recreate vanilla (broken?) behavior of resetting start time of AIWander:
 | 
			
		||||
                MWWorld::TimeStamp currentTime = MWBase::Environment::get().getWorld()->getTimeStamp();
 | 
			
		||||
                MWWorld::TimeStamp currentTime = world->getTimeStamp();
 | 
			
		||||
                mStartTime = currentTime;
 | 
			
		||||
                playIdle(actor, mPlayedIdle);
 | 
			
		||||
                mChooseAction = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -264,18 +235,10 @@ namespace MWMechanics
 | 
			
		|||
        if(mWalking)
 | 
			
		||||
        {
 | 
			
		||||
            float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
 | 
			
		||||
            MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle,false);
 | 
			
		||||
            world->rotateObject(actor, 0, 0, zAngle, false);
 | 
			
		||||
            MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;
 | 
			
		||||
 | 
			
		||||
            // Unclog path nodes by allowing the NPC to be a small distance away from the center. This way two NPCs can be
 | 
			
		||||
            // at the same path node at the same time and both will complete instead of endlessly walking into eachother:
 | 
			
		||||
            Ogre::Vector3 destNodePos(mCurrentNode.mX, mCurrentNode.mY, mCurrentNode.mZ);
 | 
			
		||||
            Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos);
 | 
			
		||||
            actorPos[0] = actorPos[0] - mXCell;
 | 
			
		||||
            actorPos[1] = actorPos[1] - mYCell;
 | 
			
		||||
            float distance = actorPos.squaredDistance(destNodePos);
 | 
			
		||||
 | 
			
		||||
            if(distance < 1200 || mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2]))
 | 
			
		||||
            if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2]))
 | 
			
		||||
            {
 | 
			
		||||
                stopWalking(actor);
 | 
			
		||||
                mMoveNow = false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,6 @@
 | 
			
		|||
#include "../mwbase/world.hpp"
 | 
			
		||||
#include "../mwbase/windowmanager.hpp"
 | 
			
		||||
#include "../mwbase/dialoguemanager.hpp"
 | 
			
		||||
#include "../mwbase/soundmanager.hpp"
 | 
			
		||||
 | 
			
		||||
#include "../mwworld/class.hpp"
 | 
			
		||||
#include "../mwworld/player.hpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -189,6 +188,9 @@ namespace MWMechanics
 | 
			
		|||
 | 
			
		||||
    void MechanicsManager::updateCell(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr)
 | 
			
		||||
    {
 | 
			
		||||
        if(old == mWatched)
 | 
			
		||||
            mWatched = ptr;
 | 
			
		||||
 | 
			
		||||
        if(MWWorld::Class::get(ptr).isActor())
 | 
			
		||||
            mActors.updateActor(old, ptr);
 | 
			
		||||
        else
 | 
			
		||||
| 
						 | 
				
			
			@ -213,98 +215,76 @@ namespace MWMechanics
 | 
			
		|||
 | 
			
		||||
    void MechanicsManager::update(float duration, bool paused)
 | 
			
		||||
    {
 | 
			
		||||
        if (!mWatched.isEmpty())
 | 
			
		||||
        if(!mWatched.isEmpty())
 | 
			
		||||
        {
 | 
			
		||||
            MWMechanics::CreatureStats& stats =
 | 
			
		||||
                MWWorld::Class::get (mWatched).getCreatureStats (mWatched);
 | 
			
		||||
 | 
			
		||||
            MWMechanics::NpcStats& npcStats =
 | 
			
		||||
                MWWorld::Class::get (mWatched).getNpcStats (mWatched);
 | 
			
		||||
 | 
			
		||||
            static const char *attributeNames[8] =
 | 
			
		||||
            MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager();
 | 
			
		||||
            const MWMechanics::NpcStats &stats = mWatched.getClass().getNpcStats(mWatched);
 | 
			
		||||
            for(int i = 0;i < ESM::Attribute::Length;++i)
 | 
			
		||||
            {
 | 
			
		||||
                "AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5",
 | 
			
		||||
                "AttribVal6", "AttribVal7", "AttribVal8"
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            static const char *dynamicNames[3] =
 | 
			
		||||
            {
 | 
			
		||||
                "HBar", "MBar", "FBar"
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            for (int i=0; i<8; ++i)
 | 
			
		||||
            {
 | 
			
		||||
                if (stats.getAttribute(i)!=mWatchedCreature.getAttribute(i))
 | 
			
		||||
                if(stats.getAttribute(i) != mWatchedStats.getAttribute(i))
 | 
			
		||||
                {
 | 
			
		||||
                    mWatchedCreature.setAttribute(i, stats.getAttribute(i));
 | 
			
		||||
                    std::stringstream attrname;
 | 
			
		||||
                    attrname << "AttribVal"<<(i+1);
 | 
			
		||||
 | 
			
		||||
                    MWBase::Environment::get().getWindowManager()->setValue (attributeNames[i], stats.getAttribute(i));
 | 
			
		||||
                    mWatchedStats.setAttribute(i, stats.getAttribute(i));
 | 
			
		||||
                    winMgr->setValue(attrname.str(), stats.getAttribute(i));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (stats.getHealth() != mWatchedCreature.getHealth()) {
 | 
			
		||||
                mWatchedCreature.setHealth(stats.getHealth());
 | 
			
		||||
                MWBase::Environment::get().getWindowManager()->setValue(dynamicNames[0], stats.getHealth());
 | 
			
		||||
            if(stats.getHealth() != mWatchedStats.getHealth())
 | 
			
		||||
            {
 | 
			
		||||
                static const std::string hbar("HBar");
 | 
			
		||||
                mWatchedStats.setHealth(stats.getHealth());
 | 
			
		||||
                winMgr->setValue(hbar, stats.getHealth());
 | 
			
		||||
            }
 | 
			
		||||
            if (stats.getMagicka() != mWatchedCreature.getMagicka()) {
 | 
			
		||||
                mWatchedCreature.setMagicka(stats.getMagicka());
 | 
			
		||||
                MWBase::Environment::get().getWindowManager()->setValue(dynamicNames[1], stats.getMagicka());
 | 
			
		||||
            if(stats.getMagicka() != mWatchedStats.getMagicka())
 | 
			
		||||
            {
 | 
			
		||||
                static const std::string mbar("MBar");
 | 
			
		||||
                mWatchedStats.setMagicka(stats.getMagicka());
 | 
			
		||||
                winMgr->setValue(mbar, stats.getMagicka());
 | 
			
		||||
            }
 | 
			
		||||
            if (stats.getFatigue() != mWatchedCreature.getFatigue()) {
 | 
			
		||||
                mWatchedCreature.setFatigue(stats.getFatigue());
 | 
			
		||||
                MWBase::Environment::get().getWindowManager()->setValue(dynamicNames[2], stats.getFatigue());
 | 
			
		||||
            if(stats.getFatigue() != mWatchedStats.getFatigue())
 | 
			
		||||
            {
 | 
			
		||||
                static const std::string fbar("FBar");
 | 
			
		||||
                mWatchedStats.setFatigue(stats.getFatigue());
 | 
			
		||||
                winMgr->setValue(fbar, stats.getFatigue());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(npcStats.getTimeToStartDrowning() != mWatchedNpc.getTimeToStartDrowning())
 | 
			
		||||
            if(stats.getTimeToStartDrowning() != mWatchedStats.getTimeToStartDrowning())
 | 
			
		||||
            {
 | 
			
		||||
                mWatchedNpc.setTimeToStartDrowning(npcStats.getTimeToStartDrowning());
 | 
			
		||||
                if(npcStats.getTimeToStartDrowning()>=20.0)
 | 
			
		||||
                {
 | 
			
		||||
                    MWBase::Environment::get().getWindowManager()->setDrowningBarVisibility(false);
 | 
			
		||||
                }
 | 
			
		||||
                mWatchedStats.setTimeToStartDrowning(stats.getTimeToStartDrowning());
 | 
			
		||||
                if(stats.getTimeToStartDrowning() >= 20.0f)
 | 
			
		||||
                    winMgr->setDrowningBarVisibility(false);
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    MWBase::Environment::get().getWindowManager()->setDrowningBarVisibility(true);
 | 
			
		||||
                    MWBase::Environment::get().getWindowManager()->setDrowningTimeLeft(npcStats.getTimeToStartDrowning());
 | 
			
		||||
                    winMgr->setDrowningBarVisibility(true);
 | 
			
		||||
                    winMgr->setDrowningTimeLeft(stats.getTimeToStartDrowning());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            bool update = false;
 | 
			
		||||
 | 
			
		||||
            //Loop over ESM::Skill::SkillEnum
 | 
			
		||||
            for(int i = 0; i < 27; ++i)
 | 
			
		||||
            for(int i = 0; i < ESM::Skill::Length; ++i)
 | 
			
		||||
            {
 | 
			
		||||
                if(npcStats.getSkill (i) != mWatchedNpc.getSkill (i))
 | 
			
		||||
                if(stats.getSkill(i) != mWatchedStats.getSkill(i))
 | 
			
		||||
                {
 | 
			
		||||
                    update = true;
 | 
			
		||||
                    mWatchedNpc.getSkill (i) = npcStats.getSkill (i);
 | 
			
		||||
                    MWBase::Environment::get().getWindowManager()->setValue((ESM::Skill::SkillEnum)i, npcStats.getSkill (i));
 | 
			
		||||
                    mWatchedStats.getSkill(i) = stats.getSkill(i);
 | 
			
		||||
                    winMgr->setValue((ESM::Skill::SkillEnum)i, stats.getSkill(i));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (update)
 | 
			
		||||
                MWBase::Environment::get().getWindowManager()->updateSkillArea();
 | 
			
		||||
            if(update)
 | 
			
		||||
                winMgr->updateSkillArea();
 | 
			
		||||
 | 
			
		||||
            MWBase::Environment::get().getWindowManager()->setValue ("level", stats.getLevel());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //update drowning sound
 | 
			
		||||
        MWBase::World *world = MWBase::Environment::get().getWorld();
 | 
			
		||||
        MWBase::SoundManager * sndmgr = MWBase::Environment::get().getSoundManager();
 | 
			
		||||
        MWWorld::Ptr playerPtr = world->getPlayer().getPlayer();
 | 
			
		||||
        NpcStats& playerStats = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr);
 | 
			
		||||
        if(!sndmgr->getSoundPlaying(MWWorld::Ptr(), "drown") && playerStats.getTimeToStartDrowning()==0.0)
 | 
			
		||||
        {
 | 
			
		||||
            sndmgr->playSound("drown",1.0,1.0,MWBase::SoundManager::Play_TypeSfx,MWBase::SoundManager::Play_Loop);
 | 
			
		||||
        }
 | 
			
		||||
        if(playerStats.getTimeToStartDrowning()>0.0)
 | 
			
		||||
        {
 | 
			
		||||
            //no need to check if it's playing, stop sound does nothing in that case
 | 
			
		||||
            sndmgr->stopSound("drown");
 | 
			
		||||
            winMgr->setValue("level", stats.getLevel());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (mUpdatePlayer)
 | 
			
		||||
        {
 | 
			
		||||
            MWBase::World *world = MWBase::Environment::get().getWorld();
 | 
			
		||||
 | 
			
		||||
            // basic player profile; should not change anymore after the creation phase is finished.
 | 
			
		||||
            MWBase::WindowManager *winMgr =
 | 
			
		||||
                MWBase::Environment::get().getWindowManager();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,8 +25,7 @@ namespace MWMechanics
 | 
			
		|||
    class MechanicsManager : public MWBase::MechanicsManager
 | 
			
		||||
    {
 | 
			
		||||
            MWWorld::Ptr mWatched;
 | 
			
		||||
            CreatureStats mWatchedCreature;
 | 
			
		||||
            NpcStats mWatchedNpc;
 | 
			
		||||
            NpcStats mWatchedStats;
 | 
			
		||||
            bool mUpdatePlayer;
 | 
			
		||||
            bool mClassSelected;
 | 
			
		||||
            bool mRaceSelected;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -422,7 +422,7 @@ void MWMechanics::NpcStats::modifyProfit(int diff)
 | 
			
		|||
    mProfit += diff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float MWMechanics::NpcStats::getTimeToStartDrowning()
 | 
			
		||||
float MWMechanics::NpcStats::getTimeToStartDrowning() const
 | 
			
		||||
{
 | 
			
		||||
    return mTimeToStartDrowning;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -431,13 +431,3 @@ void MWMechanics::NpcStats::setTimeToStartDrowning(float time)
 | 
			
		|||
    assert(time>=0 && time<=20);
 | 
			
		||||
    mTimeToStartDrowning=time;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float MWMechanics::NpcStats::getLastDrowningHitTime()
 | 
			
		||||
{
 | 
			
		||||
    return mLastDrowningHit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MWMechanics::NpcStats::setLastDrowningHitTime(float time)
 | 
			
		||||
{
 | 
			
		||||
    mLastDrowningHit=time;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -147,15 +147,10 @@ namespace MWMechanics
 | 
			
		|||
 | 
			
		||||
            int getWerewolfKills() const;
 | 
			
		||||
 | 
			
		||||
            float getTimeToStartDrowning();
 | 
			
		||||
            float getTimeToStartDrowning() const;
 | 
			
		||||
            /// Sets time left for the creature to drown if it stays underwater.
 | 
			
		||||
            /// @param time value from [0,20]
 | 
			
		||||
            void setTimeToStartDrowning(float time);
 | 
			
		||||
 | 
			
		||||
            float getLastDrowningHitTime();
 | 
			
		||||
            /// Sets time since last hit caused by drowning.
 | 
			
		||||
            /// @param time value from [0,0.33]
 | 
			
		||||
            void setLastDrowningHitTime(float time);
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -147,13 +147,13 @@ namespace MWMechanics
 | 
			
		|||
        mIsPathConstructed = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void PathFinder::buildPath(ESM::Pathgrid::Point startPoint, ESM::Pathgrid::Point endPoint,
 | 
			
		||||
        const ESM::Pathgrid* pathGrid, float xCell, float yCell, bool allowShortcuts)
 | 
			
		||||
    void PathFinder::buildPath(const ESM::Pathgrid::Point &startPoint, const ESM::Pathgrid::Point &endPoint,
 | 
			
		||||
                               const ESM::Pathgrid *pathGrid, float xCell, float yCell, bool allowShortcuts)
 | 
			
		||||
    {
 | 
			
		||||
        if(allowShortcuts)
 | 
			
		||||
        {
 | 
			
		||||
            if(MWBase::Environment::get().getWorld()->castRay(startPoint.mX, startPoint.mY, startPoint.mZ, endPoint.mX, endPoint.mY,
 | 
			
		||||
                endPoint.mZ))
 | 
			
		||||
            if(MWBase::Environment::get().getWorld()->castRay(startPoint.mX, startPoint.mY, startPoint.mZ,
 | 
			
		||||
                                                              endPoint.mX, endPoint.mY, endPoint.mZ))
 | 
			
		||||
                allowShortcuts = false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -184,14 +184,14 @@ namespace MWMechanics
 | 
			
		|||
            mIsPathConstructed = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    float PathFinder::getZAngleToNext(float x, float y)
 | 
			
		||||
    float PathFinder::getZAngleToNext(float x, float y) const
 | 
			
		||||
    {
 | 
			
		||||
        // This should never happen (programmers should have an if statement checking mIsPathConstructed that prevents this call
 | 
			
		||||
        // if otherwise).
 | 
			
		||||
        if(mPath.empty())
 | 
			
		||||
            return 0;
 | 
			
		||||
 | 
			
		||||
        ESM::Pathgrid::Point nextPoint = *mPath.begin();
 | 
			
		||||
        const ESM::Pathgrid::Point &nextPoint = *mPath.begin();
 | 
			
		||||
        float directionX = nextPoint.mX - x;
 | 
			
		||||
        float directionY = nextPoint.mY - y;
 | 
			
		||||
        float directionResult = sqrt(directionX * directionX + directionY * directionY);
 | 
			
		||||
| 
						 | 
				
			
			@ -205,7 +205,7 @@ namespace MWMechanics
 | 
			
		|||
            return true;
 | 
			
		||||
 | 
			
		||||
        ESM::Pathgrid::Point nextPoint = *mPath.begin();
 | 
			
		||||
        if(distanceZCorrected(nextPoint, x, y, z) < 40)
 | 
			
		||||
        if(distanceZCorrected(nextPoint, x, y, z) < 64)
 | 
			
		||||
        {
 | 
			
		||||
            mPath.pop_front();
 | 
			
		||||
            if(mPath.empty())
 | 
			
		||||
| 
						 | 
				
			
			@ -217,15 +217,5 @@ namespace MWMechanics
 | 
			
		|||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::list<ESM::Pathgrid::Point> PathFinder::getPath()
 | 
			
		||||
    {
 | 
			
		||||
        return mPath;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool PathFinder::isPathConstructed()
 | 
			
		||||
    {
 | 
			
		||||
        return mIsPathConstructed;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,15 +12,18 @@ namespace MWMechanics
 | 
			
		|||
            PathFinder();
 | 
			
		||||
 | 
			
		||||
            void clearPath();
 | 
			
		||||
            void buildPath(ESM::Pathgrid::Point startPoint, ESM::Pathgrid::Point endPoint,
 | 
			
		||||
                const ESM::Pathgrid* pathGrid, float xCell = 0, float yCell = 0, bool allowShortcuts = 1);
 | 
			
		||||
            void buildPath(const ESM::Pathgrid::Point &startPoint, const ESM::Pathgrid::Point &endPoint,
 | 
			
		||||
                           const ESM::Pathgrid* pathGrid, float xCell = 0, float yCell = 0,
 | 
			
		||||
                           bool allowShortcuts = true);
 | 
			
		||||
 | 
			
		||||
            bool checkPathCompleted(float x, float y, float z);
 | 
			
		||||
            ///< \Returns true if the last point of the path has been reached.
 | 
			
		||||
            float getZAngleToNext(float x, float y);
 | 
			
		||||
            float getZAngleToNext(float x, float y) const;
 | 
			
		||||
 | 
			
		||||
            std::list<ESM::Pathgrid::Point> getPath();
 | 
			
		||||
            bool isPathConstructed();
 | 
			
		||||
            bool isPathConstructed() const
 | 
			
		||||
            {
 | 
			
		||||
                return mIsPathConstructed;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
            std::list<ESM::Pathgrid::Point> mPath;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,6 +42,18 @@ namespace MWMechanics
 | 
			
		|||
                mBase = mModified = value;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            void modify(const T& diff)
 | 
			
		||||
            {
 | 
			
		||||
                mBase += diff;
 | 
			
		||||
                if(mBase >= static_cast<T>(0))
 | 
			
		||||
                    mModified += diff;
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    mModified += diff - mBase;
 | 
			
		||||
                    mBase = static_cast<T>(0);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /// Set base and adjust modified accordingly.
 | 
			
		||||
            void setBase (const T& value)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,8 @@
 | 
			
		|||
#include <OgreRoot.h>
 | 
			
		||||
#include <OgreHardwarePixelBuffer.h>
 | 
			
		||||
 | 
			
		||||
#include <components/loadinglistener/loadinglistener.hpp>
 | 
			
		||||
 | 
			
		||||
#include "../mwbase/environment.hpp"
 | 
			
		||||
#include "../mwbase/world.hpp"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +30,7 @@ namespace MWRender
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    void GlobalMap::render ()
 | 
			
		||||
    void GlobalMap::render (Loading::Listener* loadingListener)
 | 
			
		||||
    {
 | 
			
		||||
        Ogre::TexturePtr tex;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -53,6 +55,11 @@ namespace MWRender
 | 
			
		|||
        mWidth = cellSize*(mMaxX-mMinX+1);
 | 
			
		||||
        mHeight = cellSize*(mMaxY-mMinY+1);
 | 
			
		||||
 | 
			
		||||
        loadingListener->loadingOn();
 | 
			
		||||
        loadingListener->setLabel("Creating map");
 | 
			
		||||
        loadingListener->setProgressRange((mMaxX-mMinX+1) * (mMaxY-mMinY+1));
 | 
			
		||||
        loadingListener->setProgress(0);
 | 
			
		||||
 | 
			
		||||
        mExploredBuffer.resize((mMaxX-mMinX+1) * (mMaxY-mMinY+1) * 4);
 | 
			
		||||
 | 
			
		||||
        //if (!boost::filesystem::exists(mCacheDir + "/GlobalMap.png"))
 | 
			
		||||
| 
						 | 
				
			
			@ -147,6 +154,7 @@ namespace MWRender
 | 
			
		|||
                            data[texelY * mWidth * 3 + texelX * 3+2] = b;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    loadingListener->increaseProgress(1);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -177,6 +185,8 @@ namespace MWRender
 | 
			
		|||
 | 
			
		||||
        memcpy(mOverlayTexture->getBuffer()->lock(Ogre::HardwareBuffer::HBL_DISCARD), &buffer[0], mWidth*mHeight*4);
 | 
			
		||||
        mOverlayTexture->getBuffer()->unlock();
 | 
			
		||||
 | 
			
		||||
        loadingListener->loadingOff();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void GlobalMap::worldPosToImageSpace(float x, float z, float& imageX, float& imageY)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,11 @@
 | 
			
		|||
 | 
			
		||||
#include <OgreTexture.h>
 | 
			
		||||
 | 
			
		||||
namespace Loading
 | 
			
		||||
{
 | 
			
		||||
    class Listener;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace MWRender
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +18,7 @@ namespace MWRender
 | 
			
		|||
    public:
 | 
			
		||||
        GlobalMap(const std::string& cacheDir);
 | 
			
		||||
 | 
			
		||||
        void render();
 | 
			
		||||
        void render(Loading::Listener* loadingListener);
 | 
			
		||||
 | 
			
		||||
        int getWidth() { return mWidth; }
 | 
			
		||||
        int getHeight() { return mHeight; }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -370,8 +370,8 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
 | 
			
		|||
    MWBase::Environment::get().getWindowManager()->setPlayerDir(playerdirection.x, playerdirection.y);
 | 
			
		||||
 | 
			
		||||
    // explore radius (squared)
 | 
			
		||||
    const float sqrExploreRadius = (mInterior ? 0.01 : 0.09) * sFogOfWarResolution*sFogOfWarResolution;
 | 
			
		||||
    const float exploreRadius = (mInterior ? 0.1 : 0.3) * sFogOfWarResolution; // explore radius from 0 to sFogOfWarResolution
 | 
			
		||||
    const float exploreRadius = (mInterior ? 0.1 : 0.3) * (sFogOfWarResolution-1); // explore radius from 0 to sFogOfWarResolution-1
 | 
			
		||||
    const float sqrExploreRadius = Math::Sqr(exploreRadius);
 | 
			
		||||
    const float exploreRadiusUV = exploreRadius / sFogOfWarResolution; // explore radius from 0 to 1 (UV space)
 | 
			
		||||
 | 
			
		||||
    // change the affected fog of war textures (in a 3x3 grid around the player)
 | 
			
		||||
| 
						 | 
				
			
			@ -406,11 +406,8 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
 | 
			
		|||
                {
 | 
			
		||||
                    for (int texU = 0; texU<sFogOfWarResolution; ++texU)
 | 
			
		||||
                    {
 | 
			
		||||
                        // fix into range of 0 ... sFogOfWarResolution
 | 
			
		||||
                        int _texU = texU * (float(sFogOfWarResolution+1) / float(sFogOfWarResolution));
 | 
			
		||||
                        int _texV = texV * (float(sFogOfWarResolution+1) / float(sFogOfWarResolution));
 | 
			
		||||
 | 
			
		||||
                        float sqrDist = Math::Sqr((_texU + mx*sFogOfWarResolution) - u*sFogOfWarResolution) + Math::Sqr((_texV + my*sFogOfWarResolution) - v*sFogOfWarResolution);
 | 
			
		||||
                        float sqrDist = Math::Sqr((texU + mx*(sFogOfWarResolution-1)) - u*(sFogOfWarResolution-1))
 | 
			
		||||
                                + Math::Sqr((texV + my*(sFogOfWarResolution-1)) - v*(sFogOfWarResolution-1));
 | 
			
		||||
                        uint32 clr = mBuffers[texName][i];
 | 
			
		||||
                        uint8 alpha = (clr >> 24);
 | 
			
		||||
                        alpha = std::min( alpha, (uint8) (std::max(0.f, std::min(1.f, (sqrDist/sqrExploreRadius)))*255) );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,7 @@
 | 
			
		|||
 | 
			
		||||
#include <components/esm/loadstat.hpp>
 | 
			
		||||
#include <components/settings/settings.hpp>
 | 
			
		||||
#include <components/terrain/terrain.hpp>
 | 
			
		||||
#include <components/terrain/world.hpp>
 | 
			
		||||
 | 
			
		||||
#include "../mwworld/esmstore.hpp"
 | 
			
		||||
#include "../mwworld/class.hpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -82,7 +82,7 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b
 | 
			
		|||
        Settings::Manager::setString("shader mode", "General", openGL ? (glES ? "glsles" : "glsl") : "hlsl");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5);
 | 
			
		||||
    mRendering.adjustCamera(Settings::Manager::getFloat("field of view", "General"), 5);
 | 
			
		||||
 | 
			
		||||
    mRendering.getWindow()->addListener(this);
 | 
			
		||||
    mRendering.setWindowListener(this);
 | 
			
		||||
| 
						 | 
				
			
			@ -1018,12 +1018,15 @@ void RenderingManager::enableTerrain(bool enable)
 | 
			
		|||
    {
 | 
			
		||||
        if (!mTerrain)
 | 
			
		||||
        {
 | 
			
		||||
            mTerrain = new Terrain::Terrain(mRendering.getScene(), new MWRender::TerrainStorage(), RV_Terrain,
 | 
			
		||||
            Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
 | 
			
		||||
            Loading::ScopedLoad load(listener);
 | 
			
		||||
            mTerrain = new Terrain::World(listener, mRendering.getScene(), new MWRender::TerrainStorage(), RV_Terrain,
 | 
			
		||||
                                            Settings::Manager::getBool("distant land", "Terrain"),
 | 
			
		||||
                                            Settings::Manager::getBool("shader", "Terrain"));
 | 
			
		||||
            mTerrain->applyMaterials(Settings::Manager::getBool("enabled", "Shadows"),
 | 
			
		||||
                                     Settings::Manager::getBool("split", "Shadows"));
 | 
			
		||||
            mTerrain->update(mRendering.getCamera()->getRealPosition());
 | 
			
		||||
            mTerrain->setLoadingListener(NULL);
 | 
			
		||||
        }
 | 
			
		||||
        mTerrain->setVisible(true);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,7 +40,7 @@ namespace sh
 | 
			
		|||
 | 
			
		||||
namespace Terrain
 | 
			
		||||
{
 | 
			
		||||
    class Terrain;
 | 
			
		||||
    class World;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace MWRender
 | 
			
		||||
| 
						 | 
				
			
			@ -234,7 +234,7 @@ private:
 | 
			
		|||
 | 
			
		||||
    OcclusionQuery* mOcclusionQuery;
 | 
			
		||||
 | 
			
		||||
    Terrain::Terrain* mTerrain;
 | 
			
		||||
    Terrain::World* mTerrain;
 | 
			
		||||
 | 
			
		||||
    MWRender::Water *mWater;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1037,7 +1037,6 @@ public:
 | 
			
		|||
VideoPlayer::VideoPlayer(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* window)
 | 
			
		||||
    : mState(NULL)
 | 
			
		||||
    , mSceneMgr(sceneMgr)
 | 
			
		||||
    , mVideoMaterial(NULL)
 | 
			
		||||
    , mRectangle(NULL)
 | 
			
		||||
    , mNode(NULL)
 | 
			
		||||
    , mAllowSkipping(false)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,11 +4,10 @@
 | 
			
		|||
#include <algorithm>
 | 
			
		||||
#include <map>
 | 
			
		||||
 | 
			
		||||
#include "../mwworld/esmstore.hpp"
 | 
			
		||||
 | 
			
		||||
#include "../mwbase/environment.hpp"
 | 
			
		||||
#include "../mwbase/world.hpp"
 | 
			
		||||
 | 
			
		||||
#include "../mwworld/esmstore.hpp"
 | 
			
		||||
#include "../mwworld/player.hpp"
 | 
			
		||||
 | 
			
		||||
#include "sound_output.hpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -103,6 +102,7 @@ namespace MWSound
 | 
			
		|||
 | 
			
		||||
    SoundManager::~SoundManager()
 | 
			
		||||
    {
 | 
			
		||||
        mUnderwaterSound.reset();
 | 
			
		||||
        mActiveSounds.clear();
 | 
			
		||||
        mMusic.reset();
 | 
			
		||||
        mOutput.reset();
 | 
			
		||||
| 
						 | 
				
			
			@ -474,27 +474,32 @@ namespace MWSound
 | 
			
		|||
 | 
			
		||||
    void SoundManager::updateRegionSound(float duration)
 | 
			
		||||
    {
 | 
			
		||||
        MWWorld::Ptr::CellStore *current = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell();
 | 
			
		||||
        static float sTimeToNextEnvSound = 0.0f;
 | 
			
		||||
        static int total = 0;
 | 
			
		||||
        static std::string regionName = "";
 | 
			
		||||
        static float timePassed = 0.0;
 | 
			
		||||
        static float sTimePassed = 0.0;
 | 
			
		||||
        MWBase::World *world = MWBase::Environment::get().getWorld();
 | 
			
		||||
        const MWWorld::Ptr player = world->getPlayer().getPlayer();
 | 
			
		||||
        const ESM::Cell *cell = player.getCell()->mCell;
 | 
			
		||||
 | 
			
		||||
        //If the region has changed
 | 
			
		||||
        timePassed += duration;
 | 
			
		||||
        if(!current->mCell->isExterior() || timePassed < 10)
 | 
			
		||||
        sTimePassed += duration;
 | 
			
		||||
        if(!cell->isExterior() || sTimePassed < sTimeToNextEnvSound)
 | 
			
		||||
            return;
 | 
			
		||||
        timePassed = 0;
 | 
			
		||||
 | 
			
		||||
        if(regionName != current->mCell->mRegion)
 | 
			
		||||
        float a = std::rand() / (double)RAND_MAX;
 | 
			
		||||
        // NOTE: We should use the "Minimum Time Between Environmental Sounds" and
 | 
			
		||||
        // "Maximum Time Between Environmental Sounds" fallback settings here.
 | 
			
		||||
        sTimeToNextEnvSound = 5.0f*a + 15.0f*(1.0f-a);
 | 
			
		||||
        sTimePassed = 0;
 | 
			
		||||
 | 
			
		||||
        if(regionName != cell->mRegion)
 | 
			
		||||
        {
 | 
			
		||||
            regionName = current->mCell->mRegion;
 | 
			
		||||
            regionName = cell->mRegion;
 | 
			
		||||
            total = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const ESM::Region *regn =
 | 
			
		||||
            MWBase::Environment::get().getWorld()->getStore().get<ESM::Region>().search(regionName);
 | 
			
		||||
 | 
			
		||||
        if (regn == NULL)
 | 
			
		||||
        const ESM::Region *regn = world->getStore().get<ESM::Region>().search(regionName);
 | 
			
		||||
        if(regn == NULL)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        std::vector<ESM::Region::SoundRef>::const_iterator soundIter;
 | 
			
		||||
| 
						 | 
				
			
			@ -550,15 +555,13 @@ namespace MWSound
 | 
			
		|||
        {
 | 
			
		||||
            env = Env_Underwater;
 | 
			
		||||
            //play underwater sound
 | 
			
		||||
            //HACK: this sound is always played underwater, so set volume and pitch higher (it's then lowered)
 | 
			
		||||
            //Currently not possible to play looping sound with no environment
 | 
			
		||||
            if(!getSoundPlaying(MWWorld::Ptr(), "Underwater"))
 | 
			
		||||
                playSound("Underwater", 1.11, 1.42 ,Play_TypeSfx, Play_Loop );
 | 
			
		||||
            if(!(mUnderwaterSound && mUnderwaterSound->isPlaying()))
 | 
			
		||||
                mUnderwaterSound = playSound("Underwater", 1.0f, 1.0f, Play_TypeSfx, Play_LoopNoEnv);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        else if(mUnderwaterSound)
 | 
			
		||||
        {
 | 
			
		||||
            //no need to check if it's playing, stop sound does nothing in that case
 | 
			
		||||
            stopSound("Underwater");
 | 
			
		||||
            mUnderwaterSound->stop();
 | 
			
		||||
            mUnderwaterSound.reset();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        mOutput->updateListener(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,6 +44,8 @@ namespace MWSound
 | 
			
		|||
        typedef std::map<MWBase::SoundPtr,PtrIDPair> SoundMap;
 | 
			
		||||
        SoundMap mActiveSounds;
 | 
			
		||||
 | 
			
		||||
        MWBase::SoundPtr mUnderwaterSound;
 | 
			
		||||
 | 
			
		||||
        Ogre::Vector3 mListenerPos;
 | 
			
		||||
        Ogre::Vector3 mListenerDir;
 | 
			
		||||
        Ogre::Vector3 mListenerUp;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,7 +80,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::end()
 | 
			
		|||
bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2)
 | 
			
		||||
{
 | 
			
		||||
    /// \todo add current enchantment charge here when it is implemented
 | 
			
		||||
    if (  ptr1.getCellRef().mRefID == ptr2.getCellRef().mRefID
 | 
			
		||||
    if (  Misc::StringUtils::ciEqual(ptr1.getCellRef().mRefID, ptr2.getCellRef().mRefID)
 | 
			
		||||
          && MWWorld::Class::get(ptr1).getScript(ptr1) == "" // item with a script never stacks
 | 
			
		||||
          && MWWorld::Class::get(ptr1).getEnchantment(ptr1) == "" // item with enchantment never stacks (we could revisit this later, but for now it makes selecting items in the spell window much easier)
 | 
			
		||||
        && ptr1.getCellRef().mOwner == ptr2.getCellRef().mOwner
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,8 @@
 | 
			
		|||
 | 
			
		||||
#include <boost/filesystem/operations.hpp>
 | 
			
		||||
 | 
			
		||||
#include <components/loadinglistener/loadinglistener.hpp>
 | 
			
		||||
 | 
			
		||||
namespace MWWorld
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -21,8 +23,10 @@ static bool isCacheableRecord(int id)
 | 
			
		|||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ESMStore::load(ESM::ESMReader &esm)
 | 
			
		||||
void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener)
 | 
			
		||||
{
 | 
			
		||||
    listener->setProgressRange(1000);
 | 
			
		||||
 | 
			
		||||
    std::set<std::string> missing;
 | 
			
		||||
 | 
			
		||||
    ESM::Dialogue *dialogue = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -109,6 +113,7 @@ void ESMStore::load(ESM::ESMReader &esm)
 | 
			
		|||
                mIds[id] = n.val;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        listener->setProgress(esm.getFileOffset() / (float)esm.getFileSize() * 1000);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* This information isn't needed on screen. But keep the code around
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,11 @@
 | 
			
		|||
#include <components/esm/records.hpp>
 | 
			
		||||
#include "store.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Loading
 | 
			
		||||
{
 | 
			
		||||
    class Listener;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace MWWorld
 | 
			
		||||
{
 | 
			
		||||
    class ESMStore
 | 
			
		||||
| 
						 | 
				
			
			@ -158,7 +163,7 @@ namespace MWWorld
 | 
			
		|||
            mNpcs.insert(mPlayerTemplate);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void load(ESM::ESMReader &esm);
 | 
			
		||||
        void load(ESM::ESMReader &esm, Loading::Listener* listener);
 | 
			
		||||
 | 
			
		||||
        template <class T>
 | 
			
		||||
        const Store<T> &get() const {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,13 +25,12 @@ namespace
 | 
			
		|||
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    void insertCellRefList(MWRender::RenderingManager& rendering,
 | 
			
		||||
        T& cellRefList, MWWorld::CellStore &cell, MWWorld::PhysicsSystem& physics, bool rescale)
 | 
			
		||||
        T& cellRefList, MWWorld::CellStore &cell, MWWorld::PhysicsSystem& physics, bool rescale, Loading::Listener* loadingListener)
 | 
			
		||||
    {
 | 
			
		||||
        if (!cellRefList.mList.empty())
 | 
			
		||||
        {
 | 
			
		||||
            const MWWorld::Class& class_ =
 | 
			
		||||
                MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.mList.begin(), &cell));
 | 
			
		||||
            int current = 0;
 | 
			
		||||
            for (typename T::List::iterator it = cellRefList.mList.begin();
 | 
			
		||||
                it != cellRefList.mList.end(); it++)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -43,8 +42,6 @@ namespace
 | 
			
		|||
                        it->mRef.mScale = 2;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                ++current;
 | 
			
		||||
 | 
			
		||||
                if (it->mData.getCount() && it->mData.isEnabled())
 | 
			
		||||
                {
 | 
			
		||||
                    MWWorld::Ptr ptr (&*it, &cell);
 | 
			
		||||
| 
						 | 
				
			
			@ -68,6 +65,8 @@ namespace
 | 
			
		|||
                        std::cerr << error + e.what() << std::endl;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                loadingListener->increaseProgress(1);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -117,7 +116,7 @@ namespace MWWorld
 | 
			
		|||
        mActiveCells.erase(*iter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Scene::loadCell (Ptr::CellStore *cell)
 | 
			
		||||
    void Scene::loadCell (Ptr::CellStore *cell, Loading::Listener* loadingListener)
 | 
			
		||||
    {
 | 
			
		||||
        // register local scripts
 | 
			
		||||
        MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell);
 | 
			
		||||
| 
						 | 
				
			
			@ -150,7 +149,7 @@ namespace MWWorld
 | 
			
		|||
 | 
			
		||||
            // ... then references. This is important for adjustPosition to work correctly.
 | 
			
		||||
            /// \todo rescale depending on the state of a new GMST
 | 
			
		||||
            insertCell (*cell, true);
 | 
			
		||||
            insertCell (*cell, true, loadingListener);
 | 
			
		||||
 | 
			
		||||
            mRendering.cellAdded (cell);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -200,17 +199,15 @@ namespace MWWorld
 | 
			
		|||
    void Scene::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos)
 | 
			
		||||
    {
 | 
			
		||||
        Nif::NIFFile::CacheLock cachelock;
 | 
			
		||||
        const MWWorld::Store<ESM::GameSetting> &gmst =
 | 
			
		||||
            MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
 | 
			
		||||
 | 
			
		||||
        mRendering.preCellChange(mCurrentCell);
 | 
			
		||||
        Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
 | 
			
		||||
        Loading::ScopedLoad load(loadingListener);
 | 
			
		||||
 | 
			
		||||
        // remove active
 | 
			
		||||
        MWBase::Environment::get().getMechanicsManager()->remove(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
 | 
			
		||||
 | 
			
		||||
        std::string loadingExteriorText;
 | 
			
		||||
 | 
			
		||||
        loadingExteriorText = gmst.find ("sLoadingMessage3")->getString();
 | 
			
		||||
        std::string loadingExteriorText = "#{sLoadingMessage3}";
 | 
			
		||||
        loadingListener->setLabel(loadingExteriorText);
 | 
			
		||||
 | 
			
		||||
        CellStoreCollection::iterator active = mActiveCells.begin();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -232,7 +229,6 @@ namespace MWWorld
 | 
			
		|||
            ++numUnload;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        int current = 0;
 | 
			
		||||
        active = mActiveCells.begin();
 | 
			
		||||
        while (active!=mActiveCells.end())
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -247,11 +243,10 @@ namespace MWWorld
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
            unloadCell (active++);
 | 
			
		||||
            ++current;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        int numLoad = 0;
 | 
			
		||||
        // get the number of cells to load
 | 
			
		||||
        int refsToLoad = 0;
 | 
			
		||||
        // get the number of refs to load
 | 
			
		||||
        for (int x=X-1; x<=X+1; ++x)
 | 
			
		||||
            for (int y=Y-1; y<=Y+1; ++y)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -269,11 +264,12 @@ namespace MWWorld
 | 
			
		|||
                }
 | 
			
		||||
 | 
			
		||||
                if (iter==mActiveCells.end())
 | 
			
		||||
                    ++numLoad;
 | 
			
		||||
                    refsToLoad += countRefs(*MWBase::Environment::get().getWorld()->getExterior(x, y));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        loadingListener->setProgressRange(refsToLoad);
 | 
			
		||||
 | 
			
		||||
        // Load cells
 | 
			
		||||
        current = 0;
 | 
			
		||||
        for (int x=X-1; x<=X+1; ++x)
 | 
			
		||||
            for (int y=Y-1; y<=Y+1; ++y)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -294,11 +290,7 @@ namespace MWWorld
 | 
			
		|||
                {
 | 
			
		||||
                    CellStore *cell = MWBase::Environment::get().getWorld()->getExterior(x, y);
 | 
			
		||||
 | 
			
		||||
                    //Loading Exterior loading text
 | 
			
		||||
                    MWBase::Environment::get().getWindowManager ()->setLoadingProgress (loadingExteriorText, 0, current, numLoad);
 | 
			
		||||
 | 
			
		||||
                    loadCell (cell);
 | 
			
		||||
                    ++current;
 | 
			
		||||
                    loadCell (cell, loadingListener);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -330,7 +322,7 @@ namespace MWWorld
 | 
			
		|||
 | 
			
		||||
        mCellChanged = true;
 | 
			
		||||
 | 
			
		||||
        MWBase::Environment::get().getWindowManager ()->loadingDone ();
 | 
			
		||||
        loadingListener->removeWallpaper();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //We need the ogre renderer and a scene node.
 | 
			
		||||
| 
						 | 
				
			
			@ -356,13 +348,14 @@ namespace MWWorld
 | 
			
		|||
    void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position)
 | 
			
		||||
    {
 | 
			
		||||
        MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0.5);
 | 
			
		||||
        const MWWorld::Store<ESM::GameSetting> &gmst =
 | 
			
		||||
            MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
 | 
			
		||||
 | 
			
		||||
        mRendering.enableTerrain(false);
 | 
			
		||||
 | 
			
		||||
        std::string loadingInteriorText;
 | 
			
		||||
        loadingInteriorText = gmst.find ("sLoadingMessage2")->getString();
 | 
			
		||||
        Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
 | 
			
		||||
        Loading::ScopedLoad load(loadingListener);
 | 
			
		||||
 | 
			
		||||
        std::string loadingInteriorText = "#{sLoadingMessage2}";
 | 
			
		||||
        loadingListener->setLabel(loadingInteriorText);
 | 
			
		||||
 | 
			
		||||
        CellStore *cell = MWBase::Environment::get().getWorld()->getInterior(cellName);
 | 
			
		||||
        bool loadcell = (mCurrentCell == NULL);
 | 
			
		||||
| 
						 | 
				
			
			@ -406,13 +399,15 @@ namespace MWWorld
 | 
			
		|||
            ++current;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        int refsToLoad = countRefs(*cell);
 | 
			
		||||
        loadingListener->setProgressRange(refsToLoad);
 | 
			
		||||
 | 
			
		||||
        // Load cell.
 | 
			
		||||
        std::cout << "cellName: " << cell->mCell->mName << std::endl;
 | 
			
		||||
 | 
			
		||||
        //Loading Interior loading text
 | 
			
		||||
        MWBase::Environment::get().getWindowManager ()->setLoadingProgress (loadingInteriorText, 0, 0, 1);
 | 
			
		||||
 | 
			
		||||
        loadCell (cell);
 | 
			
		||||
        loadCell (cell, loadingListener);
 | 
			
		||||
 | 
			
		||||
        mCurrentCell = cell;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -429,7 +424,7 @@ namespace MWWorld
 | 
			
		|||
        mCellChanged = true;
 | 
			
		||||
        MWBase::Environment::get().getWorld ()->getFader ()->fadeIn(0.5);
 | 
			
		||||
 | 
			
		||||
        MWBase::Environment::get().getWindowManager ()->loadingDone ();
 | 
			
		||||
        loadingListener->removeWallpaper();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Scene::changeToExteriorCell (const ESM::Position& position)
 | 
			
		||||
| 
						 | 
				
			
			@ -454,30 +449,54 @@ namespace MWWorld
 | 
			
		|||
        mCellChanged = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Scene::insertCell (Ptr::CellStore &cell, bool rescale)
 | 
			
		||||
    int Scene::countRefs (const Ptr::CellStore& cell)
 | 
			
		||||
    {
 | 
			
		||||
        return cell.mActivators.mList.size()
 | 
			
		||||
                + cell.mPotions.mList.size()
 | 
			
		||||
                + cell.mAppas.mList.size()
 | 
			
		||||
                + cell.mArmors.mList.size()
 | 
			
		||||
                + cell.mBooks.mList.size()
 | 
			
		||||
                + cell.mClothes.mList.size()
 | 
			
		||||
                + cell.mContainers.mList.size()
 | 
			
		||||
                + cell.mDoors.mList.size()
 | 
			
		||||
                + cell.mIngreds.mList.size()
 | 
			
		||||
                + cell.mCreatureLists.mList.size()
 | 
			
		||||
                + cell.mItemLists.mList.size()
 | 
			
		||||
                + cell.mLights.mList.size()
 | 
			
		||||
                + cell.mLockpicks.mList.size()
 | 
			
		||||
                + cell.mMiscItems.mList.size()
 | 
			
		||||
                + cell.mProbes.mList.size()
 | 
			
		||||
                + cell.mRepairs.mList.size()
 | 
			
		||||
                + cell.mStatics.mList.size()
 | 
			
		||||
                + cell.mWeapons.mList.size()
 | 
			
		||||
                + cell.mCreatures.mList.size()
 | 
			
		||||
                + cell.mNpcs.mList.size();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Scene::insertCell (Ptr::CellStore &cell, bool rescale, Loading::Listener* loadingListener)
 | 
			
		||||
    {
 | 
			
		||||
        // Loop through all references in the cell
 | 
			
		||||
        insertCellRefList(mRendering, cell.mActivators, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mPotions, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mAppas, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mArmors, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mBooks, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mClothes, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mContainers, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mDoors, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mIngreds, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mCreatureLists, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mItemLists, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mLights, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mLockpicks, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mMiscItems, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mProbes, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mRepairs, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mStatics, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mWeapons, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mActivators, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mPotions, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mAppas, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mArmors, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mBooks, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mClothes, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mContainers, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mDoors, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mIngreds, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mCreatureLists, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mItemLists, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mLights, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mLockpicks, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mMiscItems, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mProbes, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mRepairs, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mStatics, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mWeapons, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        // Load NPCs and creatures _after_ everything else (important for adjustPosition to work correctly)
 | 
			
		||||
        insertCellRefList(mRendering, cell.mCreatures, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mNpcs, cell, *mPhysics, rescale);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mCreatures, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
        insertCellRefList(mRendering, cell.mNpcs, cell, *mPhysics, rescale, loadingListener);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Scene::addObjectToScene (const Ptr& ptr)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,7 +56,9 @@ namespace MWWorld
 | 
			
		|||
            void playerCellChange (CellStore *cell, const ESM::Position& position,
 | 
			
		||||
                bool adjustPlayerPos = true);
 | 
			
		||||
 | 
			
		||||
            void insertCell (Ptr::CellStore &cell, bool rescale);
 | 
			
		||||
            void insertCell (Ptr::CellStore &cell, bool rescale, Loading::Listener* loadingListener);
 | 
			
		||||
 | 
			
		||||
            int countRefs (const Ptr::CellStore& cell);
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -66,7 +68,7 @@ namespace MWWorld
 | 
			
		|||
 | 
			
		||||
            void unloadCell (CellStoreCollection::iterator iter);
 | 
			
		||||
 | 
			
		||||
            void loadCell (CellStore *cell);
 | 
			
		||||
            void loadCell (CellStore *cell, Loading::Listener* loadingListener);
 | 
			
		||||
 | 
			
		||||
            void changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos);
 | 
			
		||||
            ///< Move from exterior to interior or from interior cell to a different
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -167,6 +167,11 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering,MWWorld::Fa
 | 
			
		|||
    setFallbackWeather(blizzard,"blizzard");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WeatherManager::~WeatherManager()
 | 
			
		||||
{
 | 
			
		||||
    stopSounds(true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WeatherManager::setWeather(const String& weather, bool instant)
 | 
			
		||||
{
 | 
			
		||||
    if (weather == mCurrentWeather && mNextWeather == "")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -120,6 +120,7 @@ namespace MWWorld
 | 
			
		|||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        WeatherManager(MWRender::RenderingManager*,MWWorld::Fallback* fallback);
 | 
			
		||||
        ~WeatherManager();
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Change the weather in the specified region
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -184,11 +184,14 @@ namespace MWWorld
 | 
			
		|||
        int idx = 0;
 | 
			
		||||
        // NOTE: We might need to reserve one more for the running game / save.
 | 
			
		||||
        mEsm.resize(master.size() + plugins.size());
 | 
			
		||||
        Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
 | 
			
		||||
        listener->loadingOn();
 | 
			
		||||
        for (std::vector<std::string>::size_type i = 0; i < master.size(); i++, idx++)
 | 
			
		||||
        {
 | 
			
		||||
            boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master[i]));
 | 
			
		||||
 | 
			
		||||
            std::cout << "Loading ESM " << masterPath.string() << "\n";
 | 
			
		||||
            listener->setLabel(masterPath.filename().string());
 | 
			
		||||
 | 
			
		||||
            // This parses the ESM file
 | 
			
		||||
            ESM::ESMReader lEsm;
 | 
			
		||||
| 
						 | 
				
			
			@ -197,7 +200,7 @@ namespace MWWorld
 | 
			
		|||
            lEsm.setGlobalReaderList(&mEsm);
 | 
			
		||||
            lEsm.open (masterPath.string());
 | 
			
		||||
            mEsm[idx] = lEsm;
 | 
			
		||||
            mStore.load (mEsm[idx]);
 | 
			
		||||
            mStore.load (mEsm[idx], listener);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (std::vector<std::string>::size_type i = 0; i < plugins.size(); i++, idx++)
 | 
			
		||||
| 
						 | 
				
			
			@ -205,6 +208,7 @@ namespace MWWorld
 | 
			
		|||
            boost::filesystem::path pluginPath (fileCollections.getCollection (".esp").getPath (plugins[i]));
 | 
			
		||||
 | 
			
		||||
            std::cout << "Loading ESP " << pluginPath.string() << "\n";
 | 
			
		||||
            listener->setLabel(pluginPath.filename().string());
 | 
			
		||||
 | 
			
		||||
            // This parses the ESP file
 | 
			
		||||
            ESM::ESMReader lEsm;
 | 
			
		||||
| 
						 | 
				
			
			@ -213,8 +217,9 @@ namespace MWWorld
 | 
			
		|||
            lEsm.setGlobalReaderList(&mEsm);
 | 
			
		||||
            lEsm.open (pluginPath.string());
 | 
			
		||||
            mEsm[idx] = lEsm;
 | 
			
		||||
            mStore.load (mEsm[idx]);
 | 
			
		||||
            mStore.load (mEsm[idx], listener);
 | 
			
		||||
        }
 | 
			
		||||
        listener->loadingOff();
 | 
			
		||||
 | 
			
		||||
        // insert records that may not be present in all versions of MW
 | 
			
		||||
        if (mEsm[0].getFormat() == 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,14 +11,15 @@ if (GTEST_FOUND AND GMOCK_FOUND)
 | 
			
		|||
    include_directories(${GMOCK_INCLUDE_DIRS})
 | 
			
		||||
 | 
			
		||||
    file(GLOB UNITTEST_SRC_FILES
 | 
			
		||||
        components/misc/*.cpp
 | 
			
		||||
        components/misc/test_*.cpp
 | 
			
		||||
        components/file_finder/test_*.cpp
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    source_group(apps\\openmw_test_suite FILES openmw_test_suite.cpp ${UNITTEST_SRC_FILES})
 | 
			
		||||
 | 
			
		||||
    add_executable(openmw_test_suite openmw_test_suite.cpp ${UNITTEST_SRC_FILES})
 | 
			
		||||
 | 
			
		||||
    target_link_libraries(openmw_test_suite ${GMOCK_BOTH_LIBRARIES} ${GTEST_BOTH_LIBRARIES})
 | 
			
		||||
    target_link_libraries(openmw_test_suite ${GMOCK_BOTH_LIBRARIES} ${GTEST_BOTH_LIBRARIES} components)
 | 
			
		||||
    # Fix for not visible pthreads functions for linker with glibc 2.15
 | 
			
		||||
    if (UNIX AND NOT APPLE)
 | 
			
		||||
        target_link_libraries(openmw_test_suite ${CMAKE_THREAD_LIBS_INIT})
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,66 @@
 | 
			
		|||
#include <gtest/gtest.h>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include "components/file_finder/file_finder.hpp"
 | 
			
		||||
 | 
			
		||||
struct FileFinderTest : public ::testing::Test
 | 
			
		||||
{
 | 
			
		||||
  protected:
 | 
			
		||||
    FileFinderTest()
 | 
			
		||||
      : mTestDir("./filefinder_test_dir/")
 | 
			
		||||
      , mTestFile("test.txt")
 | 
			
		||||
      , mTestFileUppercase("TEST.TXT")
 | 
			
		||||
      , mTestFileNotFound("foobarbaz.txt")
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void SetUp()
 | 
			
		||||
    {
 | 
			
		||||
      boost::filesystem::create_directory(boost::filesystem::path(mTestDir));
 | 
			
		||||
 | 
			
		||||
      std::ofstream ofs(std::string(mTestDir + mTestFile).c_str(), std::ofstream::out);
 | 
			
		||||
      ofs << std::endl;
 | 
			
		||||
      ofs.close();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void TearDown()
 | 
			
		||||
    {
 | 
			
		||||
      boost::filesystem::remove_all(boost::filesystem::path(mTestDir));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string mTestDir;
 | 
			
		||||
    std::string mTestFile;
 | 
			
		||||
    std::string mTestFileUppercase;
 | 
			
		||||
    std::string mTestFileNotFound;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TEST_F(FileFinderTest, FileFinder_has_file)
 | 
			
		||||
{
 | 
			
		||||
  FileFinder::FileFinder fileFinder(mTestDir);
 | 
			
		||||
  ASSERT_TRUE(fileFinder.has(mTestFile));
 | 
			
		||||
  ASSERT_TRUE(fileFinder.has(mTestFileUppercase));
 | 
			
		||||
  ASSERT_TRUE(fileFinder.lookup(mTestFile) == std::string(mTestDir + mTestFile));
 | 
			
		||||
  ASSERT_TRUE(fileFinder.lookup(mTestFileUppercase) == std::string(mTestDir + mTestFile));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(FileFinderTest, FileFinder_does_not_have_file)
 | 
			
		||||
{
 | 
			
		||||
  FileFinder::FileFinder fileFinder(mTestDir);
 | 
			
		||||
  ASSERT_FALSE(fileFinder.has(mTestFileNotFound));
 | 
			
		||||
  ASSERT_TRUE(fileFinder.lookup(mTestFileNotFound).empty());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(FileFinderTest, FileFinderStrict_has_file)
 | 
			
		||||
{
 | 
			
		||||
  FileFinder::FileFinderStrict fileFinder(mTestDir);
 | 
			
		||||
  ASSERT_TRUE(fileFinder.has(mTestFile));
 | 
			
		||||
  ASSERT_FALSE(fileFinder.has(mTestFileUppercase));
 | 
			
		||||
  ASSERT_TRUE(fileFinder.lookup(mTestFile) == std::string(mTestDir + mTestFile));
 | 
			
		||||
  ASSERT_FALSE(fileFinder.lookup(mTestFileUppercase) == std::string(mTestDir + mTestFile));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(FileFinderTest, FileFinderStrict_does_not_have_file)
 | 
			
		||||
{
 | 
			
		||||
  FileFinder::FileFinderStrict fileFinder(mTestDir);
 | 
			
		||||
  ASSERT_FALSE(fileFinder.has(mTestFileNotFound));
 | 
			
		||||
  ASSERT_TRUE(fileFinder.lookup(mTestFileNotFound).empty());
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,74 @@
 | 
			
		|||
#include <gtest/gtest.h>
 | 
			
		||||
#include <boost/filesystem.hpp>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
 | 
			
		||||
#include "components/file_finder/search.hpp"
 | 
			
		||||
 | 
			
		||||
struct SearchTest : public ::testing::Test
 | 
			
		||||
{
 | 
			
		||||
  protected:
 | 
			
		||||
    SearchTest()
 | 
			
		||||
      : mTestDir("./search_test_dir/")
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void SetUp()
 | 
			
		||||
    {
 | 
			
		||||
      boost::filesystem::create_directory(boost::filesystem::path(mTestDir));
 | 
			
		||||
 | 
			
		||||
      std::ofstream ofs(std::string(mTestDir + "test2.txt").c_str(), std::ofstream::out);
 | 
			
		||||
      ofs << std::endl;
 | 
			
		||||
      ofs.close();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void TearDown()
 | 
			
		||||
    {
 | 
			
		||||
      boost::filesystem::remove_all(boost::filesystem::path(mTestDir));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string mTestDir;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TEST_F(SearchTest, file_not_found)
 | 
			
		||||
{
 | 
			
		||||
  struct Result : public FileFinder::ReturnPath
 | 
			
		||||
  {
 | 
			
		||||
    Result(const boost::filesystem::path& expectedPath)
 | 
			
		||||
      : mExpectedPath(expectedPath)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void add(const boost::filesystem::path& p)
 | 
			
		||||
    {
 | 
			
		||||
      ASSERT_FALSE(p == mExpectedPath);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      boost::filesystem::path mExpectedPath;
 | 
			
		||||
 | 
			
		||||
  } r(boost::filesystem::path(mTestDir  + "test.txt"));
 | 
			
		||||
 | 
			
		||||
  FileFinder::find(mTestDir, r, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(SearchTest, file_found)
 | 
			
		||||
{
 | 
			
		||||
  struct Result : public FileFinder::ReturnPath
 | 
			
		||||
  {
 | 
			
		||||
    Result(const boost::filesystem::path& expectedPath)
 | 
			
		||||
      : mExpectedPath(expectedPath)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void add(const boost::filesystem::path& p)
 | 
			
		||||
    {
 | 
			
		||||
      ASSERT_TRUE(p == mExpectedPath);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      boost::filesystem::path mExpectedPath;
 | 
			
		||||
 | 
			
		||||
  } r(boost::filesystem::path(mTestDir  + "test2.txt"));
 | 
			
		||||
 | 
			
		||||
  FileFinder::find(mTestDir, r, false);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								apps/openmw_test_suite/components/misc/test_slicearray.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								apps/openmw_test_suite/components/misc/test_slicearray.cpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
#include <gtest/gtest.h>
 | 
			
		||||
#include "components/misc/slice_array.hpp"
 | 
			
		||||
 | 
			
		||||
struct SliceArrayTest : public ::testing::Test
 | 
			
		||||
{
 | 
			
		||||
  protected:
 | 
			
		||||
    virtual void SetUp()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void TearDown()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TEST_F(SliceArrayTest, hello_string)
 | 
			
		||||
{
 | 
			
		||||
  Misc::SString s("hello");
 | 
			
		||||
  ASSERT_EQ(sizeof("hello") - 1, s.length);
 | 
			
		||||
  ASSERT_FALSE(s=="hel");
 | 
			
		||||
  ASSERT_FALSE(s=="hell");
 | 
			
		||||
  ASSERT_TRUE(s=="hello");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(SliceArrayTest, othello_string_with_offset_2_and_size_4)
 | 
			
		||||
{
 | 
			
		||||
  Misc::SString s("othello" + 2, 4);
 | 
			
		||||
  ASSERT_EQ(sizeof("hell") - 1, s.length);
 | 
			
		||||
  ASSERT_FALSE(s=="hel");
 | 
			
		||||
  ASSERT_TRUE(s=="hell");
 | 
			
		||||
  ASSERT_FALSE(s=="hello");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,79 @@
 | 
			
		|||
#include <gtest/gtest.h>
 | 
			
		||||
#include "components/misc/stringops.hpp"
 | 
			
		||||
 | 
			
		||||
TEST(simple_test, dummy)
 | 
			
		||||
struct StringOpsTest : public ::testing::Test
 | 
			
		||||
{
 | 
			
		||||
  EXPECT_EQ(true, true);
 | 
			
		||||
  protected:
 | 
			
		||||
    virtual void SetUp()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void TearDown()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TEST_F(StringOpsTest, begins_matching)
 | 
			
		||||
{
 | 
			
		||||
  ASSERT_TRUE(Misc::begins("abc", "a"));
 | 
			
		||||
  ASSERT_TRUE(Misc::begins("abc", "ab"));
 | 
			
		||||
  ASSERT_TRUE(Misc::begins("abc", "abc"));
 | 
			
		||||
  ASSERT_TRUE(Misc::begins("abcd", "abc"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(StringOpsTest, begins_not_matching)
 | 
			
		||||
{
 | 
			
		||||
  ASSERT_FALSE(Misc::begins("abc", "b"));
 | 
			
		||||
  ASSERT_FALSE(Misc::begins("abc", "bc"));
 | 
			
		||||
  ASSERT_FALSE(Misc::begins("abc", "bcd"));
 | 
			
		||||
  ASSERT_FALSE(Misc::begins("abc", "abcd"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(StringOpsTest, ibegins_matching)
 | 
			
		||||
{
 | 
			
		||||
  ASSERT_TRUE(Misc::ibegins("Abc", "a"));
 | 
			
		||||
  ASSERT_TRUE(Misc::ibegins("aBc", "ab"));
 | 
			
		||||
  ASSERT_TRUE(Misc::ibegins("abC", "abc"));
 | 
			
		||||
  ASSERT_TRUE(Misc::ibegins("abcD", "abc"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(StringOpsTest, ibegins_not_matching)
 | 
			
		||||
{
 | 
			
		||||
  ASSERT_FALSE(Misc::ibegins("abc", "b"));
 | 
			
		||||
  ASSERT_FALSE(Misc::ibegins("abc", "bc"));
 | 
			
		||||
  ASSERT_FALSE(Misc::ibegins("abc", "bcd"));
 | 
			
		||||
  ASSERT_FALSE(Misc::ibegins("abc", "abcd"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(StringOpsTest, ends_matching)
 | 
			
		||||
{
 | 
			
		||||
  ASSERT_TRUE(Misc::ends("abc", "c"));
 | 
			
		||||
  ASSERT_TRUE(Misc::ends("abc", "bc"));
 | 
			
		||||
  ASSERT_TRUE(Misc::ends("abc", "abc"));
 | 
			
		||||
  ASSERT_TRUE(Misc::ends("abcd", "abcd"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(StringOpsTest, ends_not_matching)
 | 
			
		||||
{
 | 
			
		||||
  ASSERT_FALSE(Misc::ends("abc", "b"));
 | 
			
		||||
  ASSERT_FALSE(Misc::ends("abc", "ab"));
 | 
			
		||||
  ASSERT_FALSE(Misc::ends("abc", "bcd"));
 | 
			
		||||
  ASSERT_FALSE(Misc::ends("abc", "abcd"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(StringOpsTest, iends_matching)
 | 
			
		||||
{
 | 
			
		||||
  ASSERT_TRUE(Misc::iends("Abc", "c"));
 | 
			
		||||
  ASSERT_TRUE(Misc::iends("aBc", "bc"));
 | 
			
		||||
  ASSERT_TRUE(Misc::iends("abC", "abc"));
 | 
			
		||||
  ASSERT_TRUE(Misc::iends("abcD", "abcd"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(StringOpsTest, iends_not_matching)
 | 
			
		||||
{
 | 
			
		||||
  ASSERT_FALSE(Misc::iends("abc", "b"));
 | 
			
		||||
  ASSERT_FALSE(Misc::iends("abc", "ab"));
 | 
			
		||||
  ASSERT_FALSE(Misc::iends("abc", "bcd"));
 | 
			
		||||
  ASSERT_FALSE(Misc::iends("abc", "abcd"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,8 +5,8 @@
 | 
			
		|||
int main(int argc, char** argv) {
 | 
			
		||||
  // The following line causes Google Mock to throw an exception on failure,
 | 
			
		||||
  // which will be interpreted by your testing framework as a test failure.
 | 
			
		||||
  ::testing::GTEST_FLAG(throw_on_failure) = true;
 | 
			
		||||
  ::testing::GTEST_FLAG(throw_on_failure) = false;
 | 
			
		||||
  ::testing::InitGoogleMock(&argc, argv);
 | 
			
		||||
 | 
			
		||||
  return RUN_ALL_TESTS();
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,7 +67,11 @@ add_component_dir (translation
 | 
			
		|||
    )
 | 
			
		||||
    
 | 
			
		||||
add_component_dir (terrain
 | 
			
		||||
    quadtreenode chunk terrain storage material
 | 
			
		||||
    quadtreenode chunk world storage material
 | 
			
		||||
    )
 | 
			
		||||
    
 | 
			
		||||
add_component_dir (loadinglistener
 | 
			
		||||
    loadinglistener
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
find_package(Qt4 COMPONENTS QtCore QtGui)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -70,6 +70,11 @@ public:
 | 
			
		|||
 | 
			
		||||
  void openRaw(const std::string &file);
 | 
			
		||||
 | 
			
		||||
  /// Get the file size. Make sure that the file has been opened!
 | 
			
		||||
  size_t getFileSize() { return mEsm->size(); }
 | 
			
		||||
  /// Get the current position in the file. Make sure that the file has been opened!
 | 
			
		||||
  size_t getFileOffset() { return mEsm->tell(); }
 | 
			
		||||
 | 
			
		||||
  // This is a quick hack for multiple esm/esp files. Each plugin introduces its own
 | 
			
		||||
  //  terrain palette, but ESMReader does not pass a reference to the correct plugin
 | 
			
		||||
  //  to the individual load() methods. This hack allows to pass this reference
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ namespace ESM
 | 
			
		|||
 | 
			
		||||
    enum VarType
 | 
			
		||||
    {
 | 
			
		||||
        VT_Unknown,
 | 
			
		||||
        VT_Unknown = 0,
 | 
			
		||||
        VT_None,
 | 
			
		||||
        VT_Short, // stored as a float, kinda
 | 
			
		||||
        VT_Int,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										35
									
								
								components/loadinglistener/loadinglistener.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								components/loadinglistener/loadinglistener.hpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
#ifndef COMPONENTS_LOADINGLISTENER_H
 | 
			
		||||
#define COMPONENTS_LOADINGLISTENER_H
 | 
			
		||||
 | 
			
		||||
namespace Loading
 | 
			
		||||
{
 | 
			
		||||
    class Listener
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        virtual void setLabel (const std::string& label) = 0;
 | 
			
		||||
 | 
			
		||||
        // Use ScopedLoad instead of using these directly
 | 
			
		||||
        virtual void loadingOn() = 0;
 | 
			
		||||
        virtual void loadingOff() = 0;
 | 
			
		||||
 | 
			
		||||
        /// Indicate that some progress has been made, without specifying how much
 | 
			
		||||
        virtual void indicateProgress () = 0;
 | 
			
		||||
 | 
			
		||||
        virtual void setProgressRange (size_t range) = 0;
 | 
			
		||||
        virtual void setProgress (size_t value) = 0;
 | 
			
		||||
        virtual void increaseProgress (size_t increase) = 0;
 | 
			
		||||
 | 
			
		||||
        /// Indicate the scene is now ready to be shown
 | 
			
		||||
        virtual void removeWallpaper() = 0;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Used for stopping a loading sequence when the object goes out of scope
 | 
			
		||||
    struct ScopedLoad
 | 
			
		||||
    {
 | 
			
		||||
        ScopedLoad(Listener* l) : mListener(l) { mListener->loadingOn(); }
 | 
			
		||||
        ~ScopedLoad() { mListener->loadingOff(); }
 | 
			
		||||
        Listener* mListener;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -4,7 +4,7 @@
 | 
			
		|||
#include <OgreHardwareBufferManager.h>
 | 
			
		||||
 | 
			
		||||
#include "quadtreenode.hpp"
 | 
			
		||||
#include "terrain.hpp"
 | 
			
		||||
#include "world.hpp"
 | 
			
		||||
#include "storage.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Terrain
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
#include <OgreSceneManager.h>
 | 
			
		||||
#include <OgreManualObject.h>
 | 
			
		||||
 | 
			
		||||
#include "terrain.hpp"
 | 
			
		||||
#include "world.hpp"
 | 
			
		||||
#include "chunk.hpp"
 | 
			
		||||
#include "storage.hpp"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -13,6 +13,13 @@ using namespace Terrain;
 | 
			
		|||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
    int Log2( int n )
 | 
			
		||||
    {
 | 
			
		||||
        assert(n > 0);
 | 
			
		||||
        int targetlevel = 0;
 | 
			
		||||
        while (n >>= 1) ++targetlevel;
 | 
			
		||||
        return targetlevel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Utility functions for neighbour finding algorithm
 | 
			
		||||
    ChildDirection reflect(ChildDirection dir, Direction dir2)
 | 
			
		||||
| 
						 | 
				
			
			@ -132,7 +139,7 @@ namespace
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QuadTreeNode::QuadTreeNode(Terrain* terrain, ChildDirection dir, float size, const Ogre::Vector2 ¢er, QuadTreeNode* parent)
 | 
			
		||||
QuadTreeNode::QuadTreeNode(World* terrain, ChildDirection dir, float size, const Ogre::Vector2 ¢er, QuadTreeNode* parent)
 | 
			
		||||
    : mSize(size)
 | 
			
		||||
    , mCenter(center)
 | 
			
		||||
    , mParent(parent)
 | 
			
		||||
| 
						 | 
				
			
			@ -161,7 +168,7 @@ QuadTreeNode::QuadTreeNode(Terrain* terrain, ChildDirection dir, float size, con
 | 
			
		|||
    pos = mCenter - pos;
 | 
			
		||||
    mSceneNode->setPosition(Ogre::Vector3(pos.x*8192, pos.y*8192, 0));
 | 
			
		||||
 | 
			
		||||
    mLodLevel = log2(mSize);
 | 
			
		||||
    mLodLevel = Log2(mSize);
 | 
			
		||||
 | 
			
		||||
    mMaterialGenerator = new MaterialGenerator(mTerrain->getShadersEnabled());
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -220,7 +227,7 @@ const Ogre::AxisAlignedBox& QuadTreeNode::getBoundingBox()
 | 
			
		|||
    return mBounds;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QuadTreeNode::update(const Ogre::Vector3 &cameraPos)
 | 
			
		||||
void QuadTreeNode::update(const Ogre::Vector3 &cameraPos, Loading::Listener* loadingListener)
 | 
			
		||||
{
 | 
			
		||||
    const Ogre::AxisAlignedBox& bounds = getBoundingBox();
 | 
			
		||||
    if (bounds.isNull())
 | 
			
		||||
| 
						 | 
				
			
			@ -254,6 +261,9 @@ void QuadTreeNode::update(const Ogre::Vector3 &cameraPos)
 | 
			
		|||
 | 
			
		||||
    bool hadChunk = hasChunk();
 | 
			
		||||
 | 
			
		||||
    if (loadingListener)
 | 
			
		||||
        loadingListener->indicateProgress();
 | 
			
		||||
 | 
			
		||||
    if (!distantLand && dist > 8192*2)
 | 
			
		||||
    {
 | 
			
		||||
        if (mIsActive)
 | 
			
		||||
| 
						 | 
				
			
			@ -341,7 +351,7 @@ void QuadTreeNode::update(const Ogre::Vector3 &cameraPos)
 | 
			
		|||
        }
 | 
			
		||||
        assert(hasChildren() && "Leaf node's LOD needs to be 0");
 | 
			
		||||
        for (int i=0; i<4; ++i)
 | 
			
		||||
            mChildren[i]->update(cameraPos);
 | 
			
		||||
            mChildren[i]->update(cameraPos, loadingListener);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
		Reference in a new issue