Post merge

actorid
Jason Hooks 13 years ago
commit 20288de685

@ -1,7 +1,11 @@
#include "graphicspage.hpp"
#include <QtGui> #include <QtGui>
#include "graphicspage.hpp" #include <boost/lexical_cast.hpp>
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#include <components/settings/settings.hpp>
GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent) GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent)
: QWidget(parent) : QWidget(parent)
@ -17,12 +21,9 @@ GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent)
renderSystemLayout->addWidget(rendererLabel, 0, 0, 1, 1); renderSystemLayout->addWidget(rendererLabel, 0, 0, 1, 1);
renderSystemLayout->addWidget(mRendererComboBox, 0, 1, 1, 1); renderSystemLayout->addWidget(mRendererComboBox, 0, 1, 1, 1);
mRendererStackedWidget = new QStackedWidget(rendererGroup);
QVBoxLayout *rendererGroupLayout = new QVBoxLayout(rendererGroup); QVBoxLayout *rendererGroupLayout = new QVBoxLayout(rendererGroup);
rendererGroupLayout->addLayout(renderSystemLayout); rendererGroupLayout->addLayout(renderSystemLayout);
rendererGroupLayout->addWidget(mRendererStackedWidget);
// Display // Display
QGroupBox *displayGroup = new QGroupBox(tr("Display"), this); QGroupBox *displayGroup = new QGroupBox(tr("Display"), this);
@ -52,107 +53,33 @@ GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent)
void GraphicsPage::createPages() void GraphicsPage::createPages()
{ {
// OpenGL rendering settings QWidget *main = new QWidget();
QWidget *mOGLRendererPage = new QWidget(); QGridLayout *grid = new QGridLayout(main);
QLabel *OGLRTTLabel = new QLabel(tr("Preferred RTT Mode:"), mOGLRendererPage);
mOGLRTTComboBox = new QComboBox(mOGLRendererPage);
QLabel *OGLAntiAliasingLabel = new QLabel(tr("Antialiasing:"), mOGLRendererPage);
mOGLAntiAliasingComboBox = new QComboBox(mOGLRendererPage);
QGridLayout *OGLRendererLayout = new QGridLayout(mOGLRendererPage);
QSpacerItem *vSpacer1 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Expanding);
OGLRendererLayout->addWidget(OGLRTTLabel, 0, 0, 1, 1);
OGLRendererLayout->addWidget(mOGLRTTComboBox, 0, 1, 1, 1);
OGLRendererLayout->addWidget(OGLAntiAliasingLabel, 1, 0, 1, 1);
OGLRendererLayout->addWidget(mOGLAntiAliasingComboBox, 1, 1, 1, 1);
OGLRendererLayout->addItem(vSpacer1, 2, 1, 1, 1);
// OpenGL display settings
QWidget *mOGLDisplayPage = new QWidget();
QLabel *OGLResolutionLabel = new QLabel(tr("Resolution:"), mOGLDisplayPage);
mOGLResolutionComboBox = new QComboBox(mOGLDisplayPage);
QLabel *OGLFrequencyLabel = new QLabel(tr("Display Frequency:"), mOGLDisplayPage);
mOGLFrequencyComboBox = new QComboBox(mOGLDisplayPage);
mOGLVSyncCheckBox = new QCheckBox(tr("Vertical Sync"), mOGLDisplayPage);
mOGLFullScreenCheckBox = new QCheckBox(tr("Full Screen"), mOGLDisplayPage);
QGridLayout *OGLDisplayLayout = new QGridLayout(mOGLDisplayPage);
QSpacerItem *vSpacer2 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Minimum);
OGLDisplayLayout->addWidget(OGLResolutionLabel, 0, 0, 1, 1);
OGLDisplayLayout->addWidget(mOGLResolutionComboBox, 0, 1, 1, 1);
OGLDisplayLayout->addWidget(OGLFrequencyLabel, 1, 0, 1, 1);
OGLDisplayLayout->addWidget(mOGLFrequencyComboBox, 1, 1, 1, 1);
OGLDisplayLayout->addItem(vSpacer2, 2, 1, 1, 1);
OGLDisplayLayout->addWidget(mOGLVSyncCheckBox, 3, 0, 1, 1);
OGLDisplayLayout->addWidget(mOGLFullScreenCheckBox, 6, 0, 1, 1);
// Direct3D rendering settings
QWidget *mD3DRendererPage = new QWidget();
QLabel *D3DRenderDeviceLabel = new QLabel(tr("Rendering Device:"), mD3DRendererPage); mVSyncCheckBox = new QCheckBox(tr("Vertical Sync"), main);
mD3DRenderDeviceComboBox = new QComboBox(mD3DRendererPage); grid->addWidget(mVSyncCheckBox, 0, 0, 1, 1);
QLabel *D3DAntiAliasingLabel = new QLabel(tr("Antialiasing:"), mD3DRendererPage); mFullScreenCheckBox = new QCheckBox(tr("Full Screen"), main);
mD3DAntiAliasingComboBox = new QComboBox(mD3DRendererPage); grid->addWidget(mFullScreenCheckBox, 1, 0, 1, 1);
QLabel *D3DFloatingPointLabel = new QLabel(tr("Floating-point Mode:"), mD3DRendererPage); QLabel *antiAliasingLabel = new QLabel(tr("Antialiasing:"), main);
mD3DFloatingPointComboBox = new QComboBox(mD3DRendererPage); mAntiAliasingComboBox = new QComboBox(main);
grid->addWidget(antiAliasingLabel, 2, 0, 1, 1);
grid->addWidget(mAntiAliasingComboBox, 2, 1, 1, 1);
mD3DNvPerfCheckBox = new QCheckBox(tr("Allow NVPerfHUD"), mD3DRendererPage); QLabel *resolutionLabel = new QLabel(tr("Resolution:"), main);
mResolutionComboBox = new QComboBox(main);
grid->addWidget(resolutionLabel, 3, 0, 1, 1);
grid->addWidget(mResolutionComboBox, 3, 1, 1, 1);
QGridLayout *D3DRendererLayout = new QGridLayout(mD3DRendererPage); QSpacerItem *vSpacer1 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Expanding);
QSpacerItem *vSpacer3 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Minimum); grid->addItem(vSpacer1, 4, 0, 1, 1);
QSpacerItem *vSpacer4 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Expanding);
D3DRendererLayout->addWidget(D3DRenderDeviceLabel, 0, 0, 1, 1);
D3DRendererLayout->addWidget(mD3DRenderDeviceComboBox, 0, 1, 1, 1);
D3DRendererLayout->addWidget(D3DAntiAliasingLabel, 1, 0, 1, 1);
D3DRendererLayout->addWidget(mD3DAntiAliasingComboBox, 1, 1, 1, 1);
D3DRendererLayout->addWidget(D3DFloatingPointLabel, 2, 0, 1, 1);
D3DRendererLayout->addWidget(mD3DFloatingPointComboBox, 2, 1, 1, 1);
D3DRendererLayout->addItem(vSpacer3, 3, 1, 1, 1);
D3DRendererLayout->addWidget(mD3DNvPerfCheckBox, 4, 0, 1, 1);
D3DRendererLayout->addItem(vSpacer4, 5, 1, 1, 1);
// Direct3D display settings
QWidget *mD3DDisplayPage = new QWidget();
QLabel *D3DResolutionLabel = new QLabel(tr("Resolution:"), mD3DDisplayPage);
mD3DResolutionComboBox = new QComboBox(mD3DDisplayPage);
mD3DVSyncCheckBox = new QCheckBox(tr("Vertical Sync"), mD3DDisplayPage);
mD3DFullScreenCheckBox = new QCheckBox(tr("Full Screen"), mD3DDisplayPage);
QGridLayout *mD3DDisplayLayout = new QGridLayout(mD3DDisplayPage);
QSpacerItem *vSpacer5 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Minimum);
mD3DDisplayLayout->addWidget(D3DResolutionLabel, 0, 0, 1, 1);
mD3DDisplayLayout->addWidget(mD3DResolutionComboBox, 0, 1, 1, 1);
mD3DDisplayLayout->addItem(vSpacer5, 1, 1, 1, 1);
mD3DDisplayLayout->addWidget(mD3DVSyncCheckBox, 2, 0, 1, 1);
mD3DDisplayLayout->addWidget(mD3DFullScreenCheckBox, 5, 0, 1, 1);
// Add the created pages
mRendererStackedWidget->addWidget(mOGLRendererPage);
mRendererStackedWidget->addWidget(mD3DRendererPage);
mDisplayStackedWidget->addWidget(mOGLDisplayPage); mDisplayStackedWidget->addWidget(main);
mDisplayStackedWidget->addWidget(mD3DDisplayPage);
} }
void GraphicsPage::setupConfig() void GraphicsPage::setupConfig()
{ {
QString ogreCfg = mCfgMgr.getOgreConfigPath().string().c_str();
QFile file(ogreCfg);
mOgreConfig = new QSettings(ogreCfg, QSettings::IniFormat);
} }
void GraphicsPage::setupOgre() void GraphicsPage::setupOgre()
@ -164,32 +91,12 @@ void GraphicsPage::setupOgre()
Ogre::LogManager* logMgr = OGRE_NEW Ogre::LogManager; Ogre::LogManager* logMgr = OGRE_NEW Ogre::LogManager;
logMgr->createLog((mCfgMgr.getLogPath().string() + "/launcherOgre.log"), true, false, false); logMgr->createLog((mCfgMgr.getLogPath().string() + "/launcherOgre.log"), true, false, false);
QString ogreCfg = QString::fromStdString(mCfgMgr.getOgreConfigPath().string());
file.setFileName(ogreCfg);
//we need to check that the path to the configuration file exists before we
//try and create an instance of Ogre::Root otherwise Ogre raises an exception
QDir configDir = QFileInfo(file).dir();
if ( !configDir.exists() && !configDir.mkpath(configDir.path()) )
{
QMessageBox msgBox;
msgBox.setWindowTitle("Error creating config file");
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setText(QString(tr("<br><b>Failed to create the configuration file</b><br><br> \
Make sure you have write access to<br>%1<br><br>")).arg(configDir.path()));
msgBox.exec();
qApp->exit(1);
return;
}
try try
{ {
#if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9) #if defined(ENABLE_PLUGIN_GL) || defined(ENABLE_PLUGIN_Direct3D9)
mOgre = new Ogre::Root("", file.fileName().toStdString(), "./launcherOgre.log"); mOgre = new Ogre::Root("", "", "./launcherOgre.log");
#else #else
mOgre = new Ogre::Root(pluginCfg.toStdString(), file.fileName().toStdString(), "./launcherOgre.log"); mOgre = new Ogre::Root(pluginCfg.toStdString(), "", "./launcherOgre.log");
#endif #endif
} }
catch(Ogre::Exception &ex) catch(Ogre::Exception &ex)
@ -228,11 +135,19 @@ void GraphicsPage::setupOgre()
mRendererComboBox->addItem((*r)->getName().c_str()); mRendererComboBox->addItem((*r)->getName().c_str());
} }
int index = mRendererComboBox->findText(mOgreConfig->value("Render System").toString()); int index = mRendererComboBox->findText(QString::fromStdString(Settings::Manager::getString("render system", "Video")));
if ( index != -1) { if ( index != -1) {
mRendererComboBox->setCurrentIndex(index); mRendererComboBox->setCurrentIndex(index);
} }
else
{
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
mRendererComboBox->setCurrentIndex(mRendererComboBox->findText("Direct3D9 Rendering Subsystem"));
#else
mRendererComboBox->setCurrentIndex(mRendererComboBox->findText("OpenGL Rendering Subsystem"));
#endif
}
// Create separate rendersystems // Create separate rendersystems
QString openGLName = mRendererComboBox->itemText(mRendererComboBox->findText(QString("OpenGL"), Qt::MatchStartsWith)); QString openGLName = mRendererComboBox->itemText(mRendererComboBox->findText(QString("OpenGL"), Qt::MatchStartsWith));
@ -255,217 +170,44 @@ void GraphicsPage::setupOgre()
} }
// Now fill the GUI elements // Now fill the GUI elements
// OpenGL mAntiAliasingComboBox->clear();
if (mOpenGLRenderSystem) { mResolutionComboBox->clear();
mOGLRTTComboBox->addItems(getAvailableOptions(QString("RTT Preferred Mode"), mOpenGLRenderSystem)); mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem));
mOGLAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mOpenGLRenderSystem)); mResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mSelectedRenderSystem));
mOGLResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mOpenGLRenderSystem));
mOGLFrequencyComboBox->addItems(getAvailableOptions(QString("Display Frequency"), mOpenGLRenderSystem));
}
// Direct3D
if (mDirect3DRenderSystem) {
mD3DRenderDeviceComboBox->addItems(getAvailableOptions(QString("Rendering Device"), mDirect3DRenderSystem));
mD3DAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mDirect3DRenderSystem));
mD3DFloatingPointComboBox->addItems(getAvailableOptions(QString("Floating-point mode"), mDirect3DRenderSystem));
mD3DResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mDirect3DRenderSystem));
}
} }
void GraphicsPage::readConfig() void GraphicsPage::readConfig()
{ {
// Read the config file settings if (Settings::Manager::getBool("vsync", "Video"))
if (mOpenGLRenderSystem) { mVSyncCheckBox->setCheckState(Qt::Checked);
int index = mOGLRTTComboBox->findText(getConfigValue("RTT Preferred Mode", mOpenGLRenderSystem));
if ( index != -1) {
mOGLRTTComboBox->setCurrentIndex(index);
}
index = mOGLAntiAliasingComboBox->findText(getConfigValue("FSAA", mOpenGLRenderSystem));
if ( index != -1){
mOGLAntiAliasingComboBox->setCurrentIndex(index);
}
index = mOGLResolutionComboBox->findText(getConfigValue("Video Mode", mOpenGLRenderSystem));
if ( index != -1) {
mOGLResolutionComboBox->setCurrentIndex(index);
}
index = mOGLFrequencyComboBox->findText(getConfigValue("Display Frequency", mOpenGLRenderSystem));
if ( index != -1) {
mOGLFrequencyComboBox->setCurrentIndex(index);
}
// Now we do the same for the checkboxes
if (getConfigValue("VSync", mOpenGLRenderSystem) == QLatin1String("Yes")) {
mOGLVSyncCheckBox->setCheckState(Qt::Checked);
}
if (getConfigValue("Full Screen", mOpenGLRenderSystem) == QLatin1String("Yes")) {
mOGLFullScreenCheckBox->setCheckState(Qt::Checked);
}
}
if (mDirect3DRenderSystem) {
int index = mD3DRenderDeviceComboBox->findText(getConfigValue("Rendering Device", mDirect3DRenderSystem));
if ( index != -1) {
mD3DRenderDeviceComboBox->setCurrentIndex(index);
}
index = mD3DAntiAliasingComboBox->findText(getConfigValue("FSAA", mDirect3DRenderSystem));
if ( index != -1) {
mD3DAntiAliasingComboBox->setCurrentIndex(index);
}
index = mD3DFloatingPointComboBox->findText(getConfigValue("Floating-point mode", mDirect3DRenderSystem));
if ( index != -1) {
mD3DFloatingPointComboBox->setCurrentIndex(index);
}
index = mD3DResolutionComboBox->findText(getConfigValue("Video Mode", mDirect3DRenderSystem));
if ( index != -1) {
mD3DResolutionComboBox->setCurrentIndex(index);
}
if (getConfigValue("Allow NVPerfHUD", mDirect3DRenderSystem) == QLatin1String("Yes")) { if (Settings::Manager::getBool("fullscreen", "Video"))
mD3DNvPerfCheckBox->setCheckState(Qt::Checked); mFullScreenCheckBox->setCheckState(Qt::Checked);
}
if (getConfigValue("VSync", mDirect3DRenderSystem) == QLatin1String("Yes")) { int aaIndex = mAntiAliasingComboBox->findText(QString::fromStdString(Settings::Manager::getString("antialiasing", "Video")));
mD3DVSyncCheckBox->setCheckState(Qt::Checked); if (aaIndex != -1)
} mAntiAliasingComboBox->setCurrentIndex(aaIndex);
if (getConfigValue("Full Screen", mDirect3DRenderSystem) == QLatin1String("Yes")) { std::string resolution = boost::lexical_cast<std::string>(Settings::Manager::getInt("resolution x", "Video"))
mD3DFullScreenCheckBox->setCheckState(Qt::Checked); + " x " + boost::lexical_cast<std::string>(Settings::Manager::getInt("resolution y", "Video"));
} int resIndex = mResolutionComboBox->findText(QString::fromStdString(resolution));
} if (resIndex != -1)
mResolutionComboBox->setCurrentIndex(resIndex);
} }
void GraphicsPage::writeConfig() void GraphicsPage::writeConfig()
{ {
mOgre->setRenderSystem(mSelectedRenderSystem); Settings::Manager::setBool("vsync", "Video", mVSyncCheckBox->checkState());
Settings::Manager::setBool("fullscreen", "Video", mFullScreenCheckBox->checkState());
if (mDirect3DRenderSystem) { Settings::Manager::setString("antialiasing", "Video", mAntiAliasingComboBox->currentText().toStdString());
// Nvidia Performance HUD
if (mD3DNvPerfCheckBox->checkState() == Qt::Checked) { std::string resolution = mResolutionComboBox->currentText().toStdString();
mDirect3DRenderSystem->setConfigOption("Allow NVPerfHUD", "Yes"); // parse resolution x and y from a string like "800 x 600"
} else { size_t xPos = resolution.find("x");
mDirect3DRenderSystem->setConfigOption("Allow NVPerfHUD", "No"); int resX = boost::lexical_cast<int>(resolution.substr(0, xPos-1));
} int resY = boost::lexical_cast<int>(resolution.substr(xPos+2, resolution.size()-(xPos+2)));
Settings::Manager::setInt("resolution x", "Video", resX);
// Antialiasing Settings::Manager::setInt("resolution y", "Video", resY);
mDirect3DRenderSystem->setConfigOption("FSAA", mD3DAntiAliasingComboBox->currentText().toStdString());
// Full screen
if (mD3DFullScreenCheckBox->checkState() == Qt::Checked) {
mDirect3DRenderSystem->setConfigOption("Full Screen", "Yes");
} else {
mDirect3DRenderSystem->setConfigOption("Full Screen", "No");
}
// Rendering device
mDirect3DRenderSystem->setConfigOption("Rendering Device", mD3DRenderDeviceComboBox->currentText().toStdString());
// VSync
if (mD3DVSyncCheckBox->checkState() == Qt::Checked) {
mDirect3DRenderSystem->setConfigOption("VSync", "Yes");
} else {
mDirect3DRenderSystem->setConfigOption("VSync", "No");
}
// Resolution
mDirect3DRenderSystem->setConfigOption("Video Mode", mD3DResolutionComboBox->currentText().toStdString());
}
if (mOpenGLRenderSystem) {
// Display Frequency
mOpenGLRenderSystem->setConfigOption("Display Frequency", mOGLFrequencyComboBox->currentText().toStdString());
// Antialiasing
mOpenGLRenderSystem->setConfigOption("FSAA", mOGLAntiAliasingComboBox->currentText().toStdString());
// Full screen
if (mOGLFullScreenCheckBox->checkState() == Qt::Checked) {
mOpenGLRenderSystem->setConfigOption("Full Screen", "Yes");
} else {
mOpenGLRenderSystem->setConfigOption("Full Screen", "No");
}
// RTT mode
mOpenGLRenderSystem->setConfigOption("RTT Preferred Mode", mOGLRTTComboBox->currentText().toStdString());
// VSync
if (mOGLVSyncCheckBox->checkState() == Qt::Checked) {
mOpenGLRenderSystem->setConfigOption("VSync", "Yes");
} else {
mOpenGLRenderSystem->setConfigOption("VSync", "No");
}
// Resolution
mOpenGLRenderSystem->setConfigOption("Video Mode", mOGLResolutionComboBox->currentText().toStdString());
}
// Now we validate the options
QString ogreError = QString::fromStdString(mSelectedRenderSystem->validateConfigOptions());
if (!ogreError.isEmpty()) {
QMessageBox msgBox;
msgBox.setWindowTitle("Error validating Ogre configuration");
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setText(tr("<br><b>A problem occured while validating the graphics options</b><br><br> \
The graphics options could not be saved.<br><br> \
Press \"Show Details...\" for more information.<br>"));
msgBox.setDetailedText(ogreError);
msgBox.exec();
Ogre::LogManager::getSingletonPtr()->logMessage( "Caught exception in validateConfigOptions");
qCritical("Error validating configuration");
qApp->exit(1);
return;
}
// Write the settings to the config file
try
{
mOgre->saveConfig();
}
catch(Ogre::Exception &ex)
{
QString ogreError = QString::fromStdString(ex.getFullDescription().c_str());
QMessageBox msgBox;
msgBox.setWindowTitle("Error writing Ogre configuration file");
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setText(tr("<br><b>Could not write the graphics configuration</b><br><br> \
Please make sure you have the right permissions and try again.<br><br> \
Press \"Show Details...\" for more information.<br>"));
msgBox.setDetailedText(ogreError);
msgBox.exec();
qCritical("Error saving Ogre configuration, the error reported was:\n %s", qPrintable(ogreError));
qApp->exit(1);
return;
}
}
QString GraphicsPage::getConfigValue(const QString &key, Ogre::RenderSystem *renderer)
{
QString result;
mOgreConfig->beginGroup(renderer->getName().c_str());
result = mOgreConfig->value(key).toString();
mOgreConfig->endGroup();
return result;
} }
QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer) QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer)
@ -484,7 +226,12 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy
{ {
if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0)
result << QString::fromStdString((*opt_it).c_str()).simplified(); {
if (key == "FSAA" && *opt_it == "0")
result << QString("none");
else
result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromStdString((*opt_it).c_str()).simplified();
}
} }
} }
@ -494,15 +241,11 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy
void GraphicsPage::rendererChanged(const QString &renderer) void GraphicsPage::rendererChanged(const QString &renderer)
{ {
if (renderer.contains("Direct3D")) { mSelectedRenderSystem = mOgre->getRenderSystemByName(renderer.toStdString());
mRendererStackedWidget->setCurrentIndex(1);
mDisplayStackedWidget->setCurrentIndex(1);
}
if (renderer.contains("OpenGL")) { mAntiAliasingComboBox->clear();
mRendererStackedWidget->setCurrentIndex(0); mResolutionComboBox->clear();
mDisplayStackedWidget->setCurrentIndex(0);
}
mSelectedRenderSystem = mOgre->getRenderSystemByName(renderer.toStdString()); mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem));
mResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mSelectedRenderSystem));
} }

@ -49,33 +49,15 @@ private:
QComboBox *mRendererComboBox; QComboBox *mRendererComboBox;
QStackedWidget *mRendererStackedWidget;
QStackedWidget *mDisplayStackedWidget; QStackedWidget *mDisplayStackedWidget;
// OpenGL QComboBox *mAntiAliasingComboBox;
QComboBox *mOGLRTTComboBox; QComboBox *mResolutionComboBox;
QComboBox *mOGLAntiAliasingComboBox; QCheckBox *mVSyncCheckBox;
QComboBox *mOGLResolutionComboBox; QCheckBox *mFullScreenCheckBox;
QComboBox *mOGLFrequencyComboBox;
QCheckBox *mOGLVSyncCheckBox;
QCheckBox *mOGLFullScreenCheckBox;
// Direct3D
QComboBox *mD3DRenderDeviceComboBox;
QComboBox *mD3DAntiAliasingComboBox;
QComboBox *mD3DFloatingPointComboBox;
QComboBox *mD3DResolutionComboBox;
QCheckBox *mD3DNvPerfCheckBox;
QCheckBox *mD3DVSyncCheckBox;
QCheckBox *mD3DFullScreenCheckBox;
QSettings *mOgreConfig;
Files::ConfigurationManager &mCfgMgr; Files::ConfigurationManager &mCfgMgr;
QString getConfigValue(const QString &key, Ogre::RenderSystem *renderer);
QStringList getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer); QStringList getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer);
void createPages(); void createPages();

@ -7,6 +7,28 @@
MainDialog::MainDialog() MainDialog::MainDialog()
{ {
// Create the settings manager and load default settings file
const std::string localdefault = mCfgMgr.getLocalPath().string() + "/settings-default.cfg";
const std::string globaldefault = mCfgMgr.getGlobalPath().string() + "/settings-default.cfg";
// prefer local
if (boost::filesystem::exists(localdefault))
mSettings.loadDefault(localdefault);
else if (boost::filesystem::exists(globaldefault))
mSettings.loadDefault(globaldefault);
else
throw std::runtime_error ("No default settings file found! Make sure the file \"settings-default.cfg\" was properly installed.");
// load user settings if they exist, otherwise just load the default settings as user settings
const std::string settingspath = mCfgMgr.getUserPath().string() + "/settings.cfg";
if (boost::filesystem::exists(settingspath))
mSettings.loadUser(settingspath);
else if (boost::filesystem::exists(localdefault))
mSettings.loadUser(localdefault);
else if (boost::filesystem::exists(globaldefault))
mSettings.loadUser(globaldefault);
mIconWidget = new QListWidget; mIconWidget = new QListWidget;
mIconWidget->setObjectName("IconWidget"); mIconWidget->setObjectName("IconWidget");
mIconWidget->setViewMode(QListView::IconMode); mIconWidget->setViewMode(QListView::IconMode);
@ -178,6 +200,11 @@ void MainDialog::closeEvent(QCloseEvent *event)
// Now write all config files // Now write all config files
mDataFilesPage->writeConfig(); mDataFilesPage->writeConfig();
mGraphicsPage->writeConfig(); mGraphicsPage->writeConfig();
// Save user settings
const std::string settingspath = mCfgMgr.getUserPath().string() + "/settings.cfg";
mSettings.saveUser(settingspath);
event->accept(); event->accept();
} }

@ -4,6 +4,7 @@
#include <QDialog> #include <QDialog>
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#include <components/settings/settings.hpp>
class QListWidget; class QListWidget;
class QListWidgetItem; class QListWidgetItem;
@ -41,6 +42,7 @@ private:
DataFilesPage *mDataFilesPage; DataFilesPage *mDataFilesPage;
Files::ConfigurationManager mCfgMgr; Files::ConfigurationManager mCfgMgr;
Settings::Manager mSettings;
}; };
#endif #endif

@ -8,7 +8,9 @@
#include <algorithm> #include <algorithm>
#include <sstream> #include <sstream>
MwIniImporter::MwIniImporter() { MwIniImporter::MwIniImporter()
: mVerbose(false)
{
const char *map[][2] = const char *map[][2] =
{ {
{ "fps", "General:Show FPS" }, { "fps", "General:Show FPS" },
@ -124,9 +126,9 @@ MwIniImporter::multistrmap MwIniImporter::loadCfgFile(std::string filename) {
void MwIniImporter::merge(multistrmap &cfg, multistrmap &ini) { void MwIniImporter::merge(multistrmap &cfg, multistrmap &ini) {
multistrmap::iterator cfgIt; multistrmap::iterator cfgIt;
multistrmap::iterator iniIt; multistrmap::iterator iniIt;
for(strmap::iterator it=mMergeMap.begin(); it!=mMergeMap.end(); it++) { for(strmap::iterator it=mMergeMap.begin(); it!=mMergeMap.end(); ++it) {
if((iniIt = ini.find(it->second)) != ini.end()) { if((iniIt = ini.find(it->second)) != ini.end()) {
for(std::vector<std::string>::iterator vc = iniIt->second.begin(); vc != iniIt->second.end(); vc++) { for(std::vector<std::string>::iterator vc = iniIt->second.begin(); vc != iniIt->second.end(); ++vc) {
cfg.erase(it->first); cfg.erase(it->first);
insertMultistrmap(cfg, it->first, *vc); insertMultistrmap(cfg, it->first, *vc);
} }
@ -139,9 +141,9 @@ void MwIniImporter::mergeFallback(multistrmap &cfg, multistrmap &ini) {
multistrmap::iterator cfgIt; multistrmap::iterator cfgIt;
multistrmap::iterator iniIt; multistrmap::iterator iniIt;
for(std::vector<std::string>::iterator it=mMergeFallback.begin(); it!=mMergeFallback.end(); it++) { for(std::vector<std::string>::iterator it=mMergeFallback.begin(); it!=mMergeFallback.end(); ++it) {
if((iniIt = ini.find(*it)) != ini.end()) { if((iniIt = ini.find(*it)) != ini.end()) {
for(std::vector<std::string>::iterator vc = iniIt->second.begin(); vc != iniIt->second.end(); vc++) { for(std::vector<std::string>::iterator vc = iniIt->second.begin(); vc != iniIt->second.end(); ++vc) {
std::string value(*it); std::string value(*it);
std::replace( value.begin(), value.end(), ' ', '_' ); std::replace( value.begin(), value.end(), ' ', '_' );
std::replace( value.begin(), value.end(), ':', '_' ); std::replace( value.begin(), value.end(), ':', '_' );
@ -176,7 +178,7 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, multistrmap &ini) {
break; break;
} }
for(std::vector<std::string>::iterator entry = it->second.begin(); entry!=it->second.end(); entry++) { for(std::vector<std::string>::iterator entry = it->second.begin(); entry!=it->second.end(); ++entry) {
std::string filetype(entry->substr(entry->length()-4, 3)); std::string filetype(entry->substr(entry->length()-4, 3));
std::transform(filetype.begin(), filetype.end(), filetype.begin(), ::tolower); std::transform(filetype.begin(), filetype.end(), filetype.begin(), ::tolower);
@ -194,22 +196,22 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, multistrmap &ini) {
cfg.erase("master"); cfg.erase("master");
cfg.insert( std::make_pair<std::string, std::vector<std::string> > ("master", std::vector<std::string>() ) ); cfg.insert( std::make_pair<std::string, std::vector<std::string> > ("master", std::vector<std::string>() ) );
for(std::vector<std::string>::iterator it=esmFiles.begin(); it!=esmFiles.end(); it++) { for(std::vector<std::string>::iterator it=esmFiles.begin(); it!=esmFiles.end(); ++it) {
cfg["master"].push_back(*it); cfg["master"].push_back(*it);
} }
cfg.erase("plugin"); cfg.erase("plugin");
cfg.insert( std::make_pair<std::string, std::vector<std::string> > ("plugin", std::vector<std::string>() ) ); cfg.insert( std::make_pair<std::string, std::vector<std::string> > ("plugin", std::vector<std::string>() ) );
for(std::vector<std::string>::iterator it=espFiles.begin(); it!=espFiles.end(); it++) { for(std::vector<std::string>::iterator it=espFiles.begin(); it!=espFiles.end(); ++it) {
cfg["plugin"].push_back(*it); cfg["plugin"].push_back(*it);
} }
} }
void MwIniImporter::writeToFile(boost::iostreams::stream<boost::iostreams::file_sink> &out, multistrmap &cfg) { void MwIniImporter::writeToFile(boost::iostreams::stream<boost::iostreams::file_sink> &out, multistrmap &cfg) {
for(multistrmap::iterator it=cfg.begin(); it != cfg.end(); it++) { for(multistrmap::iterator it=cfg.begin(); it != cfg.end(); ++it) {
for(std::vector<std::string>::iterator entry=it->second.begin(); entry != it->second.end(); entry++) { for(std::vector<std::string>::iterator entry=it->second.begin(); entry != it->second.end(); ++entry) {
out << (it->first) << "=" << (*entry) << std::endl; out << (it->first) << "=" << (*entry) << std::endl;
} }
} }

@ -27,7 +27,8 @@ add_openmw_dir (mwgui
text_input widgets race class birth review window_manager console dialogue text_input widgets race class birth review window_manager console dialogue
dialogue_history window_base stats_window messagebox journalwindow charactercreation dialogue_history window_base stats_window messagebox journalwindow charactercreation
map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list
formatting itemwidget inventorywindow container hud countdialog tradewindow formatting inventorywindow container hud countdialog tradewindow settingswindow
confirmationdialog alchemywindow referenceinterface spellwindow
) )
add_openmw_dir (mwdialogue add_openmw_dir (mwdialogue
@ -49,7 +50,7 @@ add_openmw_dir (mwworld
refdata world physicssystem scene globals class action nullaction actionteleport refdata world physicssystem scene globals class action nullaction actionteleport
containerstore actiontalk actiontake manualref player cellfunctors containerstore actiontalk actiontake manualref player cellfunctors
cells localscripts customdata weather inventorystore ptr actionopen actionread cells localscripts customdata weather inventorystore ptr actionopen actionread
actionequip timestamp actionequip timestamp actionalchemy
) )
add_openmw_dir (mwclass add_openmw_dir (mwclass

@ -105,7 +105,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
// frame. // frame.
// passing of time // passing of time
if (MWBase::Environment::get().getWindowManager()->getMode()==MWGui::GM_Game) if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
MWBase::Environment::get().getWorld()->advanceTime ( MWBase::Environment::get().getWorld()->advanceTime (
mEnvironment.getFrameDuration()*MWBase::Environment::get().getWorld()->getTimeScaleFactor()/3600); mEnvironment.getFrameDuration()*MWBase::Environment::get().getWorld()->getTimeScaleFactor()/3600);
@ -116,9 +116,9 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
// update actors // update actors
std::vector<std::pair<std::string, Ogre::Vector3> > movement; std::vector<std::pair<std::string, Ogre::Vector3> > movement;
MWBase::Environment::get().getMechanicsManager()->update (movement, mEnvironment.getFrameDuration(), MWBase::Environment::get().getMechanicsManager()->update (movement, mEnvironment.getFrameDuration(),
MWBase::Environment::get().getWindowManager()->getMode()!=MWGui::GM_Game); MWBase::Environment::get().getWindowManager()->isGuiMode());
if (MWBase::Environment::get().getWindowManager()->getMode()==MWGui::GM_Game) if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
MWBase::Environment::get().getWorld()->doPhysics (movement, mEnvironment.getFrameDuration()); MWBase::Environment::get().getWorld()->doPhysics (movement, mEnvironment.getFrameDuration());
// update world // update world
@ -268,15 +268,6 @@ void OMW::Engine::go()
mOgre = new OEngine::Render::OgreRenderer; mOgre = new OEngine::Render::OgreRenderer;
//we need to ensure the path to the configuration exists before creating an
//instance of ogre root so that Ogre doesn't raise an exception when trying to
//access it
const boost::filesystem::path configPath = mCfgMgr.getOgreConfigPath().parent_path();
if ( !boost::filesystem::exists(configPath) )
{
boost::filesystem::create_directories(configPath);
}
// Create the settings manager and load default settings file // Create the settings manager and load default settings file
Settings::Manager settings; Settings::Manager settings;
const std::string localdefault = mCfgMgr.getLocalPath().string() + "/settings-default.cfg"; const std::string localdefault = mCfgMgr.getLocalPath().string() + "/settings-default.cfg";
@ -308,10 +299,20 @@ void OMW::Engine::go()
else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg")) else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg"))
nifOverrides.loadTransparencyOverrides(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg"); nifOverrides.loadTransparencyOverrides(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg");
mOgre->configure(!boost::filesystem::is_regular_file(mCfgMgr.getOgreConfigPath()), std::string renderSystem = settings.getString("render system", "Video");
mCfgMgr.getOgreConfigPath().string(), if (renderSystem == "")
{
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
renderSystem = "Direct3D9 Rendering Subsystem";
#else
renderSystem = "OpenGL Rendering Subsystem";
#endif
}
mOgre->configure(
mCfgMgr.getLogPath().string(), mCfgMgr.getLogPath().string(),
mCfgMgr.getPluginsConfigPath().string(), false); mCfgMgr.getPluginsConfigPath().string(),
renderSystem,
false);
// This has to be added BEFORE MyGUI is initialized, as it needs // This has to be added BEFORE MyGUI is initialized, as it needs
// to find core.xml here. // to find core.xml here.
@ -325,7 +326,14 @@ void OMW::Engine::go()
addZipResource(mResDir / "mygui" / "Obliviontt.zip"); addZipResource(mResDir / "mygui" / "Obliviontt.zip");
// Create the window // Create the window
mOgre->createWindow("OpenMW"); OEngine::Render::WindowSettings windowSettings;
windowSettings.fullscreen = settings.getBool("fullscreen", "Video");
windowSettings.window_x = settings.getInt("resolution x", "Video");
windowSettings.window_y = settings.getInt("resolution y", "Video");
windowSettings.vsync = settings.getBool("vsync", "Video");
std::string aa = settings.getString("antialiasing", "Video");
windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0";
mOgre->createWindow("OpenMW", windowSettings);
loadBSA(); loadBSA();
@ -413,7 +421,7 @@ void OMW::Engine::go()
void OMW::Engine::activate() void OMW::Engine::activate()
{ {
if (MWBase::Environment::get().getWindowManager()->getMode()!=MWGui::GM_Game) if (MWBase::Environment::get().getWindowManager()->isGuiMode())
return; return;
std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle(); std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle();

@ -9,6 +9,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/actionalchemy.hpp"
#include "../mwworld/world.hpp" #include "../mwworld/world.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
@ -140,4 +141,10 @@ namespace MWClass
return info; return info;
} }
boost::shared_ptr<MWWorld::Action> Apparatus::use (const MWWorld::Ptr& ptr) const
{
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionAlchemy());
}
} }

@ -44,6 +44,10 @@ namespace MWClass
virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const;
///< Return name of inventory icon. ///< Return name of inventory icon.
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
///< Generate action for using via inventory menu
}; };
} }

@ -81,24 +81,15 @@ namespace MWClass
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref =
ptr.get<ESM::Creature>(); ptr.get<ESM::Creature>();
const std::string &model = ref->base->model; const std::string &model = ref->base->model;
assert (ref->base != NULL); assert (ref->base != NULL);
if(!model.empty()){ if(!model.empty()){
physics.insertObjectPhysics(ptr, "meshes\\" + model); physics.insertObjectPhysics(ptr, "meshes\\" + model);
} }
}
void Creature::enable (const MWWorld::Ptr& ptr) const
{
MWBase::Environment::get().getMechanicsManager()->addActor (ptr); MWBase::Environment::get().getMechanicsManager()->addActor (ptr);
} }
void Creature::disable (const MWWorld::Ptr& ptr) const
{
MWBase::Environment::get().getMechanicsManager()->removeActor (ptr);
}
std::string Creature::getName (const MWWorld::Ptr& ptr) const std::string Creature::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData> *ref =

@ -22,12 +22,6 @@ namespace MWClass
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const;
virtual void enable (const MWWorld::Ptr& ptr) const;
///< Enable reference; only does the non-rendering part
virtual void disable (const MWWorld::Ptr& ptr) const;
///< Enable reference; only does the non-rendering part
virtual std::string getName (const MWWorld::Ptr& ptr) const; virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -135,6 +135,19 @@ namespace MWClass
text += MWGui::ToolTips::getMiscString(ref->base->script, "Script"); text += MWGui::ToolTips::getMiscString(ref->base->script, "Script");
} }
MWGui::Widgets::SpellEffectList list;
for (int i=0; i<4; ++i)
{
if (ref->base->data.effectID[i] < 0)
continue;
MWGui::Widgets::SpellEffectParams params;
params.mEffectID = ref->base->data.effectID[i];
params.mAttribute = ref->base->data.attributes[i];
params.mSkill = ref->base->data.skills[i];
list.push_back(params);
}
info.effects = list;
info.text = text; info.text = text;
return info; return info;

@ -9,6 +9,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/actionequip.hpp"
#include "../mwworld/nullaction.hpp" #include "../mwworld/nullaction.hpp"
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwworld/world.hpp" #include "../mwworld/world.hpp"
@ -55,12 +56,6 @@ namespace MWClass
if(!model.empty()){ if(!model.empty()){
physics.insertObjectPhysics(ptr, "meshes\\" + model); physics.insertObjectPhysics(ptr, "meshes\\" + model);
} }
}
void Light::enable (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
ptr.get<ESM::Light>();
if (!ref->base->sound.empty()) if (!ref->base->sound.empty())
{ {
@ -182,4 +177,11 @@ namespace MWClass
return info; return info;
} }
boost::shared_ptr<MWWorld::Action> Light::use (const MWWorld::Ptr& ptr) const
{
MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0);
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionEquip(ptr));
}
} }

@ -14,11 +14,6 @@ namespace MWClass
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const;
virtual void enable (const MWWorld::Ptr& ptr) const;
///< Enable reference; only does the non-rendering part
/// \attention This is not the same as the script instruction with the same name. References
/// should only be enabled while in an active cell.
virtual std::string getName (const MWWorld::Ptr& ptr) const; virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.
@ -53,6 +48,10 @@ namespace MWClass
virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const;
///< Return name of inventory icon. ///< Return name of inventory icon.
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
///< Generate action for using via inventory menu
}; };
} }

@ -9,6 +9,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/actionequip.hpp"
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwworld/world.hpp" #include "../mwworld/world.hpp"
#include "../mwgui/window_manager.hpp" #include "../mwgui/window_manager.hpp"
@ -155,4 +156,11 @@ namespace MWClass
return info; return info;
} }
boost::shared_ptr<MWWorld::Action> Lockpick::use (const MWWorld::Ptr& ptr) const
{
MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0);
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionEquip(ptr));
}
} }

@ -48,6 +48,10 @@ namespace MWClass
virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const;
///< Return name of inventory icon. ///< Return name of inventory icon.
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
///< Generate action for using via inventory menu
}; };
} }

@ -110,44 +110,32 @@ namespace MWClass
void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{ {
renderingInterface.getActors().insertNPC(ptr, getInventoryStore(ptr)); renderingInterface.getActors().insertNPC(ptr, getInventoryStore(ptr));
} }
void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const
{ {
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
ptr.get<ESM::NPC>(); ptr.get<ESM::NPC>();
assert (ref->base != NULL); assert (ref->base != NULL);
std::string headID = ref->base->head; std::string headID = ref->base->head;
std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4);
bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_"; bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_";
std::string smodel = "meshes\\base_anim.nif"; std::string smodel = "meshes\\base_anim.nif";
if(beast) if(beast)
smodel = "meshes\\base_animkna.nif"; smodel = "meshes\\base_animkna.nif";
//physics.insertObjectPhysics(ptr, smodel);
}
void Npc::enable (const MWWorld::Ptr& ptr) const
{
MWBase::Environment::get().getMechanicsManager()->addActor (ptr); MWBase::Environment::get().getMechanicsManager()->addActor (ptr);
} }
void Npc::disable (const MWWorld::Ptr& ptr) const
{
MWBase::Environment::get().getMechanicsManager()->removeActor (ptr);
}
std::string Npc::getName (const MWWorld::Ptr& ptr) const std::string Npc::getName (const MWWorld::Ptr& ptr) const
{ {
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =

@ -19,12 +19,6 @@ namespace MWClass
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const; virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const;
virtual void enable (const MWWorld::Ptr& ptr) const;
///< Enable reference; only does the non-rendering part
virtual void disable (const MWWorld::Ptr& ptr) const;
///< Enable reference; only does the non-rendering part
virtual std::string getName (const MWWorld::Ptr& ptr) const; virtual std::string getName (const MWWorld::Ptr& ptr) const;
///< \return name (the one that is to be presented to the user; not the internal one); ///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string. /// can return an empty string.

@ -132,7 +132,7 @@ namespace MWClass
text += "\n" + store.gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight); text += "\n" + store.gameSettings.search("sWeight")->str + ": " + MWGui::ToolTips::toString(ref->base->data.weight);
text += MWGui::ToolTips::getValueString(ref->base->data.value, store.gameSettings.search("sValue")->str); text += MWGui::ToolTips::getValueString(ref->base->data.value, store.gameSettings.search("sValue")->str);
info.effects = &ref->base->effects; info.effects = MWGui::Widgets::MWEffectList::effectListFromESM(&ref->base->effects);
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner"); text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");

@ -9,6 +9,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/actionequip.hpp"
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwworld/world.hpp" #include "../mwworld/world.hpp"
#include "../mwgui/window_manager.hpp" #include "../mwgui/window_manager.hpp"
@ -154,4 +155,11 @@ namespace MWClass
return info; return info;
} }
boost::shared_ptr<MWWorld::Action> Probe::use (const MWWorld::Ptr& ptr) const
{
MWBase::Environment::get().getSoundManager()->playSound (getUpSoundId(ptr), 1.0, 1.0);
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionEquip(ptr));
}
} }

@ -48,6 +48,10 @@ namespace MWClass
virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const; virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const;
///< Return name of inventory icon. ///< Return name of inventory icon.
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
///< Generate action for using via inventory menu
}; };
} }

@ -607,7 +607,7 @@ namespace MWDialogue
void DialogueManager::parseText(std::string text) void DialogueManager::parseText(std::string text)
{ {
std::list<std::string>::iterator it; std::list<std::string>::iterator it;
for(it = actorKnownTopics.begin();it != actorKnownTopics.end();it++) for(it = actorKnownTopics.begin();it != actorKnownTopics.end();++it)
{ {
size_t pos = find_str_ci(text,*it,0); size_t pos = find_str_ci(text,*it,0);
if(pos !=std::string::npos) if(pos !=std::string::npos)
@ -635,7 +635,7 @@ namespace MWDialogue
actorKnownTopics.clear(); actorKnownTopics.clear();
//initialise the GUI //initialise the GUI
MWBase::Environment::get().getInputManager()->setGuiMode(MWGui::GM_Dialogue); MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Dialogue);
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
win->startDialogue(actor, MWWorld::Class::get (actor).getName (actor)); win->startDialogue(actor, MWWorld::Class::get (actor).getName (actor));
@ -843,7 +843,7 @@ namespace MWDialogue
void DialogueManager::goodbyeSelected() void DialogueManager::goodbyeSelected()
{ {
MWBase::Environment::get().getInputManager()->setGuiMode(MWGui::GM_Game); MWBase::Environment::get().getWindowManager()->popGuiMode();
} }
void DialogueManager::questionAnswered(std::string answere) void DialogueManager::questionAnswered(std::string answere)

@ -0,0 +1,512 @@
#include "alchemywindow.hpp"
#include <boost/algorithm/string.hpp>
#include "../mwbase/environment.hpp"
#include "../mwworld/world.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/manualref.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwsound/soundmanager.hpp"
#include "window_manager.hpp"
namespace
{
std::string getIconPath(MWWorld::Ptr ptr)
{
std::string path = std::string("icons\\");
path += MWWorld::Class::get(ptr).getInventoryIcon(ptr);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
return path;
}
}
namespace MWGui
{
AlchemyWindow::AlchemyWindow(WindowManager& parWindowManager)
: WindowBase("openmw_alchemy_window_layout.xml", parWindowManager)
, ContainerBase(0)
{
getWidget(mCreateButton, "CreateButton");
getWidget(mCancelButton, "CancelButton");
getWidget(mIngredient1, "Ingredient1");
getWidget(mIngredient2, "Ingredient2");
getWidget(mIngredient3, "Ingredient3");
getWidget(mIngredient4, "Ingredient4");
getWidget(mApparatus1, "Apparatus1");
getWidget(mApparatus2, "Apparatus2");
getWidget(mApparatus3, "Apparatus3");
getWidget(mApparatus4, "Apparatus4");
getWidget(mEffectsBox, "CreatedEffects");
getWidget(mNameEdit, "NameEdit");
mIngredient1->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
mIngredient2->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
mIngredient3->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
mIngredient4->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onIngredientSelected);
MyGUI::Widget* buttonBox = mCancelButton->getParent();
int cancelButtonWidth = mCancelButton->getTextSize().width + 24;
mCancelButton->setCoord(buttonBox->getWidth() - cancelButtonWidth,
mCancelButton->getTop(), cancelButtonWidth, mCancelButton->getHeight());
int createButtonWidth = mCreateButton->getTextSize().width + 24;
mCreateButton->setCoord(buttonBox->getWidth() - createButtonWidth - cancelButtonWidth - 4,
mCreateButton->getTop(), createButtonWidth, mCreateButton->getHeight());
mCreateButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCreateButtonClicked);
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCancelButtonClicked);
MyGUI::ScrollView* itemView;
MyGUI::Widget* containerWidget;
getWidget(containerWidget, "Items");
getWidget(itemView, "ItemView");
setWidgets(containerWidget, itemView);
center();
}
void AlchemyWindow::onCancelButtonClicked(MyGUI::Widget* _sender)
{
mWindowManager.popGuiMode();
mWindowManager.popGuiMode();
}
void AlchemyWindow::onCreateButtonClicked(MyGUI::Widget* _sender)
{
// check if mortar & pestle is available (always needed)
/// \todo check albemic, calcinator, retort (sometimes needed)
if (!mApparatus1->isUserString("ToolTipType"))
{
mWindowManager.messageBox("#{sNotifyMessage45}", std::vector<std::string>());
return;
}
// make sure 2 or more ingredients were selected
int numIngreds = 0;
if (mIngredient1->isUserString("ToolTipType"))
++numIngreds;
if (mIngredient2->isUserString("ToolTipType"))
++numIngreds;
if (mIngredient3->isUserString("ToolTipType"))
++numIngreds;
if (mIngredient4->isUserString("ToolTipType"))
++numIngreds;
if (numIngreds < 2)
{
mWindowManager.messageBox("#{sNotifyMessage6a}", std::vector<std::string>());
return;
}
// make sure a name was entered
std::string name = mNameEdit->getCaption();
boost::algorithm::trim(name);
if (name == "")
{
mWindowManager.messageBox("#{sNotifyMessage37}", std::vector<std::string>());
return;
}
// if there are no created effects, the potion will always fail (but the ingredients won't be destroyed)
if (mEffects.empty())
{
mWindowManager.messageBox("#{sNotifyMessage8}", std::vector<std::string>());
MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f);
return;
}
if (rand() % 2 == 0) /// \todo
{
ESM::Potion newPotion;
newPotion.name = mNameEdit->getCaption();
ESM::EffectList effects;
for (unsigned int i=0; i<4; ++i)
{
if (mEffects.size() >= i+1)
{
ESM::ENAMstruct effect;
effect.effectID = mEffects[i].mEffectID;
effect.area = 0;
effect.range = ESM::RT_Self;
effect.skill = mEffects[i].mSkill;
effect.attribute = mEffects[i].mAttribute;
effect.magnMin = 1; /// \todo
effect.magnMax = 10; /// \todo
effect.duration = 60; /// \todo
effects.list.push_back(effect);
}
}
// UESP Wiki / Morrowind:Alchemy
// "The weight of a potion is an average of the weight of the ingredients, rounded down."
// note by scrawl: not rounding down here, I can't imagine a created potion to
// have 0 weight when using ingredients with 0.1 weight respectively
float weight = 0;
if (mIngredient1->isUserString("ToolTipType"))
weight += mIngredient1->getUserData<MWWorld::Ptr>()->get<ESM::Ingredient>()->base->data.weight;
if (mIngredient2->isUserString("ToolTipType"))
weight += mIngredient2->getUserData<MWWorld::Ptr>()->get<ESM::Ingredient>()->base->data.weight;
if (mIngredient3->isUserString("ToolTipType"))
weight += mIngredient3->getUserData<MWWorld::Ptr>()->get<ESM::Ingredient>()->base->data.weight;
if (mIngredient4->isUserString("ToolTipType"))
weight += mIngredient4->getUserData<MWWorld::Ptr>()->get<ESM::Ingredient>()->base->data.weight;
newPotion.data.weight = weight / float(numIngreds);
newPotion.data.value = 100; /// \todo
newPotion.effects = effects;
// pick a random mesh and icon
std::vector<std::string> names;
/// \todo is the mesh/icon dependent on alchemy skill?
names.push_back("standard");
names.push_back("bargain");
names.push_back("cheap");
names.push_back("fresh");
names.push_back("exclusive");
names.push_back("quality");
int random = rand() % names.size();
newPotion.model = "m\\misc_potion_" + names[random ] + "_01.nif";
newPotion.icon = "m\\tx_potion_" + names[random ] + "_01.dds";
// check if a similiar potion record exists already
bool found = false;
std::string objectId;
typedef std::map<std::string, ESM::Potion> PotionMap;
PotionMap potions = MWBase::Environment::get().getWorld()->getStore().potions.list;
for (PotionMap::const_iterator it = potions.begin(); it != potions.end(); ++it)
{
if (found) break;
if (it->second.data.value == newPotion.data.value
&& it->second.data.weight == newPotion.data.weight
&& it->second.name == newPotion.name
&& it->second.effects.list.size() == newPotion.effects.list.size())
{
// check effects
for (unsigned int i=0; i < it->second.effects.list.size(); ++i)
{
const ESM::ENAMstruct& a = it->second.effects.list[i];
const ESM::ENAMstruct& b = newPotion.effects.list[i];
if (a.effectID == b.effectID
&& a.area == b.area
&& a.range == b.range
&& a.skill == b.skill
&& a.attribute == b.attribute
&& a.magnMin == b.magnMin
&& a.magnMax == b.magnMax
&& a.duration == b.duration)
{
found = true;
objectId = it->first;
break;
}
}
}
}
if (!found)
{
std::pair<std::string, const ESM::Potion*> result = MWBase::Environment::get().getWorld()->createRecord(newPotion);
objectId = result.first;
}
// create a reference and add it to player inventory
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), objectId);
MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
ref.getPtr().getRefData().setCount(1);
store.add(ref.getPtr());
mWindowManager.messageBox("#{sPotionSuccess}", std::vector<std::string>());
MWBase::Environment::get().getSoundManager()->playSound("potion success", 1.f, 1.f);
}
else
{
// potion failed
mWindowManager.messageBox("#{sNotifyMessage8}", std::vector<std::string>());
MWBase::Environment::get().getSoundManager()->playSound("potion fail", 1.f, 1.f);
}
// reduce count of the ingredients
if (mIngredient1->isUserString("ToolTipType"))
{
MWWorld::Ptr ingred = *mIngredient1->getUserData<MWWorld::Ptr>();
ingred.getRefData().setCount(ingred.getRefData().getCount()-1);
if (ingred.getRefData().getCount() == 0)
removeIngredient(mIngredient1);
}
if (mIngredient2->isUserString("ToolTipType"))
{
MWWorld::Ptr ingred = *mIngredient2->getUserData<MWWorld::Ptr>();
ingred.getRefData().setCount(ingred.getRefData().getCount()-1);
if (ingred.getRefData().getCount() == 0)
removeIngredient(mIngredient2);
}
if (mIngredient3->isUserString("ToolTipType"))
{
MWWorld::Ptr ingred = *mIngredient3->getUserData<MWWorld::Ptr>();
ingred.getRefData().setCount(ingred.getRefData().getCount()-1);
if (ingred.getRefData().getCount() == 0)
removeIngredient(mIngredient3);
}
if (mIngredient4->isUserString("ToolTipType"))
{
MWWorld::Ptr ingred = *mIngredient4->getUserData<MWWorld::Ptr>();
ingred.getRefData().setCount(ingred.getRefData().getCount()-1);
if (ingred.getRefData().getCount() == 0)
removeIngredient(mIngredient4);
}
update();
}
void AlchemyWindow::open()
{
openContainer(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
setFilter(ContainerBase::Filter_Ingredients);
// pick the best available apparatus
MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
MWWorld::Ptr bestAlbemic;
MWWorld::Ptr bestMortarPestle;
MWWorld::Ptr bestCalcinator;
MWWorld::Ptr bestRetort;
for (MWWorld::ContainerStoreIterator it(store.begin(MWWorld::ContainerStore::Type_Apparatus));
it != store.end(); ++it)
{
ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData>* ref = it->get<ESM::Apparatus>();
if (ref->base->data.type == ESM::Apparatus::Albemic
&& (bestAlbemic.isEmpty() || ref->base->data.quality > bestAlbemic.get<ESM::Apparatus>()->base->data.quality))
bestAlbemic = *it;
else if (ref->base->data.type == ESM::Apparatus::MortarPestle
&& (bestMortarPestle.isEmpty() || ref->base->data.quality > bestMortarPestle.get<ESM::Apparatus>()->base->data.quality))
bestMortarPestle = *it;
else if (ref->base->data.type == ESM::Apparatus::Calcinator
&& (bestCalcinator.isEmpty() || ref->base->data.quality > bestCalcinator.get<ESM::Apparatus>()->base->data.quality))
bestCalcinator = *it;
else if (ref->base->data.type == ESM::Apparatus::Retort
&& (bestRetort.isEmpty() || ref->base->data.quality > bestRetort.get<ESM::Apparatus>()->base->data.quality))
bestRetort = *it;
}
if (!bestMortarPestle.isEmpty())
{
mApparatus1->setUserString("ToolTipType", "ItemPtr");
mApparatus1->setUserData(bestMortarPestle);
mApparatus1->setImageTexture(getIconPath(bestMortarPestle));
}
if (!bestAlbemic.isEmpty())
{
mApparatus2->setUserString("ToolTipType", "ItemPtr");
mApparatus2->setUserData(bestAlbemic);
mApparatus2->setImageTexture(getIconPath(bestAlbemic));
}
if (!bestCalcinator.isEmpty())
{
mApparatus3->setUserString("ToolTipType", "ItemPtr");
mApparatus3->setUserData(bestCalcinator);
mApparatus3->setImageTexture(getIconPath(bestCalcinator));
}
if (!bestRetort.isEmpty())
{
mApparatus4->setUserString("ToolTipType", "ItemPtr");
mApparatus4->setUserData(bestRetort);
mApparatus4->setImageTexture(getIconPath(bestRetort));
}
}
void AlchemyWindow::onIngredientSelected(MyGUI::Widget* _sender)
{
removeIngredient(_sender);
drawItems();
update();
}
void AlchemyWindow::onSelectedItemImpl(MWWorld::Ptr item)
{
MyGUI::ImageBox* add = NULL;
// don't allow to add an ingredient that is already added
// (which could happen if two similiar ingredients don't stack because of script / owner)
bool alreadyAdded = false;
std::string name = MWWorld::Class::get(item).getName(item);
if (mIngredient1->isUserString("ToolTipType"))
{
MWWorld::Ptr item2 = *mIngredient1->getUserData<MWWorld::Ptr>();
std::string name2 = MWWorld::Class::get(item2).getName(item2);
if (name == name2)
alreadyAdded = true;
}
if (mIngredient2->isUserString("ToolTipType"))
{
MWWorld::Ptr item2 = *mIngredient2->getUserData<MWWorld::Ptr>();
std::string name2 = MWWorld::Class::get(item2).getName(item2);
if (name == name2)
alreadyAdded = true;
}
if (mIngredient3->isUserString("ToolTipType"))
{
MWWorld::Ptr item2 = *mIngredient3->getUserData<MWWorld::Ptr>();
std::string name2 = MWWorld::Class::get(item2).getName(item2);
if (name == name2)
alreadyAdded = true;
}
if (mIngredient4->isUserString("ToolTipType"))
{
MWWorld::Ptr item2 = *mIngredient4->getUserData<MWWorld::Ptr>();
std::string name2 = MWWorld::Class::get(item2).getName(item2);
if (name == name2)
alreadyAdded = true;
}
if (alreadyAdded)
return;
if (!mIngredient1->isUserString("ToolTipType"))
add = mIngredient1;
if (add == NULL && !mIngredient2->isUserString("ToolTipType"))
add = mIngredient2;
if (add == NULL && !mIngredient3->isUserString("ToolTipType"))
add = mIngredient3;
if (add == NULL && !mIngredient4->isUserString("ToolTipType"))
add = mIngredient4;
if (add != NULL)
{
add->setUserString("ToolTipType", "ItemPtr");
add->setUserData(item);
add->setImageTexture(getIconPath(item));
drawItems();
update();
std::string sound = MWWorld::Class::get(item).getUpSoundId(item);
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
}
}
std::vector<MWWorld::Ptr> AlchemyWindow::itemsToIgnore()
{
std::vector<MWWorld::Ptr> ignore;
// don't show ingredients that are currently selected in the "available ingredients" box.
if (mIngredient1->isUserString("ToolTipType"))
ignore.push_back(*mIngredient1->getUserData<MWWorld::Ptr>());
if (mIngredient2->isUserString("ToolTipType"))
ignore.push_back(*mIngredient2->getUserData<MWWorld::Ptr>());
if (mIngredient3->isUserString("ToolTipType"))
ignore.push_back(*mIngredient3->getUserData<MWWorld::Ptr>());
if (mIngredient4->isUserString("ToolTipType"))
ignore.push_back(*mIngredient4->getUserData<MWWorld::Ptr>());
return ignore;
}
void AlchemyWindow::update()
{
Widgets::SpellEffectList effects;
for (int i=0; i<4; ++i)
{
MyGUI::ImageBox* ingredient;
if (i==0)
ingredient = mIngredient1;
else if (i==1)
ingredient = mIngredient2;
else if (i==2)
ingredient = mIngredient3;
else if (i==3)
ingredient = mIngredient4;
if (!ingredient->isUserString("ToolTipType"))
continue;
// add the effects of this ingredient to list of effects
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData>* ref = ingredient->getUserData<MWWorld::Ptr>()->get<ESM::Ingredient>();
for (int i=0; i<4; ++i)
{
if (ref->base->data.effectID[i] < 0)
continue;
MWGui::Widgets::SpellEffectParams params;
params.mEffectID = ref->base->data.effectID[i];
params.mAttribute = ref->base->data.attributes[i];
params.mSkill = ref->base->data.skills[i];
effects.push_back(params);
}
// update ingredient count labels
if (ingredient->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0));
MyGUI::TextBox* text = ingredient->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label"));
text->setTextAlign(MyGUI::Align::Right);
text->setNeedMouseFocus(false);
text->setTextShadow(true);
text->setTextShadowColour(MyGUI::Colour(0,0,0));
text->setCaption(getCountString(ingredient->getUserData<MWWorld::Ptr>()->getRefData().getCount()));
}
// now remove effects that are only present once
Widgets::SpellEffectList::iterator it = effects.begin();
while (it != effects.end())
{
Widgets::SpellEffectList::iterator next = it;
++next;
bool found = false;
for (; next != effects.end(); ++next)
{
if (*next == *it)
found = true;
}
if (!found)
it = effects.erase(it);
else
++it;
}
// now remove duplicates, and don't allow more than 4 effects
Widgets::SpellEffectList old = effects;
effects.clear();
int i=0;
for (Widgets::SpellEffectList::iterator it = old.begin();
it != old.end(); ++it)
{
bool found = false;
for (Widgets::SpellEffectList::iterator it2 = effects.begin();
it2 != effects.end(); ++it2)
{
// MW considers all "foritfy attribute" effects as the same effect. See the
// "Can't create multi-state boost potions" discussion on http://www.uesp.net/wiki/Morrowind_talk:Alchemy
// thus, we are only checking effectID here and not attribute or skill
if (it2->mEffectID == it->mEffectID)
found = true;
}
if (!found && i<4)
{
++i;
effects.push_back(*it);
}
}
mEffects = effects;
while (mEffectsBox->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mEffectsBox->getChildAt(0));
MyGUI::IntCoord coord(0, 0, mEffectsBox->getWidth(), 24);
Widgets::MWEffectListPtr effectsWidget = mEffectsBox->createWidget<Widgets::MWEffectList>
("MW_StatName", coord, Align::Left | Align::Top);
effectsWidget->setWindowManager(&mWindowManager);
effectsWidget->setEffectList(effects);
std::vector<MyGUI::WidgetPtr> effectItems;
effectsWidget->createEffectWidgets(effectItems, mEffectsBox, coord, false, 0);
effectsWidget->setCoord(coord);
}
void AlchemyWindow::removeIngredient(MyGUI::Widget* ingredient)
{
ingredient->clearUserStrings();
static_cast<MyGUI::ImageBox*>(ingredient)->setImageTexture("");
if (ingredient->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0));
}
}

@ -0,0 +1,51 @@
#ifndef MWGUI_ALCHEMY_H
#define MWGUI_ALCHEMY_H
#include "window_base.hpp"
#include "container.hpp"
namespace MWGui
{
class AlchemyWindow : public WindowBase, public ContainerBase
{
public:
AlchemyWindow(WindowManager& parWindowManager);
virtual void open();
protected:
MyGUI::Button* mCreateButton;
MyGUI::Button* mCancelButton;
MyGUI::ImageBox* mIngredient1;
MyGUI::ImageBox* mIngredient2;
MyGUI::ImageBox* mIngredient3;
MyGUI::ImageBox* mIngredient4;
MyGUI::ImageBox* mApparatus1;
MyGUI::ImageBox* mApparatus2;
MyGUI::ImageBox* mApparatus3;
MyGUI::ImageBox* mApparatus4;
MyGUI::Widget* mEffectsBox;
MyGUI::EditBox* mNameEdit;
Widgets::SpellEffectList mEffects; // effects of created potion
void onCancelButtonClicked(MyGUI::Widget* _sender);
void onCreateButtonClicked(MyGUI::Widget* _sender);
void onIngredientSelected(MyGUI::Widget* _sender);
virtual void onSelectedItemImpl(MWWorld::Ptr item);
virtual std::vector<MWWorld::Ptr> itemsToIgnore();
void removeIngredient(MyGUI::Widget* ingredient);
virtual void onReferenceUnavailable() { ; }
void update();
};
}
#endif

@ -1,13 +1,14 @@
#include "bookwindow.hpp" #include "bookwindow.hpp"
#include "formatting.hpp" #include <boost/lexical_cast.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwinput/inputmanager.hpp" #include "../mwinput/inputmanager.hpp"
#include "../mwsound/soundmanager.hpp" #include "../mwsound/soundmanager.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include <boost/lexical_cast.hpp> #include "formatting.hpp"
#include "window_manager.hpp"
using namespace MWGui; using namespace MWGui;
@ -91,7 +92,7 @@ void BookWindow::onCloseButtonClicked (MyGUI::Widget* _sender)
// no 3d sounds because the object could be in a container. // no 3d sounds because the object could be in a container.
MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0); MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0);
MWBase::Environment::get().getInputManager()->setGuiMode(MWGui::GM_Game); mWindowManager.popGuiMode();
} }
void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender) void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender)
@ -101,7 +102,7 @@ void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender)
MWWorld::ActionTake take(mBook); MWWorld::ActionTake take(mBook);
take.execute(); take.execute();
MWBase::Environment::get().getInputManager()->setGuiMode (GM_Game); mWindowManager.popGuiMode();
} }
void BookWindow::onNextPageButtonClicked (MyGUI::Widget* _sender) void BookWindow::onNextPageButtonClicked (MyGUI::Widget* _sender)

@ -110,7 +110,6 @@ using namespace MWGui;
CharacterCreation::CharacterCreation(WindowManager* _wm) CharacterCreation::CharacterCreation(WindowManager* _wm)
: mNameDialog(0) : mNameDialog(0)
, mRaceDialog(0) , mRaceDialog(0)
, mDialogueWindow(0)
, mClassChoiceDialog(0) , mClassChoiceDialog(0)
, mGenerateClassQuestionDialog(0) , mGenerateClassQuestionDialog(0)
, mGenerateClassResultDialog(0) , mGenerateClassResultDialog(0)
@ -118,11 +117,62 @@ CharacterCreation::CharacterCreation(WindowManager* _wm)
, mCreateClassDialog(0) , mCreateClassDialog(0)
, mBirthSignDialog(0) , mBirthSignDialog(0)
, mReviewDialog(0) , mReviewDialog(0)
, mGenerateClassStep(0)
, mWM(_wm) , mWM(_wm)
{ {
mCreationStage = CSE_NotStarted; mCreationStage = CSE_NotStarted;
} }
void CharacterCreation::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
{
if (mReviewDialog)
{
static const char *ids[] =
{
"AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5",
"AttribVal6", "AttribVal7", "AttribVal8",
0
};
for (int i=0; ids[i]; ++i)
{
if (ids[i]==id)
mReviewDialog->setAttribute(ESM::Attribute::AttributeID(i), value);
}
}
}
void CharacterCreation::setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value)
{
if (mReviewDialog)
{
if (id == "HBar")
{
mReviewDialog->setHealth (value);
}
else if (id == "MBar")
{
mReviewDialog->setMagicka (value);
}
else if (id == "FBar")
{
mReviewDialog->setFatigue (value);
}
}
}
void CharacterCreation::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value)
{
if (mReviewDialog)
mReviewDialog->setSkillValue(parSkill, value);
}
void CharacterCreation::configureSkills (const SkillList& major, const SkillList& minor)
{
if (mReviewDialog)
mReviewDialog->configureSkills(major, minor);
}
void CharacterCreation::spawnDialog(const char id) void CharacterCreation::spawnDialog(const char id)
{ {
switch (id) switch (id)
@ -209,20 +259,22 @@ void CharacterCreation::spawnDialog(const char id)
mReviewDialog->setFatigue(mPlayerFatigue); mReviewDialog->setFatigue(mPlayerFatigue);
{ {
std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> >::iterator end = mPlayerAttributes.end(); std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> > attributes = mWM->getPlayerAttributeValues();
for (std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> >::iterator it = mPlayerAttributes.begin(); it != end; ++it) for (std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> >::iterator it = attributes.begin();
it != attributes.end(); ++it)
{ {
mReviewDialog->setAttribute(it->first, it->second); mReviewDialog->setAttribute(it->first, it->second);
} }
} }
{ {
std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> >::iterator end = mPlayerSkillValues.end(); std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> > skills = mWM->getPlayerSkillValues();
for (std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> >::iterator it = mPlayerSkillValues.begin(); it != end; ++it) for (std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> >::iterator it = skills.begin();
it != skills.end(); ++it)
{ {
mReviewDialog->setSkillValue(it->first, it->second); mReviewDialog->setSkillValue(it->first, it->second);
} }
mReviewDialog->configureSkills(mPlayerMajorSkills, mPlayerMinorSkills); mReviewDialog->configureSkills(mWM->getPlayerMajorSkills(), mWM->getPlayerMinorSkills());
} }
mReviewDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogDone); mReviewDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogDone);
@ -253,7 +305,7 @@ void CharacterCreation::onReviewDialogDone(WindowBase* parWindow)
if (mReviewDialog) if (mReviewDialog)
mWM->removeDialog(mReviewDialog); mWM->removeDialog(mReviewDialog);
mWM->setGuiMode(GM_Game); mWM->popGuiMode();
} }
void CharacterCreation::onReviewDialogBack() void CharacterCreation::onReviewDialogBack()
@ -261,7 +313,7 @@ void CharacterCreation::onReviewDialogBack()
if (mReviewDialog) if (mReviewDialog)
mWM->removeDialog(mReviewDialog); mWM->removeDialog(mReviewDialog);
mWM->setGuiMode(GM_Birth); mWM->pushGuiMode(GM_Birth);
} }
void CharacterCreation::onReviewActivateDialog(int parDialog) void CharacterCreation::onReviewActivateDialog(int parDialog)
@ -270,19 +322,21 @@ void CharacterCreation::onReviewActivateDialog(int parDialog)
mWM->removeDialog(mReviewDialog); mWM->removeDialog(mReviewDialog);
mCreationStage = CSE_ReviewNext; mCreationStage = CSE_ReviewNext;
mWM->popGuiMode();
switch(parDialog) switch(parDialog)
{ {
case ReviewDialog::NAME_DIALOG: case ReviewDialog::NAME_DIALOG:
mWM->setGuiMode(GM_Name); mWM->pushGuiMode(GM_Name);
break; break;
case ReviewDialog::RACE_DIALOG: case ReviewDialog::RACE_DIALOG:
mWM->setGuiMode(GM_Race); mWM->pushGuiMode(GM_Race);
break; break;
case ReviewDialog::CLASS_DIALOG: case ReviewDialog::CLASS_DIALOG:
mWM->setGuiMode(GM_Class); mWM->pushGuiMode(GM_Class);
break; break;
case ReviewDialog::BIRTHSIGN_DIALOG: case ReviewDialog::BIRTHSIGN_DIALOG:
mWM->setGuiMode(GM_Birth); mWM->pushGuiMode(GM_Birth);
}; };
} }
@ -304,13 +358,19 @@ void CharacterCreation::onPickClassDialogDone(WindowBase* parWindow)
//TODO This bit gets repeated a few times; wrap it in a function //TODO This bit gets repeated a few times; wrap it in a function
if (mCreationStage == CSE_ReviewNext) if (mCreationStage == CSE_ReviewNext)
mWM->setGuiMode(GM_Review); {
mWM->popGuiMode();
mWM->pushGuiMode(GM_Review);
}
else if (mCreationStage >= CSE_ClassChosen) else if (mCreationStage >= CSE_ClassChosen)
mWM->setGuiMode(GM_Birth); {
mWM->popGuiMode();
mWM->pushGuiMode(GM_Birth);
}
else else
{ {
mCreationStage = CSE_ClassChosen; mCreationStage = CSE_ClassChosen;
mWM->setGuiMode(GM_Game); mWM->popGuiMode();
} }
} }
@ -324,7 +384,8 @@ void CharacterCreation::onPickClassDialogBack()
mWM->removeDialog(mPickClassDialog); mWM->removeDialog(mPickClassDialog);
} }
mWM->setGuiMode(GM_Class); mWM->popGuiMode();
mWM->pushGuiMode(GM_Class);
} }
void CharacterCreation::onClassChoice(int _index) void CharacterCreation::onClassChoice(int _index)
@ -334,19 +395,21 @@ void CharacterCreation::onClassChoice(int _index)
mWM->removeDialog(mClassChoiceDialog); mWM->removeDialog(mClassChoiceDialog);
} }
mWM->popGuiMode();
switch(_index) switch(_index)
{ {
case ClassChoiceDialog::Class_Generate: case ClassChoiceDialog::Class_Generate:
mWM->setGuiMode(GM_ClassGenerate); mWM->pushGuiMode(GM_ClassGenerate);
break; break;
case ClassChoiceDialog::Class_Pick: case ClassChoiceDialog::Class_Pick:
mWM->setGuiMode(GM_ClassPick); mWM->pushGuiMode(GM_ClassPick);
break; break;
case ClassChoiceDialog::Class_Create: case ClassChoiceDialog::Class_Create:
mWM->setGuiMode(GM_ClassCreate); mWM->pushGuiMode(GM_ClassCreate);
break; break;
case ClassChoiceDialog::Class_Back: case ClassChoiceDialog::Class_Back:
mWM->setGuiMode(GM_Race); mWM->pushGuiMode(GM_Race);
break; break;
}; };
@ -363,13 +426,19 @@ void CharacterCreation::onNameDialogDone(WindowBase* parWindow)
} }
if (mCreationStage == CSE_ReviewNext) if (mCreationStage == CSE_ReviewNext)
mWM->setGuiMode(GM_Review); {
mWM->popGuiMode();
mWM->pushGuiMode(GM_Review);
}
else if (mCreationStage >= CSE_NameChosen) else if (mCreationStage >= CSE_NameChosen)
mWM->setGuiMode(GM_Race); {
mWM->popGuiMode();
mWM->pushGuiMode(GM_Race);
}
else else
{ {
mCreationStage = CSE_NameChosen; mCreationStage = CSE_NameChosen;
mWM->setGuiMode(GM_Game); mWM->popGuiMode();
} }
} }
@ -383,7 +452,8 @@ void CharacterCreation::onRaceDialogBack()
mWM->removeDialog(mRaceDialog); mWM->removeDialog(mRaceDialog);
} }
mWM->setGuiMode(GM_Name); mWM->popGuiMode();
mWM->pushGuiMode(GM_Name);
} }
void CharacterCreation::onRaceDialogDone(WindowBase* parWindow) void CharacterCreation::onRaceDialogDone(WindowBase* parWindow)
@ -398,13 +468,19 @@ void CharacterCreation::onRaceDialogDone(WindowBase* parWindow)
} }
if (mCreationStage == CSE_ReviewNext) if (mCreationStage == CSE_ReviewNext)
mWM->setGuiMode(GM_Review); {
else if(mCreationStage >= CSE_RaceChosen) mWM->popGuiMode();
mWM->setGuiMode(GM_Class); mWM->pushGuiMode(GM_Review);
}
else if (mCreationStage >= CSE_RaceChosen)
{
mWM->popGuiMode();
mWM->pushGuiMode(GM_Class);
}
else else
{ {
mCreationStage = CSE_RaceChosen; mCreationStage = CSE_RaceChosen;
mWM->setGuiMode(GM_Game); mWM->popGuiMode();
} }
} }
@ -419,11 +495,14 @@ void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow)
} }
if (mCreationStage >= CSE_BirthSignChosen) if (mCreationStage >= CSE_BirthSignChosen)
mWM->setGuiMode(GM_Review); {
mWM->popGuiMode();
mWM->pushGuiMode(GM_Review);
}
else else
{ {
mCreationStage = CSE_BirthSignChosen; mCreationStage = CSE_BirthSignChosen;
mWM->setGuiMode(GM_Game); mWM->popGuiMode();
} }
} }
@ -435,7 +514,8 @@ void CharacterCreation::onBirthSignDialogBack()
mWM->removeDialog(mBirthSignDialog); mWM->removeDialog(mBirthSignDialog);
} }
mWM->setGuiMode(GM_Class); mWM->popGuiMode();
mWM->pushGuiMode(GM_Class);
} }
void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow) void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow)
@ -470,13 +550,19 @@ void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow)
} }
if (mCreationStage == CSE_ReviewNext) if (mCreationStage == CSE_ReviewNext)
mWM->setGuiMode(GM_Review); {
mWM->popGuiMode();
mWM->pushGuiMode(GM_Review);
}
else if (mCreationStage >= CSE_ClassChosen) else if (mCreationStage >= CSE_ClassChosen)
mWM->setGuiMode(GM_Birth); {
mWM->popGuiMode();
mWM->pushGuiMode(GM_Birth);
}
else else
{ {
mCreationStage = CSE_ClassChosen; mCreationStage = CSE_ClassChosen;
mWM->setGuiMode(GM_Game); mWM->popGuiMode();
} }
} }
@ -485,7 +571,8 @@ void CharacterCreation::onCreateClassDialogBack()
if (mCreateClassDialog) if (mCreateClassDialog)
mWM->removeDialog(mCreateClassDialog); mWM->removeDialog(mCreateClassDialog);
mWM->setGuiMode(GM_Class); mWM->popGuiMode();
mWM->pushGuiMode(GM_Class);
} }
void CharacterCreation::onClassQuestionChosen(int _index) void CharacterCreation::onClassQuestionChosen(int _index)
@ -496,7 +583,8 @@ void CharacterCreation::onClassQuestionChosen(int _index)
mWM->removeDialog(mGenerateClassQuestionDialog); mWM->removeDialog(mGenerateClassQuestionDialog);
if (_index < 0 || _index >= 3) if (_index < 0 || _index >= 3)
{ {
mWM->setGuiMode(GM_Class); mWM->popGuiMode();
mWM->pushGuiMode(GM_Class);
return; return;
} }
@ -581,7 +669,8 @@ void CharacterCreation::showClassQuestionDialog()
if (mGenerateClassStep > sGenerateClassSteps.size()) if (mGenerateClassStep > sGenerateClassSteps.size())
{ {
mWM->setGuiMode(GM_Class); mWM->popGuiMode();
mWM->pushGuiMode(GM_Class);
return; return;
} }
@ -610,7 +699,8 @@ void CharacterCreation::onGenerateClassBack()
mWM->removeDialog(mGenerateClassResultDialog); mWM->removeDialog(mGenerateClassResultDialog);
MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass); MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass);
mWM->setGuiMode(GM_Class); mWM->popGuiMode();
mWM->pushGuiMode(GM_Class);
} }
void CharacterCreation::onGenerateClassDone(WindowBase* parWindow) void CharacterCreation::onGenerateClassDone(WindowBase* parWindow)
@ -620,13 +710,19 @@ void CharacterCreation::onGenerateClassDone(WindowBase* parWindow)
MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass); MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass);
if (mCreationStage == CSE_ReviewNext) if (mCreationStage == CSE_ReviewNext)
mWM->setGuiMode(GM_Review); {
mWM->popGuiMode();
mWM->pushGuiMode(GM_Review);
}
else if (mCreationStage >= CSE_ClassChosen) else if (mCreationStage >= CSE_ClassChosen)
mWM->setGuiMode(GM_Birth); {
mWM->popGuiMode();
mWM->pushGuiMode(GM_Birth);
}
else else
{ {
mCreationStage = CSE_ClassChosen; mCreationStage = CSE_ClassChosen;
mWM->setGuiMode(GM_Game); mWM->popGuiMode();
} }
} }
@ -634,7 +730,6 @@ CharacterCreation::~CharacterCreation()
{ {
delete mNameDialog; delete mNameDialog;
delete mRaceDialog; delete mRaceDialog;
delete mDialogueWindow;
delete mClassChoiceDialog; delete mClassChoiceDialog;
delete mGenerateClassQuestionDialog; delete mGenerateClassQuestionDialog;
delete mGenerateClassResultDialog; delete mGenerateClassResultDialog;

@ -42,11 +42,15 @@ namespace MWGui
void setPlayerFatigue (const MWMechanics::DynamicStat<int>& value); void setPlayerFatigue (const MWMechanics::DynamicStat<int>& value);
void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value);
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);
void configureSkills (const SkillList& major, const SkillList& minor);
private: private:
//Dialogs //Dialogs
TextInputDialog* mNameDialog; TextInputDialog* mNameDialog;
RaceDialog* mRaceDialog; RaceDialog* mRaceDialog;
DialogueWindow* mDialogueWindow;
ClassChoiceDialog* mClassChoiceDialog; ClassChoiceDialog* mClassChoiceDialog;
InfoBoxDialog* mGenerateClassQuestionDialog; InfoBoxDialog* mGenerateClassQuestionDialog;
GenerateClassResultDialog* mGenerateClassResultDialog; GenerateClassResultDialog* mGenerateClassResultDialog;
@ -62,9 +66,6 @@ namespace MWGui
std::string mPlayerRaceId; std::string mPlayerRaceId;
std::string mPlayerBirthSignId; std::string mPlayerBirthSignId;
ESM::Class mPlayerClass; ESM::Class mPlayerClass;
std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> > mPlayerAttributes;
SkillList mPlayerMajorSkills, mPlayerMinorSkills;
std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> > mPlayerSkillValues;
MWMechanics::DynamicStat<int> mPlayerHealth; MWMechanics::DynamicStat<int> mPlayerHealth;
MWMechanics::DynamicStat<int> mPlayerMagicka; MWMechanics::DynamicStat<int> mPlayerMagicka;
MWMechanics::DynamicStat<int> mPlayerFatigue; MWMechanics::DynamicStat<int> mPlayerFatigue;

@ -1,6 +1,4 @@
#include "class.hpp" #include "class.hpp"
#include "window_manager.hpp"
#include "components/esm_store/store.hpp"
#include <assert.h> #include <assert.h>
#include <iterator> #include <iterator>
@ -8,6 +6,11 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <components/esm_store/store.hpp>
#include "window_manager.hpp"
#include "tooltips.hpp"
#undef min #undef min
#undef max #undef max
@ -79,17 +82,13 @@ PickClassDialog::PickClassDialog(WindowManager& parWindowManager)
// Centre dialog // Centre dialog
center(); center();
setText("SpecializationT", mWindowManager.getGameSettingString("sChooseClassMenu1", "Specialization"));
getWidget(specializationName, "SpecializationName"); getWidget(specializationName, "SpecializationName");
setText("FavoriteAttributesT", mWindowManager.getGameSettingString("sChooseClassMenu2", "Favorite Attributes:"));
getWidget(favoriteAttribute[0], "FavoriteAttribute0"); getWidget(favoriteAttribute[0], "FavoriteAttribute0");
getWidget(favoriteAttribute[1], "FavoriteAttribute1"); getWidget(favoriteAttribute[1], "FavoriteAttribute1");
favoriteAttribute[0]->setWindowManager(&mWindowManager); favoriteAttribute[0]->setWindowManager(&mWindowManager);
favoriteAttribute[1]->setWindowManager(&mWindowManager); favoriteAttribute[1]->setWindowManager(&mWindowManager);
setText("MajorSkillT", mWindowManager.getGameSettingString("sChooseClassMenu3", "Major Skills:"));
setText("MinorSkillT", mWindowManager.getGameSettingString("sChooseClassMenu4", "Minor Skills:"));
for(int i = 0; i < 5; i++) for(int i = 0; i < 5; i++)
{ {
char theIndex = '0'+i; char theIndex = '0'+i;
@ -231,15 +230,21 @@ void PickClassDialog::updateStats()
"sSpecializationMagic", "sSpecializationMagic",
"sSpecializationStealth" "sSpecializationStealth"
}; };
specializationName->setCaption(mWindowManager.getGameSettingString(specIds[specialization], specIds[specialization])); std::string specName = mWindowManager.getGameSettingString(specIds[specialization], specIds[specialization]);
specializationName->setCaption(specName);
ToolTips::createSpecializationToolTip(specializationName, specName, specialization);
favoriteAttribute[0]->setAttributeId(klass->data.attribute[0]); favoriteAttribute[0]->setAttributeId(klass->data.attribute[0]);
favoriteAttribute[1]->setAttributeId(klass->data.attribute[1]); favoriteAttribute[1]->setAttributeId(klass->data.attribute[1]);
ToolTips::createAttributeToolTip(favoriteAttribute[0], favoriteAttribute[0]->getAttributeId());
ToolTips::createAttributeToolTip(favoriteAttribute[1], favoriteAttribute[1]->getAttributeId());
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
{ {
majorSkill[i]->setSkillNumber(klass->data.skills[i][0]); minorSkill[i]->setSkillNumber(klass->data.skills[i][0]);
minorSkill[i]->setSkillNumber(klass->data.skills[i][1]); majorSkill[i]->setSkillNumber(klass->data.skills[i][1]);
ToolTips::createSkillToolTip(minorSkill[i], klass->data.skills[i][0]);
ToolTips::createSkillToolTip(majorSkill[i], klass->data.skills[i][1]);
} }
classImage->setImageTexture(std::string("textures\\levelup\\") + currentClassId + ".dds"); classImage->setImageTexture(std::string("textures\\levelup\\") + currentClassId + ".dds");
@ -387,7 +392,6 @@ CreateClassDialog::CreateClassDialog(WindowManager& parWindowManager)
setText("SpecializationT", mWindowManager.getGameSettingString("sChooseClassMenu1", "Specialization")); setText("SpecializationT", mWindowManager.getGameSettingString("sChooseClassMenu1", "Specialization"));
getWidget(specializationName, "SpecializationName"); getWidget(specializationName, "SpecializationName");
specializationName->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], ""));
specializationName->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onSpecializationClicked); specializationName->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onSpecializationClicked);
setText("FavoriteAttributesT", mWindowManager.getGameSettingString("sChooseClassMenu2", "Favorite Attributes:")); setText("FavoriteAttributesT", mWindowManager.getGameSettingString("sChooseClassMenu2", "Favorite Attributes:"));
@ -451,6 +455,9 @@ CreateClassDialog::CreateClassDialog(WindowManager& parWindowManager)
minorSkill[2]->setSkillId(ESM::Skill::Spear); minorSkill[2]->setSkillId(ESM::Skill::Spear);
minorSkill[3]->setSkillId(ESM::Skill::Athletics); minorSkill[3]->setSkillId(ESM::Skill::Athletics);
minorSkill[4]->setSkillId(ESM::Skill::Enchant); minorSkill[4]->setSkillId(ESM::Skill::Enchant);
setSpecialization(0);
update();
} }
CreateClassDialog::~CreateClassDialog() CreateClassDialog::~CreateClassDialog()
@ -461,6 +468,18 @@ CreateClassDialog::~CreateClassDialog()
delete descDialog; delete descDialog;
} }
void CreateClassDialog::update()
{
for (int i = 0; i < 5; ++i)
{
ToolTips::createSkillToolTip(majorSkill[i], majorSkill[i]->getSkillId());
ToolTips::createSkillToolTip(minorSkill[i], minorSkill[i]->getSkillId());
}
ToolTips::createAttributeToolTip(favoriteAttribute0, favoriteAttribute0->getAttributeId());
ToolTips::createAttributeToolTip(favoriteAttribute1, favoriteAttribute1->getAttributeId());
}
std::string CreateClassDialog::getName() const std::string CreateClassDialog::getName() const
{ {
return editName->getOnlyText(); return editName->getOnlyText();
@ -499,7 +518,7 @@ std::vector<ESM::Skill::SkillEnum> CreateClassDialog::getMinorSkills() const
std::vector<ESM::Skill::SkillEnum> v; std::vector<ESM::Skill::SkillEnum> v;
for(int i=0; i < 5; i++) for(int i=0; i < 5; i++)
{ {
v.push_back(majorSkill[i]->getSkillId()); v.push_back(minorSkill[i]->getSkillId());
} }
return v; return v;
} }
@ -539,19 +558,29 @@ void CreateClassDialog::open()
void CreateClassDialog::onDialogCancel() void CreateClassDialog::onDialogCancel()
{ {
if (specDialog) if (specDialog)
specDialog->setVisible(false); {
mWindowManager.removeDialog(specDialog);
specDialog = 0;
}
if (attribDialog) if (attribDialog)
attribDialog->setVisible(false); {
mWindowManager.removeDialog(attribDialog);
attribDialog = 0;
}
if (skillDialog) if (skillDialog)
skillDialog->setVisible(false); {
mWindowManager.removeDialog(skillDialog);
skillDialog = 0;
}
if (descDialog) if (descDialog)
descDialog->setVisible(false); {
// TODO: Delete dialogs here mWindowManager.removeDialog(descDialog);
descDialog = 0;
}
} }
void CreateClassDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender) void CreateClassDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender)
{ {
if (specDialog)
delete specDialog; delete specDialog;
specDialog = new SelectSpecializationDialog(mWindowManager); specDialog = new SelectSpecializationDialog(mWindowManager);
specDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel); specDialog->eventCancel += MyGUI::newDelegate(this, &CreateClassDialog::onDialogCancel);
@ -562,13 +591,27 @@ void CreateClassDialog::onSpecializationClicked(MyGUI::WidgetPtr _sender)
void CreateClassDialog::onSpecializationSelected() void CreateClassDialog::onSpecializationSelected()
{ {
specializationId = specDialog->getSpecializationId(); specializationId = specDialog->getSpecializationId();
specializationName->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[specializationId], "")); setSpecialization(specializationId);
specDialog->setVisible(false);
mWindowManager.removeDialog(specDialog);
specDialog = 0;
}
void CreateClassDialog::setSpecialization(int id)
{
specializationId = (ESM::Class::Specialization) id;
static const char *specIds[3] = {
"sSpecializationCombat",
"sSpecializationMagic",
"sSpecializationStealth"
};
std::string specName = mWindowManager.getGameSettingString(specIds[specializationId], specIds[specializationId]);
specializationName->setCaption(specName);
ToolTips::createSpecializationToolTip(specializationName, specName, specializationId);
} }
void CreateClassDialog::onAttributeClicked(Widgets::MWAttributePtr _sender) void CreateClassDialog::onAttributeClicked(Widgets::MWAttributePtr _sender)
{ {
if (attribDialog)
delete attribDialog; delete attribDialog;
attribDialog = new SelectAttributeDialog(mWindowManager); attribDialog = new SelectAttributeDialog(mWindowManager);
attribDialog->setAffectedWidget(_sender); attribDialog->setAffectedWidget(_sender);
@ -592,12 +635,14 @@ void CreateClassDialog::onAttributeSelected()
favoriteAttribute0->setAttributeId(favoriteAttribute1->getAttributeId()); favoriteAttribute0->setAttributeId(favoriteAttribute1->getAttributeId());
} }
attribute->setAttributeId(id); attribute->setAttributeId(id);
attribDialog->setVisible(false); mWindowManager.removeDialog(attribDialog);
attribDialog = 0;
update();
} }
void CreateClassDialog::onSkillClicked(Widgets::MWSkillPtr _sender) void CreateClassDialog::onSkillClicked(Widgets::MWSkillPtr _sender)
{ {
if (skillDialog)
delete skillDialog; delete skillDialog;
skillDialog = new SelectSkillDialog(mWindowManager); skillDialog = new SelectSkillDialog(mWindowManager);
skillDialog->setAffectedWidget(_sender); skillDialog->setAffectedWidget(_sender);
@ -625,7 +670,9 @@ void CreateClassDialog::onSkillSelected()
} }
skill->setSkillId(skillDialog->getSkillId()); skill->setSkillId(skillDialog->getSkillId());
skillDialog->setVisible(false); mWindowManager.removeDialog(skillDialog);
skillDialog = 0;
update();
} }
void CreateClassDialog::onDescriptionClicked(MyGUI::Widget* _sender) void CreateClassDialog::onDescriptionClicked(MyGUI::Widget* _sender)
@ -640,6 +687,7 @@ void CreateClassDialog::onDescriptionEntered(WindowBase* parWindow)
{ {
description = descDialog->getTextInput(); description = descDialog->getTextInput();
mWindowManager.removeDialog(descDialog); mWindowManager.removeDialog(descDialog);
descDialog = 0;
} }
void CreateClassDialog::onOkClicked(MyGUI::Widget* _sender) void CreateClassDialog::onOkClicked(MyGUI::Widget* _sender)
@ -665,20 +713,35 @@ SelectSpecializationDialog::SelectSpecializationDialog(WindowManager& parWindowM
getWidget(specialization0, "Specialization0"); getWidget(specialization0, "Specialization0");
getWidget(specialization1, "Specialization1"); getWidget(specialization1, "Specialization1");
getWidget(specialization2, "Specialization2"); getWidget(specialization2, "Specialization2");
specialization0->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], "")); std::string combat = mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Combat], "");
std::string magic = mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Magic], "");
std::string stealth = mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Stealth], "");
specialization0->setCaption(combat);
specialization0->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); specialization0->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked);
specialization1->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Magic], "")); specialization1->setCaption(magic);
specialization1->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); specialization1->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked);
specialization2->setCaption(mWindowManager.getGameSettingString(ESM::Class::gmstSpecializationIds[ESM::Class::Stealth], "")); specialization2->setCaption(stealth);
specialization2->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked); specialization2->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onSpecializationClicked);
specializationId = ESM::Class::Combat; specializationId = ESM::Class::Combat;
ToolTips::createSpecializationToolTip(specialization0, combat, ESM::Class::Combat);
ToolTips::createSpecializationToolTip(specialization1, magic, ESM::Class::Magic);
ToolTips::createSpecializationToolTip(specialization2, stealth, ESM::Class::Stealth);
MyGUI::ButtonPtr cancelButton; MyGUI::ButtonPtr cancelButton;
getWidget(cancelButton, "CancelButton"); getWidget(cancelButton, "CancelButton");
cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", "")); cancelButton->setCaption(mWindowManager.getGameSettingString("sCancel", ""));
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked);
int buttonWidth = cancelButton->getTextSize().width + 24; int buttonWidth = cancelButton->getTextSize().width + 24;
cancelButton->setCoord(216 - buttonWidth, 90, buttonWidth, 21); cancelButton->setCoord(216 - buttonWidth, 90, buttonWidth, 21);
MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget);
}
SelectSpecializationDialog::~SelectSpecializationDialog()
{
MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget);
} }
// widget controls // widget controls
@ -721,6 +784,7 @@ SelectAttributeDialog::SelectAttributeDialog(WindowManager& parWindowManager)
attribute->setWindowManager(&parWindowManager); attribute->setWindowManager(&parWindowManager);
attribute->setAttributeId(ESM::Attribute::attributeIds[i]); attribute->setAttributeId(ESM::Attribute::attributeIds[i]);
attribute->eventClicked += MyGUI::newDelegate(this, &SelectAttributeDialog::onAttributeClicked); attribute->eventClicked += MyGUI::newDelegate(this, &SelectAttributeDialog::onAttributeClicked);
ToolTips::createAttributeToolTip(attribute, attribute->getAttributeId());
} }
MyGUI::ButtonPtr cancelButton; MyGUI::ButtonPtr cancelButton;
@ -729,6 +793,13 @@ SelectAttributeDialog::SelectAttributeDialog(WindowManager& parWindowManager)
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked);
int buttonWidth = cancelButton->getTextSize().width + 24; int buttonWidth = cancelButton->getTextSize().width + 24;
cancelButton->setCoord(186 - buttonWidth, 180, buttonWidth, 21); cancelButton->setCoord(186 - buttonWidth, 180, buttonWidth, 21);
MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget);
}
SelectAttributeDialog::~SelectAttributeDialog()
{
MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget);
} }
// widget controls // widget controls
@ -810,6 +881,7 @@ SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager)
skills[spec][i].widget->setWindowManager(&mWindowManager); skills[spec][i].widget->setWindowManager(&mWindowManager);
skills[spec][i].widget->setSkillId(skills[spec][i].skillId); skills[spec][i].widget->setSkillId(skills[spec][i].skillId);
skills[spec][i].widget->eventClicked += MyGUI::newDelegate(this, &SelectSkillDialog::onSkillClicked); skills[spec][i].widget->eventClicked += MyGUI::newDelegate(this, &SelectSkillDialog::onSkillClicked);
ToolTips::createSkillToolTip(skills[spec][i].widget, skills[spec][i].widget->getSkillId());
} }
} }
@ -819,6 +891,13 @@ SelectSkillDialog::SelectSkillDialog(WindowManager& parWindowManager)
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked); cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked);
int buttonWidth = cancelButton->getTextSize().width + 24; int buttonWidth = cancelButton->getTextSize().width + 24;
cancelButton->setCoord(447 - buttonWidth, 218, buttonWidth, 21); cancelButton->setCoord(447 - buttonWidth, 218, buttonWidth, 21);
MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget);
}
SelectSkillDialog::~SelectSkillDialog()
{
MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget);
} }
// widget controls // widget controls
@ -853,6 +932,13 @@ DescriptionDialog::DescriptionDialog(WindowManager& parWindowManager)
// Make sure the edit box has focus // Make sure the edit box has focus
MyGUI::InputManager::getInstance().setKeyFocusWidget(textEdit); MyGUI::InputManager::getInstance().setKeyFocusWidget(textEdit);
MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget);
}
DescriptionDialog::~DescriptionDialog()
{
MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget);
} }
// widget controls // widget controls

@ -139,6 +139,7 @@ namespace MWGui
{ {
public: public:
SelectSpecializationDialog(WindowManager& parWindowManager); SelectSpecializationDialog(WindowManager& parWindowManager);
~SelectSpecializationDialog();
ESM::Class::Specialization getSpecializationId() const { return specializationId; } ESM::Class::Specialization getSpecializationId() const { return specializationId; }
@ -169,6 +170,7 @@ namespace MWGui
{ {
public: public:
SelectAttributeDialog(WindowManager& parWindowManager); SelectAttributeDialog(WindowManager& parWindowManager);
~SelectAttributeDialog();
ESM::Attribute::AttributeID getAttributeId() const { return attributeId; } ESM::Attribute::AttributeID getAttributeId() const { return attributeId; }
Widgets::MWAttributePtr getAffectedWidget() const { return affectedWidget; } Widgets::MWAttributePtr getAffectedWidget() const { return affectedWidget; }
@ -201,6 +203,7 @@ namespace MWGui
{ {
public: public:
SelectSkillDialog(WindowManager& parWindowManager); SelectSkillDialog(WindowManager& parWindowManager);
~SelectSkillDialog();
ESM::Skill::SkillEnum getSkillId() const { return skillId; } ESM::Skill::SkillEnum getSkillId() const { return skillId; }
Widgets::MWSkillPtr getAffectedWidget() const { return affectedWidget; } Widgets::MWSkillPtr getAffectedWidget() const { return affectedWidget; }
@ -236,6 +239,7 @@ namespace MWGui
{ {
public: public:
DescriptionDialog(WindowManager& parWindowManager); DescriptionDialog(WindowManager& parWindowManager);
~DescriptionDialog();
std::string getTextInput() const { return textEdit ? textEdit->getOnlyText() : ""; } std::string getTextInput() const { return textEdit ? textEdit->getOnlyText() : ""; }
void setTextInput(const std::string &text) { if (textEdit) textEdit->setOnlyText(text); } void setTextInput(const std::string &text) { if (textEdit) textEdit->setOnlyText(text); }
@ -285,6 +289,10 @@ namespace MWGui
void onDescriptionEntered(WindowBase* parWindow); void onDescriptionEntered(WindowBase* parWindow);
void onDialogCancel(); void onDialogCancel();
void setSpecialization(int id);
void update();
private: private:
MyGUI::EditPtr editName; MyGUI::EditPtr editName;
MyGUI::TextBox* specializationName; MyGUI::TextBox* specializationName;

@ -0,0 +1,70 @@
#include "confirmationdialog.hpp"
#include <boost/lexical_cast.hpp>
#include "../mwbase/environment.hpp"
#include "../mwworld/world.hpp"
namespace MWGui
{
ConfirmationDialog::ConfirmationDialog(WindowManager& parWindowManager) :
WindowBase("openmw_confirmation_dialog_layout.xml", parWindowManager)
{
getWidget(mMessage, "Message");
getWidget(mOkButton, "OkButton");
getWidget(mCancelButton, "CancelButton");
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ConfirmationDialog::onCancelButtonClicked);
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ConfirmationDialog::onOkButtonClicked);
}
void ConfirmationDialog::open(const std::string& message)
{
setVisible(true);
mMessage->setCaptionWithReplacing(message);
int height = mMessage->getTextSize().height + 72;
mMainWidget->setSize(mMainWidget->getWidth(), height);
mMessage->setSize(mMessage->getWidth(), mMessage->getTextSize().height+24);
center();
// make other gui elements inaccessible while this dialog is open
MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget);
int okButtonWidth = mOkButton->getTextSize().width + 24;
mOkButton->setCoord(mMainWidget->getWidth() - 30 - okButtonWidth,
mOkButton->getTop(),
okButtonWidth,
mOkButton->getHeight());
int cancelButtonWidth = mCancelButton->getTextSize().width + 24;
mCancelButton->setCoord(mMainWidget->getWidth() - 30 - okButtonWidth - cancelButtonWidth - 8,
mCancelButton->getTop(),
cancelButtonWidth,
mCancelButton->getHeight());
}
void ConfirmationDialog::onCancelButtonClicked(MyGUI::Widget* _sender)
{
eventCancelClicked();
close();
}
void ConfirmationDialog::onOkButtonClicked(MyGUI::Widget* _sender)
{
eventOkClicked();
close();
}
void ConfirmationDialog::close()
{
setVisible(false);
MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget);
}
}

@ -0,0 +1,35 @@
#ifndef MWGUI_CONFIRMATIONDIALOG_H
#define MWGUI_CONFIRMATIONDIALOG_H
#include "window_base.hpp"
namespace MWGui
{
class ConfirmationDialog : public WindowBase
{
public:
ConfirmationDialog(WindowManager& parWindowManager);
void open(const std::string& message);
typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void;
/** Event : Ok button was clicked.\n
signature : void method()\n
*/
EventHandle_Void eventOkClicked;
EventHandle_Void eventCancelClicked;
private:
MyGUI::EditBox* mMessage;
MyGUI::Button* mOkButton;
MyGUI::Button* mCancelButton;
void onCancelButtonClicked(MyGUI::Widget* _sender);
void onOkButtonClicked(MyGUI::Widget* _sender);
void close();
};
}
#endif

@ -138,6 +138,7 @@ namespace MWGui
void Console::disable() void Console::disable()
{ {
setVisible(false); setVisible(false);
setSelectedObject(MWWorld::Ptr());
// Remove keyboard focus from the console input whenever the // Remove keyboard focus from the console input whenever the
// console is turned off // console is turned off
MyGUI::InputManager::getInstance().setKeyFocusWidget(NULL); MyGUI::InputManager::getInstance().setKeyFocusWidget(NULL);
@ -240,7 +241,7 @@ namespace MWGui
{ {
try try
{ {
ConsoleInterpreterContext interpreterContext (*this, MWWorld::Ptr()); ConsoleInterpreterContext interpreterContext (*this, mPtr);
Interpreter::Interpreter interpreter; Interpreter::Interpreter interpreter;
MWScript::installOpcodes (interpreter); MWScript::installOpcodes (interpreter);
std::vector<Interpreter::Type_Code> code; std::vector<Interpreter::Type_Code> code;
@ -267,7 +268,7 @@ namespace MWGui
/* Are there quotation marks? */ /* Are there quotation marks? */
if( tmp.find('"') != string::npos ) { if( tmp.find('"') != string::npos ) {
int numquotes=0; int numquotes=0;
for(string::iterator it=tmp.begin(); it < tmp.end(); it++) { for(string::iterator it=tmp.begin(); it < tmp.end(); ++it) {
if( *it == '"' ) if( *it == '"' )
numquotes++; numquotes++;
} }
@ -310,7 +311,7 @@ namespace MWGui
} }
/* Iterate through the vector. */ /* Iterate through the vector. */
for(vector<string>::iterator it=mNames.begin(); it < mNames.end();it++) { for(vector<string>::iterator it=mNames.begin(); it < mNames.end();++it) {
bool string_different=false; bool string_different=false;
/* Is the string shorter than the input string? If yes skip it. */ /* Is the string shorter than the input string? If yes skip it. */
@ -358,7 +359,7 @@ namespace MWGui
int i = tmp.length(); int i = tmp.length();
for(string::iterator iter=matches.front().begin()+tmp.length(); iter < matches.front().end(); iter++, i++) { for(string::iterator iter=matches.front().begin()+tmp.length(); iter < matches.front().end(); iter++, i++) {
for(vector<string>::iterator it=matches.begin(); it < matches.end();it++) { for(vector<string>::iterator it=matches.begin(); it < matches.end();++it) {
if( tolower((*it)[i]) != tolower(*iter) ) { if( tolower((*it)[i]) != tolower(*iter) ) {
/* Append the longest match to the end of the output string*/ /* Append the longest match to the end of the output string*/
output.append(matches.front().substr( 0, i)); output.append(matches.front().substr( 0, i));
@ -370,4 +371,24 @@ namespace MWGui
/* All keywords match with the shortest. Append it to the output string and return it. */ /* All keywords match with the shortest. Append it to the output string and return it. */
return output.append(matches.front()); return output.append(matches.front());
} }
void Console::onResChange(int width, int height)
{
setCoord(10,10, width-10, height/2);
}
void Console::setSelectedObject(const MWWorld::Ptr& object)
{
mPtr = object;
if (!mPtr.isEmpty())
setTitle("#{sConsoleTitle} (" + mPtr.getCellRef().refID + ")");
else
setTitle("#{sConsoleTitle}");
MyGUI::InputManager::getInstance().setKeyFocusWidget(command);
}
void Console::onReferenceUnavailable()
{
setSelectedObject(MWWorld::Ptr());
}
} }

@ -16,9 +16,11 @@
#include "../mwscript/compilercontext.hpp" #include "../mwscript/compilercontext.hpp"
#include "../mwscript/interpretercontext.hpp" #include "../mwscript/interpretercontext.hpp"
#include "referenceinterface.hpp"
namespace MWGui namespace MWGui
{ {
class Console : private OEngine::GUI::Layout, private Compiler::ErrorHandler class Console : private OEngine::GUI::Layout, private Compiler::ErrorHandler, public ReferenceInterface
{ {
private: private:
@ -39,6 +41,16 @@ namespace MWGui
/// \note The list may contain duplicates (if a name is a keyword and an identifier at the same /// \note The list may contain duplicates (if a name is a keyword and an identifier at the same
/// time). /// time).
public:
void setSelectedObject(const MWWorld::Ptr& object);
///< Set the implicit object for script execution
protected:
virtual void onReferenceUnavailable();
public: public:
MyGUI::EditPtr command; MyGUI::EditPtr command;
MyGUI::EditPtr history; MyGUI::EditPtr history;
@ -58,6 +70,8 @@ namespace MWGui
void setFont(const std::string &fntName); void setFont(const std::string &fntName);
void onResChange(int width, int height);
void clearHistory(); void clearHistory();
// Print a message to the console. Messages may contain color // Print a message to the console. Messages may contain color

@ -119,7 +119,7 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender)
else else
onContainerClicked(mContainerWidget); onContainerClicked(mContainerWidget);
} }
else else if (isTrading())
{ {
MWWorld::Ptr object = (*_sender->getUserData<MWWorld::Ptr>()); MWWorld::Ptr object = (*_sender->getUserData<MWWorld::Ptr>());
int count = object.getRefData().getCount(); int count = object.getRefData().getCount();
@ -179,6 +179,10 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender)
} }
} }
} }
else
{
onSelectedItemImpl(*_sender->getUserData<MWWorld::Ptr>());
}
} }
void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count) void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count)
@ -260,16 +264,16 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender)
if(mDragAndDrop->mIsOnDragAndDrop) //drop item here if(mDragAndDrop->mIsOnDragAndDrop) //drop item here
{ {
MWWorld::Ptr object = *mDragAndDrop->mDraggedWidget->getUserData<MWWorld::Ptr>(); MWWorld::Ptr object = *mDragAndDrop->mDraggedWidget->getUserData<MWWorld::Ptr>();
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
if (mDragAndDrop->mDraggedFrom != this) if (mDragAndDrop->mDraggedFrom != this)
{ {
assert(object.getContainerStore() && "Item is not in a container!"); assert(object.getContainerStore() && "Item is not in a container!");
// check the container's Organic flag (if this is a container). container with Organic flag doesn't allow putting items inside // check the container's Organic flag (if this is a container). container with Organic flag doesn't allow putting items inside
if (mContainer.getTypeName() == typeid(ESM::Container).name()) if (mPtr.getTypeName() == typeid(ESM::Container).name())
{ {
ESMS::LiveCellRef<ESM::Container, MWWorld::RefData>* ref = mContainer.get<ESM::Container>(); ESMS::LiveCellRef<ESM::Container, MWWorld::RefData>* ref = mPtr.get<ESM::Container>();
if (ref->base->flags & ESM::Container::Organic) if (ref->base->flags & ESM::Container::Organic)
{ {
// user notification // user notification
@ -284,13 +288,13 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender)
// check that we don't exceed the allowed weight (only for containers, not for inventory) // check that we don't exceed the allowed weight (only for containers, not for inventory)
if (!isInventory()) if (!isInventory())
{ {
float capacity = MWWorld::Class::get(mContainer).getCapacity(mContainer); float capacity = MWWorld::Class::get(mPtr).getCapacity(mPtr);
// try adding the item, and if weight is exceeded, just remove it again. // try adding the item, and if weight is exceeded, just remove it again.
object.getRefData().setCount(mDragAndDrop->mDraggedCount); object.getRefData().setCount(mDragAndDrop->mDraggedCount);
MWWorld::ContainerStoreIterator it = containerStore.add(object); MWWorld::ContainerStoreIterator it = containerStore.add(object);
float curWeight = MWWorld::Class::get(mContainer).getEncumbrance(mContainer); float curWeight = MWWorld::Class::get(mPtr).getEncumbrance(mPtr);
if (curWeight > capacity) if (curWeight > capacity)
{ {
it->getRefData().setCount(0); it->getRefData().setCount(0);
@ -342,8 +346,7 @@ void ContainerBase::setFilter(ContainerBase::Filter filter)
void ContainerBase::openContainer(MWWorld::Ptr container) void ContainerBase::openContainer(MWWorld::Ptr container)
{ {
mContainer = container; mPtr = container;
drawItems();
} }
void ContainerBase::drawItems() void ContainerBase::drawItems()
@ -352,15 +355,12 @@ void ContainerBase::drawItems()
{ {
MyGUI::Gui::getInstance().destroyWidget(mContainerWidget->getChildAt(0)); MyGUI::Gui::getInstance().destroyWidget(mContainerWidget->getChildAt(0));
} }
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
int x = 0; int x = 0;
int y = 0; int y = 0;
int maxHeight = mItemView->getSize().height - 58; int maxHeight = mItemView->getSize().height - 58;
int index = 0;
bool onlyMagic = false; bool onlyMagic = false;
int categories; int categories;
if (mFilter == Filter_All) if (mFilter == Filter_All)
@ -381,8 +381,10 @@ void ContainerBase::drawItems()
categories = MWWorld::ContainerStore::Type_Miscellaneous + MWWorld::ContainerStore::Type_Book categories = MWWorld::ContainerStore::Type_Miscellaneous + MWWorld::ContainerStore::Type_Book
+ MWWorld::ContainerStore::Type_Ingredient + MWWorld::ContainerStore::Type_Repair + MWWorld::ContainerStore::Type_Ingredient + MWWorld::ContainerStore::Type_Repair
+ MWWorld::ContainerStore::Type_Lockpick + MWWorld::ContainerStore::Type_Light + MWWorld::ContainerStore::Type_Lockpick + MWWorld::ContainerStore::Type_Light
+ MWWorld::ContainerStore::Type_Apparatus; + MWWorld::ContainerStore::Type_Apparatus + MWWorld::ContainerStore::Type_Probe;
} }
else if (mFilter == Filter_Ingredients)
categories = MWWorld::ContainerStore::Type_Ingredient;
/// \todo performance improvement: don't create/destroy all the widgets everytime the container window changes size, only reposition them /// \todo performance improvement: don't create/destroy all the widgets everytime the container window changes size, only reposition them
@ -454,7 +456,6 @@ void ContainerBase::drawItems()
for (std::vector< std::pair<MWWorld::Ptr, ItemState> >::const_iterator it=items.begin(); for (std::vector< std::pair<MWWorld::Ptr, ItemState> >::const_iterator it=items.begin();
it != items.end(); ++it) it != items.end(); ++it)
{ {
index++;
const MWWorld::Ptr* iter = &((*it).first); const MWWorld::Ptr* iter = &((*it).first);
int displayCount = iter->getRefData().getCount(); int displayCount = iter->getRefData().getCount();
@ -465,7 +466,7 @@ void ContainerBase::drawItems()
if(displayCount > 0 && !(onlyMagic && it->second != ItemState_Barter && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" && iter->getTypeName() != typeid(ESM::Potion).name())) if(displayCount > 0 && !(onlyMagic && it->second != ItemState_Barter && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" && iter->getTypeName() != typeid(ESM::Potion).name()))
{ {
std::string path = std::string("icons\\"); std::string path = std::string("icons\\");
path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter); path += MWWorld::Class::get(*iter).getInventoryIcon(*iter);
// background widget (for the "equipped" frame and magic item background image) // background widget (for the "equipped" frame and magic item background image)
bool isMagic = (MWWorld::Class::get(*iter).getEnchantment(*iter) != ""); bool isMagic = (MWWorld::Class::get(*iter).getEnchantment(*iter) != "");
@ -514,6 +515,7 @@ void ContainerBase::drawItems()
text->setNeedMouseFocus(false); text->setNeedMouseFocus(false);
text->setTextShadow(true); text->setTextShadow(true);
text->setTextShadowColour(MyGUI::Colour(0,0,0)); text->setTextShadowColour(MyGUI::Colour(0,0,0));
text->setCaption(getCountString(displayCount));
y += 42; y += 42;
if (y > maxHeight) if (y > maxHeight)
@ -522,13 +524,14 @@ void ContainerBase::drawItems()
y = 0; y = 0;
} }
text->setCaption(getCountString(displayCount));
} }
} }
MyGUI::IntSize size = MyGUI::IntSize(std::max(mItemView->getSize().width, x+42), mItemView->getSize().height); MyGUI::IntSize size = MyGUI::IntSize(std::max(mItemView->getSize().width, x+42), mItemView->getSize().height);
mItemView->setCanvasSize(size); mItemView->setCanvasSize(size);
mContainerWidget->setSize(size); mContainerWidget->setSize(size);
notifyContentChanged();
} }
std::string ContainerBase::getCountString(const int count) std::string ContainerBase::getCountString(const int count)
@ -551,7 +554,7 @@ void ContainerBase::addBarteredItem(MWWorld::Ptr item, int count)
void ContainerBase::addItem(MWWorld::Ptr item, int count) void ContainerBase::addItem(MWWorld::Ptr item, int count)
{ {
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
int origCount = item.getRefData().getCount(); int origCount = item.getRefData().getCount();
@ -563,7 +566,7 @@ void ContainerBase::addItem(MWWorld::Ptr item, int count)
void ContainerBase::transferBoughtItems() void ContainerBase::transferBoughtItems()
{ {
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
for (MWWorld::ContainerStoreIterator it(mBoughtItems.begin()); it != mBoughtItems.end(); ++it) for (MWWorld::ContainerStoreIterator it(mBoughtItems.begin()); it != mBoughtItems.end(); ++it)
{ {
@ -581,7 +584,7 @@ void ContainerBase::returnBoughtItems(MWWorld::ContainerStore& store)
MWWorld::ContainerStore& ContainerBase::getContainerStore() MWWorld::ContainerStore& ContainerBase::getContainerStore()
{ {
MWWorld::ContainerStore& store = MWWorld::Class::get(mContainer).getContainerStore(mContainer); MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
return store; return store;
} }
@ -630,13 +633,14 @@ void ContainerWindow::open(MWWorld::Ptr container)
{ {
openContainer(container); openContainer(container);
setTitle(MWWorld::Class::get(container).getName(container)); setTitle(MWWorld::Class::get(container).getName(container));
drawItems();
} }
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
{ {
if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop)
{ {
MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game); MWBase::Environment::get().getWindowManager()->popGuiMode();
} }
} }
@ -645,7 +649,7 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender)
if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop)
{ {
// transfer everything into the player's inventory // transfer everything into the player's inventory
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::ContainerStore& playerStore = MWWorld::Class::get(player).getContainerStore(player); MWWorld::ContainerStore& playerStore = MWWorld::Class::get(player).getContainerStore(player);
@ -667,6 +671,11 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender)
containerStore.clear(); containerStore.clear();
MWBase::Environment::get().getWindowManager()->setGuiMode(GM_Game); MWBase::Environment::get().getWindowManager()->popGuiMode();
} }
} }
void ContainerWindow::onReferenceUnavailable()
{
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
}

@ -2,15 +2,14 @@
#define MGUI_CONTAINER_H #define MGUI_CONTAINER_H
#include <components/esm_store/store.hpp> #include <components/esm_store/store.hpp>
#include "../mwclass/container.hpp"
#include <sstream>
#include <set>
#include <string>
#include <utility>
#include "window_base.hpp" #include "window_base.hpp"
#include "referenceinterface.hpp"
#include "../mwclass/container.hpp"
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/containerstore.hpp" #include "../mwworld/containerstore.hpp"
#include <vector>
namespace MWWorld namespace MWWorld
{ {
@ -43,7 +42,7 @@ namespace MWGui
int mDraggedCount; int mDraggedCount;
}; };
class ContainerBase class ContainerBase : public ReferenceInterface
{ {
public: public:
ContainerBase(DragAndDrop* dragAndDrop); ContainerBase(DragAndDrop* dragAndDrop);
@ -55,7 +54,9 @@ namespace MWGui
Filter_Weapon = 0x02, Filter_Weapon = 0x02,
Filter_Apparel = 0x03, Filter_Apparel = 0x03,
Filter_Magic = 0x04, Filter_Magic = 0x04,
Filter_Misc = 0x05 Filter_Misc = 0x05,
Filter_Ingredients = 0x06
}; };
enum ItemState enum ItemState
@ -87,7 +88,6 @@ namespace MWGui
MyGUI::Widget* mSelectedItem; MyGUI::Widget* mSelectedItem;
DragAndDrop* mDragAndDrop; DragAndDrop* mDragAndDrop;
MWWorld::Ptr mContainer;
Filter mFilter; Filter mFilter;
@ -116,8 +116,12 @@ namespace MWGui
virtual bool isTrading() { return false; } virtual bool isTrading() { return false; }
virtual void onSelectedItemImpl(MWWorld::Ptr item) { ; }
virtual bool ignoreEquippedItems() { return false; } virtual bool ignoreEquippedItems() { return false; }
virtual std::vector<MWWorld::Ptr> itemsToIgnore() { return std::vector<MWWorld::Ptr>(); } virtual std::vector<MWWorld::Ptr> itemsToIgnore() { return std::vector<MWWorld::Ptr>(); }
virtual void notifyContentChanged() { ; }
}; };
class ContainerWindow : public ContainerBase, public WindowBase class ContainerWindow : public ContainerBase, public WindowBase
@ -136,6 +140,8 @@ namespace MWGui
void onWindowResize(MyGUI::Window* window); void onWindowResize(MyGUI::Window* window);
void onCloseButtonClicked(MyGUI::Widget* _sender); void onCloseButtonClicked(MyGUI::Widget* _sender);
void onTakeAllButtonClicked(MyGUI::Widget* _sender); void onTakeAllButtonClicked(MyGUI::Widget* _sender);
virtual void onReferenceUnavailable();
}; };
} }
#endif // CONTAINER_H #endif // CONTAINER_H

@ -17,9 +17,6 @@ namespace MWGui
getWidget(mOkButton, "OkButton"); getWidget(mOkButton, "OkButton");
getWidget(mCancelButton, "CancelButton"); getWidget(mCancelButton, "CancelButton");
mOkButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sOk")->str);
mCancelButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sCancel")->str);
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onCancelButtonClicked); mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onCancelButtonClicked);
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onOkButtonClicked); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onOkButtonClicked);
mItemEdit->eventEditTextChange += MyGUI::newDelegate(this, &CountDialog::onEditTextChange); mItemEdit->eventEditTextChange += MyGUI::newDelegate(this, &CountDialog::onEditTextChange);

@ -112,15 +112,6 @@ void DialogueWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel)
history->setVScrollPosition(history->getVScrollPosition() - _rel*0.3); history->setVScrollPosition(history->getVScrollPosition() - _rel*0.3);
} }
void DialogueWindow::open()
{
topicsList->clear();
pTopicsText.clear();
history->eraseText(0,history->getTextLength());
updateOptions();
setVisible(true);
}
void DialogueWindow::onByeClicked(MyGUI::Widget* _sender) void DialogueWindow::onByeClicked(MyGUI::Widget* _sender)
{ {
MWBase::Environment::get().getDialogueManager()->goodbyeSelected(); MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
@ -133,8 +124,8 @@ void DialogueWindow::onSelectTopic(std::string topic)
if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarter")->str) if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarter")->str)
{ {
/// \todo check if the player is allowed to trade with this actor (e.g. faction rank high enough)? /// \todo check if the player is allowed to trade with this actor (e.g. faction rank high enough)?
mWindowManager.setGuiMode(GM_Barter); mWindowManager.pushGuiMode(GM_Barter);
mWindowManager.getTradeWindow()->startTrade(mActor); mWindowManager.getTradeWindow()->startTrade(mPtr);
} }
else else
@ -144,9 +135,13 @@ void DialogueWindow::onSelectTopic(std::string topic)
void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName) void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName)
{ {
mEnabled = true; mEnabled = true;
mActor = actor; mPtr = actor;
topicsList->setEnabled(true); topicsList->setEnabled(true);
setTitle(npcName); setTitle(npcName);
topicsList->clear();
history->eraseText(0,history->getTextLength());
updateOptions();
} }
void DialogueWindow::setKeywords(std::list<std::string> keyWords) void DialogueWindow::setKeywords(std::list<std::string> keyWords)
@ -161,7 +156,7 @@ void DialogueWindow::setKeywords(std::list<std::string> keyWords)
if (anyService) if (anyService)
topicsList->addSeparator(); topicsList->addSeparator();
for(std::list<std::string>::iterator it = keyWords.begin(); it != keyWords.end(); it++) for(std::list<std::string>::iterator it = keyWords.begin(); it != keyWords.end(); ++it)
{ {
topicsList->addItem(*it); topicsList->addItem(*it);
} }
@ -173,7 +168,6 @@ void DialogueWindow::removeKeyword(std::string keyWord)
if(topicsList->hasItem(keyWord)) if(topicsList->hasItem(keyWord))
{ {
topicsList->removeItem(keyWord); topicsList->removeItem(keyWord);
pTopicsText.erase(keyWord);
} }
topicsList->adjustSize(); topicsList->adjustSize();
} }
@ -249,7 +243,6 @@ void DialogueWindow::updateOptions()
{ {
//Clear the list of topics //Clear the list of topics
topicsList->clear(); topicsList->clear();
pTopicsText.clear();
history->eraseText(0,history->getTextLength()); history->eraseText(0,history->getTextLength());
pDispositionBar->setProgressRange(100); pDispositionBar->setProgressRange(100);
@ -264,3 +257,8 @@ void DialogueWindow::goodbye()
topicsList->setEnabled(false); topicsList->setEnabled(false);
mEnabled = false; mEnabled = false;
} }
void DialogueWindow::onReferenceUnavailable()
{
mWindowManager.removeGuiMode(GM_Dialogue);
}

@ -2,6 +2,7 @@
#define MWGUI_DIALOGE_H #define MWGUI_DIALOGE_H
#include "window_base.hpp" #include "window_base.hpp"
#include "referenceinterface.hpp"
#include <boost/array.hpp> #include <boost/array.hpp>
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
@ -25,13 +26,11 @@ namespace MWGui
{ {
class DialogueHistory; class DialogueHistory;
class DialogueWindow: public WindowBase class DialogueWindow: public WindowBase, public ReferenceInterface
{ {
public: public:
DialogueWindow(WindowManager& parWindowManager); DialogueWindow(WindowManager& parWindowManager);
void open();
// Events // Events
typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void;
@ -60,6 +59,8 @@ namespace MWGui
void onMouseWheel(MyGUI::Widget* _sender, int _rel); void onMouseWheel(MyGUI::Widget* _sender, int _rel);
void onWindowResize(MyGUI::Window* _sender); void onWindowResize(MyGUI::Window* _sender);
virtual void onReferenceUnavailable();
private: private:
void updateOptions(); void updateOptions();
/** /**
@ -72,13 +73,10 @@ namespace MWGui
bool mEnabled; bool mEnabled;
MWWorld::Ptr mActor; // actor being talked to
DialogueHistory* history; DialogueHistory* history;
Widgets::MWList* topicsList; Widgets::MWList* topicsList;
MyGUI::ProgressPtr pDispositionBar; MyGUI::ProgressPtr pDispositionBar;
MyGUI::EditPtr pDispositionText; MyGUI::EditPtr pDispositionText;
std::map<std::string,std::string> pTopicsText;// this map links keyword and "real" text.
}; };
} }
#endif #endif

@ -12,8 +12,10 @@
#include "../mwworld/world.hpp" #include "../mwworld/world.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "inventorywindow.hpp"
#include "window_manager.hpp" #include "window_manager.hpp"
#include "container.hpp" #include "container.hpp"
#include "console.hpp"
using namespace MWGui; using namespace MWGui;
@ -41,35 +43,60 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop)
, effectBoxBaseRight(0) , effectBoxBaseRight(0)
, minimapBoxBaseRight(0) , minimapBoxBaseRight(0)
, mDragAndDrop(dragAndDrop) , mDragAndDrop(dragAndDrop)
, mCellNameTimer(0.0f)
, mCellNameBox(NULL)
, mMapVisible(true)
, mWeaponVisible(true)
, mSpellVisible(true)
, mWorldMouseOver(false)
{ {
setCoord(0,0, width, height); setCoord(0,0, width, height);
// Energy bars // Energy bars
getWidget(mHealthFrame, "HealthFrame");
getWidget(health, "Health"); getWidget(health, "Health");
getWidget(magicka, "Magicka"); getWidget(magicka, "Magicka");
getWidget(stamina, "Stamina"); getWidget(stamina, "Stamina");
hmsBaseLeft = health->getLeft();
hmsBaseLeft = mHealthFrame->getLeft();
MyGUI::Widget *healthFrame, *magickaFrame, *fatigueFrame;
getWidget(healthFrame, "HealthFrame");
getWidget(magickaFrame, "MagickaFrame");
getWidget(fatigueFrame, "FatigueFrame");
healthFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked);
magickaFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked);
fatigueFrame->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onHMSClicked);
const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize();
// Item and spell images and status bars // Item and spell images and status bars
getWidget(weapBox, "WeapBox"); getWidget(weapBox, "WeapBox");
getWidget(weapImage, "WeapImage"); getWidget(weapImage, "WeapImage");
getWidget(weapStatus, "WeapStatus"); getWidget(weapStatus, "WeapStatus");
weapBoxBaseLeft = weapBox->getLeft(); weapBoxBaseLeft = weapBox->getLeft();
weapBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWeaponClicked);
getWidget(spellBox, "SpellBox"); getWidget(spellBox, "SpellBox");
getWidget(spellImage, "SpellImage"); getWidget(spellImage, "SpellImage");
getWidget(spellStatus, "SpellStatus"); getWidget(spellStatus, "SpellStatus");
spellBoxBaseLeft = spellBox->getLeft(); spellBoxBaseLeft = spellBox->getLeft();
spellBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked);
getWidget(effectBox, "EffectBox"); getWidget(effectBox, "EffectBox");
getWidget(effect1, "Effect1"); getWidget(effect1, "Effect1");
effectBoxBaseRight = effectBox->getRight(); effectBoxBaseRight = viewSize.width - effectBox->getRight();
effectBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked);
getWidget(minimapBox, "MiniMapBox"); getWidget(minimapBox, "MiniMapBox");
minimapBoxBaseRight = minimapBox->getRight(); minimapBoxBaseRight = viewSize.width - minimapBox->getRight();
minimapBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked);
getWidget(minimap, "MiniMap"); getWidget(minimap, "MiniMap");
getWidget(compass, "Compass"); getWidget(compass, "Compass");
getWidget(mCellNameBox, "CellName");
getWidget(mWeaponSpellBox, "WeaponSpellName");
getWidget(crosshair, "Crosshair"); getWidget(crosshair, "Crosshair");
setFpsLevel(fpsLevel); setFpsLevel(fpsLevel);
@ -77,15 +104,9 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop)
getWidget(trianglecounter, "TriangleCounter"); getWidget(trianglecounter, "TriangleCounter");
getWidget(batchcounter, "BatchCounter"); getWidget(batchcounter, "BatchCounter");
// These are just demo values, you should replace these with
// real calls from outside the class later.
setWeapIcon("icons\\w\\tx_knife_iron.dds");
setWeapStatus(90, 100);
setSpellIcon("icons\\s\\b_tx_s_rstor_health.dds");
setSpellStatus(65, 100);
setEffect("icons\\s\\tx_s_chameleon.dds"); setEffect("icons\\s\\tx_s_chameleon.dds");
LocalMapBase::init(minimap, this); LocalMapBase::init(minimap, compass, this);
mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked); mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked);
mMainWidget->eventMouseMove += MyGUI::newDelegate(this, &HUD::onWorldMouseOver); mMainWidget->eventMouseMove += MyGUI::newDelegate(this, &HUD::onWorldMouseOver);
@ -94,6 +115,8 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop)
void HUD::setFpsLevel(int level) void HUD::setFpsLevel(int level)
{ {
fpscounter = 0;
MyGUI::Widget* fps; MyGUI::Widget* fps;
getWidget(fps, "FPSBoxAdv"); getWidget(fps, "FPSBoxAdv");
fps->setVisible(false); fps->setVisible(false);
@ -116,6 +139,7 @@ void HUD::setFpsLevel(int level)
void HUD::setFPS(float fps) void HUD::setFPS(float fps)
{ {
if (fpscounter)
fpscounter->setCaption(boost::lexical_cast<std::string>((int)fps)); fpscounter->setCaption(boost::lexical_cast<std::string>((int)fps));
} }
@ -129,28 +153,6 @@ void HUD::setBatchCount(size_t count)
batchcounter->setCaption(boost::lexical_cast<std::string>(count)); batchcounter->setCaption(boost::lexical_cast<std::string>(count));
} }
void HUD::setWeapIcon(const char *str)
{
weapImage->setImageTexture(str);
}
void HUD::setSpellIcon(const char *str)
{
spellImage->setImageTexture(str);
}
void HUD::setWeapStatus(int s, int smax)
{
weapStatus->setProgressRange(smax);
weapStatus->setProgressPosition(s);
}
void HUD::setSpellStatus(int s, int smax)
{
spellStatus->setProgressRange(smax);
spellStatus->setProgressPosition(s);
}
void HUD::setEffect(const char *img) void HUD::setEffect(const char *img)
{ {
effect1->setImageTexture(img); effect1->setImageTexture(img);
@ -192,35 +194,6 @@ void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<int>& v
} }
} }
void HUD::setPlayerDir(const float x, const float y)
{
if (!minimapBox->getVisible() || (x == mLastPositionX && y == mLastPositionY)) return;
MyGUI::ISubWidget* main = compass->getSubWidgetMain();
MyGUI::RotatingSkin* rotatingSubskin = main->castType<MyGUI::RotatingSkin>();
rotatingSubskin->setCenter(MyGUI::IntPoint(16,16));
float angle = std::atan2(x,y);
rotatingSubskin->setAngle(angle);
mLastPositionX = x;
mLastPositionY = y;
}
void HUD::setPlayerPos(const float x, const float y)
{
if (!minimapBox->getVisible() || (x == mLastDirectionX && y == mLastDirectionY)) return;
MyGUI::IntSize size = minimap->getCanvasSize();
MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height);
MyGUI::IntCoord viewsize = minimap->getCoord();
MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top);
minimap->setViewOffset(pos);
compass->setPosition(MyGUI::IntPoint(x*512-16, y*512-16));
mLastDirectionX = x;
mLastDirectionY = y;
}
void HUD::setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible) void HUD::setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible)
{ {
int weapDx = 0, spellDx = 0; int weapDx = 0, spellDx = 0;
@ -228,7 +201,12 @@ void HUD::setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellV
spellDx = weapDx = weapBoxBaseLeft - hmsBaseLeft; spellDx = weapDx = weapBoxBaseLeft - hmsBaseLeft;
if (!weapVisible) if (!weapVisible)
spellDx -= spellBoxBaseLeft - weapBoxBaseLeft; spellDx += spellBoxBaseLeft - weapBoxBaseLeft;
mWeaponVisible = weapVisible;
mSpellVisible = spellVisible;
if (!mWeaponVisible && !mSpellVisible)
mWeaponSpellBox->setVisible(false);
health->setVisible(hmsVisible); health->setVisible(hmsVisible);
stamina->setVisible(hmsVisible); stamina->setVisible(hmsVisible);
@ -241,13 +219,16 @@ void HUD::setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellV
void HUD::setBottomRightVisibility(bool effectBoxVisible, bool minimapBoxVisible) void HUD::setBottomRightVisibility(bool effectBoxVisible, bool minimapBoxVisible)
{ {
const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize();
// effect box can have variable width -> variable left coordinate // effect box can have variable width -> variable left coordinate
int effectsDx = 0; int effectsDx = 0;
if (!minimapBoxVisible) if (!minimapBoxVisible)
effectsDx = minimapBoxBaseRight - effectBoxBaseRight; effectsDx = (viewSize.width - minimapBoxBaseRight) - (viewSize.width - effectBoxBaseRight);
mMapVisible = minimapBoxVisible;
minimapBox->setVisible(minimapBoxVisible); minimapBox->setVisible(minimapBoxVisible);
effectBox->setPosition(effectBoxBaseRight - effectBox->getWidth() + effectsDx, effectBox->getTop()); effectBox->setPosition((viewSize.width - effectBoxBaseRight) - effectBox->getWidth() + effectsDx, effectBox->getTop());
effectBox->setVisible(effectBoxVisible); effectBox->setVisible(effectBoxVisible);
} }
@ -286,6 +267,33 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender)
mDragAndDrop->mDraggedWidget = 0; mDragAndDrop->mDraggedWidget = 0;
MWBase::Environment::get().getWindowManager()->setDragDrop(false); MWBase::Environment::get().getWindowManager()->setDragDrop(false);
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems();
}
else
{
GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode();
if ( (mode != GM_Console) && (mode != GM_Container) && (mode != GM_Inventory) )
return;
std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle();
MWWorld::Ptr object;
try
{
object = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle);
}
catch (std::exception& e)
{
return;
}
if (mode == GM_Console)
MWBase::Environment::get().getWindowManager()->getConsole()->setSelectedObject(object);
else if ((mode == GM_Container) || (mode == GM_Inventory))
{
// pick up object
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->pickUpObject(object);
}
} }
} }
@ -293,6 +301,8 @@ void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y)
{ {
if (mDragAndDrop->mIsOnDragAndDrop) if (mDragAndDrop->mIsOnDragAndDrop)
{ {
mWorldMouseOver = false;
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition(); MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition();
float mouseX = cursorPosition.left / float(viewSize.width); float mouseX = cursorPosition.left / float(viewSize.width);
@ -312,11 +322,195 @@ void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y)
else else
{ {
MyGUI::PointerManager::getInstance().setPointer("arrow"); MyGUI::PointerManager::getInstance().setPointer("arrow");
/// \todo make it possible to pick up objects with the mouse, if inventory or container window is open mWorldMouseOver = true;
} }
} }
void HUD::onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new) void HUD::onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new)
{ {
MyGUI::PointerManager::getInstance().setPointer("arrow"); MyGUI::PointerManager::getInstance().setPointer("arrow");
mWorldMouseOver = false;
}
void HUD::onHMSClicked(MyGUI::Widget* _sender)
{
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Stats);
}
void HUD::onMapClicked(MyGUI::Widget* _sender)
{
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Map);
}
void HUD::onWeaponClicked(MyGUI::Widget* _sender)
{
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Inventory);
}
void HUD::onMagicClicked(MyGUI::Widget* _sender)
{
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Magic);
}
void HUD::setCellName(const std::string& cellName)
{
if (mCellName != cellName)
{
mCellNameTimer = 5.0f;
mCellName = cellName;
mCellNameBox->setCaption(mCellName);
mCellNameBox->setVisible(mMapVisible);
}
}
void HUD::onFrame(float dt)
{
mCellNameTimer -= dt;
mWeaponSpellTimer -= dt;
if (mCellNameTimer < 0)
mCellNameBox->setVisible(false);
if (mWeaponSpellTimer < 0)
mWeaponSpellBox->setVisible(false);
}
void HUD::onResChange(int width, int height)
{
setCoord(0, 0, width, height);
}
void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent)
{
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId);
std::string spellName = spell->name;
if (spellName != mSpellName && mSpellVisible)
{
mWeaponSpellTimer = 5.0f;
mSpellName = spellName;
mWeaponSpellBox->setCaption(mSpellName);
mWeaponSpellBox->setVisible(true);
}
spellStatus->setProgressRange(100);
spellStatus->setProgressPosition(successChancePercent);
if (spellImage->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(spellImage->getChildAt(0));
spellBox->setUserString("ToolTipType", "Spell");
spellBox->setUserString("Spell", spellId);
// use the icon of the first effect
const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(spell->effects.list.front().effectID);
std::string icon = effect->icon;
int slashPos = icon.find("\\");
icon.insert(slashPos+1, "b_");
icon = std::string("icons\\") + icon;
Widgets::fixTexturePath(icon);
spellImage->setImageTexture(icon);
}
void HUD::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent)
{
std::string itemName = MWWorld::Class::get(item).getName(item);
if (itemName != mSpellName && mSpellVisible)
{
mWeaponSpellTimer = 5.0f;
mSpellName = itemName;
mWeaponSpellBox->setCaption(mSpellName);
mWeaponSpellBox->setVisible(true);
}
spellStatus->setProgressRange(100);
spellStatus->setProgressPosition(chargePercent);
if (spellImage->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(spellImage->getChildAt(0));
spellBox->setUserString("ToolTipType", "ItemPtr");
spellBox->setUserData(item);
spellImage->setImageTexture("textures\\menu_icon_magic_mini.dds");
MyGUI::ImageBox* itemBox = spellImage->createWidgetReal<MyGUI::ImageBox>("ImageBox", MyGUI::FloatCoord(0,0,1,1)
, MyGUI::Align::Stretch);
std::string path = std::string("icons\\");
path+=MWWorld::Class::get(item).getInventoryIcon(item);
Widgets::fixTexturePath(path);
itemBox->setImageTexture(path);
itemBox->setNeedMouseFocus(false);
}
void HUD::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent)
{
std::string itemName = MWWorld::Class::get(item).getName(item);
if (itemName != mWeaponName && mWeaponVisible)
{
mWeaponSpellTimer = 5.0f;
mWeaponName = itemName;
mWeaponSpellBox->setCaption(mWeaponName);
mWeaponSpellBox->setVisible(true);
}
weapBox->setUserString("ToolTipType", "ItemPtr");
weapBox->setUserData(item);
weapStatus->setProgressRange(100);
weapStatus->setProgressPosition(durabilityPercent);
if (weapImage->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(weapImage->getChildAt(0));
std::string path = std::string("icons\\");
path+=MWWorld::Class::get(item).getInventoryIcon(item);
Widgets::fixTexturePath(path);
if (MWWorld::Class::get(item).getEnchantment(item) != "")
{
weapImage->setImageTexture("textures\\menu_icon_magic_mini.dds");
MyGUI::ImageBox* itemBox = weapImage->createWidgetReal<MyGUI::ImageBox>("ImageBox", MyGUI::FloatCoord(0,0,1,1)
, MyGUI::Align::Stretch);
itemBox->setImageTexture(path);
itemBox->setNeedMouseFocus(false);
}
else
weapImage->setImageTexture(path);
}
void HUD::unsetSelectedSpell()
{
std::string spellName = "#{sNone}";
if (spellName != mSpellName && mSpellVisible)
{
mWeaponSpellTimer = 5.0f;
mSpellName = spellName;
mWeaponSpellBox->setCaptionWithReplacing(mSpellName);
mWeaponSpellBox->setVisible(true);
}
if (spellImage->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(spellImage->getChildAt(0));
spellStatus->setProgressRange(100);
spellStatus->setProgressPosition(0);
spellImage->setImageTexture("");
spellBox->clearUserStrings();
}
void HUD::unsetSelectedWeapon()
{
std::string itemName = "#{sSkillHandtohand}";
if (itemName != mWeaponName && mWeaponVisible)
{
mWeaponSpellTimer = 5.0f;
mWeaponName = itemName;
mWeaponSpellBox->setCaptionWithReplacing(mWeaponName);
mWeaponSpellBox->setVisible(true);
}
if (weapImage->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(weapImage->getChildAt(0));
weapStatus->setProgressRange(100);
weapStatus->setProgressPosition(0);
weapImage->setImageTexture("icons\\k\\stealth_handtohand.dds");
weapBox->clearUserStrings();
} }

@ -3,6 +3,7 @@
#include <openengine/gui/layout.hpp> #include <openengine/gui/layout.hpp>
#include "../mwmechanics/stat.hpp" #include "../mwmechanics/stat.hpp"
#include "../mwworld/ptr.hpp"
namespace MWGui namespace MWGui
{ {
@ -12,22 +13,30 @@ namespace MWGui
{ {
public: public:
HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop); HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop);
void setWeapIcon(const char *str);
void setSpellIcon(const char *str);
void setWeapStatus(int s, int smax);
void setSpellStatus(int s, int smax);
void setEffect(const char *img); void setEffect(const char *img);
void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value); void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value);
void setFPS(float fps); void setFPS(float fps);
void setTriangleCount(size_t count); void setTriangleCount(size_t count);
void setBatchCount(size_t count); void setBatchCount(size_t count);
void setPlayerDir(const float x, const float y);
void setPlayerPos(const float x, const float y);
void setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible); void setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible);
void setBottomRightVisibility(bool effectBoxVisible, bool minimapVisible); void setBottomRightVisibility(bool effectBoxVisible, bool minimapVisible);
void setFpsLevel(const int level); void setFpsLevel(const int level);
void setSelectedSpell(const std::string& spellId, int successChancePercent);
void setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent);
void setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent);
void unsetSelectedSpell();
void unsetSelectedWeapon();
void onFrame(float dt);
void onResChange(int width, int height);
void setCellName(const std::string& cellName);
bool getWorldMouseOver() { return mWorldMouseOver; }
MyGUI::ProgressPtr health, magicka, stamina; MyGUI::ProgressPtr health, magicka, stamina;
MyGUI::Widget* mHealthFrame;
MyGUI::Widget *weapBox, *spellBox; MyGUI::Widget *weapBox, *spellBox;
MyGUI::ImageBox *weapImage, *spellImage; MyGUI::ImageBox *weapImage, *spellImage;
MyGUI::ProgressPtr weapStatus, spellStatus; MyGUI::ProgressPtr weapStatus, spellStatus;
@ -36,6 +45,8 @@ namespace MWGui
MyGUI::ScrollView* minimap; MyGUI::ScrollView* minimap;
MyGUI::ImageBox* compass; MyGUI::ImageBox* compass;
MyGUI::ImageBox* crosshair; MyGUI::ImageBox* crosshair;
MyGUI::TextBox* mCellNameBox;
MyGUI::TextBox* mWeaponSpellBox;
MyGUI::WidgetPtr fpsbox; MyGUI::WidgetPtr fpsbox;
MyGUI::TextBox* fpscounter; MyGUI::TextBox* fpscounter;
@ -50,8 +61,25 @@ namespace MWGui
DragAndDrop* mDragAndDrop; DragAndDrop* mDragAndDrop;
std::string mCellName;
float mCellNameTimer;
std::string mWeaponName;
std::string mSpellName;
float mWeaponSpellTimer;
bool mMapVisible;
bool mWeaponVisible;
bool mSpellVisible;
bool mWorldMouseOver;
void onWorldClicked(MyGUI::Widget* _sender); void onWorldClicked(MyGUI::Widget* _sender);
void onWorldMouseOver(MyGUI::Widget* _sender, int x, int y); void onWorldMouseOver(MyGUI::Widget* _sender, int x, int y);
void onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new); void onWorldMouseLostFocus(MyGUI::Widget* _sender, MyGUI::Widget* _new);
void onHMSClicked(MyGUI::Widget* _sender);
void onWeaponClicked(MyGUI::Widget* _sender);
void onMagicClicked(MyGUI::Widget* _sender);
void onMapClicked(MyGUI::Widget* _sender);
}; };
} }

@ -15,11 +15,14 @@
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwworld/manualref.hpp" #include "../mwworld/manualref.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwsound/soundmanager.hpp"
#include "window_manager.hpp" #include "window_manager.hpp"
#include "widgets.hpp" #include "widgets.hpp"
#include "bookwindow.hpp" #include "bookwindow.hpp"
#include "scrollwindow.hpp" #include "scrollwindow.hpp"
#include "spellwindow.hpp"
namespace namespace
{ {
@ -91,13 +94,13 @@ namespace MWGui
mFilterAll->setStateSelected(true); mFilterAll->setStateSelected(true);
setCoord(0, 342, 600, 258); setCoord(0, 342, 498, 258);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
openContainer(player); openContainer(player);
} }
void InventoryWindow::openInventory() void InventoryWindow::open()
{ {
updateEncumbranceBar(); updateEncumbranceBar();
@ -155,7 +158,7 @@ namespace MWGui
if (mDragAndDrop->mDraggedFrom != this) if (mDragAndDrop->mDraggedFrom != this)
{ {
// add item to the player's inventory // add item to the player's inventory
MWWorld::ContainerStore& invStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); MWWorld::ContainerStore& invStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
MWWorld::ContainerStoreIterator it = invStore.begin(); MWWorld::ContainerStoreIterator it = invStore.begin();
int origCount = ptr.getRefData().getCount(); int origCount = ptr.getRefData().getCount();
@ -187,12 +190,21 @@ namespace MWGui
mWindowManager.setDragDrop(false); mWindowManager.setDragDrop(false);
drawItems(); drawItems();
// update selected weapon icon
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
MWWorld::ContainerStoreIterator weaponSlot = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
if (weaponSlot == invStore.end())
mWindowManager.unsetSelectedWeapon();
else
mWindowManager.setSelectedWeapon(*weaponSlot, 100); /// \todo track weapon durability
} }
} }
std::vector<MWWorld::Ptr> InventoryWindow::getEquippedItems() std::vector<MWWorld::Ptr> InventoryWindow::getEquippedItems()
{ {
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mContainer).getInventoryStore(mContainer); MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
std::vector<MWWorld::Ptr> items; std::vector<MWWorld::Ptr> items;
@ -210,7 +222,7 @@ namespace MWGui
void InventoryWindow::_unequipItem(MWWorld::Ptr item) void InventoryWindow::_unequipItem(MWWorld::Ptr item)
{ {
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mContainer).getInventoryStore(mContainer); MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot)
{ {
@ -244,7 +256,7 @@ namespace MWGui
int InventoryWindow::getPlayerGold() int InventoryWindow::getPlayerGold()
{ {
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mContainer).getInventoryStore(mContainer); MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
for (MWWorld::ContainerStoreIterator it = invStore.begin(); for (MWWorld::ContainerStoreIterator it = invStore.begin();
it != invStore.end(); ++it) it != invStore.end(); ++it)
@ -259,4 +271,79 @@ namespace MWGui
{ {
mTrading = true; mTrading = true;
} }
void InventoryWindow::notifyContentChanged()
{
// update the spell window just in case new enchanted items were added to inventory
if (mWindowManager.getSpellWindow())
mWindowManager.getSpellWindow()->updateSpells();
// update selected weapon icon
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
MWWorld::ContainerStoreIterator weaponSlot = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
if (weaponSlot == invStore.end())
mWindowManager.unsetSelectedWeapon();
else
mWindowManager.setSelectedWeapon(*weaponSlot, 100); /// \todo track weapon durability
}
void InventoryWindow::pickUpObject (MWWorld::Ptr object)
{
/// \todo scripts
// make sure the object is of a type that can be picked up
std::string type = object.getTypeName();
if ( (type != typeid(ESM::Apparatus).name())
&& (type != typeid(ESM::Armor).name())
&& (type != typeid(ESM::Book).name())
&& (type != typeid(ESM::Clothing).name())
&& (type != typeid(ESM::Ingredient).name())
&& (type != typeid(ESM::Light).name())
&& (type != typeid(ESM::Miscellaneous).name())
&& (type != typeid(ESM::Tool).name())
&& (type != typeid(ESM::Probe).name())
&& (type != typeid(ESM::Repair).name())
&& (type != typeid(ESM::Weapon).name())
&& (type != typeid(ESM::Potion).name()))
return;
// sound
std::string sound = MWWorld::Class::get(object).getUpSoundId(object);
MWBase::Environment::get().getSoundManager()->playSound(sound, 1, 1);
int count = object.getRefData().getCount();
// add to player inventory
// can't use ActionTake here because we need an MWWorld::Ptr to the newly inserted object
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Ptr newObject = *MWWorld::Class::get (player).getContainerStore (player).add (object);
// remove from world
MWBase::Environment::get().getWorld()->deleteObject (object);
mDragAndDrop->mIsOnDragAndDrop = true;
mDragAndDrop->mDraggedCount = count;
std::string path = std::string("icons\\");
path += MWWorld::Class::get(newObject).getInventoryIcon(newObject);
MyGUI::ImageBox* baseWidget = mContainerWidget->createWidget<ImageBox>("ImageBox", MyGUI::IntCoord(0, 0, 42, 42), MyGUI::Align::Default);
baseWidget->detachFromWidget();
baseWidget->attachToWidget(mDragAndDrop->mDragAndDropWidget);
baseWidget->setUserData(newObject);
mDragAndDrop->mDraggedWidget = baseWidget;
ImageBox* image = baseWidget->createWidget<ImageBox>("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default);
int pos = path.rfind(".");
path.erase(pos);
path.append(".dds");
image->setImageTexture(path);
image->setNeedMouseFocus(false);
// text widget that shows item count
MyGUI::TextBox* text = image->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label"));
text->setTextAlign(MyGUI::Align::Right);
text->setNeedMouseFocus(false);
text->setTextShadow(true);
text->setTextShadowColour(MyGUI::Colour(0,0,0));
text->setCaption(getCountString(count));
mDragAndDrop->mDraggedFrom = this;
}
} }

@ -11,13 +11,15 @@ namespace MWGui
public: public:
InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop); InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop);
void openInventory(); virtual void open();
/// start trading, disables item drag&drop /// start trading, disables item drag&drop
void startTrade(); void startTrade();
void onFrame(); void onFrame();
void pickUpObject (MWWorld::Ptr object);
int getPlayerGold(); int getPlayerGold();
protected: protected:
@ -48,6 +50,10 @@ namespace MWGui
virtual bool isInventory() { return true; } virtual bool isInventory() { return true; }
virtual std::vector<MWWorld::Ptr> getEquippedItems(); virtual std::vector<MWWorld::Ptr> getEquippedItems();
virtual void _unequipItem(MWWorld::Ptr item); virtual void _unequipItem(MWWorld::Ptr item);
virtual void onReferenceUnavailable() { ; }
virtual void notifyContentChanged();
}; };
} }

@ -131,7 +131,7 @@ void MWGui::JournalWindow::open()
book journal; book journal;
journal.endLine = 0; journal.endLine = 0;
for(std::deque<MWDialogue::StampedJournalEntry>::const_iterator it = MWBase::Environment::get().getJournal()->begin();it!=MWBase::Environment::get().getJournal()->end();it++) for(std::deque<MWDialogue::StampedJournalEntry>::const_iterator it = MWBase::Environment::get().getJournal()->begin();it!=MWBase::Environment::get().getJournal()->end();++it)
{ {
std::string a = it->getText(MWBase::Environment::get().getWorld()->getStore()); std::string a = it->getText(MWBase::Environment::get().getWorld()->getStore());
journal = formatText(a,journal,10,17); journal = formatText(a,journal,10,17);
@ -141,7 +141,7 @@ void MWGui::JournalWindow::open()
//std::string a = MWBase::Environment::get().getJournal()->begin()->getText(MWBase::Environment::get().getWorld()->getStore()); //std::string a = MWBase::Environment::get().getJournal()->begin()->getText(MWBase::Environment::get().getWorld()->getStore());
//std::list<std::string> journal = formatText(a,10,20,1); //std::list<std::string> journal = formatText(a,10,20,1);
bool left = true; bool left = true;
for(std::list<std::string>::iterator it = journal.pages.begin(); it != journal.pages.end();it++) for(std::list<std::string>::iterator it = journal.pages.begin(); it != journal.pages.end();++it)
{ {
if(left) if(left)
{ {

@ -11,6 +11,7 @@ LocalMapBase::LocalMapBase()
, mInterior(false) , mInterior(false)
, mFogOfWar(true) , mFogOfWar(true)
, mLocalMap(NULL) , mLocalMap(NULL)
, mMapDragAndDrop(false)
, mPrefix() , mPrefix()
, mChanged(true) , mChanged(true)
, mLayout(NULL) , mLayout(NULL)
@ -18,13 +19,41 @@ LocalMapBase::LocalMapBase()
, mLastPositionY(0.0f) , mLastPositionY(0.0f)
, mLastDirectionX(0.0f) , mLastDirectionX(0.0f)
, mLastDirectionY(0.0f) , mLastDirectionY(0.0f)
, mCompass(NULL)
{ {
} }
void LocalMapBase::init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout) void LocalMapBase::init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, OEngine::GUI::Layout* layout, bool mapDragAndDrop)
{ {
mLocalMap = widget; mLocalMap = widget;
mLayout = layout; mLayout = layout;
mMapDragAndDrop = mapDragAndDrop;
mCompass = compass;
// create 3x3 map widgets, 512x512 each, holding a 1024x1024 texture each
const int widgetSize = 512;
for (int mx=0; mx<3; ++mx)
{
for (int my=0; my<3; ++my)
{
MyGUI::ImageBox* map = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
MyGUI::IntCoord(mx*widgetSize, my*widgetSize, widgetSize, widgetSize),
MyGUI::Align::Top | MyGUI::Align::Left, "Map_" + boost::lexical_cast<std::string>(mx) + "_" + boost::lexical_cast<std::string>(my));
MyGUI::ImageBox* fog = map->createWidget<MyGUI::ImageBox>("ImageBox",
MyGUI::IntCoord(0, 0, widgetSize, widgetSize),
MyGUI::Align::Top | MyGUI::Align::Left, "Map_" + boost::lexical_cast<std::string>(mx) + "_" + boost::lexical_cast<std::string>(my) + "_fog");
if (!mMapDragAndDrop)
{
map->setNeedMouseFocus(false);
fog->setNeedMouseFocus(false);
}
mMapWidgets.push_back(map);
mFogWidgets.push_back(fog);
}
}
} }
void LocalMapBase::setCellPrefix(const std::string& prefix) void LocalMapBase::setCellPrefix(const std::string& prefix)
@ -47,10 +76,10 @@ void LocalMapBase::applyFogOfWar()
{ {
std::string name = "Map_" + boost::lexical_cast<std::string>(mx) + "_" std::string name = "Map_" + boost::lexical_cast<std::string>(mx) + "_"
+ boost::lexical_cast<std::string>(my); + boost::lexical_cast<std::string>(my);
std::string image = mPrefix+"_"+ boost::lexical_cast<std::string>(mCurX + (mx-1)) + "_" std::string image = mPrefix+"_"+ boost::lexical_cast<std::string>(mCurX + (mx-1)) + "_"
+ boost::lexical_cast<std::string>(mCurY + (mInterior ? (my-1) : -1*(my-1))); + boost::lexical_cast<std::string>(mCurY + (mInterior ? (my-1) : -1*(my-1)));
MyGUI::ImageBox* fog; MyGUI::ImageBox* fog = mFogWidgets[my + 3*mx];
mLayout->getWidget(fog, name+"_fog");
fog->setImageTexture(mFogOfWar ? fog->setImageTexture(mFogOfWar ?
((MyGUI::RenderManager::getInstance().getTexture(image+"_fog") != 0) ? image+"_fog" ((MyGUI::RenderManager::getInstance().getTexture(image+"_fog") != 0) ? image+"_fog"
: "black.png" ) : "black.png" )
@ -66,14 +95,13 @@ void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
{ {
for (int my=0; my<3; ++my) for (int my=0; my<3; ++my)
{ {
std::string name = "Map_" + boost::lexical_cast<std::string>(mx) + "_"
+ boost::lexical_cast<std::string>(my);
std::string image = mPrefix+"_"+ boost::lexical_cast<std::string>(x + (mx-1)) + "_" std::string image = mPrefix+"_"+ boost::lexical_cast<std::string>(x + (mx-1)) + "_"
+ boost::lexical_cast<std::string>(y + (interior ? (my-1) : -1*(my-1))); + boost::lexical_cast<std::string>(y + (interior ? (my-1) : -1*(my-1)));
MyGUI::ImageBox* box; std::string name = "Map_" + boost::lexical_cast<std::string>(mx) + "_"
mLayout->getWidget(box, name); + boost::lexical_cast<std::string>(my);
MyGUI::ImageBox* box = mMapWidgets[my + 3*mx];
if (MyGUI::RenderManager::getInstance().getTexture(image) != 0) if (MyGUI::RenderManager::getInstance().getTexture(image) != 0)
box->setImageTexture(image); box->setImageTexture(image);
@ -86,6 +114,42 @@ void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
mCurY = y; mCurY = y;
mChanged = false; mChanged = false;
applyFogOfWar(); applyFogOfWar();
// set the compass texture again, because MyGUI determines sorting of ImageBox widgets
// based on the last setImageTexture call
std::string tex = "textures\\compass.dds";
mCompass->setImageTexture("");
mCompass->setImageTexture(tex);
}
void LocalMapBase::setPlayerPos(const float x, const float y)
{
if (x == mLastPositionX && y == mLastPositionY)
return;
MyGUI::IntSize size = mLocalMap->getCanvasSize();
MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height);
MyGUI::IntCoord viewsize = mLocalMap->getCoord();
MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top);
mLocalMap->setViewOffset(pos);
mCompass->setPosition(MyGUI::IntPoint(512+x*512-16, 512+y*512-16));
mLastPositionX = x;
mLastPositionY = y;
}
void LocalMapBase::setPlayerDir(const float x, const float y)
{
if (x == mLastDirectionX && y == mLastDirectionY)
return;
MyGUI::ISubWidget* main = mCompass->getSubWidgetMain();
MyGUI::RotatingSkin* rotatingSubskin = main->castType<MyGUI::RotatingSkin>();
rotatingSubskin->setCenter(MyGUI::IntPoint(16,16));
float angle = std::atan2(x,y);
rotatingSubskin->setAngle(angle);
mLastDirectionX = x;
mLastDirectionY = y;
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
@ -102,7 +166,7 @@ MapWindow::MapWindow(WindowManager& parWindowManager) :
getWidget(mButton, "WorldButton"); getWidget(mButton, "WorldButton");
mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked); mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked);
mButton->setCaption(mWindowManager.getGameSettingString("sWorld", "")); mButton->setCaptionWithReplacing("#{sWorld}");
int width = mButton->getTextSize().width + 24; int width = mButton->getTextSize().width + 24;
mButton->setCoord(mMainWidget->getSize().width - width - 22, mMainWidget->getSize().height - 64, width, 22); mButton->setCoord(mMainWidget->getSize().width - width - 22, mMainWidget->getSize().height - 64, width, 22);
@ -111,7 +175,7 @@ MapWindow::MapWindow(WindowManager& parWindowManager) :
eventbox->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); eventbox->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
eventbox->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); eventbox->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
LocalMapBase::init(mLocalMap, this); LocalMapBase::init(mLocalMap, mPlayerArrow, this);
} }
void MapWindow::setCellName(const std::string& cellName) void MapWindow::setCellName(const std::string& cellName)
@ -119,33 +183,6 @@ void MapWindow::setCellName(const std::string& cellName)
setTitle(cellName); setTitle(cellName);
} }
void MapWindow::setPlayerPos(const float x, const float y)
{
if (mGlobal || !mVisible || (x == mLastPositionX && y == mLastPositionY)) return;
MyGUI::IntSize size = mLocalMap->getCanvasSize();
MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height);
MyGUI::IntCoord viewsize = mLocalMap->getCoord();
MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top);
mLocalMap->setViewOffset(pos);
mPlayerArrow->setPosition(MyGUI::IntPoint(x*512-16, y*512-16));
mLastPositionX = x;
mLastPositionY = y;
}
void MapWindow::setPlayerDir(const float x, const float y)
{
if (!mVisible || (x == mLastDirectionX && y == mLastDirectionY)) return;
MyGUI::ISubWidget* main = mPlayerArrow->getSubWidgetMain();
MyGUI::RotatingSkin* rotatingSubskin = main->castType<MyGUI::RotatingSkin>();
rotatingSubskin->setCenter(MyGUI::IntPoint(16,16));
float angle = std::atan2(x,y);
rotatingSubskin->setAngle(angle);
mLastDirectionX = x;
mLastDirectionY = y;
}
void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
{ {
if (_id!=MyGUI::MouseButton::Left) return; if (_id!=MyGUI::MouseButton::Left) return;
@ -172,8 +209,8 @@ void MapWindow::onWorldButtonClicked(MyGUI::Widget* _sender)
mGlobalMap->setVisible(mGlobal); mGlobalMap->setVisible(mGlobal);
mLocalMap->setVisible(!mGlobal); mLocalMap->setVisible(!mGlobal);
mButton->setCaption( mGlobal ? mWindowManager.getGameSettingString("sWorld", "") : mButton->setCaptionWithReplacing( mGlobal ? "#{sLocal}" :
mWindowManager.getGameSettingString("sLocal", "")); "#{sWorld}");
int width = mButton->getTextSize().width + 24; int width = mButton->getTextSize().width + 24;
mButton->setCoord(mMainWidget->getSize().width - width - 22, mMainWidget->getSize().height - 64, width, 22); mButton->setCoord(mMainWidget->getSize().width - width - 22, mMainWidget->getSize().height - 64, width, 22);
} }

@ -9,10 +9,12 @@ namespace MWGui
{ {
public: public:
LocalMapBase(); LocalMapBase();
void init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout); void init(MyGUI::ScrollView* widget, MyGUI::ImageBox* compass, OEngine::GUI::Layout* layout, bool mapDragAndDrop=false);
void setCellPrefix(const std::string& prefix); void setCellPrefix(const std::string& prefix);
void setActiveCell(const int x, const int y, bool interior=false); void setActiveCell(const int x, const int y, bool interior=false);
void setPlayerDir(const float x, const float y);
void setPlayerPos(const float x, const float y);
void toggleFogOfWar(); void toggleFogOfWar();
@ -20,14 +22,20 @@ namespace MWGui
int mCurX, mCurY; int mCurX, mCurY;
bool mInterior; bool mInterior;
MyGUI::ScrollView* mLocalMap; MyGUI::ScrollView* mLocalMap;
MyGUI::ImageBox* mCompass;
std::string mPrefix; std::string mPrefix;
bool mChanged; bool mChanged;
bool mFogOfWar; bool mFogOfWar;
std::vector<MyGUI::ImageBox*> mMapWidgets;
std::vector<MyGUI::ImageBox*> mFogWidgets;
void applyFogOfWar(); void applyFogOfWar();
OEngine::GUI::Layout* mLayout; OEngine::GUI::Layout* mLayout;
bool mMapDragAndDrop;
float mLastPositionX; float mLastPositionX;
float mLastPositionY; float mLastPositionY;
float mLastDirectionX; float mLastDirectionX;
@ -40,8 +48,6 @@ namespace MWGui
MapWindow(WindowManager& parWindowManager); MapWindow(WindowManager& parWindowManager);
virtual ~MapWindow(){} virtual ~MapWindow(){}
void setPlayerPos(const float x, const float y);
void setPlayerDir(const float x, const float y);
void setCellName(const std::string& cellName); void setCellName(const std::string& cellName);
private: private:

@ -58,7 +58,7 @@ void MessageBoxManager::onFrame (float frameDuration)
if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) { if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) {
delete mInterMessageBoxe; delete mInterMessageBoxe;
mInterMessageBoxe = NULL; mInterMessageBoxe = NULL;
mWindowManager->setNextMode(GM_Game); mWindowManager->popGuiMode();
} }
} }
@ -161,7 +161,7 @@ MessageBox::MessageBox(MessageBoxManager& parMessageBoxManager, const std::strin
getWidget(mMessageWidget, "message"); getWidget(mMessageWidget, "message");
mMessageWidget->setOverflowToTheLeft(true); mMessageWidget->setOverflowToTheLeft(true);
mMessageWidget->addText(cMessage); mMessageWidget->setCaptionWithReplacing(cMessage);
MyGUI::IntSize size; MyGUI::IntSize size;
size.width = mFixedWidth; size.width = mFixedWidth;

@ -5,7 +5,7 @@ namespace MWGui
{ {
enum GuiMode enum GuiMode
{ {
GM_Game, // Game mode, only HUD GM_Settings, // Settings window
GM_Inventory, // Inventory mode GM_Inventory, // Inventory mode
GM_Container, GM_Container,
GM_MainMenu, // Main menu mode GM_MainMenu, // Main menu mode
@ -15,6 +15,7 @@ namespace MWGui
GM_Scroll, // Read scroll GM_Scroll, // Read scroll
GM_Book, // Read book GM_Book, // Read book
GM_Alchemy, // Make potions
GM_Dialogue, // NPC interaction GM_Dialogue, // NPC interaction
GM_Barter, GM_Barter,

@ -1,7 +1,4 @@
#include "race.hpp" #include "race.hpp"
#include "window_manager.hpp"
#include "widgets.hpp"
#include "components/esm_store/store.hpp"
#include <assert.h> #include <assert.h>
#include <iostream> #include <iostream>
@ -10,6 +7,12 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <components/esm_store/store.hpp>
#include "window_manager.hpp"
#include "widgets.hpp"
#include "tooltips.hpp"
using namespace MWGui; using namespace MWGui;
using namespace Widgets; using namespace Widgets;
@ -51,7 +54,7 @@ RaceDialog::RaceDialog(WindowManager& parWindowManager)
prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousFace); prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousFace);
nextButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectNextFace); nextButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectNextFace);
setText("HairChoiceT", mWindowManager.getGameSettingString("sRaceMenu3", "Change Hair")); setText("HairChoiceT", mWindowManager.getGameSettingString("sRaceMenu4", "Change Hair"));
getWidget(prevButton, "PrevHairButton"); getWidget(prevButton, "PrevHairButton");
getWidget(nextButton, "NextHairButton"); getWidget(nextButton, "NextHairButton");
prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousHair); prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousHair);
@ -255,6 +258,8 @@ void RaceDialog::updateSkills()
skillWidget->setWindowManager(&mWindowManager); skillWidget->setWindowManager(&mWindowManager);
skillWidget->setSkillNumber(skillId); skillWidget->setSkillNumber(skillId);
skillWidget->setSkillValue(MWSkill::SkillValue(race->data.bonus[i].bonus)); skillWidget->setSkillValue(MWSkill::SkillValue(race->data.bonus[i].bonus));
ToolTips::createSkillToolTip(skillWidget, skillId);
skillItems.push_back(skillWidget); skillItems.push_back(skillWidget);
@ -288,6 +293,8 @@ void RaceDialog::updateSpellPowers()
spellPowerWidget = spellPowerList->createWidget<MWSpell>("MW_StatName", coord, MyGUI::Align::Default, std::string("SpellPower") + boost::lexical_cast<std::string>(i)); spellPowerWidget = spellPowerList->createWidget<MWSpell>("MW_StatName", coord, MyGUI::Align::Default, std::string("SpellPower") + boost::lexical_cast<std::string>(i));
spellPowerWidget->setWindowManager(&mWindowManager); spellPowerWidget->setWindowManager(&mWindowManager);
spellPowerWidget->setSpellId(spellpower); spellPowerWidget->setSpellId(spellpower);
spellPowerWidget->setUserString("ToolTipType", "Spell");
spellPowerWidget->setUserString("Spell", spellpower);
spellPowerItems.push_back(spellPowerWidget); spellPowerItems.push_back(spellPowerWidget);

@ -0,0 +1,28 @@
#include "referenceinterface.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/world.hpp"
#include "../mwbase/environment.hpp"
namespace MWGui
{
ReferenceInterface::ReferenceInterface()
: mCurrentPlayerCell(NULL)
{
}
void ReferenceInterface::checkReferenceAvailable()
{
if (mPtr.isEmpty())
return;
MWWorld::Ptr::CellStore* playerCell = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell();
// check if player has changed cell, or count of the reference has become 0
if ((playerCell != mCurrentPlayerCell && mCurrentPlayerCell != NULL)
|| mPtr.getRefData().getCount() == 0)
onReferenceUnavailable();
mCurrentPlayerCell = playerCell;
}
}

@ -0,0 +1,29 @@
#ifndef MWGUI_REFERENCEINTERFACE_H
#define MWGUI_REFERENCEINTERFACE_H
#include "../mwworld/ptr.hpp"
namespace MWGui
{
/// \brief this class is intended for GUI interfaces that access an MW-Reference
/// for example dialogue window accesses an NPC, or Container window accesses a Container
/// these classes have to be automatically closed if the reference becomes unavailable
/// make sure that checkReferenceAvailable() is called every frame and that onReferenceUnavailable() has been overridden
class ReferenceInterface
{
public:
ReferenceInterface();
void checkReferenceAvailable(); ///< closes the window, if the MW-reference has become unavailable
protected:
virtual void onReferenceUnavailable() = 0; ///< called when reference has become unavailable
MWWorld::Ptr mPtr;
private:
MWWorld::Ptr::CellStore* mCurrentPlayerCell;
};
}
#endif

@ -1,12 +1,15 @@
#include "review.hpp" #include "review.hpp"
#include "window_manager.hpp"
#include "widgets.hpp" #include <cmath>
#include "components/esm_store/store.hpp"
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <cmath> #include <components/esm_store/store.hpp>
#include "window_manager.hpp"
#include "widgets.hpp"
#include "tooltips.hpp"
#undef min #undef min
#undef max #undef max
@ -74,7 +77,7 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager)
getWidget(skillAreaWidget, "Skills"); getWidget(skillAreaWidget, "Skills");
getWidget(skillClientWidget, "SkillClient"); getWidget(skillClientWidget, "SkillClient");
getWidget(skillScrollerWidget, "SkillScroller"); getWidget(skillScrollerWidget, "SkillScroller");
skillClientWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel);
skillScrollerWidget->eventScrollChangePosition += MyGUI::newDelegate(this, &ReviewDialog::onScrollChangePosition); skillScrollerWidget->eventScrollChangePosition += MyGUI::newDelegate(this, &ReviewDialog::onScrollChangePosition);
updateScroller(); updateScroller();
@ -137,13 +140,17 @@ void ReviewDialog::setRace(const std::string &raceId_)
raceId = raceId_; raceId = raceId_;
const ESM::Race *race = mWindowManager.getStore().races.search(raceId); const ESM::Race *race = mWindowManager.getStore().races.search(raceId);
if (race) if (race)
{
ToolTips::createRaceToolTip(raceWidget, race);
raceWidget->setCaption(race->name); raceWidget->setCaption(race->name);
}
} }
void ReviewDialog::setClass(const ESM::Class& class_) void ReviewDialog::setClass(const ESM::Class& class_)
{ {
klass = class_; klass = class_;
classWidget->setCaption(klass.name); classWidget->setCaption(klass.name);
ToolTips::createClassToolTip(classWidget, klass);
} }
void ReviewDialog::setBirthSign(const std::string& signId) void ReviewDialog::setBirthSign(const std::string& signId)
@ -151,22 +158,31 @@ void ReviewDialog::setBirthSign(const std::string& signId)
birthSignId = signId; birthSignId = signId;
const ESM::BirthSign *sign = mWindowManager.getStore().birthSigns.search(birthSignId); const ESM::BirthSign *sign = mWindowManager.getStore().birthSigns.search(birthSignId);
if (sign) if (sign)
{
birthSignWidget->setCaption(sign->name); birthSignWidget->setCaption(sign->name);
ToolTips::createBirthsignToolTip(birthSignWidget, birthSignId);
}
} }
void ReviewDialog::setHealth(const MWMechanics::DynamicStat<int>& value) void ReviewDialog::setHealth(const MWMechanics::DynamicStat<int>& value)
{ {
health->setValue(value.getCurrent(), value.getModified()); health->setValue(value.getCurrent(), value.getModified());
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
health->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr);
} }
void ReviewDialog::setMagicka(const MWMechanics::DynamicStat<int>& value) void ReviewDialog::setMagicka(const MWMechanics::DynamicStat<int>& value)
{ {
magicka->setValue(value.getCurrent(), value.getModified()); magicka->setValue(value.getCurrent(), value.getModified());
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
magicka->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr);
} }
void ReviewDialog::setFatigue(const MWMechanics::DynamicStat<int>& value) void ReviewDialog::setFatigue(const MWMechanics::DynamicStat<int>& value)
{ {
fatigue->setValue(value.getCurrent(), value.getModified()); fatigue->setValue(value.getCurrent(), value.getModified());
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
fatigue->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
} }
void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat<int>& value) void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat<int>& value)
@ -195,6 +211,7 @@ void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanic
widget->setCaption(text); widget->setCaption(text);
widget->_setWidgetState(state); widget->_setWidgetState(state);
} }
} }
void ReviewDialog::configureSkills(const std::vector<int>& major, const std::vector<int>& minor) void ReviewDialog::configureSkills(const std::vector<int>& major, const std::vector<int>& minor)
@ -214,11 +231,15 @@ void ReviewDialog::configureSkills(const std::vector<int>& major, const std::vec
if (skillSet.find(skill) == skillSet.end()) if (skillSet.find(skill) == skillSet.end())
miscSkills.push_back(skill); miscSkills.push_back(skill);
} }
updateSkillArea();
} }
void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
{ {
MyGUI::ImageBox* separator = skillClientWidget->createWidget<MyGUI::ImageBox>("MW_HLine", MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), MyGUI::Align::Default); MyGUI::ImageBox* separator = skillClientWidget->createWidget<MyGUI::ImageBox>("MW_HLine", MyGUI::IntCoord(10, coord1.top, coord1.width + coord2.width - 4, 18), MyGUI::Align::Default);
separator->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel);
skillWidgets.push_back(separator); skillWidgets.push_back(separator);
coord1.top += separator->getHeight(); coord1.top += separator->getHeight();
@ -228,6 +249,7 @@ void ReviewDialog::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2
void ReviewDialog::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) void ReviewDialog::addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
{ {
MyGUI::TextBox* groupWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), MyGUI::Align::Default); MyGUI::TextBox* groupWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height), MyGUI::Align::Default);
groupWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel);
groupWidget->setCaption(label); groupWidget->setCaption(label);
skillWidgets.push_back(groupWidget); skillWidgets.push_back(groupWidget);
@ -235,17 +257,19 @@ void ReviewDialog::addGroup(const std::string &label, MyGUI::IntCoord &coord1, M
coord2.top += lineHeight; coord2.top += lineHeight;
} }
MyGUI::TextBox* ReviewDialog::addValueItem(const std::string text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) MyGUI::TextBox* ReviewDialog::addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
{ {
MyGUI::TextBox* skillNameWidget; MyGUI::TextBox* skillNameWidget;
MyGUI::TextBox* skillValueWidget; MyGUI::TextBox* skillValueWidget;
skillNameWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandText", coord1, MyGUI::Align::Default); skillNameWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandText", coord1, MyGUI::Align::Default);
skillNameWidget->setCaption(text); skillNameWidget->setCaption(text);
skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel);
skillValueWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandTextRight", coord2, MyGUI::Align::Top | MyGUI::Align::Right); skillValueWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandTextRight", coord2, MyGUI::Align::Top | MyGUI::Align::Right);
skillValueWidget->setCaption(value); skillValueWidget->setCaption(value);
skillValueWidget->_setWidgetState(state); skillValueWidget->_setWidgetState(state);
skillValueWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel);
skillWidgets.push_back(skillNameWidget); skillWidgets.push_back(skillNameWidget);
skillWidgets.push_back(skillValueWidget); skillWidgets.push_back(skillValueWidget);
@ -256,12 +280,13 @@ MyGUI::TextBox* ReviewDialog::addValueItem(const std::string text, const std::st
return skillValueWidget; return skillValueWidget;
} }
void ReviewDialog::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) void ReviewDialog::addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
{ {
MyGUI::TextBox* skillNameWidget; MyGUI::TextBox* skillNameWidget;
skillNameWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default); skillNameWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default);
skillNameWidget->setCaption(text); skillNameWidget->setCaption(text);
skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel);
skillWidgets.push_back(skillNameWidget); skillWidgets.push_back(skillNameWidget);
@ -297,6 +322,12 @@ void ReviewDialog::addSkills(const SkillList &skills, const std::string &titleId
else if (modified < base) else if (modified < base)
state = "decreased"; state = "decreased";
MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast<std::string>(static_cast<int>(modified)), state, coord1, coord2); MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), boost::lexical_cast<std::string>(static_cast<int>(modified)), state, coord1, coord2);
for (int i=0; i<2; ++i)
{
ToolTips::createSkillToolTip(skillWidgets[skillWidgets.size()-1-i], skillId);
}
skillWidgetMap[skillId] = widget; skillWidgetMap[skillId] = widget;
} }
} }
@ -330,6 +361,8 @@ void ReviewDialog::updateScroller()
{ {
skillScrollerWidget->setScrollRange(std::max(clientHeight - skillClientWidget->getHeight(), 0)); skillScrollerWidget->setScrollRange(std::max(clientHeight - skillClientWidget->getHeight(), 0));
skillScrollerWidget->setScrollPage(std::max(skillClientWidget->getHeight() - lineHeight, 0)); skillScrollerWidget->setScrollPage(std::max(skillClientWidget->getHeight() - lineHeight, 0));
if (clientHeight != 0)
skillScrollerWidget->setTrackSize( (skillAreaWidget->getHeight() / float(clientHeight)) * skillScrollerWidget->getLineSize() );
} }
// widget controls // widget controls
@ -363,3 +396,15 @@ void ReviewDialog::onBirthSignClicked(MyGUI::Widget* _sender)
{ {
eventActivateDialog(BIRTHSIGN_DIALOG); eventActivateDialog(BIRTHSIGN_DIALOG);
} }
void ReviewDialog::onMouseWheel(MyGUI::Widget* _sender, int _rel)
{
if (skillScrollerWidget->getScrollPosition() - _rel*0.3 < 0)
skillScrollerWidget->setScrollPosition(0);
else if (skillScrollerWidget->getScrollPosition() - _rel*0.3 > skillScrollerWidget->getScrollRange()-1)
skillScrollerWidget->setScrollPosition(skillScrollerWidget->getScrollRange()-1);
else
skillScrollerWidget->setScrollPosition(skillScrollerWidget->getScrollPosition() - _rel*0.3);
onScrollChangePosition(skillScrollerWidget, skillScrollerWidget->getScrollPosition());
}

@ -68,12 +68,14 @@ namespace MWGui
void onClassClicked(MyGUI::Widget* _sender); void onClassClicked(MyGUI::Widget* _sender);
void onBirthSignClicked(MyGUI::Widget* _sender); void onBirthSignClicked(MyGUI::Widget* _sender);
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
private: private:
void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
MyGUI::TextBox* addValueItem(const std::string text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); MyGUI::TextBox* addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
void addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
void updateScroller(); void updateScroller();
void updateSkillArea(); void updateSkillArea();

@ -1,12 +1,13 @@
#include "scrollwindow.hpp" #include "scrollwindow.hpp"
#include "formatting.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwinput/inputmanager.hpp" #include "../mwinput/inputmanager.hpp"
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwsound/soundmanager.hpp" #include "../mwsound/soundmanager.hpp"
#include "formatting.hpp"
#include "window_manager.hpp"
using namespace MWGui; using namespace MWGui;
ScrollWindow::ScrollWindow (WindowManager& parWindowManager) : ScrollWindow::ScrollWindow (WindowManager& parWindowManager) :
@ -55,7 +56,7 @@ void ScrollWindow::onCloseButtonClicked (MyGUI::Widget* _sender)
{ {
MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0); MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0);
MWBase::Environment::get().getInputManager()->setGuiMode (GM_Game); mWindowManager.popGuiMode();
} }
void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender) void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender)
@ -65,5 +66,5 @@ void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender)
MWWorld::ActionTake take(mScroll); MWWorld::ActionTake take(mScroll);
take.execute(); take.execute();
MWBase::Environment::get().getInputManager()->setGuiMode (GM_Game); mWindowManager.popGuiMode();
} }

@ -0,0 +1,342 @@
#include "settingswindow.hpp"
#include <OgreRoot.h>
#include <OgreRenderSystem.h>
#include <OgreString.h>
#include <boost/lexical_cast.hpp>
#include <components/settings/settings.hpp>
#include "../mwbase/environment.hpp"
#include "../mwworld/world.hpp"
#include "../mwsound/soundmanager.hpp"
#include "../mwinput/inputmanager.hpp"
#include "window_manager.hpp"
#include "confirmationdialog.hpp"
namespace
{
std::string fpsLevelToStr(int level)
{
if (level == 0)
return "#{sOff}";
else if (level == 1)
return "Basic";
else
return "Detailed";
}
std::string textureFilteringToStr(const std::string& val)
{
if (val == "none")
return "None";
else if (val == "anisotropic")
return "Anisotropic";
else if (val == "bilinear")
return "Bilinear";
else
return "Trilinear";
}
}
namespace MWGui
{
SettingsWindow::SettingsWindow(WindowManager& parWindowManager) :
WindowBase("openmw_settings_window_layout.xml", parWindowManager)
{
getWidget(mOkButton, "OkButton");
getWidget(mResolutionList, "ResolutionList");
getWidget(mMenuTransparencySlider, "MenuTransparencySlider");
getWidget(mToolTipDelaySlider, "ToolTipDelaySlider");
getWidget(mViewDistanceSlider, "ViewDistanceSlider");
getWidget(mFullscreenButton, "FullscreenButton");
getWidget(mVSyncButton, "VSyncButton");
getWidget(mFPSButton, "FPSButton");
getWidget(mFOVSlider, "FOVSlider");
getWidget(mMasterVolumeSlider, "MasterVolume");
getWidget(mVoiceVolumeSlider, "VoiceVolume");
getWidget(mEffectsVolumeSlider, "EffectsVolume");
getWidget(mFootstepsVolumeSlider, "FootstepsVolume");
getWidget(mMusicVolumeSlider, "MusicVolume");
getWidget(mAnisotropySlider, "AnisotropySlider");
getWidget(mTextureFilteringButton, "TextureFilteringButton");
getWidget(mAnisotropyLabel, "AnisotropyLabel");
getWidget(mAnisotropyBox, "AnisotropyBox");
getWidget(mWaterShaderButton, "WaterShaderButton");
getWidget(mReflectObjectsButton, "ReflectObjectsButton");
getWidget(mReflectActorsButton, "ReflectActorsButton");
getWidget(mReflectTerrainButton, "ReflectTerrainButton");
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked);
mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mWaterShaderButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mReflectObjectsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mReflectTerrainButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mReflectActorsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mTextureFilteringButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onTextureFilteringToggled);
mVSyncButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled);
mMenuTransparencySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mFOVSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mToolTipDelaySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected);
mAnisotropySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mMasterVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mVoiceVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mEffectsVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mFootstepsVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mMusicVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
center();
int okSize = mOkButton->getTextSize().width + 24;
mOkButton->setCoord(mMainWidget->getWidth()-16-okSize, mOkButton->getTop(),
okSize, mOkButton->getHeight());
// fill resolution list
Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem();
const Ogre::StringVector& videoModes = rs->getConfigOptions()["Video Mode"].possibleValues;
for (Ogre::StringVector::const_iterator it=videoModes.begin();
it!=videoModes.end(); ++it)
{
mResolutionList->addItem(*it);
}
// read settings
int menu_transparency = (mMenuTransparencySlider->getScrollRange()-1) * Settings::Manager::getFloat("menu transparency", "GUI");
mMenuTransparencySlider->setScrollPosition(menu_transparency);
int tooltip_delay = (mToolTipDelaySlider->getScrollRange()-1) * Settings::Manager::getFloat("tooltip delay", "GUI");
mToolTipDelaySlider->setScrollPosition(tooltip_delay);
float fovVal = (Settings::Manager::getFloat("field of view", "General")-sFovMin)/(sFovMax-sFovMin);
mFOVSlider->setScrollPosition(fovVal * (mFOVSlider->getScrollRange()-1));
MyGUI::TextBox* fovText;
getWidget(fovText, "FovText");
fovText->setCaption("Field of View (" + boost::lexical_cast<std::string>(int(Settings::Manager::getFloat("field of view", "General"))) + ")");
float anisotropyVal = Settings::Manager::getInt("anisotropy", "General") / 16.0;
mAnisotropySlider->setScrollPosition(anisotropyVal * (mAnisotropySlider->getScrollRange()-1));
std::string tf = Settings::Manager::getString("texture filtering", "General");
mTextureFilteringButton->setCaption(textureFilteringToStr(tf));
mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast<std::string>(Settings::Manager::getInt("anisotropy", "General")) + ")");
mAnisotropyBox->setVisible(tf == "anisotropic");
float val = (Settings::Manager::getFloat("max viewing distance", "Viewing distance")-sViewDistMin)/(sViewDistMax-sViewDistMin);
int viewdist = (mViewDistanceSlider->getScrollRange()-1) * val;
mViewDistanceSlider->setScrollPosition(viewdist);
mMasterVolumeSlider->setScrollPosition(Settings::Manager::getFloat("master volume", "Sound") * (mMasterVolumeSlider->getScrollRange()-1));
mMusicVolumeSlider->setScrollPosition(Settings::Manager::getFloat("music volume", "Sound") * (mMusicVolumeSlider->getScrollRange()-1));
mEffectsVolumeSlider->setScrollPosition(Settings::Manager::getFloat("sfx volume", "Sound") * (mEffectsVolumeSlider->getScrollRange()-1));
mFootstepsVolumeSlider->setScrollPosition(Settings::Manager::getFloat("footsteps volume", "Sound") * (mFootstepsVolumeSlider->getScrollRange()-1));
mVoiceVolumeSlider->setScrollPosition(Settings::Manager::getFloat("voice volume", "Sound") * (mVoiceVolumeSlider->getScrollRange()-1));
mWaterShaderButton->setCaptionWithReplacing(Settings::Manager::getBool("shader", "Water") ? "#{sOn}" : "#{sOff}");
mReflectObjectsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect objects", "Water") ? "#{sOn}" : "#{sOff}");
mReflectActorsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect actors", "Water") ? "#{sOn}" : "#{sOff}");
mReflectTerrainButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect terrain", "Water") ? "#{sOn}" : "#{sOff}");
if (!MWRender::RenderingManager::waterShaderSupported())
{
mWaterShaderButton->setEnabled(false);
mReflectObjectsButton->setEnabled(false);
mReflectActorsButton->setEnabled(false);
mReflectTerrainButton->setEnabled(false);
}
mFullscreenButton->setCaptionWithReplacing(Settings::Manager::getBool("fullscreen", "Video") ? "#{sOn}" : "#{sOff}");
mVSyncButton->setCaptionWithReplacing(Settings::Manager::getBool("vsync", "Video") ? "#{sOn}": "#{sOff}");
mFPSButton->setCaptionWithReplacing(fpsLevelToStr(Settings::Manager::getInt("fps", "HUD")));
}
void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender)
{
mWindowManager.popGuiMode();
}
void SettingsWindow::onResolutionSelected(MyGUI::ListBox* _sender, size_t index)
{
if (index == MyGUI::ITEM_NONE)
return;
ConfirmationDialog* dialog = mWindowManager.getConfirmationDialog();
dialog->open("#{sNotifyMessage67}");
dialog->eventOkClicked.clear();
dialog->eventOkClicked += MyGUI::newDelegate(this, &SettingsWindow::onResolutionAccept);
dialog->eventCancelClicked.clear();
dialog->eventCancelClicked += MyGUI::newDelegate(this, &SettingsWindow::onResolutionAccept);
}
void SettingsWindow::onResolutionAccept()
{
std::string resStr = mResolutionList->getItemNameAt(mResolutionList->getIndexSelected());
size_t xPos = resStr.find("x");
std::string resXStr = resStr.substr(0, xPos-1);
Ogre::StringUtil::trim(resXStr);
std::string resYStr = resStr.substr(xPos+2, resStr.size()-(xPos+2));
Ogre::StringUtil::trim(resYStr);
int resX = boost::lexical_cast<int>(resXStr);
int resY = boost::lexical_cast<int>(resYStr);
Settings::Manager::setInt("resolution x", "Video", resX);
Settings::Manager::setInt("resolution y", "Video", resY);
apply();
mResolutionList->setIndexSelected(MyGUI::ITEM_NONE);
}
void SettingsWindow::onResolutionCancel()
{
mResolutionList->setIndexSelected(MyGUI::ITEM_NONE);
}
void SettingsWindow::onButtonToggled(MyGUI::Widget* _sender)
{
std::string on = mWindowManager.getGameSettingString("sOn", "On");
std::string off = mWindowManager.getGameSettingString("sOff", "On");
bool newState;
if (_sender->castType<MyGUI::Button>()->getCaption() == on)
{
_sender->castType<MyGUI::Button>()->setCaption(off);
newState = false;
}
else
{
_sender->castType<MyGUI::Button>()->setCaption(on);
newState = true;
}
if (_sender == mFullscreenButton)
{
// check if this resolution is supported in fullscreen
bool supported = false;
for (unsigned int i=0; i<mResolutionList->getItemCount(); ++i)
{
std::string resStr = mResolutionList->getItemNameAt(i);
size_t xPos = resStr.find("x");
std::string resXStr = resStr.substr(0, xPos-1);
Ogre::StringUtil::trim(resXStr);
std::string resYStr = resStr.substr(xPos+2, resStr.size()-(xPos+2));
Ogre::StringUtil::trim(resYStr);
int resX = boost::lexical_cast<int>(resXStr);
int resY = boost::lexical_cast<int>(resYStr);
if (resX == Settings::Manager::getInt("resolution x", "Video")
&& resY == Settings::Manager::getInt("resolution y", "Video"))
supported = true;
}
if (!supported)
{
std::string msg = "This resolution is not supported in Fullscreen mode. Please select a resolution from the list.";
MWBase::Environment::get().getWindowManager()->
messageBox(msg, std::vector<std::string>());
_sender->castType<MyGUI::Button>()->setCaption(off);
}
else
{
Settings::Manager::setBool("fullscreen", "Video", newState);
apply();
}
}
else if (_sender == mVSyncButton)
{
Settings::Manager::setBool("vsync", "Video", newState);
MWBase::Environment::get().getWindowManager()->
messageBox("VSync will be applied after a restart", std::vector<std::string>());
}
else
{
if (_sender == mWaterShaderButton)
Settings::Manager::setBool("shader", "Water", newState);
else if (_sender == mReflectObjectsButton)
{
Settings::Manager::setBool("reflect misc", "Water", newState);
Settings::Manager::setBool("reflect statics", "Water", newState);
Settings::Manager::setBool("reflect statics small", "Water", newState);
}
else if (_sender == mReflectActorsButton)
Settings::Manager::setBool("reflect actors", "Water", newState);
else if (_sender == mReflectTerrainButton)
Settings::Manager::setBool("reflect terrain", "Water", newState);
apply();
}
}
void SettingsWindow::onFpsToggled(MyGUI::Widget* _sender)
{
int newLevel = (Settings::Manager::getInt("fps", "HUD") + 1) % 3;
Settings::Manager::setInt("fps", "HUD", newLevel);
mFPSButton->setCaptionWithReplacing(fpsLevelToStr(newLevel));
apply();
}
void SettingsWindow::onTextureFilteringToggled(MyGUI::Widget* _sender)
{
std::string current = Settings::Manager::getString("texture filtering", "General");
std::string next;
if (current == "none")
next = "bilinear";
else if (current == "bilinear")
next = "trilinear";
else if (current == "trilinear")
next = "anisotropic";
else
next = "none";
mTextureFilteringButton->setCaption(textureFilteringToStr(next));
mAnisotropyBox->setVisible(next == "anisotropic");
Settings::Manager::setString("texture filtering", "General", next);
apply();
}
void SettingsWindow::onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos)
{
float val = pos / float(scroller->getScrollRange()-1);
if (scroller == mMenuTransparencySlider)
Settings::Manager::setFloat("menu transparency", "GUI", val);
else if (scroller == mToolTipDelaySlider)
Settings::Manager::setFloat("tooltip delay", "GUI", val);
else if (scroller == mViewDistanceSlider)
Settings::Manager::setFloat("max viewing distance", "Viewing distance", (1-val) * sViewDistMin + val * sViewDistMax);
else if (scroller == mFOVSlider)
{
MyGUI::TextBox* fovText;
getWidget(fovText, "FovText");
fovText->setCaption("Field of View (" + boost::lexical_cast<std::string>(int((1-val) * sFovMin + val * sFovMax)) + ")");
Settings::Manager::setFloat("field of view", "General", (1-val) * sFovMin + val * sFovMax);
}
else if (scroller == mAnisotropySlider)
{
mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast<std::string>(int(val*16)) + ")");
Settings::Manager::setInt("anisotropy", "General", val * 16);
}
else if (scroller == mMasterVolumeSlider)
Settings::Manager::setFloat("master volume", "Sound", val);
else if (scroller == mVoiceVolumeSlider)
Settings::Manager::setFloat("voice volume", "Sound", val);
else if (scroller == mEffectsVolumeSlider)
Settings::Manager::setFloat("sfx volume", "Sound", val);
else if (scroller == mFootstepsVolumeSlider)
Settings::Manager::setFloat("footsteps volume", "Sound", val);
else if (scroller == mMusicVolumeSlider)
Settings::Manager::setFloat("music volume", "Sound", val);
apply();
}
void SettingsWindow::apply()
{
const Settings::CategorySettingVector changed = Settings::Manager::apply();
MWBase::Environment::get().getWorld()->processChangedSettings(changed);
MWBase::Environment::get().getSoundManager()->processChangedSettings(changed);
MWBase::Environment::get().getWindowManager()->processChangedSettings(changed);
MWBase::Environment::get().getInputManager()->processChangedSettings(changed);
}
}

@ -0,0 +1,67 @@
#ifndef MWGUI_SETTINGS_H
#define MWGUI_SETTINGS_H
#include "window_base.hpp"
namespace MWGui
{
class WindowManager;
}
namespace MWGui
{
class SettingsWindow : public WindowBase
{
public:
SettingsWindow(WindowManager& parWindowManager);
private:
static int const sFovMin = 30;
static int const sFovMax = 140;
static int const sViewDistMin = 2000;
static int const sViewDistMax = 5600;
protected:
MyGUI::Button* mOkButton;
MyGUI::ScrollBar* mMenuTransparencySlider;
MyGUI::ScrollBar* mToolTipDelaySlider;
// graphics
MyGUI::ListBox* mResolutionList;
MyGUI::Button* mFullscreenButton;
MyGUI::Button* mVSyncButton;
MyGUI::Button* mFPSButton;
MyGUI::ScrollBar* mViewDistanceSlider;
MyGUI::ScrollBar* mFOVSlider;
MyGUI::ScrollBar* mAnisotropySlider;
MyGUI::Button* mTextureFilteringButton;
MyGUI::TextBox* mAnisotropyLabel;
MyGUI::Widget* mAnisotropyBox;
MyGUI::Button* mWaterShaderButton;
MyGUI::Button* mReflectObjectsButton;
MyGUI::Button* mReflectActorsButton;
MyGUI::Button* mReflectTerrainButton;
// audio
MyGUI::ScrollBar* mMasterVolumeSlider;
MyGUI::ScrollBar* mVoiceVolumeSlider;
MyGUI::ScrollBar* mEffectsVolumeSlider;
MyGUI::ScrollBar* mFootstepsVolumeSlider;
MyGUI::ScrollBar* mMusicVolumeSlider;
void onOkButtonClicked(MyGUI::Widget* _sender);
void onFpsToggled(MyGUI::Widget* _sender);
void onTextureFilteringToggled(MyGUI::Widget* _sender);
void onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos);
void onButtonToggled(MyGUI::Widget* _sender);
void onResolutionSelected(MyGUI::ListBox* _sender, size_t index);
void onResolutionAccept();
void onResolutionCancel();
void apply();
};
}
#endif

@ -0,0 +1,459 @@
#include "spellwindow.hpp"
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>
#include "../mwworld/world.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwbase/environment.hpp"
#include "../mwmechanics/spells.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/spellsuccess.hpp"
#include "../mwsound/soundmanager.hpp"
#include "window_manager.hpp"
#include "inventorywindow.hpp"
#include "confirmationdialog.hpp"
namespace
{
bool sortSpells(const std::string& left, const std::string& right)
{
const ESM::Spell* a = MWBase::Environment::get().getWorld()->getStore().spells.find(left);
const ESM::Spell* b = MWBase::Environment::get().getWorld()->getStore().spells.find(right);
int cmp = a->name.compare(b->name);
return cmp < 0;
}
bool sortItems(const MWWorld::Ptr& left, const MWWorld::Ptr& right)
{
int cmp = MWWorld::Class::get(left).getName(left).compare(
MWWorld::Class::get(right).getName(right));
return cmp < 0;
}
}
namespace MWGui
{
SpellWindow::SpellWindow(WindowManager& parWindowManager)
: WindowPinnableBase("openmw_spell_window_layout.xml", parWindowManager)
, mHeight(0)
, mWidth(0)
{
getWidget(mSpellView, "SpellView");
getWidget(mEffectBox, "EffectsBox");
setCoord(498, 300, 302, 300);
updateSpells();
mMainWidget->castType<MyGUI::Window>()->eventWindowChangeCoord += MyGUI::newDelegate(this, &SpellWindow::onWindowResize);
}
void SpellWindow::onPinToggled()
{
mWindowManager.setSpellVisibility(!mPinned);
}
void SpellWindow::open()
{
updateSpells();
}
void SpellWindow::updateSpells()
{
const int spellHeight = 18;
mHeight = 0;
while (mSpellView->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mSpellView->getChildAt(0));
// retrieve all player spells, divide them into Powers and Spells and sort them
std::vector<std::string> spellList;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player);
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
MWMechanics::Spells& spells = stats.mSpells;
// the following code switches between selected enchanted item and selected spell (only one of these
// can be active at a time)
std::string selectedSpell = spells.getSelectedSpell();
MWWorld::Ptr selectedItem;
if (store.getSelectedEnchantItem() != store.end())
{
selectedSpell = "";
selectedItem = *store.getSelectedEnchantItem();
bool allowSelectedItem = true;
// make sure that the item is still in the player inventory, otherwise it can't be selected
bool found = false;
for (MWWorld::ContainerStoreIterator it(store.begin()); it != store.end(); ++it)
{
if (*it == selectedItem)
found = true;
}
if (!found)
allowSelectedItem = false;
// if the selected item can be equipped, make sure that it actually is equipped
std::pair<std::vector<int>, bool> slots;
slots = MWWorld::Class::get(selectedItem).getEquipmentSlots(selectedItem);
if (!slots.first.empty())
{
bool equipped = false;
for (int i=0; i < MWWorld::InventoryStore::Slots; ++i)
{
if (store.getSlot(i) != store.end() && *store.getSlot(i) == selectedItem)
{
equipped = true;
break;
}
}
if (!equipped)
allowSelectedItem = false;
}
if (!allowSelectedItem)
{
store.setSelectedEnchantItem(store.end());
spells.setSelectedSpell("");
mWindowManager.unsetSelectedSpell();
selectedItem = MWWorld::Ptr();
}
}
for (MWMechanics::Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
{
spellList.push_back(*it);
}
std::vector<std::string> powers;
std::vector<std::string>::iterator it = spellList.begin();
while (it != spellList.end())
{
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it);
if (spell->data.type == ESM::Spell::ST_Power)
{
powers.push_back(*it);
it = spellList.erase(it);
}
else if (spell->data.type == ESM::Spell::ST_Ability)
{
// abilities are always active and don't show in the spell window.
it = spellList.erase(it);
}
else
++it;
}
std::sort(powers.begin(), powers.end(), sortSpells);
std::sort(spellList.begin(), spellList.end(), sortSpells);
// retrieve player's enchanted items
std::vector<MWWorld::Ptr> items;
for (MWWorld::ContainerStoreIterator it(store.begin()); it != store.end(); ++it)
{
std::string enchantId = MWWorld::Class::get(*it).getEnchantment(*it);
if (enchantId != "")
{
// only add items with "Cast once" or "Cast on use"
const ESM::Enchantment* enchant = MWBase::Environment::get().getWorld()->getStore().enchants.find(enchantId);
int type = enchant->data.type;
if (type != ESM::Enchantment::CastOnce
&& type != ESM::Enchantment::WhenUsed)
continue;
items.push_back(*it);
}
}
std::sort(items.begin(), items.end(), sortItems);
int height = estimateHeight(items.size() + powers.size() + spellList.size());
bool scrollVisible = height > mSpellView->getHeight();
mWidth = mSpellView->getWidth() - (scrollVisible ? 18 : 0);
// powers
addGroup("#{sPowers}", "");
for (std::vector<std::string>::const_iterator it = powers.begin(); it != powers.end(); ++it)
{
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it);
MyGUI::Button* t = mSpellView->createWidget<MyGUI::Button>("SpellText",
MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top);
t->setCaption(spell->name);
t->setTextAlign(MyGUI::Align::Left);
t->setUserString("ToolTipType", "Spell");
t->setUserString("Spell", *it);
t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel);
t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onSpellSelected);
if (*it == selectedSpell)
t->setStateSelected(true);
mHeight += spellHeight;
}
// other spells
addGroup("#{sSpells}", "#{sCostChance}");
for (std::vector<std::string>::const_iterator it = spellList.begin(); it != spellList.end(); ++it)
{
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(*it);
MyGUI::Button* t = mSpellView->createWidget<MyGUI::Button>("SpellText",
MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top);
t->setCaption(spell->name);
t->setTextAlign(MyGUI::Align::Left);
t->setUserString("ToolTipType", "Spell");
t->setUserString("Spell", *it);
t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel);
t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onSpellSelected);
t->setStateSelected(*it == selectedSpell);
// cost / success chance
MyGUI::Button* costChance = mSpellView->createWidget<MyGUI::Button>("SpellText",
MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top);
std::string cost = boost::lexical_cast<std::string>(spell->data.cost);
std::string chance = boost::lexical_cast<std::string>(int(MWMechanics::getSpellSuccessChance(*it, player)));
costChance->setCaption(cost + "/" + chance);
costChance->setTextAlign(MyGUI::Align::Right);
costChance->setNeedMouseFocus(false);
costChance->setStateSelected(*it == selectedSpell);
mHeight += spellHeight;
}
// enchanted items
addGroup("#{sMagicItem}", "#{sCostCharge}");
for (std::vector<MWWorld::Ptr>::const_iterator it = items.begin(); it != items.end(); ++it)
{
MWWorld::Ptr item = *it;
const ESM::Enchantment* enchant = MWBase::Environment::get().getWorld()->getStore().enchants.find(MWWorld::Class::get(item).getEnchantment(item));
// check if the item is currently equipped (will display in a different color)
bool equipped = false;
for (int i=0; i < MWWorld::InventoryStore::Slots; ++i)
{
if (store.getSlot(i) != store.end() && *store.getSlot(i) == item)
{
equipped = true;
break;
}
}
MyGUI::Button* t = mSpellView->createWidget<MyGUI::Button>(equipped ? "SpellText" : "SpellTextUnequipped",
MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top);
t->setCaption(MWWorld::Class::get(item).getName(item));
t->setTextAlign(MyGUI::Align::Left);
t->setUserData(item);
t->setUserString("ToolTipType", "ItemPtr");
t->setUserString("Equipped", equipped ? "true" : "false");
t->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onEnchantedItemSelected);
t->eventMouseWheel += MyGUI::newDelegate(this, &SpellWindow::onMouseWheel);
t->setStateSelected(item == selectedItem);
// cost / charge
MyGUI::Button* costCharge = mSpellView->createWidget<MyGUI::Button>(equipped ? "SpellText" : "SpellTextUnequipped",
MyGUI::IntCoord(4, mHeight, mWidth-8, spellHeight), MyGUI::Align::Left | MyGUI::Align::Top);
std::string cost = boost::lexical_cast<std::string>(enchant->data.cost);
std::string charge = boost::lexical_cast<std::string>(enchant->data.charge); /// \todo track current charge
if (enchant->data.type == ESM::Enchantment::CastOnce)
{
// this is Morrowind behaviour
cost = "100";
charge = "100";
}
costCharge->setCaption(cost + "/" + charge);
costCharge->setTextAlign(MyGUI::Align::Right);
costCharge->setNeedMouseFocus(false);
costCharge->setStateSelected(item == selectedItem);
mHeight += spellHeight;
}
mSpellView->setCanvasSize(mSpellView->getWidth(), std::max(mSpellView->getHeight(), mHeight));
}
void SpellWindow::addGroup(const std::string &label, const std::string& label2)
{
if (mSpellView->getChildCount() > 0)
{
MyGUI::ImageBox* separator = mSpellView->createWidget<MyGUI::ImageBox>("MW_HLine",
MyGUI::IntCoord(4, mHeight, mWidth-8, 18),
MyGUI::Align::Left | MyGUI::Align::Top);
separator->setNeedMouseFocus(false);
mHeight += 18;
}
MyGUI::TextBox* groupWidget = mSpellView->createWidget<MyGUI::TextBox>("SandBrightText",
MyGUI::IntCoord(0, mHeight, mWidth, 24),
MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch);
groupWidget->setCaptionWithReplacing(label);
groupWidget->setTextAlign(MyGUI::Align::Left);
groupWidget->setNeedMouseFocus(false);
if (label2 != "")
{
MyGUI::TextBox* groupWidget2 = mSpellView->createWidget<MyGUI::TextBox>("SandBrightText",
MyGUI::IntCoord(0, mHeight, mWidth-4, 24),
MyGUI::Align::Left | MyGUI::Align::Top);
groupWidget2->setCaptionWithReplacing(label2);
groupWidget2->setTextAlign(MyGUI::Align::Right);
groupWidget2->setNeedMouseFocus(false);
}
mHeight += 24;
}
void SpellWindow::onWindowResize(MyGUI::Window* _sender)
{
updateSpells();
}
void SpellWindow::onEnchantedItemSelected(MyGUI::Widget* _sender)
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player);
MWMechanics::Spells& spells = stats.mSpells;
MWWorld::Ptr item = *_sender->getUserData<MWWorld::Ptr>();
// retrieve ContainerStoreIterator to the item
MWWorld::ContainerStoreIterator it = store.begin();
for (; it != store.end(); ++it)
{
if (*it == item)
{
break;
}
}
assert(it != store.end());
// equip, if it can be equipped and is not already equipped
if (_sender->getUserString("Equipped") == "false"
&& !MWWorld::Class::get(item).getEquipmentSlots(item).first.empty())
{
// sound
MWBase::Environment::get().getSoundManager()->playSound(MWWorld::Class::get(item).getUpSoundId(item), 1.0, 1.0);
// Note: can't use Class::use here because enchanted scrolls for example would then open the scroll window instead of equipping
/// \todo the following code is pretty much copy&paste from ActionEquip, put it in a function?
// slots that this item can be equipped in
std::pair<std::vector<int>, bool> slots = MWWorld::Class::get(item).getEquipmentSlots(item);
// equip the item in the first free slot
for (std::vector<int>::const_iterator slot=slots.first.begin();
slot!=slots.first.end(); ++slot)
{
// if all slots are occupied, replace the last slot
if (slot == --slots.first.end())
{
store.equip(*slot, it);
break;
}
if (store.getSlot(*slot) == store.end())
{
// slot is not occupied
store.equip(*slot, it);
break;
}
}
/// \todo scripts?
// since we changed equipping status, update the inventory window
mWindowManager.getInventoryWindow()->drawItems();
}
store.setSelectedEnchantItem(it);
spells.setSelectedSpell("");
mWindowManager.setSelectedEnchantItem(item, 100); /// \todo track charge %
updateSpells();
}
void SpellWindow::onSpellSelected(MyGUI::Widget* _sender)
{
std::string spellId = _sender->getUserString("Spell");
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
MWWorld::InventoryStore& store = MWWorld::Class::get(player).getInventoryStore(player);
MWMechanics::Spells& spells = stats.mSpells;
if (MyGUI::InputManager::getInstance().isShiftPressed())
{
// delete spell, if allowed
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId);
if (spell->data.flags & ESM::Spell::F_Always
|| spell->data.type == ESM::Spell::ST_Power)
{
mWindowManager.messageBox("#{sDeleteSpellError}", std::vector<std::string>());
}
else
{
// ask for confirmation
mSpellToDelete = spellId;
ConfirmationDialog* dialog = mWindowManager.getConfirmationDialog();
std::string question = mWindowManager.getGameSettingString("sQuestionDeleteSpell", "Delete %s?");
question = boost::str(boost::format(question) % spell->name);
dialog->open(question);
dialog->eventOkClicked.clear();
dialog->eventOkClicked += MyGUI::newDelegate(this, &SpellWindow::onDeleteSpellAccept);
dialog->eventCancelClicked.clear();
}
}
else
{
spells.setSelectedSpell(spellId);
store.setSelectedEnchantItem(store.end());
mWindowManager.setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player)));
}
updateSpells();
}
int SpellWindow::estimateHeight(int numSpells) const
{
int height = 0;
height += 24 * 3 + 18 * 2; // group headings
height += numSpells * 18;
return height;
}
void SpellWindow::onMouseWheel(MyGUI::Widget* _sender, int _rel)
{
if (mSpellView->getViewOffset().top + _rel*0.3 > 0)
mSpellView->setViewOffset(MyGUI::IntPoint(0, 0));
else
mSpellView->setViewOffset(MyGUI::IntPoint(0, mSpellView->getViewOffset().top + _rel*0.3));
}
void SpellWindow::onDeleteSpellAccept()
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
MWMechanics::Spells& spells = stats.mSpells;
if (spells.getSelectedSpell() == mSpellToDelete)
{
spells.setSelectedSpell("");
mWindowManager.unsetSelectedSpell();
}
spells.remove(mSpellToDelete);
updateSpells();
}
}

@ -0,0 +1,39 @@
#ifndef MWGUI_SPELLWINDOW_H
#define MWGUI_SPELLWINDOW_H
#include "window_pinnable_base.hpp"
namespace MWGui
{
class SpellWindow : public WindowPinnableBase
{
public:
SpellWindow(WindowManager& parWindowManager);
void updateSpells();
protected:
MyGUI::ScrollView* mSpellView;
MyGUI::Widget* mEffectBox;
int mHeight;
int mWidth;
std::string mSpellToDelete;
void addGroup(const std::string& label, const std::string& label2);
int estimateHeight(int numSpells) const;
void onWindowResize(MyGUI::Window* _sender);
void onEnchantedItemSelected(MyGUI::Widget* _sender);
void onSpellSelected(MyGUI::Widget* _sender);
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
void onDeleteSpellAccept();
virtual void onPinToggled();
virtual void open();
};
}
#endif

@ -12,6 +12,7 @@
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "window_manager.hpp" #include "window_manager.hpp"
#include "tooltips.hpp"
using namespace MWGui; using namespace MWGui;
@ -77,8 +78,6 @@ StatsWindow::StatsWindow (WindowManager& parWindowManager)
MyGUI::WindowPtr t = static_cast<MyGUI::WindowPtr>(mMainWidget); MyGUI::WindowPtr t = static_cast<MyGUI::WindowPtr>(mMainWidget);
t->eventWindowChangeCoord += MyGUI::newDelegate(this, &StatsWindow::onWindowResize); t->eventWindowChangeCoord += MyGUI::newDelegate(this, &StatsWindow::onWindowResize);
setupToolTips();
} }
void StatsWindow::onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos) void StatsWindow::onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos)
@ -256,6 +255,8 @@ void StatsWindow::configureSkills (const std::vector<int>& major, const std::vec
if (skillSet.find(skill) == skillSet.end()) if (skillSet.find(skill) == skillSet.end())
miscSkills.push_back(skill); miscSkills.push_back(skill);
} }
updateSkillArea();
} }
void StatsWindow::onFrame () void StatsWindow::onFrame ()
@ -339,7 +340,7 @@ MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::st
return skillValueWidget; return skillValueWidget;
} }
MyGUI::Widget* StatsWindow::addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2) MyGUI::Widget* StatsWindow::addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
{ {
MyGUI::TextBox* skillNameWidget; MyGUI::TextBox* skillNameWidget;
@ -444,32 +445,17 @@ void StatsWindow::updateSkillArea()
const ESM::Race* playerRace = store.races.find (MWBase::Environment::get().getWorld()->getPlayer().getRace()); const ESM::Race* playerRace = store.races.find (MWBase::Environment::get().getWorld()->getPlayer().getRace());
MyGUI::Widget* raceWidget; MyGUI::Widget* raceWidget;
getWidget(raceWidget, "RaceText"); getWidget(raceWidget, "RaceText");
raceWidget->setUserString("Caption_CenteredCaption", playerRace->name); ToolTips::createRaceToolTip(raceWidget, playerRace);
raceWidget->setUserString("Caption_CenteredCaptionText", playerRace->description);
getWidget(raceWidget, "Race_str"); getWidget(raceWidget, "Race_str");
raceWidget->setUserString("Caption_CenteredCaption", playerRace->name); ToolTips::createRaceToolTip(raceWidget, playerRace);
raceWidget->setUserString("Caption_CenteredCaptionText", playerRace->description);
// class tooltip // class tooltip
MyGUI::Widget* classWidget; MyGUI::Widget* classWidget;
const ESM::Class& playerClass = MWBase::Environment::get().getWorld()->getPlayer().getClass(); const ESM::Class& playerClass = MWBase::Environment::get().getWorld()->getPlayer().getClass();
int spec = playerClass.data.specialization;
std::string specStr;
if (spec == 0)
specStr = "#{sSpecializationCombat}";
else if (spec == 1)
specStr = "#{sSpecializationMagic}";
else if (spec == 2)
specStr = "#{sSpecializationStealth}";
getWidget(classWidget, "ClassText"); getWidget(classWidget, "ClassText");
classWidget->setUserString("Caption_ClassName", playerClass.name); ToolTips::createClassToolTip(classWidget, playerClass);
classWidget->setUserString("Caption_ClassDescription", playerClass.description);
classWidget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr);
getWidget(classWidget, "Class_str"); getWidget(classWidget, "Class_str");
classWidget->setUserString("Caption_ClassName", playerClass.name); ToolTips::createClassToolTip(classWidget, playerClass);
classWidget->setUserString("Caption_ClassDescription", playerClass.description);
classWidget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr);
if (!mFactions.empty()) if (!mFactions.empty())
{ {
@ -536,61 +522,8 @@ void StatsWindow::updateSkillArea()
addGroup(mWindowManager.getGameSettingString("sBirthSign", "Sign"), coord1, coord2); addGroup(mWindowManager.getGameSettingString("sBirthSign", "Sign"), coord1, coord2);
const ESM::BirthSign *sign = store.birthSigns.find(birthSignId); const ESM::BirthSign *sign = store.birthSigns.find(birthSignId);
MyGUI::Widget* w = addItem(sign->name, coord1, coord2); MyGUI::Widget* w = addItem(sign->name, coord1, coord2);
w->setUserString("ToolTipType", "Layout");
w->setUserString("ToolTipLayout", "BirthSignToolTip");
std::string image = sign->texture;
image.replace(image.size()-3, 3, "dds");
w->setUserString("ImageTexture_BirthSignImage", "textures\\" + image);
std::string text;
text += sign->name;
text += "\n#BF9959" + sign->description;
std::vector<std::string> abilities, powers, spells; ToolTips::createBirthsignToolTip(w, birthSignId);
std::vector<std::string>::const_iterator it = sign->powers.list.begin();
std::vector<std::string>::const_iterator end = sign->powers.list.end();
for (; it != end; ++it)
{
const std::string &spellId = *it;
const ESM::Spell *spell = store.spells.search(spellId);
if (!spell)
continue; // Skip spells which cannot be found
ESM::Spell::SpellType type = static_cast<ESM::Spell::SpellType>(spell->data.type);
if (type != ESM::Spell::ST_Spell && type != ESM::Spell::ST_Ability && type != ESM::Spell::ST_Power)
continue; // We only want spell, ability and powers.
if (type == ESM::Spell::ST_Ability)
abilities.push_back(spellId);
else if (type == ESM::Spell::ST_Power)
powers.push_back(spellId);
else if (type == ESM::Spell::ST_Spell)
spells.push_back(spellId);
}
struct{ const std::vector<std::string> &spells; std::string label; } categories[3] = {
{abilities, "sBirthsignmenu1"},
{powers, "sPowers"},
{spells, "sBirthsignmenu2"}
};
for (int category = 0; category < 3; ++category)
{
for (std::vector<std::string>::const_iterator it = categories[category].spells.begin(); it != categories[category].spells.end(); ++it)
{
if (it == categories[category].spells.begin())
{
text += std::string("\n#DDC79E") + std::string("#{") + categories[category].label + "}";
}
const std::string &spellId = *it;
const ESM::Spell *spell = store.spells.search(spellId);
text += "\n#BF9959" + spell->name;
}
}
w->setUserString("Caption_BirthSignText", text);
} }
// Add a line separator if there are items above // Add a line separator if there are items above
@ -633,116 +566,3 @@ void StatsWindow::onPinToggled()
{ {
mWindowManager.setHMSVisibility(!mPinned); mWindowManager.setHMSVisibility(!mPinned);
} }
void StatsWindow::setupToolTips()
{
const ESMS::ESMStore &store = mWindowManager.getStore();
MyGUI::Widget* widget;
/// \todo move this into the .layout file!
getWidget(widget, "Attrib1");
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "AttributeToolTip");
widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeStrength")->str);
widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sStrDesc")->str);
widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_strength.dds");
getWidget(widget, "AttribVal1");
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "AttributeToolTip");
widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeStrength")->str);
widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sStrDesc")->str);
widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_strength.dds");
getWidget(widget, "Attrib2");
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "AttributeToolTip");
widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeIntelligence")->str);
widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sIntDesc")->str);
widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_int.dds");
getWidget(widget, "AttribVal2");
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "AttributeToolTip");
widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeIntelligence")->str);
widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sIntDesc")->str);
widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_int.dds");
getWidget(widget, "Attrib3");
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "AttributeToolTip");
widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeWillpower")->str);
widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sWilDesc")->str);
widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_wilpower.dds");
getWidget(widget, "AttribVal3");
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "AttributeToolTip");
widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeWillpower")->str);
widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sWilDesc")->str);
widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_wilpower.dds");
getWidget(widget, "Attrib4");
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "AttributeToolTip");
widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeAgility")->str);
widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sAgiDesc")->str);
widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_agility.dds");
getWidget(widget, "AttribVal4");
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "AttributeToolTip");
widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeAgility")->str);
widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sAgiDesc")->str);
widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_agility.dds");
getWidget(widget, "Attrib5");
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "AttributeToolTip");
widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeSpeed")->str);
widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sSpdDesc")->str);
widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_speed.dds");
getWidget(widget, "AttribVal5");
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "AttributeToolTip");
widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeSpeed")->str);
widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sSpdDesc")->str);
widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_speed.dds");
getWidget(widget, "Attrib6");
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "AttributeToolTip");
widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeEndurance")->str);
widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sEndDesc")->str);
widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_endurance.dds");
getWidget(widget, "AttribVal6");
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "AttributeToolTip");
widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeEndurance")->str);
widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sEndDesc")->str);
widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_endurance.dds");
getWidget(widget, "Attrib7");
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "AttributeToolTip");
widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributePersonality")->str);
widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sPerDesc")->str);
widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_personality.dds");
getWidget(widget, "AttribVal7");
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "AttributeToolTip");
widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributePersonality")->str);
widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sPerDesc")->str);
widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_personality.dds");
getWidget(widget, "Attrib8");
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "AttributeToolTip");
widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeLuck")->str);
widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sLucDesc")->str);
widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_luck.dds");
getWidget(widget, "AttribVal8");
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "AttributeToolTip");
widget->setUserString("Caption_AttributeName", store.gameSettings.find ("sAttributeLuck")->str);
widget->setUserString("Caption_AttributeDescription", store.gameSettings.find ("sLucDesc")->str);
widget->setUserString("ImageTexture_AttributeImage", "icons\\k\\attribute_luck.dds");
}

@ -47,11 +47,9 @@ namespace MWGui
void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); void addGroup(const std::string &label, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
MyGUI::TextBox* addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); MyGUI::TextBox* addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
MyGUI::Widget* addItem(const std::string text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); MyGUI::Widget* addItem(const std::string& text, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2);
void updateScroller(); void updateScroller();
void setupToolTips();
void setFactions (const FactionList& factions); void setFactions (const FactionList& factions);
void setBirthSign (const std::string &signId); void setBirthSign (const std::string &signId);

@ -8,6 +8,8 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <components/settings/settings.hpp>
using namespace MWGui; using namespace MWGui;
using namespace MyGUI; using namespace MyGUI;
@ -19,6 +21,10 @@ ToolTips::ToolTips(WindowManager* windowManager) :
, mEnabled(true) , mEnabled(true)
, mFocusToolTipX(0.0) , mFocusToolTipX(0.0)
, mFocusToolTipY(0.0) , mFocusToolTipY(0.0)
, mDelay(0.0)
, mRemainingDelay(0.0)
, mLastMouseX(0)
, mLastMouseY(0)
{ {
getWidget(mDynamicToolTipBox, "DynamicToolTipBox"); getWidget(mDynamicToolTipBox, "DynamicToolTipBox");
@ -28,6 +34,9 @@ ToolTips::ToolTips(WindowManager* windowManager) :
// even if the mouse is over the tooltip // even if the mouse is over the tooltip
mDynamicToolTipBox->setNeedMouseFocus(false); mDynamicToolTipBox->setNeedMouseFocus(false);
mMainWidget->setNeedMouseFocus(false); mMainWidget->setNeedMouseFocus(false);
mDelay = Settings::Manager::getFloat("tooltip delay", "GUI");
mRemainingDelay = mDelay;
} }
void ToolTips::setEnabled(bool enabled) void ToolTips::setEnabled(bool enabled)
@ -37,10 +46,10 @@ void ToolTips::setEnabled(bool enabled)
void ToolTips::onFrame(float frameDuration) void ToolTips::onFrame(float frameDuration)
{ {
MyGUI::Gui::getInstance().destroyWidget(mDynamicToolTipBox); while (mDynamicToolTipBox->getChildCount())
mDynamicToolTipBox = mMainWidget->createWidget<Widget>("HUD_Box", {
IntCoord(0, 0, mMainWidget->getCoord().width, mMainWidget->getCoord().height), MyGUI::Gui::getInstance().destroyWidget(mDynamicToolTipBox->getChildAt(0));
Align::Stretch, "DynamicToolTipBox"); }
// start by hiding everything // start by hiding everything
for (unsigned int i=0; i < mMainWidget->getChildCount(); ++i) for (unsigned int i=0; i < mMainWidget->getChildCount(); ++i)
@ -57,6 +66,60 @@ void ToolTips::onFrame(float frameDuration)
if (!mGameMode) if (!mGameMode)
{ {
const MyGUI::IntPoint& mousePos = InputManager::getInstance().getMousePosition();
if (mWindowManager->getWorldMouseOver() && ((mWindowManager->getMode() == GM_Console)
|| (mWindowManager->getMode() == GM_Container)
|| (mWindowManager->getMode() == GM_Inventory)))
{
std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle();
try
{
mFocusObject = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle);
}
catch (std::exception& e)
{
return;
}
MyGUI::IntSize tooltipSize = getToolTipViaPtr(true);
IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24);
// make the tooltip stay completely in the viewport
if ((tooltipPosition.left + tooltipSize.width) > viewSize.width)
{
tooltipPosition.left = viewSize.width - tooltipSize.width;
}
if ((tooltipPosition.top + tooltipSize.height) > viewSize.height)
{
tooltipPosition.top = viewSize.height - tooltipSize.height;
}
setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height);
}
else
{
const MyGUI::IntPoint& lastPressed = InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left);
if (mousePos == lastPressed) // mouseclick makes tooltip disappear
return;
if (mousePos.left == mLastMouseX && mousePos.top == mLastMouseY)
{
mRemainingDelay -= frameDuration;
}
else
{
mRemainingDelay = mDelay;
}
mLastMouseX = mousePos.left;
mLastMouseY = mousePos.top;
if (mRemainingDelay > 0)
return;
Widget* focus = InputManager::getInstance().getMouseFocusWidget(); Widget* focus = InputManager::getInstance().getMouseFocusWidget();
if (focus == 0) if (focus == 0)
{ {
@ -65,10 +128,20 @@ void ToolTips::onFrame(float frameDuration)
IntSize tooltipSize; IntSize tooltipSize;
// try to go 1 level up until there is a widget that has tooltip
// this is necessary because some skin elements are actually separate widgets
int i=0;
while (!focus->isUserString("ToolTipType"))
{
focus = focus->getParent();
if (!focus)
return;
++i;
}
std::string type = focus->getUserString("ToolTipType"); std::string type = focus->getUserString("ToolTipType");
std::string text = focus->getUserString("ToolTipText"); std::string text = focus->getUserString("ToolTipText");
ToolTipInfo info;
if (type == "") if (type == "")
{ {
return; return;
@ -78,6 +151,29 @@ void ToolTips::onFrame(float frameDuration)
mFocusObject = *focus->getUserData<MWWorld::Ptr>(); mFocusObject = *focus->getUserData<MWWorld::Ptr>();
tooltipSize = getToolTipViaPtr(false); tooltipSize = getToolTipViaPtr(false);
} }
else if (type == "Spell")
{
ToolTipInfo info;
const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.find(focus->getUserString("Spell"));
info.caption = spell->name;
Widgets::SpellEffectList effects;
std::vector<ESM::ENAMstruct>::const_iterator end = spell->effects.list.end();
for (std::vector<ESM::ENAMstruct>::const_iterator it = spell->effects.list.begin(); it != end; ++it)
{
Widgets::SpellEffectParams params;
params.mEffectID = it->effectID;
params.mSkill = it->skill;
params.mAttribute = it->attribute;
params.mDuration = it->duration;
params.mMagnMin = it->magnMin;
params.mMagnMax = it->magnMax;
params.mRange = it->range;
params.mIsConstant = (spell->data.type == ESM::Spell::ST_Ability);
effects.push_back(params);
}
info.effects = effects;
tooltipSize = createToolTip(info);
}
else if (type == "Layout") else if (type == "Layout")
{ {
// tooltip defined in the layout // tooltip defined in the layout
@ -157,6 +253,7 @@ void ToolTips::onFrame(float frameDuration)
setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height); setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height);
} }
}
else else
{ {
if (!mFocusObject.isEmpty()) if (!mFocusObject.isEmpty())
@ -285,7 +382,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
IntSize totalSize = IntSize( std::max(textSize.width, captionSize.width + ((image != "") ? imageCaptionHPadding : 0)), IntSize totalSize = IntSize( std::max(textSize.width, captionSize.width + ((image != "") ? imageCaptionHPadding : 0)),
((text != "") ? textSize.height + imageCaptionVPadding : 0) + captionHeight ); ((text != "") ? textSize.height + imageCaptionVPadding : 0) + captionHeight );
if (info.effects != 0) if (!info.effects.empty())
{ {
Widget* effectArea = mDynamicToolTipBox->createWidget<Widget>("", Widget* effectArea = mDynamicToolTipBox->createWidget<Widget>("",
IntCoord(0, totalSize.height, 300, 300-totalSize.height), IntCoord(0, totalSize.height, 300, 300-totalSize.height),
@ -305,7 +402,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
effectsWidget->setEffectList(info.effects); effectsWidget->setEffectList(info.effects);
std::vector<MyGUI::WidgetPtr> effectItems; std::vector<MyGUI::WidgetPtr> effectItems;
effectsWidget->createEffectWidgets(effectItems, effectArea, coord, true, Widgets::MWEffectList::EF_Potion); effectsWidget->createEffectWidgets(effectItems, effectArea, coord, true, Widgets::MWEffectList::EF_NoTarget);
totalSize.height += coord.top-6; totalSize.height += coord.top-6;
totalSize.width = std::max(totalSize.width, coord.width); totalSize.width = std::max(totalSize.width, coord.width);
} }
@ -321,7 +418,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
Widgets::MWEffectListPtr enchantWidget = enchantArea->createWidget<Widgets::MWEffectList> Widgets::MWEffectListPtr enchantWidget = enchantArea->createWidget<Widgets::MWEffectList>
("MW_StatName", coord, Align::Default, "ToolTipEnchantWidget"); ("MW_StatName", coord, Align::Default, "ToolTipEnchantWidget");
enchantWidget->setWindowManager(mWindowManager); enchantWidget->setWindowManager(mWindowManager);
enchantWidget->setEffectList(&enchant->effects); enchantWidget->setEffectList(Widgets::MWEffectList::effectListFromESM(&enchant->effects));
std::vector<MyGUI::WidgetPtr> enchantEffectItems; std::vector<MyGUI::WidgetPtr> enchantEffectItems;
int flag = (enchant->data.type == ESM::Enchantment::ConstantEffect) ? Widgets::MWEffectList::EF_Constant : 0; int flag = (enchant->data.type == ESM::Enchantment::ConstantEffect) ? Widgets::MWEffectList::EF_Constant : 0;
@ -339,7 +436,6 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
TextBox* chargeText = enchantArea->createWidget<TextBox>("SandText", IntCoord(0, 0, 10, 18), Align::Default, "ToolTipEnchantChargeText"); TextBox* chargeText = enchantArea->createWidget<TextBox>("SandText", IntCoord(0, 0, 10, 18), Align::Default, "ToolTipEnchantChargeText");
chargeText->setCaption(store.gameSettings.search("sCharges")->str); chargeText->setCaption(store.gameSettings.search("sCharges")->str);
chargeText->setProperty("Static", "true");
const int chargeTextWidth = chargeText->getTextSize().width + 5; const int chargeTextWidth = chargeText->getTextSize().width + 5;
const int chargeAndTextWidth = chargeWidth + chargeTextWidth; const int chargeAndTextWidth = chargeWidth + chargeTextWidth;
@ -440,3 +536,156 @@ void ToolTips::setFocusObjectScreenCoords(float min_x, float min_y, float max_x,
mFocusToolTipX = (min_x + max_x) / 2; mFocusToolTipX = (min_x + max_x) / 2;
mFocusToolTipY = min_y; mFocusToolTipY = min_y;
} }
void ToolTips::createSkillToolTip(MyGUI::Widget* widget, int skillId)
{
if (skillId == -1)
return;
const std::string &skillNameId = ESMS::Skill::sSkillNameIds[skillId];
const ESM::Skill* skill = MWBase::Environment::get().getWorld()->getStore().skills.search(skillId);
assert(skill);
const ESM::Attribute* attr = MWBase::Environment::get().getWorld()->getStore().attributes.search(skill->data.attribute);
assert(attr);
std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId];
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "SkillNoProgressToolTip");
widget->setUserString("Caption_SkillNoProgressName", "#{"+skillNameId+"}");
widget->setUserString("Caption_SkillNoProgressDescription", skill->description);
widget->setUserString("Caption_SkillNoProgressAttribute", "#{sGoverningAttribute}: #{" + attr->name + "}");
widget->setUserString("ImageTexture_SkillNoProgressImage", icon);
widget->setUserString("ToolTipLayout", "SkillNoProgressToolTip");
widget->setUserString("ToolTipLayout", "SkillNoProgressToolTip");
}
void ToolTips::createAttributeToolTip(MyGUI::Widget* widget, int attributeId)
{
if (attributeId == -1)
return;
const ESM::Attribute* attr = MWBase::Environment::get().getWorld()->getStore().attributes.search(attributeId);
assert(attr);
std::string icon = ESM::Attribute::attributeIcons[attributeId];
std::string name = ESM::Attribute::gmstAttributeIds[attributeId];
std::string desc = ESM::Attribute::gmstAttributeDescIds[attributeId];
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "AttributeToolTip");
widget->setUserString("Caption_AttributeName", "#{"+name+"}");
widget->setUserString("Caption_AttributeDescription", "#{"+desc+"}");
widget->setUserString("ImageTexture_AttributeImage", icon);
}
void ToolTips::createSpecializationToolTip(MyGUI::Widget* widget, const std::string& name, int specId)
{
widget->setUserString("Caption_CenteredCaption", name);
std::string specText;
// get all skills of this specialisation
std::map<int, ESM::Skill> skills = MWBase::Environment::get().getWorld()->getStore().skills.list;
for (std::map<int, ESM::Skill>::const_iterator it = skills.begin();
it != skills.end(); ++it)
{
if (it->second.data.specialization == specId)
specText += std::string("\n#{") + ESM::Skill::sSkillNameIds[it->second.index] + "}";
}
widget->setUserString("Caption_CenteredCaptionText", specText);
widget->setUserString("ToolTipLayout", "TextWithCenteredCaptionToolTip");
widget->setUserString("ToolTipType", "Layout");
}
void ToolTips::createBirthsignToolTip(MyGUI::Widget* widget, const std::string& birthsignId)
{
const ESM::BirthSign *sign = MWBase::Environment::get().getWorld()->getStore().birthSigns.find(birthsignId);
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "BirthSignToolTip");
std::string image = sign->texture;
image.replace(image.size()-3, 3, "dds");
widget->setUserString("ImageTexture_BirthSignImage", "textures\\" + image);
std::string text;
text += sign->name;
text += "\n#BF9959" + sign->description;
std::vector<std::string> abilities, powers, spells;
std::vector<std::string>::const_iterator it = sign->powers.list.begin();
std::vector<std::string>::const_iterator end = sign->powers.list.end();
for (; it != end; ++it)
{
const std::string &spellId = *it;
const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.search(spellId);
if (!spell)
continue; // Skip spells which cannot be found
ESM::Spell::SpellType type = static_cast<ESM::Spell::SpellType>(spell->data.type);
if (type != ESM::Spell::ST_Spell && type != ESM::Spell::ST_Ability && type != ESM::Spell::ST_Power)
continue; // We only want spell, ability and powers.
if (type == ESM::Spell::ST_Ability)
abilities.push_back(spellId);
else if (type == ESM::Spell::ST_Power)
powers.push_back(spellId);
else if (type == ESM::Spell::ST_Spell)
spells.push_back(spellId);
}
struct{ const std::vector<std::string> &spells; std::string label; } categories[3] = {
{abilities, "sBirthsignmenu1"},
{powers, "sPowers"},
{spells, "sBirthsignmenu2"}
};
for (int category = 0; category < 3; ++category)
{
for (std::vector<std::string>::const_iterator it = categories[category].spells.begin(); it != categories[category].spells.end(); ++it)
{
if (it == categories[category].spells.begin())
{
text += std::string("\n#DDC79E") + std::string("#{") + categories[category].label + "}";
}
const std::string &spellId = *it;
const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.search(spellId);
text += "\n#BF9959" + spell->name;
}
}
widget->setUserString("Caption_BirthSignText", text);
}
void ToolTips::createRaceToolTip(MyGUI::Widget* widget, const ESM::Race* playerRace)
{
widget->setUserString("Caption_CenteredCaption", playerRace->name);
widget->setUserString("Caption_CenteredCaptionText", playerRace->description);
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "TextWithCenteredCaptionToolTip");
}
void ToolTips::createClassToolTip(MyGUI::Widget* widget, const ESM::Class& playerClass)
{
if (playerClass.name == "")
return;
int spec = playerClass.data.specialization;
std::string specStr;
if (spec == 0)
specStr = "#{sSpecializationCombat}";
else if (spec == 1)
specStr = "#{sSpecializationMagic}";
else if (spec == 2)
specStr = "#{sSpecializationStealth}";
widget->setUserString("Caption_ClassName", playerClass.name);
widget->setUserString("Caption_ClassDescription", playerClass.description);
widget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr);
widget->setUserString("ToolTipType", "Layout");
widget->setUserString("ToolTipLayout", "ClassToolTip");
}
void ToolTips::setDelay(float delay)
{
mDelay = delay;
mRemainingDelay = mDelay;
}

@ -5,6 +5,8 @@
#include <openengine/gui/layout.hpp> #include <openengine/gui/layout.hpp>
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "widgets.hpp"
namespace MWGui namespace MWGui
{ {
class WindowManager; class WindowManager;
@ -13,11 +15,6 @@ namespace MWGui
struct ToolTipInfo struct ToolTipInfo
{ {
public: public:
ToolTipInfo() :
effects(0)
{
};
std::string caption; std::string caption;
std::string text; std::string text;
std::string icon; std::string icon;
@ -26,7 +23,7 @@ namespace MWGui
std::string enchant; std::string enchant;
// effects (for potions, ingredients) // effects (for potions, ingredients)
const ESM::EffectList* effects; Widgets::SpellEffectList effects;
}; };
class ToolTips : public OEngine::GUI::Layout class ToolTips : public OEngine::GUI::Layout
@ -44,6 +41,8 @@ namespace MWGui
void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) void toggleFullHelp(); ///< show extra info in item tooltips (owner, script)
bool getFullHelp() const; bool getFullHelp() const;
void setDelay(float delay);
void setFocusObject(const MWWorld::Ptr& focus); void setFocusObject(const MWWorld::Ptr& focus);
void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y); void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y);
///< set the screen-space position of the tooltip for focused object ///< set the screen-space position of the tooltip for focused object
@ -60,6 +59,15 @@ namespace MWGui
static std::string getCountString(const int value); static std::string getCountString(const int value);
///< @return blank string if count is 1, or else " (value)" ///< @return blank string if count is 1, or else " (value)"
// these do not create an actual tooltip, but they fill in the data that is required so the tooltip
// system knows what to show in case this widget is hovered
static void createSkillToolTip(MyGUI::Widget* widget, int skillId);
static void createAttributeToolTip(MyGUI::Widget* widget, int attributeId);
static void createSpecializationToolTip(MyGUI::Widget* widget, const std::string& name, int specId);
static void createBirthsignToolTip(MyGUI::Widget* widget, const std::string& birthsignId);
static void createRaceToolTip(MyGUI::Widget* widget, const ESM::Race* playerRace);
static void createClassToolTip(MyGUI::Widget* widget, const ESM::Class& playerClass);
private: private:
MyGUI::Widget* mDynamicToolTipBox; MyGUI::Widget* mDynamicToolTipBox;
@ -78,6 +86,12 @@ namespace MWGui
float mFocusToolTipX; float mFocusToolTipX;
float mFocusToolTipY; float mFocusToolTipY;
float mDelay;
float mRemainingDelay; // remaining time until tooltip will show
int mLastMouseX;
int mLastMouseY;
bool mGameMode; bool mGameMode;
bool mEnabled; bool mEnabled;

@ -104,6 +104,8 @@ namespace MWGui
ContainerBase::openContainer(actor); ContainerBase::openContainer(actor);
updateLabels(); updateLabels();
drawItems();
} }
void TradeWindow::onFilterChanged(MyGUI::Widget* _sender) void TradeWindow::onFilterChanged(MyGUI::Widget* _sender)
@ -157,9 +159,9 @@ namespace MWGui
// check if the merchant can afford this // check if the merchant can afford this
int merchantgold; int merchantgold;
if (mContainer.getTypeName() == typeid(ESM::NPC).name()) if (mPtr.getTypeName() == typeid(ESM::NPC).name())
{ {
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* ref = mContainer.get<ESM::NPC>(); ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* ref = mPtr.get<ESM::NPC>();
if (ref->base->npdt52.gold == -10) if (ref->base->npdt52.gold == -10)
merchantgold = ref->base->npdt12.gold; merchantgold = ref->base->npdt12.gold;
else else
@ -167,7 +169,7 @@ namespace MWGui
} }
else // ESM::Creature else // ESM::Creature
{ {
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData>* ref = mContainer.get<ESM::Creature>(); ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData>* ref = mPtr.get<ESM::Creature>();
merchantgold = ref->base->data.gold; merchantgold = ref->base->data.gold;
} }
if (mCurrentBalance > 0 && merchantgold < mCurrentBalance) if (mCurrentBalance > 0 && merchantgold < mCurrentBalance)
@ -210,7 +212,7 @@ namespace MWGui
std::string sound = "Item Gold Up"; std::string sound = "Item Gold Up";
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0); MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
mWindowManager.setGuiMode(GM_Game); mWindowManager.popGuiMode();
} }
void TradeWindow::onCancelButtonClicked(MyGUI::Widget* _sender) void TradeWindow::onCancelButtonClicked(MyGUI::Widget* _sender)
@ -218,9 +220,9 @@ namespace MWGui
// i give you back your stuff! // i give you back your stuff!
returnBoughtItems(mWindowManager.getInventoryWindow()->getContainerStore()); returnBoughtItems(mWindowManager.getInventoryWindow()->getContainerStore());
// now gimme back my stuff! // now gimme back my stuff!
mWindowManager.getInventoryWindow()->returnBoughtItems(MWWorld::Class::get(mContainer).getContainerStore(mContainer)); mWindowManager.getInventoryWindow()->returnBoughtItems(MWWorld::Class::get(mPtr).getContainerStore(mPtr));
mWindowManager.setGuiMode(GM_Game); mWindowManager.popGuiMode();
} }
void TradeWindow::updateLabels() void TradeWindow::updateLabels()
@ -240,9 +242,9 @@ namespace MWGui
} }
int merchantgold; int merchantgold;
if (mContainer.getTypeName() == typeid(ESM::NPC).name()) if (mPtr.getTypeName() == typeid(ESM::NPC).name())
{ {
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* ref = mContainer.get<ESM::NPC>(); ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* ref = mPtr.get<ESM::NPC>();
if (ref->base->npdt52.gold == -10) if (ref->base->npdt52.gold == -10)
merchantgold = ref->base->npdt12.gold; merchantgold = ref->base->npdt12.gold;
else else
@ -250,7 +252,7 @@ namespace MWGui
} }
else // ESM::Creature else // ESM::Creature
{ {
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData>* ref = mContainer.get<ESM::Creature>(); ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData>* ref = mPtr.get<ESM::Creature>();
merchantgold = ref->base->data.gold; merchantgold = ref->base->data.gold;
} }
@ -262,13 +264,13 @@ namespace MWGui
{ {
std::vector<MWWorld::Ptr> items; std::vector<MWWorld::Ptr> items;
if (mContainer.getTypeName() == typeid(ESM::Creature).name()) if (mPtr.getTypeName() == typeid(ESM::Creature).name())
{ {
// creatures don't have equipment slots. // creatures don't have equipment slots.
return items; return items;
} }
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mContainer).getInventoryStore(mContainer); MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot)
{ {
@ -285,19 +287,21 @@ namespace MWGui
bool TradeWindow::npcAcceptsItem(MWWorld::Ptr item) bool TradeWindow::npcAcceptsItem(MWWorld::Ptr item)
{ {
int services = 0; int services = 0;
if (mContainer.getTypeName() == typeid(ESM::NPC).name()) if (mPtr.getTypeName() == typeid(ESM::NPC).name())
{ {
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* ref = mContainer.get<ESM::NPC>(); ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* ref = mPtr.get<ESM::NPC>();
if (ref->base->hasAI) if (ref->base->hasAI)
services = ref->base->AI.services; services = ref->base->AI.services;
} }
else if (mContainer.getTypeName() == typeid(ESM::Creature).name()) else if (mPtr.getTypeName() == typeid(ESM::Creature).name())
{ {
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData>* ref = mContainer.get<ESM::Creature>(); ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData>* ref = mPtr.get<ESM::Creature>();
if (ref->base->hasAI) if (ref->base->hasAI)
services = ref->base->AI.services; services = ref->base->AI.services;
} }
/// \todo what about potions, there doesn't seem to be a flag for them??
if (item.getTypeName() == typeid(ESM::Weapon).name()) if (item.getTypeName() == typeid(ESM::Weapon).name())
return services & ESM::NPC::Weapon; return services & ESM::NPC::Weapon;
else if (item.getTypeName() == typeid(ESM::Armor).name()) else if (item.getTypeName() == typeid(ESM::Armor).name())
@ -327,7 +331,7 @@ namespace MWGui
std::vector<MWWorld::Ptr> TradeWindow::itemsToIgnore() std::vector<MWWorld::Ptr> TradeWindow::itemsToIgnore()
{ {
std::vector<MWWorld::Ptr> items; std::vector<MWWorld::Ptr> items;
MWWorld::ContainerStore& invStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); MWWorld::ContainerStore& invStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
for (MWWorld::ContainerStoreIterator it = invStore.begin(); for (MWWorld::ContainerStoreIterator it = invStore.begin();
it != invStore.end(); ++it) it != invStore.end(); ++it)
@ -356,4 +360,11 @@ namespace MWGui
updateLabels(); updateLabels();
} }
void TradeWindow::onReferenceUnavailable()
{
// remove both Trade and Dialogue (since you always trade with the NPC/creature that you have previously talked to)
mWindowManager.removeGuiMode(GM_Barter);
mWindowManager.removeGuiMode(GM_Dialogue);
}
} }

@ -69,6 +69,8 @@ namespace MWGui
virtual std::vector<MWWorld::Ptr> itemsToIgnore(); virtual std::vector<MWWorld::Ptr> itemsToIgnore();
void updateLabels(); void updateLabels();
virtual void onReferenceUnavailable();
}; };
} }

@ -234,8 +234,17 @@ void MWSpell::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI:
{ {
effect = creator->createWidget<MWSpellEffect>("MW_EffectImage", coord, MyGUI::Align::Default); effect = creator->createWidget<MWSpellEffect>("MW_EffectImage", coord, MyGUI::Align::Default);
effect->setWindowManager(mWindowManager); effect->setWindowManager(mWindowManager);
effect->setFlags(flags); SpellEffectParams params;
effect->setSpellEffect(*it); params.mEffectID = it->effectID;
params.mSkill = it->skill;
params.mAttribute = it->attribute;
params.mDuration = it->duration;
params.mMagnMin = it->magnMin;
params.mMagnMax = it->magnMax;
params.mRange = it->range;
params.mIsConstant = (flags & MWEffectList::EF_Constant);
params.mNoTarget = (flags & MWEffectList::EF_NoTarget);
effect->setSpellEffect(params);
effects.push_back(effect); effects.push_back(effect);
coord.top += effect->getHeight(); coord.top += effect->getHeight();
coord.width = std::max(coord.width, effect->getRequestedWidth()); coord.width = std::max(coord.width, effect->getRequestedWidth());
@ -274,7 +283,7 @@ MWEffectList::MWEffectList()
{ {
} }
void MWEffectList::setEffectList(const ESM::EffectList* list) void MWEffectList::setEffectList(const SpellEffectList& list)
{ {
mEffectList = list; mEffectList = list;
updateWidgets(); updateWidgets();
@ -283,25 +292,26 @@ void MWEffectList::setEffectList(const ESM::EffectList* list)
void MWEffectList::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, bool center, int flags) void MWEffectList::createEffectWidgets(std::vector<MyGUI::WidgetPtr> &effects, MyGUI::WidgetPtr creator, MyGUI::IntCoord &coord, bool center, int flags)
{ {
// We don't know the width of all the elements beforehand, so we do it in // We don't know the width of all the elements beforehand, so we do it in
// 2 steps: first, create all widgets and check their width // 2 steps: first, create all widgets and check their width....
MWSpellEffectPtr effect = nullptr; MWSpellEffectPtr effect = nullptr;
std::vector<ESM::ENAMstruct>::const_iterator end = mEffectList->list.end();
int maxwidth = coord.width; int maxwidth = coord.width;
for (std::vector<ESM::ENAMstruct>::const_iterator it = mEffectList->list.begin(); it != end; ++it)
for (SpellEffectList::iterator it=mEffectList.begin();
it != mEffectList.end(); ++it)
{ {
effect = creator->createWidget<MWSpellEffect>("MW_EffectImage", coord, MyGUI::Align::Default); effect = creator->createWidget<MWSpellEffect>("MW_EffectImage", coord, MyGUI::Align::Default);
effect->setWindowManager(mWindowManager); effect->setWindowManager(mWindowManager);
effect->setFlags(flags); it->mIsConstant = (flags & EF_Constant) || it->mIsConstant;
it->mNoTarget = (flags & EF_NoTarget) || it->mNoTarget;
effect->setSpellEffect(*it); effect->setSpellEffect(*it);
effects.push_back(effect); effects.push_back(effect);
if (effect->getRequestedWidth() > maxwidth) if (effect->getRequestedWidth() > maxwidth)
maxwidth = effect->getRequestedWidth(); maxwidth = effect->getRequestedWidth();
coord.top += effect->getHeight(); coord.top += effect->getHeight();
} }
// then adjust the size for all widgets // ... then adjust the size for all widgets
for (std::vector<MyGUI::WidgetPtr>::iterator it = effects.begin(); it != effects.end(); ++it) for (std::vector<MyGUI::WidgetPtr>::iterator it = effects.begin(); it != effects.end(); ++it)
{ {
effect = static_cast<MWSpellEffectPtr>(*it); effect = static_cast<MWSpellEffectPtr>(*it);
@ -334,6 +344,25 @@ MWEffectList::~MWEffectList()
{ {
} }
SpellEffectList MWEffectList::effectListFromESM(const ESM::EffectList* effects)
{
SpellEffectList result;
std::vector<ESM::ENAMstruct>::const_iterator end = effects->list.end();
for (std::vector<ESM::ENAMstruct>::const_iterator it = effects->list.begin(); it != end; ++it)
{
SpellEffectParams params;
params.mEffectID = it->effectID;
params.mSkill = it->skill;
params.mAttribute = it->attribute;
params.mDuration = it->duration;
params.mMagnMin = it->magnMin;
params.mMagnMax = it->magnMax;
params.mRange = it->range;
result.push_back(params);
}
return result;
}
/* MWSpellEffect */ /* MWSpellEffect */
MWSpellEffect::MWSpellEffect() MWSpellEffect::MWSpellEffect()
@ -341,13 +370,12 @@ MWSpellEffect::MWSpellEffect()
, imageWidget(nullptr) , imageWidget(nullptr)
, textWidget(nullptr) , textWidget(nullptr)
, mRequestedWidth(0) , mRequestedWidth(0)
, mFlags(0)
{ {
} }
void MWSpellEffect::setSpellEffect(SpellEffectValue value) void MWSpellEffect::setSpellEffect(const SpellEffectParams& params)
{ {
effect = value; mEffectParams = params;
updateWidgets(); updateWidgets();
} }
@ -357,10 +385,10 @@ void MWSpellEffect::updateWidgets()
return; return;
const ESMS::ESMStore &store = mWindowManager->getStore(); const ESMS::ESMStore &store = mWindowManager->getStore();
const ESM::MagicEffect *magicEffect = store.magicEffects.search(effect.effectID); const ESM::MagicEffect *magicEffect = store.magicEffects.search(mEffectParams.mEffectID);
if (!magicEffect)
return;
if (textWidget) if (textWidget)
{
if (magicEffect)
{ {
std::string pt = mWindowManager->getGameSettingString("spoint", ""); std::string pt = mWindowManager->getGameSettingString("spoint", "");
std::string pts = mWindowManager->getGameSettingString("spoints", ""); std::string pts = mWindowManager->getGameSettingString("spoints", "");
@ -368,13 +396,13 @@ void MWSpellEffect::updateWidgets()
std::string sec = " " + mWindowManager->getGameSettingString("ssecond", ""); std::string sec = " " + mWindowManager->getGameSettingString("ssecond", "");
std::string secs = " " + mWindowManager->getGameSettingString("sseconds", ""); std::string secs = " " + mWindowManager->getGameSettingString("sseconds", "");
std::string effectIDStr = effectIDToString(effect.effectID); std::string effectIDStr = effectIDToString(mEffectParams.mEffectID);
std::string spellLine = mWindowManager->getGameSettingString(effectIDStr, ""); std::string spellLine = mWindowManager->getGameSettingString(effectIDStr, "");
if (effect.skill >= 0 && effect.skill < ESM::Skill::Length) if (effectInvolvesSkill(effectIDStr) && mEffectParams.mSkill >= 0 && mEffectParams.mSkill < ESM::Skill::Length)
{ {
spellLine += " " + mWindowManager->getGameSettingString(ESM::Skill::sSkillNameIds[effect.skill], ""); spellLine += " " + mWindowManager->getGameSettingString(ESM::Skill::sSkillNameIds[mEffectParams.mSkill], "");
} }
if (effect.attribute >= 0 && effect.attribute < 8) if (effectInvolvesAttribute(effectIDStr) && mEffectParams.mAttribute >= 0 && mEffectParams.mAttribute < 8)
{ {
static const char *attributes[8] = { static const char *attributes[8] = {
"sAttributeStrength", "sAttributeStrength",
@ -386,36 +414,36 @@ void MWSpellEffect::updateWidgets()
"sAttributePersonality", "sAttributePersonality",
"sAttributeLuck" "sAttributeLuck"
}; };
spellLine += " " + mWindowManager->getGameSettingString(attributes[effect.attribute], ""); spellLine += " " + mWindowManager->getGameSettingString(attributes[mEffectParams.mAttribute], "");
} }
if ((effect.magnMin >= 0 || effect.magnMax >= 0) && effectHasMagnitude(effectIDStr)) if ((mEffectParams.mMagnMin >= 0 || mEffectParams.mMagnMax >= 0) && effectHasMagnitude(effectIDStr))
{ {
if (effect.magnMin == effect.magnMax) if (mEffectParams.mMagnMin == mEffectParams.mMagnMax)
spellLine += " " + boost::lexical_cast<std::string>(effect.magnMin) + " " + ((effect.magnMin == 1) ? pt : pts); spellLine += " " + boost::lexical_cast<std::string>(mEffectParams.mMagnMin) + " " + ((mEffectParams.mMagnMin == 1) ? pt : pts);
else else
{ {
spellLine += " " + boost::lexical_cast<std::string>(effect.magnMin) + to + boost::lexical_cast<std::string>(effect.magnMax) + " " + pts; spellLine += " " + boost::lexical_cast<std::string>(mEffectParams.mMagnMin) + to + boost::lexical_cast<std::string>(mEffectParams.mMagnMax) + " " + pts;
} }
} }
// constant effects have no duration and no target // constant effects have no duration and no target
if (!(mFlags & MWEffectList::EF_Constant)) if (!mEffectParams.mIsConstant)
{ {
if (effect.duration >= 0 && effectHasDuration(effectIDStr)) if (mEffectParams.mDuration >= 0 && effectHasDuration(effectIDStr))
{ {
spellLine += " " + mWindowManager->getGameSettingString("sfor", "") + " " + boost::lexical_cast<std::string>(effect.duration) + ((effect.duration == 1) ? sec : secs); spellLine += " " + mWindowManager->getGameSettingString("sfor", "") + " " + boost::lexical_cast<std::string>(mEffectParams.mDuration) + ((mEffectParams.mDuration == 1) ? sec : secs);
} }
// potions have no target // potions have no target
if (!(mFlags & MWEffectList::EF_Potion)) if (!mEffectParams.mNoTarget)
{ {
std::string on = mWindowManager->getGameSettingString("sonword", ""); std::string on = mWindowManager->getGameSettingString("sonword", "");
if (effect.range == ESM::RT_Self) if (mEffectParams.mRange == ESM::RT_Self)
spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeSelf", ""); spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeSelf", "");
else if (effect.range == ESM::RT_Touch) else if (mEffectParams.mRange == ESM::RT_Touch)
spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTouch", ""); spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTouch", "");
else if (effect.range == ESM::RT_Target) else if (mEffectParams.mRange == ESM::RT_Target)
spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTarget", ""); spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTarget", "");
} }
} }
@ -423,9 +451,6 @@ void MWSpellEffect::updateWidgets()
static_cast<MyGUI::TextBox*>(textWidget)->setCaption(spellLine); static_cast<MyGUI::TextBox*>(textWidget)->setCaption(spellLine);
mRequestedWidth = textWidget->getTextSize().width + 24; mRequestedWidth = textWidget->getTextSize().width + 24;
} }
else
static_cast<MyGUI::TextBox*>(textWidget)->setCaption("");
}
if (imageWidget) if (imageWidget)
{ {
std::string path = std::string("icons\\") + magicEffect->icon; std::string path = std::string("icons\\") + magicEffect->icon;
@ -677,6 +702,24 @@ bool MWSpellEffect::effectHasMagnitude(const std::string& effect)
return (std::find(effectsWithoutMagnitude.begin(), effectsWithoutMagnitude.end(), effect) == effectsWithoutMagnitude.end()); return (std::find(effectsWithoutMagnitude.begin(), effectsWithoutMagnitude.end(), effect) == effectsWithoutMagnitude.end());
} }
bool MWSpellEffect::effectInvolvesAttribute (const std::string& effect)
{
return (effect == "sEffectRestoreAttribute"
|| effect == "sEffectAbsorbAttribute"
|| effect == "sEffectDrainAttribute"
|| effect == "sEffectFortifyAttribute"
|| effect == "sEffectDamageAttribute");
}
bool MWSpellEffect::effectInvolvesSkill (const std::string& effect)
{
return (effect == "sEffectRestoreSkill"
|| effect == "sEffectAbsorbSkill"
|| effect == "sEffectDrainSkill"
|| effect == "sEffectFortifySkill"
|| effect == "sEffectDamageSkill");
}
MWSpellEffect::~MWSpellEffect() MWSpellEffect::~MWSpellEffect()
{ {
} }
@ -724,7 +767,7 @@ void MWDynamicStat::setValue(int cur, int max_)
static_cast<MyGUI::TextBox*>(barTextWidget)->setCaption(""); static_cast<MyGUI::TextBox*>(barTextWidget)->setCaption("");
} }
} }
void MWDynamicStat::setTitle(const std::string text) void MWDynamicStat::setTitle(const std::string& text)
{ {
if (textWidget) if (textWidget)
static_cast<MyGUI::TextBox*>(textWidget)->setCaption(text); static_cast<MyGUI::TextBox*>(textWidget)->setCaption(text);

@ -21,8 +21,58 @@ namespace MWGui
namespace Widgets namespace Widgets
{ {
class MWEffectList;
void fixTexturePath(std::string &path); void fixTexturePath(std::string &path);
struct SpellEffectParams
{
SpellEffectParams()
: mMagnMin(-1)
, mMagnMax(-1)
, mRange(-1)
, mDuration(-1)
, mSkill(-1)
, mAttribute(-1)
, mEffectID(-1)
, mNoTarget(false)
, mIsConstant(false)
{
}
bool mNoTarget; // potion effects for example have no target (target is always the player)
bool mIsConstant; // constant effect means that duration will not be displayed
// value of -1 here means the effect is unknown to the player
short mEffectID;
// value of -1 here means there is no skill/attribute
signed char mSkill, mAttribute;
// value of -1 here means the value is unavailable
int mMagnMin, mMagnMax, mRange, mDuration;
bool operator==(const SpellEffectParams& other) const
{
if (mEffectID != other.mEffectID)
return false;
bool involvesAttribute = (mEffectID == 74 // restore attribute
|| mEffectID == 85 // absorb attribute
|| mEffectID == 17 // drain attribute
|| mEffectID == 79 // fortify attribute
|| mEffectID == 22); // damage attribute
bool involvesSkill = (mEffectID == 78 // restore skill
|| mEffectID == 89 // absorb skill
|| mEffectID == 21 // drain skill
|| mEffectID == 83 // fortify skill
|| mEffectID == 26); // damage skill
return ((other.mSkill == mSkill) || !involvesSkill) && ((other.mAttribute == mAttribute) && !involvesAttribute);
}
};
typedef std::vector<SpellEffectParams> SpellEffectList;
class MYGUI_EXPORT MWSkill : public Widget class MYGUI_EXPORT MWSkill : public Widget
{ {
MYGUI_RTTI_DERIVED( MWSkill ); MYGUI_RTTI_DERIVED( MWSkill );
@ -108,6 +158,9 @@ namespace MWGui
}; };
typedef MWAttribute* MWAttributePtr; typedef MWAttribute* MWAttributePtr;
/**
* @todo remove this class and use MWEffectList instead
*/
class MWSpellEffect; class MWSpellEffect;
class MYGUI_EXPORT MWSpell : public Widget class MYGUI_EXPORT MWSpell : public Widget
{ {
@ -155,12 +208,14 @@ namespace MWGui
enum EffectFlags enum EffectFlags
{ {
EF_Potion = 0x01, // potions have no target (target is always the player) EF_NoTarget = 0x01, // potions have no target (target is always the player)
EF_Constant = 0x02 // constant effect means that duration will not be displayed EF_Constant = 0x02 // constant effect means that duration will not be displayed
}; };
void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; } void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; }
void setEffectList(const ESM::EffectList* list); void setEffectList(const SpellEffectList& list);
static SpellEffectList effectListFromESM(const ESM::EffectList* effects);
/** /**
* @param vector to store the created effect widgets * @param vector to store the created effect widgets
@ -180,7 +235,7 @@ namespace MWGui
void updateWidgets(); void updateWidgets();
WindowManager* mWindowManager; WindowManager* mWindowManager;
const ESM::EffectList* mEffectList; SpellEffectList mEffectList;
}; };
typedef MWEffectList* MWEffectListPtr; typedef MWEffectList* MWEffectListPtr;
@ -193,14 +248,13 @@ namespace MWGui
typedef ESM::ENAMstruct SpellEffectValue; typedef ESM::ENAMstruct SpellEffectValue;
void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; } void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; }
void setSpellEffect(SpellEffectValue value); void setSpellEffect(const SpellEffectParams& params);
void setFlags(int flags) { mFlags = flags; }
std::string effectIDToString(const short effectID); std::string effectIDToString(const short effectID);
bool effectHasMagnitude (const std::string& effect); bool effectHasMagnitude (const std::string& effect);
bool effectHasDuration (const std::string& effect); bool effectHasDuration (const std::string& effect);
bool effectInvolvesAttribute (const std::string& effect);
const SpellEffectValue &getSpellEffect() const { return effect; } bool effectInvolvesSkill (const std::string& effect);
int getRequestedWidth() const { return mRequestedWidth; } int getRequestedWidth() const { return mRequestedWidth; }
@ -214,8 +268,7 @@ namespace MWGui
void updateWidgets(); void updateWidgets();
WindowManager* mWindowManager; WindowManager* mWindowManager;
SpellEffectValue effect; SpellEffectParams mEffectParams;
int mFlags;
MyGUI::ImageBox* imageWidget; MyGUI::ImageBox* imageWidget;
MyGUI::TextBox* textWidget; MyGUI::TextBox* textWidget;
int mRequestedWidth; int mRequestedWidth;
@ -229,7 +282,7 @@ namespace MWGui
MWDynamicStat(); MWDynamicStat();
void setValue(int value, int max); void setValue(int value, int max);
void setTitle(const std::string text); void setTitle(const std::string& text);
int getValue() const { return value; } int getValue() const { return value; }
int getMax() const { return max; } int getMax() const { return max; }
@ -247,7 +300,6 @@ namespace MWGui
MyGUI::TextBox* barTextWidget; MyGUI::TextBox* barTextWidget;
}; };
typedef MWDynamicStat* MWDynamicStatPtr; typedef MWDynamicStat* MWDynamicStatPtr;
} }
} }

@ -1,6 +1,8 @@
#include "window_base.hpp" #include "window_base.hpp"
#include "window_manager.hpp" #include "window_manager.hpp"
#include <components/settings/settings.hpp>
using namespace MWGui; using namespace MWGui;
WindowBase::WindowBase(const std::string& parLayout, WindowManager& parWindowManager) WindowBase::WindowBase(const std::string& parLayout, WindowManager& parWindowManager)
@ -13,10 +15,25 @@ void WindowBase::open()
{ {
} }
void WindowBase::setVisible(bool visible)
{
bool wasVisible = mMainWidget->getVisible();
mMainWidget->setVisible(visible);
if (!wasVisible && visible)
open();
}
void WindowBase::center() void WindowBase::center()
{ {
// Centre dialog // Centre dialog
MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize();
// MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize();
// Note by scrawl: The following works more reliably in the case when the window was _just_
// resized and MyGUI RenderManager doesn't know about the new size yet
MyGUI::IntSize gameWindowSize = MyGUI::IntSize(Settings::Manager::getInt("resolution x", "Video"),
Settings::Manager::getInt("resolution y", "Video"));
MyGUI::IntCoord coord = mMainWidget->getCoord(); MyGUI::IntCoord coord = mMainWidget->getCoord();
coord.left = (gameWindowSize.width - coord.width)/2; coord.left = (gameWindowSize.width - coord.width)/2;
coord.top = (gameWindowSize.height - coord.height)/2; coord.top = (gameWindowSize.height - coord.height)/2;

@ -16,6 +16,7 @@ namespace MWGui
typedef MyGUI::delegates::CMultiDelegate1<WindowBase*> EventHandle_WindowBase; typedef MyGUI::delegates::CMultiDelegate1<WindowBase*> EventHandle_WindowBase;
virtual void open(); virtual void open();
virtual void setVisible(bool visible); // calls open() if visible is true and was false before
void center(); void center();
/** Event : Dialog finished, OK button clicked.\n /** Event : Dialog finished, OK button clicked.\n

@ -16,6 +16,10 @@
#include "mainmenu.hpp" #include "mainmenu.hpp"
#include "countdialog.hpp" #include "countdialog.hpp"
#include "tradewindow.hpp" #include "tradewindow.hpp"
#include "settingswindow.hpp"
#include "confirmationdialog.hpp"
#include "alchemywindow.hpp"
#include "spellwindow.hpp"
#include "../mwmechanics/mechanicsmanager.hpp" #include "../mwmechanics/mechanicsmanager.hpp"
#include "../mwinput/inputmanager.hpp" #include "../mwinput/inputmanager.hpp"
@ -35,7 +39,7 @@
using namespace MWGui; using namespace MWGui;
WindowManager::WindowManager( WindowManager::WindowManager(
const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string logpath) const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string& logpath)
: mGuiManager(NULL) : mGuiManager(NULL)
, hud(NULL) , hud(NULL)
, map(NULL) , map(NULL)
@ -45,11 +49,15 @@ WindowManager::WindowManager(
, mMessageBoxManager(NULL) , mMessageBoxManager(NULL)
, console(NULL) , console(NULL)
, mJournal(NULL) , mJournal(NULL)
, mDialogueWindow(nullptr) , mDialogueWindow(NULL)
, mBookWindow(NULL) , mBookWindow(NULL)
, mScrollWindow(NULL) , mScrollWindow(NULL)
, mCountDialog(NULL) , mCountDialog(NULL)
, mTradeWindow(NULL) , mTradeWindow(NULL)
, mSettingsWindow(NULL)
, mConfirmationDialog(NULL)
, mAlchemyWindow(NULL)
, mSpellWindow(NULL)
, mCharGen(NULL) , mCharGen(NULL)
, playerClass() , playerClass()
, playerName() , playerName()
@ -62,9 +70,6 @@ WindowManager::WindowManager(
, playerMagicka() , playerMagicka()
, playerFatigue() , playerFatigue()
, gui(NULL) , gui(NULL)
, mode(GM_Game)
, nextMode(GM_Game)
, needModeChange(false)
, garbageDialogs() , garbageDialogs()
, shown(GW_ALL) , shown(GW_ALL)
, allowed(newGame ? GW_None : GW_ALL) , allowed(newGame ? GW_None : GW_ALL)
@ -118,6 +123,10 @@ WindowManager::WindowManager(
mScrollWindow = new ScrollWindow(*this); mScrollWindow = new ScrollWindow(*this);
mBookWindow = new BookWindow(*this); mBookWindow = new BookWindow(*this);
mCountDialog = new CountDialog(*this); mCountDialog = new CountDialog(*this);
mSettingsWindow = new SettingsWindow(*this);
mConfirmationDialog = new ConfirmationDialog(*this);
mAlchemyWindow = new AlchemyWindow(*this);
mSpellWindow = new SpellWindow(*this);
// The HUD is always on // The HUD is always on
hud->setVisible(true); hud->setVisible(true);
@ -135,6 +144,9 @@ WindowManager::WindowManager(
playerSkillValues.insert(std::make_pair(ESM::Skill::skillIds[i], MWMechanics::Stat<float>())); playerSkillValues.insert(std::make_pair(ESM::Skill::skillIds[i], MWMechanics::Stat<float>()));
} }
unsetSelectedSpell();
unsetSelectedWeapon();
// Set up visibility // Set up visibility
updateVisible(); updateVisible();
} }
@ -158,6 +170,10 @@ WindowManager::~WindowManager()
delete mBookWindow; delete mBookWindow;
delete mScrollWindow; delete mScrollWindow;
delete mTradeWindow; delete mTradeWindow;
delete mSettingsWindow;
delete mConfirmationDialog;
delete mAlchemyWindow;
delete mSpellWindow;
cleanupGarbage(); cleanupGarbage();
} }
@ -178,29 +194,10 @@ void WindowManager::cleanupGarbage()
void WindowManager::update() void WindowManager::update()
{ {
cleanupGarbage(); cleanupGarbage();
if (needModeChange)
{
needModeChange = false;
MWBase::Environment::get().getInputManager()->setGuiMode(nextMode);
nextMode = GM_Game;
}
if (showFPSLevel > 0)
{
hud->setFPS(mFPS); hud->setFPS(mFPS);
hud->setTriangleCount(mTriangleCount); hud->setTriangleCount(mTriangleCount);
hud->setBatchCount(mBatchCount); hud->setBatchCount(mBatchCount);
}
}
void WindowManager::setNextMode(GuiMode newMode)
{
nextMode = newMode;
needModeChange = true;
}
void WindowManager::setGuiMode(GuiMode newMode)
{
MWBase::Environment::get().getInputManager()->setGuiMode(newMode);
} }
void WindowManager::updateVisible() void WindowManager::updateVisible()
@ -217,22 +214,38 @@ void WindowManager::updateVisible()
mScrollWindow->setVisible(false); mScrollWindow->setVisible(false);
mBookWindow->setVisible(false); mBookWindow->setVisible(false);
mTradeWindow->setVisible(false); mTradeWindow->setVisible(false);
mSettingsWindow->setVisible(false);
mAlchemyWindow->setVisible(false);
mSpellWindow->setVisible(false);
// Mouse is visible whenever we're not in game mode // Mouse is visible whenever we're not in game mode
MyGUI::PointerManager::getInstance().setVisible(isGuiMode()); MyGUI::PointerManager::getInstance().setVisible(isGuiMode());
if (mode == GM_Game) bool gameMode = !isGuiMode();
if (gameMode)
mToolTips->enterGameMode(); mToolTips->enterGameMode();
else else
mToolTips->enterGuiMode(); mToolTips->enterGuiMode();
switch(mode) { setMinimapVisibility((allowed & GW_Map) && !map->pinned());
case GM_Game: setWeaponVisibility((allowed & GW_Inventory) && !mInventoryWindow->pinned());
setSpellVisibility((allowed & GW_Magic) && !mSpellWindow->pinned());
setHMSVisibility((allowed & GW_Stats) && !mStatsWindow->pinned());
// If in game mode, don't show anything. // If in game mode, don't show anything.
break; if (gameMode)
return;
GuiMode mode = mGuiModes.back();
switch(mode) {
case GM_MainMenu: case GM_MainMenu:
menu->setVisible(true); menu->setVisible(true);
break; break;
case GM_Settings:
mSettingsWindow->setVisible(true);
break;
case GM_Console: case GM_Console:
console->enable(); console->enable();
break; break;
@ -242,6 +255,9 @@ void WindowManager::updateVisible()
case GM_Book: case GM_Book:
mBookWindow->setVisible(true); mBookWindow->setVisible(true);
break; break;
case GM_Alchemy:
mAlchemyWindow->setVisible(true);
break;
case GM_Name: case GM_Name:
case GM_Race: case GM_Race:
case GM_Class: case GM_Class:
@ -261,29 +277,24 @@ void WindowManager::updateVisible()
int eff = shown & allowed; int eff = shown & allowed;
// Show the windows we want // Show the windows we want
map -> setVisible( (eff & GW_Map) != 0 ); map -> setVisible(eff & GW_Map);
mStatsWindow -> setVisible( (eff & GW_Stats) != 0 ); mStatsWindow -> setVisible(eff & GW_Stats);
mInventoryWindow->setVisible(true); mInventoryWindow->setVisible(eff & GW_Inventory);
mInventoryWindow->openInventory(); mSpellWindow->setVisible(eff & GW_Magic);
break; break;
} }
case GM_Container: case GM_Container:
mContainerWindow->setVisible(true); mContainerWindow->setVisible(true);
mInventoryWindow->setVisible(true); mInventoryWindow->setVisible(true);
mInventoryWindow->openInventory();
break; break;
case GM_Dialogue: case GM_Dialogue:
mDialogueWindow->open(); mDialogueWindow->setVisible(true);
break; break;
case GM_Barter: case GM_Barter:
mInventoryWindow->setVisible(true); mInventoryWindow->setVisible(true);
mInventoryWindow->openInventory();
mTradeWindow->setVisible(true); mTradeWindow->setVisible(true);
break; break;
case GM_InterMessageBox: case GM_InterMessageBox:
if(!mMessageBoxManager->isInteractiveMessageBox()) {
setGuiMode(GM_Game);
}
break; break;
case GM_Journal: case GM_Journal:
mJournal->setVisible(true); mJournal->setVisible(true);
@ -291,9 +302,6 @@ void WindowManager::updateVisible()
break; break;
default: default:
// Unsupported mode, switch back to game // Unsupported mode, switch back to game
// Note: The call will eventually end up this method again but
// will stop at the check if mode is GM_Game.
setGuiMode(GM_Game);
break; break;
} }
} }
@ -301,6 +309,7 @@ void WindowManager::updateVisible()
void WindowManager::setValue (const std::string& id, const MWMechanics::Stat<int>& value) void WindowManager::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
{ {
mStatsWindow->setValue (id, value); mStatsWindow->setValue (id, value);
mCharGen->setValue(id, value);
static const char *ids[] = static const char *ids[] =
{ {
@ -331,6 +340,7 @@ void WindowManager::setValue (const std::string& id, const MWMechanics::Stat<int
void WindowManager::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value) void WindowManager::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value)
{ {
mStatsWindow->setValue(parSkill, value); mStatsWindow->setValue(parSkill, value);
mCharGen->setValue(parSkill, value);
playerSkillValues[parSkill] = value; playerSkillValues[parSkill] = value;
} }
@ -338,6 +348,7 @@ void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicS
{ {
mStatsWindow->setValue (id, value); mStatsWindow->setValue (id, value);
hud->setValue (id, value); hud->setValue (id, value);
mCharGen->setValue(id, value);
if (id == "HBar") if (id == "HBar")
{ {
playerHealth = value; playerHealth = value;
@ -390,6 +401,7 @@ void WindowManager::setPlayerClass (const ESM::Class &class_)
void WindowManager::configureSkills (const SkillList& major, const SkillList& minor) void WindowManager::configureSkills (const SkillList& major, const SkillList& minor)
{ {
mStatsWindow->configureSkills (major, minor); mStatsWindow->configureSkills (major, minor);
mCharGen->configureSkills(major, minor);
playerMajorSkills = major; playerMajorSkills = major;
playerMinorSkills = minor; playerMinorSkills = minor;
} }
@ -427,7 +439,7 @@ void WindowManager::messageBox (const std::string& message, const std::vector<st
else else
{ {
mMessageBoxManager->createInteractiveMessageBox(message, buttons); mMessageBoxManager->createInteractiveMessageBox(message, buttons);
setGuiMode(GM_InterMessageBox); pushGuiMode(GM_InterMessageBox);
} }
} }
@ -452,7 +464,7 @@ void WindowManager::onDialogueWindowBye()
//removeDialog(dialogueWindow); //removeDialog(dialogueWindow);
mDialogueWindow->setVisible(false); mDialogueWindow->setVisible(false);
} }
setGuiMode(GM_Game); popGuiMode();
} }
void WindowManager::onFrame (float frameDuration) void WindowManager::onFrame (float frameDuration)
@ -469,6 +481,13 @@ void WindowManager::onFrame (float frameDuration)
mInventoryWindow->onFrame(); mInventoryWindow->onFrame();
mStatsWindow->onFrame(); mStatsWindow->onFrame();
hud->onFrame(frameDuration);
mDialogueWindow->checkReferenceAvailable();
mTradeWindow->checkReferenceAvailable();
mContainerWindow->checkReferenceAvailable();
console->checkReferenceAvailable();
} }
const ESMS::ESMStore& WindowManager::getStore() const const ESMS::ESMStore& WindowManager::getStore() const
@ -493,6 +512,7 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell)
} }
map->setCellName( name ); map->setCellName( name );
hud->setCellName( name );
map->setCellPrefix("Cell"); map->setCellPrefix("Cell");
hud->setCellPrefix("Cell"); hud->setCellPrefix("Cell");
@ -502,6 +522,7 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell)
else else
{ {
map->setCellName( cell->cell->name ); map->setCellName( cell->cell->name );
hud->setCellName( cell->cell->name );
map->setCellPrefix( cell->cell->name ); map->setCellPrefix( cell->cell->name );
hud->setCellPrefix( cell->cell->name ); hud->setCellPrefix( cell->cell->name );
} }
@ -542,14 +563,6 @@ void WindowManager::toggleFogOfWar()
hud->toggleFogOfWar(); hud->toggleFogOfWar();
} }
int WindowManager::toggleFps()
{
showFPSLevel = (showFPSLevel+1)%3;
hud->setFpsLevel(showFPSLevel);
Settings::Manager::setInt("fps", "HUD", showFPSLevel);
return showFPSLevel;
}
void WindowManager::setFocusObject(const MWWorld::Ptr& focus) void WindowManager::setFocusObject(const MWWorld::Ptr& focus)
{ {
mToolTips->setFocusObject(focus); mToolTips->setFocusObject(focus);
@ -572,12 +585,13 @@ bool WindowManager::getFullHelp() const
void WindowManager::setWeaponVisibility(bool visible) void WindowManager::setWeaponVisibility(bool visible)
{ {
hud->weapBox->setVisible(visible); hud->setBottomLeftVisibility(hud->health->getVisible(), visible, hud->spellBox->getVisible());
} }
void WindowManager::setSpellVisibility(bool visible) void WindowManager::setSpellVisibility(bool visible)
{ {
hud->spellBox->setVisible(visible); hud->setBottomLeftVisibility(hud->health->getVisible(), hud->weapBox->getVisible(), visible);
hud->setBottomRightVisibility(visible, hud->minimapBox->getVisible());
} }
void WindowManager::setMouseVisible(bool visible) void WindowManager::setMouseVisible(bool visible)
@ -596,4 +610,125 @@ void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _r
const ESM::GameSetting *setting = MWBase::Environment::get().getWorld()->getStore().gameSettings.search(_tag); const ESM::GameSetting *setting = MWBase::Environment::get().getWorld()->getStore().gameSettings.search(_tag);
if (setting && setting->type == ESM::VT_String) if (setting && setting->type == ESM::VT_String)
_result = setting->str; _result = setting->str;
else
_result = _tag;
}
void WindowManager::processChangedSettings(const Settings::CategorySettingVector& changed)
{
hud->setFpsLevel(Settings::Manager::getInt("fps", "HUD"));
mToolTips->setDelay(Settings::Manager::getFloat("tooltip delay", "GUI"));
bool changeRes = false;
for (Settings::CategorySettingVector::const_iterator it = changed.begin();
it != changed.end(); ++it)
{
if (it->first == "Video" && (
it->second == "resolution x"
|| it->second == "resolution y"))
{
changeRes = true;
}
}
if (changeRes)
{
int x = Settings::Manager::getInt("resolution x", "Video");
int y = Settings::Manager::getInt("resolution y", "Video");
hud->onResChange(x, y);
console->onResChange(x, y);
mSettingsWindow->center();
mDragAndDrop->mDragAndDropWidget->setSize(MyGUI::IntSize(x, y));
}
}
void WindowManager::pushGuiMode(GuiMode mode)
{
if (mode==GM_Inventory && allowed==GW_None)
return;
mGuiModes.push_back(mode);
bool gameMode = !isGuiMode();
MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode);
updateVisible();
}
void WindowManager::popGuiMode()
{
if (!mGuiModes.empty())
mGuiModes.pop_back();
bool gameMode = !isGuiMode();
MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode);
updateVisible();
}
void WindowManager::removeGuiMode(GuiMode mode)
{
std::vector<GuiMode>::iterator it = mGuiModes.begin();
while (it != mGuiModes.end())
{
if (*it == mode)
it = mGuiModes.erase(it);
else
++it;
}
updateVisible();
}
void WindowManager::setSelectedSpell(const std::string& spellId, int successChancePercent)
{
hud->setSelectedSpell(spellId, successChancePercent);
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId);
mSpellWindow->setTitle(spell->name);
}
void WindowManager::setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent)
{
hud->setSelectedEnchantItem(item, chargePercent);
mSpellWindow->setTitle(MWWorld::Class::get(item).getName(item));
}
void WindowManager::setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent)
{
hud->setSelectedWeapon(item, durabilityPercent);
mInventoryWindow->setTitle(MWWorld::Class::get(item).getName(item));
}
void WindowManager::unsetSelectedSpell()
{
hud->unsetSelectedSpell();
mSpellWindow->setTitle("#{sNone}");
}
void WindowManager::unsetSelectedWeapon()
{
hud->unsetSelectedWeapon();
mInventoryWindow->setTitle("#{sSkillHandtohand}");
}
void WindowManager::getMousePosition(int &x, int &y)
{
const MyGUI::IntPoint& pos = MyGUI::InputManager::getInstance().getMousePosition();
x = pos.left;
y = pos.top;
}
void WindowManager::getMousePosition(float &x, float &y)
{
const MyGUI::IntPoint& pos = MyGUI::InputManager::getInstance().getMousePosition();
x = pos.left;
y = pos.top;
const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize();
x /= viewSize.width;
y /= viewSize.height;
}
bool WindowManager::getWorldMouseOver()
{
return hud->getWorldMouseOver();
} }

@ -17,6 +17,7 @@
#include "MyGUI_UString.h" #include "MyGUI_UString.h"
#include <components/esm_store/store.hpp> #include <components/esm_store/store.hpp>
#include <components/settings/settings.hpp>
#include <openengine/ogre/renderer.hpp> #include <openengine/ogre/renderer.hpp>
#include <openengine/gui/manager.hpp> #include <openengine/gui/manager.hpp>
@ -77,6 +78,10 @@ namespace MWGui
class MessageBoxManager; class MessageBoxManager;
class CountDialog; class CountDialog;
class TradeWindow; class TradeWindow;
class SettingsWindow;
class ConfirmationDialog;
class AlchemyWindow;
class SpellWindow;
struct ClassPoint struct ClassPoint
{ {
@ -93,11 +98,9 @@ namespace MWGui
typedef std::vector<Faction> FactionList; typedef std::vector<Faction> FactionList;
typedef std::vector<int> SkillList; typedef std::vector<int> SkillList;
WindowManager(const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string logpath); WindowManager(const Compiler::Extensions& extensions, int fpsLevel, bool newGame, OEngine::Render::OgreRenderer *mOgre, const std::string& logpath);
virtual ~WindowManager(); virtual ~WindowManager();
void setGuiMode(GuiMode newMode);
/** /**
* Should be called each frame to update windows/gui elements. * Should be called each frame to update windows/gui elements.
* This could mean updating sizes of gui elements or opening * This could mean updating sizes of gui elements or opening
@ -105,19 +108,24 @@ namespace MWGui
*/ */
void update(); void update();
void setMode(GuiMode newMode) void pushGuiMode(GuiMode mode);
{ void popGuiMode();
if (newMode==GM_Inventory && allowed==GW_None) void removeGuiMode(GuiMode mode); ///< can be anywhere in the stack
return;
mode = newMode; GuiMode getMode() const
updateVisible(); {
if (mGuiModes.empty())
throw std::runtime_error ("getMode() called, but there is no active mode");
return mGuiModes.back();
} }
void setNextMode(GuiMode newMode);
GuiMode getMode() const { return mode; } bool isGuiMode() const { return !mGuiModes.empty(); }
bool isGuiMode() const { return getMode() != GM_Game; } // Everything that is not game mode is considered "gui mode" void toggleVisible(GuiWindow wnd)
{
shown = (shown & wnd) ? (GuiWindow) (shown & ~wnd) : (GuiWindow) (shown | wnd);
updateVisible();
}
// Disallow all inventory mode windows // Disallow all inventory mode windows
void disallowAll() void disallowAll()
@ -133,13 +141,21 @@ namespace MWGui
updateVisible(); updateVisible();
} }
bool isAllowed(GuiWindow wnd) const
{
return allowed & wnd;
}
MWGui::DialogueWindow* getDialogueWindow() {return mDialogueWindow;} MWGui::DialogueWindow* getDialogueWindow() {return mDialogueWindow;}
MWGui::ContainerWindow* getContainerWindow() {return mContainerWindow;} MWGui::ContainerWindow* getContainerWindow() {return mContainerWindow;}
MWGui::InventoryWindow* getInventoryWindow() {return mInventoryWindow;} MWGui::InventoryWindow* getInventoryWindow() {return mInventoryWindow;}
MWGui::BookWindow* getBookWindow() {return mBookWindow;} MWGui::BookWindow* getBookWindow() {return mBookWindow;}
MWGui::ScrollWindow* getScrollWindow() {return mScrollWindow;} MWGui::ScrollWindow* getScrollWindow() {return mScrollWindow;}
MWGui::CountDialog* getCountDialog() {return mCountDialog;} MWGui::CountDialog* getCountDialog() {return mCountDialog;}
MWGui::ConfirmationDialog* getConfirmationDialog() {return mConfirmationDialog;}
MWGui::TradeWindow* getTradeWindow() {return mTradeWindow;} MWGui::TradeWindow* getTradeWindow() {return mTradeWindow;}
MWGui::SpellWindow* getSpellWindow() {return mSpellWindow;}
MWGui::Console* getConsole() {return console;}
MyGUI::Gui* getGui() const { return gui; } MyGUI::Gui* getGui() const { return gui; }
@ -173,15 +189,15 @@ namespace MWGui
void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y); void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y);
void setMouseVisible(bool visible); void setMouseVisible(bool visible);
void getMousePosition(int &x, int &y);
void getMousePosition(float &x, float &y);
void setDragDrop(bool dragDrop); void setDragDrop(bool dragDrop);
bool getWorldMouseOver();
void toggleFogOfWar(); void toggleFogOfWar();
void toggleFullHelp(); ///< show extra info in item tooltips (owner, script) void toggleFullHelp(); ///< show extra info in item tooltips (owner, script)
bool getFullHelp() const; bool getFullHelp() const;
int toggleFps();
///< toggle fps display @return resulting fps level
void setInteriorMapTexture(const int x, const int y); void setInteriorMapTexture(const int x, const int y);
///< set the index of the map texture that should be used (for interiors) ///< set the index of the map texture that should be used (for interiors)
@ -192,6 +208,12 @@ namespace MWGui
void setWeaponVisibility(bool visible); void setWeaponVisibility(bool visible);
void setSpellVisibility(bool visible); void setSpellVisibility(bool visible);
void setSelectedSpell(const std::string& spellId, int successChancePercent);
void setSelectedEnchantItem(const MWWorld::Ptr& item, int chargePercent);
void setSelectedWeapon(const MWWorld::Ptr& item, int durabilityPercent);
void unsetSelectedSpell();
void unsetSelectedWeapon();
template<typename T> template<typename T>
void removeDialog(T*& dialog); ///< Casts to OEngine::GUI::Layout and calls removeDialog, then resets pointer to nullptr. void removeDialog(T*& dialog); ///< Casts to OEngine::GUI::Layout and calls removeDialog, then resets pointer to nullptr.
void removeDialog(OEngine::GUI::Layout* dialog); ///< Hides dialog and schedules dialog to be deleted. void removeDialog(OEngine::GUI::Layout* dialog); ///< Hides dialog and schedules dialog to be deleted.
@ -201,6 +223,11 @@ namespace MWGui
void onFrame (float frameDuration); void onFrame (float frameDuration);
std::map<ESM::Skill::SkillEnum, MWMechanics::Stat<float> > getPlayerSkillValues() { return playerSkillValues; }
std::map<ESM::Attribute::AttributeID, MWMechanics::Stat<int> > getPlayerAttributeValues() { return playerAttributes; }
SkillList getPlayerMinorSkills() { return playerMinorSkills; }
SkillList getPlayerMajorSkills() { return playerMajorSkills; }
/** /**
* Fetches a GMST string from the store, if there is no setting with the given * Fetches a GMST string from the store, if there is no setting with the given
* ID or it is not a string the default string is returned. * ID or it is not a string the default string is returned.
@ -212,6 +239,8 @@ namespace MWGui
const ESMS::ESMStore& getStore() const; const ESMS::ESMStore& getStore() const;
void processChangedSettings(const Settings::CategorySettingVector& changed);
private: private:
OEngine::GUI::MyGUIManager *mGuiManager; OEngine::GUI::MyGUIManager *mGuiManager;
HUD *hud; HUD *hud;
@ -230,6 +259,10 @@ namespace MWGui
BookWindow* mBookWindow; BookWindow* mBookWindow;
CountDialog* mCountDialog; CountDialog* mCountDialog;
TradeWindow* mTradeWindow; TradeWindow* mTradeWindow;
SettingsWindow* mSettingsWindow;
ConfirmationDialog* mConfirmationDialog;
AlchemyWindow* mAlchemyWindow;
SpellWindow* mSpellWindow;
CharacterCreation* mCharGen; CharacterCreation* mCharGen;
@ -244,9 +277,7 @@ namespace MWGui
MyGUI::Gui *gui; // Gui MyGUI::Gui *gui; // Gui
GuiMode mode; // Current gui mode std::vector<GuiMode> mGuiModes;
GuiMode nextMode; // Next mode to activate in update()
bool needModeChange; //Whether a mode change is needed in update() [will use nextMode]
std::vector<OEngine::GUI::Layout*> garbageDialogs; std::vector<OEngine::GUI::Layout*> garbageDialogs;
void cleanupGarbage(); void cleanupGarbage();
@ -257,9 +288,6 @@ namespace MWGui
the start of the game, when windows are enabled one by one the start of the game, when windows are enabled one by one
through script commands. You can manipulate this through using through script commands. You can manipulate this through using
allow() and disableAll(). allow() and disableAll().
The setting should also affect visibility of certain HUD
elements, but this is not done yet.
*/ */
GuiWindow allowed; GuiWindow allowed;

@ -12,6 +12,7 @@ namespace MWGui
public: public:
WindowPinnableBase(const std::string& parLayout, WindowManager& parWindowManager); WindowPinnableBase(const std::string& parLayout, WindowManager& parWindowManager);
void setVisible(bool b); void setVisible(bool b);
bool pinned() { return mPinned; }
private: private:
void onWindowButtonPressed(MyGUI::Window* sender, const std::string& eventName); void onWindowButtonPressed(MyGUI::Window* sender, const std::string& eventName);

@ -69,7 +69,7 @@ namespace MWInput
A_ToggleWeapon, A_ToggleWeapon,
A_ToggleSpell, A_ToggleSpell,
A_ToggleFps, // Toggle FPS display (this is temporary) A_Settings, // Temporary hotkey
A_LAST // Marker for the last item A_LAST // Marker for the last item
}; };
@ -92,12 +92,12 @@ namespace MWInput
/* InputImpl Methods */ /* InputImpl Methods */
public:
void toggleFps() void adjustMouseRegion(int width, int height)
{ {
windows.toggleFps(); input.adjustMouseClippingSize(width, height);
} }
private:
void toggleSpell() void toggleSpell()
{ {
if (windows.isGuiMode()) return; if (windows.isGuiMode()) return;
@ -140,6 +140,15 @@ namespace MWInput
windows.messageBox ("Screenshot saved", empty); windows.messageBox ("Screenshot saved", empty);
} }
void showSettings()
{
if (mDragDrop)
return;
if (!windows.isGuiMode() || windows.getMode() != MWGui::GM_Settings)
windows.pushGuiMode(MWGui::GM_Settings);
}
/* toggleInventory() is called when the user presses the button to toggle the inventory screen. */ /* toggleInventory() is called when the user presses the button to toggle the inventory screen. */
void toggleInventory() void toggleInventory()
{ {
@ -148,13 +157,13 @@ namespace MWInput
if (mDragDrop) if (mDragDrop)
return; return;
GuiMode mode = windows.getMode(); bool gameMode = !windows.isGuiMode();
// Toggle between game mode and inventory mode // Toggle between game mode and inventory mode
if(mode == GM_Game) if(gameMode)
setGuiMode(GM_Inventory); windows.pushGuiMode(GM_Inventory);
else if(mode == GM_Inventory) else if(windows.getMode() == GM_Inventory)
setGuiMode(GM_Game); windows.popGuiMode();
// .. but don't touch any other mode. // .. but don't touch any other mode.
} }
@ -167,27 +176,32 @@ namespace MWInput
if (mDragDrop) if (mDragDrop)
return; return;
GuiMode mode = windows.getMode(); bool gameMode = !windows.isGuiMode();
// Switch to console mode no matter what mode we are currently // Switch to console mode no matter what mode we are currently
// in, except of course if we are already in console mode // in, except of course if we are already in console mode
if(mode == GM_Console) if (!gameMode)
setGuiMode(GM_Game); {
else setGuiMode(GM_Console); if (windows.getMode() == GM_Console)
windows.popGuiMode();
else
windows.pushGuiMode(GM_Console);
}
else
windows.pushGuiMode(GM_Console);
} }
void toggleJournal() void toggleJournal()
{ {
using namespace MWGui; using namespace MWGui;
GuiMode mode = windows.getMode();
// Toggle between game mode and journal mode // Toggle between game mode and journal mode
if(mode == GM_Game) bool gameMode = !windows.isGuiMode();
setGuiMode(GM_Journal);
else if(mode == GM_Journal)
setGuiMode(GM_Game);
if(gameMode)
windows.pushGuiMode(GM_Journal);
else if(windows.getMode() == GM_Journal)
windows.popGuiMode();
// .. but don't touch any other mode. // .. but don't touch any other mode.
} }
@ -259,8 +273,8 @@ namespace MWInput
"Draw Weapon"); "Draw Weapon");
disp->funcs.bind(A_ToggleSpell,boost::bind(&InputImpl::toggleSpell,this), disp->funcs.bind(A_ToggleSpell,boost::bind(&InputImpl::toggleSpell,this),
"Ready hands"); "Ready hands");
disp->funcs.bind(A_ToggleFps, boost::bind(&InputImpl::toggleFps, this), disp->funcs.bind(A_Settings, boost::bind(&InputImpl::showSettings, this),
"Toggle FPS display"); "Show settings window");
// Add the exit listener // Add the exit listener
ogre.getRoot()->addFrameListener(&exit); ogre.getRoot()->addFrameListener(&exit);
@ -282,8 +296,7 @@ namespace MWInput
lst->add(guiEvents,Event::EV_ALL); lst->add(guiEvents,Event::EV_ALL);
} }
// Start out in game mode changeInputMode(false);
setGuiMode(MWGui::GM_Game);
/********************************** /**********************************
Key binding section Key binding section
@ -307,7 +320,7 @@ namespace MWInput
disp->bind(A_ToggleWalk, KC_C); disp->bind(A_ToggleWalk, KC_C);
disp->bind(A_ToggleWeapon,KC_F); disp->bind(A_ToggleWeapon,KC_F);
disp->bind(A_ToggleSpell,KC_R); disp->bind(A_ToggleSpell,KC_R);
disp->bind(A_ToggleFps, KC_F10); disp->bind(A_Settings, KC_F2);
// Key bindings for polled keys // Key bindings for polled keys
// NOTE: These keys are constantly being polled. Only add keys that must be checked each frame. // NOTE: These keys are constantly being polled. Only add keys that must be checked each frame.
@ -348,6 +361,7 @@ namespace MWInput
windows.update(); windows.update();
// Disable movement in Gui mode // Disable movement in Gui mode
if (windows.isGuiMode()) return; if (windows.isGuiMode()) return;
// Configure player movement according to keyboard input. Actual movement will // Configure player movement according to keyboard input. Actual movement will
@ -388,14 +402,10 @@ namespace MWInput
// Switch between gui modes. Besides controlling the Gui windows // Switch between gui modes. Besides controlling the Gui windows
// this also makes sure input is directed to the right place // this also makes sure input is directed to the right place
void setGuiMode(MWGui::GuiMode mode) void changeInputMode(bool guiMode)
{ {
// Tell the GUI what to show (this also takes care of the mouse
// pointer)
windows.setMode(mode);
// Are we in GUI mode now? // Are we in GUI mode now?
if(windows.isGuiMode()) if(guiMode)
{ {
// Disable mouse look // Disable mouse look
mouse->setCamera(NULL); mouse->setCamera(NULL);
@ -431,11 +441,6 @@ namespace MWInput
delete impl; delete impl;
} }
void MWInputManager::setGuiMode(MWGui::GuiMode mode)
{
impl->setGuiMode(mode);
}
void MWInputManager::update() void MWInputManager::update()
{ {
impl->update(); impl->update();
@ -445,4 +450,25 @@ namespace MWInput
{ {
impl->setDragDrop(dragDrop); impl->setDragDrop(dragDrop);
} }
void MWInputManager::changeInputMode(bool guiMode)
{
impl->changeInputMode(guiMode);
}
void MWInputManager::processChangedSettings(const Settings::CategorySettingVector& changed)
{
bool changeRes = false;
for (Settings::CategorySettingVector::const_iterator it = changed.begin();
it != changed.end(); ++it)
{
if (it->first == "Video" && (
it->second == "resolution x"
|| it->second == "resolution y"))
changeRes = true;
}
if (changeRes)
impl->adjustMouseRegion(Settings::Manager::getInt("resolution x", "Video"), Settings::Manager::getInt("resolution y", "Video"));
}
} }

@ -3,6 +3,8 @@
#include "../mwgui/mode.hpp" #include "../mwgui/mode.hpp"
#include <components/settings/settings.hpp>
namespace OEngine namespace OEngine
{ {
namespace Render namespace Render
@ -50,9 +52,11 @@ namespace MWInput
void update(); void update();
void setDragDrop(bool dragDrop); void changeInputMode(bool guiMode);
void setGuiMode(MWGui::GuiMode mode); void processChangedSettings(const Settings::CategorySettingVector& changed);
void setDragDrop(bool dragDrop);
}; };
} }
#endif #endif

@ -71,7 +71,10 @@ namespace MWMechanics
void Actors::removeActor (const MWWorld::Ptr& ptr) void Actors::removeActor (const MWWorld::Ptr& ptr)
{ {
mActors.erase (ptr); std::set<MWWorld::Ptr>::iterator iter = mActors.find (ptr);
if (iter!=mActors.end())
mActors.erase (iter);
} }
void Actors::dropActors (const MWWorld::Ptr::CellStore *cellStore) void Actors::dropActors (const MWWorld::Ptr::CellStore *cellStore)

@ -32,6 +32,8 @@ namespace MWMechanics
void removeActor (const MWWorld::Ptr& ptr); void removeActor (const MWWorld::Ptr& ptr);
///< Deregister an actor for stats management ///< Deregister an actor for stats management
///
/// \note Ignored, if \a ptr is not a registered actor.
void dropActors (const MWWorld::Ptr::CellStore *cellStore); void dropActors (const MWWorld::Ptr::CellStore *cellStore);
///< Deregister all actors in the given cell. ///< Deregister all actors in the given cell.

@ -30,6 +30,15 @@ namespace MWMechanics
for (int i=0; i<27; ++i) for (int i=0; i<27; ++i)
npcStats.mSkill[i].setBase (player->npdt52.skills[i]); npcStats.mSkill[i].setBase (player->npdt52.skills[i]);
creatureStats.mAttributes[0].setBase (player->npdt52.strength);
creatureStats.mAttributes[1].setBase (player->npdt52.intelligence);
creatureStats.mAttributes[2].setBase (player->npdt52.willpower);
creatureStats.mAttributes[3].setBase (player->npdt52.agility);
creatureStats.mAttributes[4].setBase (player->npdt52.speed);
creatureStats.mAttributes[5].setBase (player->npdt52.endurance);
creatureStats.mAttributes[6].setBase (player->npdt52.personality);
creatureStats.mAttributes[7].setBase (player->npdt52.luck);
// race // race
if (mRaceSelected) if (mRaceSelected)
{ {

@ -28,7 +28,7 @@ namespace MWMechanics
void Spells::add (const std::string& spellId) void Spells::add (const std::string& spellId)
{ {
if (std::find (mSpells.begin(), mSpells.end(), spellId)!=mSpells.end()) if (std::find (mSpells.begin(), mSpells.end(), spellId)==mSpells.end())
mSpells.push_back (spellId); mSpells.push_back (spellId);
} }

@ -0,0 +1,99 @@
#ifndef MWMECHANICS_SPELLSUCCESS_H
#define MWMECHANICS_SPELLSUCCESS_H
#include "../mwworld/ptr.hpp"
#include "../mwworld/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "npcstats.hpp"
namespace MWMechanics
{
inline int spellSchoolToSkill(int school)
{
std::map<int, int> schoolSkillMap; // maps spell school to skill id
schoolSkillMap[0] = 11; // alteration
schoolSkillMap[1] = 13; // conjuration
schoolSkillMap[3] = 12; // illusion
schoolSkillMap[2] = 10; // destruction
schoolSkillMap[4] = 14; // mysticism
schoolSkillMap[5] = 15; // restoration
assert(schoolSkillMap.find(school) != schoolSkillMap.end());
return schoolSkillMap[school];
}
inline int getSpellSchool(const std::string& spellId, const MWWorld::Ptr& actor)
{
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId);
NpcStats& stats = MWWorld::Class::get(actor).getNpcStats(actor);
// determine the spell's school
// this is always the school where the player's respective skill is the least advanced
// out of all the magic effects' schools
const std::vector<ESM::ENAMstruct>& effects = spell->effects.list;
int school = -1;
int skillLevel = -1;
for (std::vector<ESM::ENAMstruct>::const_iterator it = effects.begin();
it != effects.end(); ++it)
{
const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(it->effectID);
int _school = effect->data.school;
int _skillLevel = stats.mSkill[spellSchoolToSkill(_school)].getModified();
if (school == -1)
{
school = _school;
skillLevel = _skillLevel;
}
else if (_skillLevel < skillLevel)
{
school = _school;
skillLevel = _skillLevel;
}
}
return school;
}
// UESP wiki / Morrowind/Spells:
// Chance of success is (Spell's skill * 2 + Willpower / 5 + Luck / 10 - Spell cost - Sound magnitude) * (Current fatigue + Maximum Fatigue * 1.5) / Maximum fatigue * 2
/**
* @param spellId ID of spell
* @param actor calculate spell success chance for this actor (depends on actor's skills)
* @attention actor has to be an NPC and not a creature!
* @return success chance from 0 to 100 (in percent)
*/
inline float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor)
{
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId);
if (spell->data.flags & ESM::Spell::F_Always // spells with this flag always succeed (usually birthsign spells)
|| spell->data.type == ESM::Spell::ST_Power) // powers always succeed, but can be cast only once per day
return 100.0;
NpcStats& stats = MWWorld::Class::get(actor).getNpcStats(actor);
CreatureStats& creatureStats = MWWorld::Class::get(actor).getCreatureStats(actor);
int skillLevel = stats.mSkill[getSpellSchool(spellId, actor)].getModified();
// Sound magic effect (reduces spell casting chance)
int soundMagnitude = creatureStats.mMagicEffects.get (MWMechanics::EffectKey (48)).mMagnitude;
int willpower = creatureStats.mAttributes[ESM::Attribute::Willpower].getModified();
int luck = creatureStats.mAttributes[ESM::Attribute::Luck].getModified();
int currentFatigue = creatureStats.mDynamic[2].getCurrent();
int maxFatigue = creatureStats.mDynamic[2].getModified();
int spellCost = spell->data.cost;
// There we go, all needed variables are there, lets go
float chance = (float(skillLevel * 2) + float(willpower)/5.0 + float(luck)/ 10.0 - spellCost - soundMagnitude) * (float(currentFatigue + maxFatigue * 1.5)) / float(maxFatigue * 2.0);
chance = std::max(0.0f, std::min(100.0f, chance)); // clamp to 0 .. 100
return chance;
}
}
#endif

@ -26,6 +26,21 @@ void Compositors::setEnabled (const bool enabled)
mEnabled = enabled; mEnabled = enabled;
} }
void Compositors::recreate()
{
Ogre::CompositorManager::getSingleton().removeCompositorChain(mViewport);
CompositorMap temp = mCompositors;
mCompositors.clear();
for (CompositorMap::iterator it=temp.begin();
it != temp.end(); ++it)
{
addCompositor(it->first, it->second.second);
setCompositorEnabled(it->first, mEnabled && it->second.first);
}
}
void Compositors::addCompositor (const std::string& name, const int priority) void Compositors::addCompositor (const std::string& name, const int priority)
{ {
int id = 0; int id = 0;
@ -47,3 +62,10 @@ void Compositors::setCompositorEnabled (const std::string& name, const bool enab
mCompositors[name].first = enabled; mCompositors[name].first = enabled;
Ogre::CompositorManager::getSingleton().setCompositorEnabled (mViewport, name, enabled && mEnabled); Ogre::CompositorManager::getSingleton().setCompositorEnabled (mViewport, name, enabled && mEnabled);
} }
void Compositors::removeAll()
{
Ogre::CompositorManager::getSingleton().removeCompositorChain(mViewport);
mCompositors.clear();
}

@ -25,6 +25,11 @@ namespace MWRender
*/ */
void setEnabled (const bool enabled); void setEnabled (const bool enabled);
void setViewport(Ogre::Viewport* vp) { mViewport = vp; }
/// recreate compositors (call this after viewport size changes)
void recreate();
bool toggle() { setEnabled(!mEnabled); return mEnabled; } bool toggle() { setEnabled(!mEnabled); return mEnabled; }
/** /**
@ -39,6 +44,8 @@ namespace MWRender
*/ */
void addCompositor (const std::string& name, const int priority); void addCompositor (const std::string& name, const int priority);
void removeAll ();
protected: protected:
/// maps compositor name to its "enabled" state /// maps compositor name to its "enabled" state
CompositorMap mCompositors; CompositorMap mCompositors;

@ -68,7 +68,7 @@ ManualObject *Debugging::createPathgridLines(const ESM::Pathgrid *pathgrid)
result->begin(PATHGRID_LINE_MATERIAL, RenderOperation::OT_LINE_LIST); result->begin(PATHGRID_LINE_MATERIAL, RenderOperation::OT_LINE_LIST);
for(ESM::Pathgrid::EdgeList::const_iterator it = pathgrid->edges.begin(); for(ESM::Pathgrid::EdgeList::const_iterator it = pathgrid->edges.begin();
it != pathgrid->edges.end(); it != pathgrid->edges.end();
it++) ++it)
{ {
const ESM::Pathgrid::Edge &edge = *it; const ESM::Pathgrid::Edge &edge = *it;
const ESM::Pathgrid::Point &p1 = pathgrid->points[edge.v0], &p2 = pathgrid->points[edge.v1]; const ESM::Pathgrid::Point &p1 = pathgrid->points[edge.v0], &p2 = pathgrid->points[edge.v1];
@ -197,7 +197,7 @@ void Debugging::togglePathgrid()
// add path grid meshes to already loaded cells // add path grid meshes to already loaded cells
mPathGridRoot = mMwRoot->createChildSceneNode(); mPathGridRoot = mMwRoot->createChildSceneNode();
for(CellList::iterator it = mActiveCells.begin(); it != mActiveCells.end(); it++) for(CellList::iterator it = mActiveCells.begin(); it != mActiveCells.end(); ++it)
{ {
enableCellPathgrid(*it); enableCellPathgrid(*it);
} }
@ -205,7 +205,7 @@ void Debugging::togglePathgrid()
else else
{ {
// remove path grid meshes from already loaded cells // remove path grid meshes from already loaded cells
for(CellList::iterator it = mActiveCells.begin(); it != mActiveCells.end(); it++) for(CellList::iterator it = mActiveCells.begin(); it != mActiveCells.end(); ++it)
{ {
disableCellPathgrid(*it); disableCellPathgrid(*it);
} }

@ -307,28 +307,53 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
// convert from world coordinates to texture UV coordinates // convert from world coordinates to texture UV coordinates
float u,v; float u,v;
std::string texName; std::string texBaseName;
if (!mInterior) if (!mInterior)
{ {
u = std::abs((pos.x - (sSize*x))/sSize); u = std::abs((pos.x - (sSize*x))/sSize);
v = 1-std::abs((pos.y + (sSize*y))/sSize); v = 1-std::abs((pos.y + (sSize*y))/sSize);
texName = "Cell_"+coordStr(x,y); texBaseName = "Cell_";
} }
else else
{ {
u = (pos.x - min.x - sSize*x)/sSize; u = (pos.x - min.x - sSize*x)/sSize;
v = (pos.y - min.y - sSize*y)/sSize; v = (pos.y - min.y - sSize*y)/sSize;
texName = mInteriorName + "_" + coordStr(x,y); texBaseName = mInteriorName + "_";
} }
MWBase::Environment::get().getWindowManager()->setPlayerPos(u, v); MWBase::Environment::get().getWindowManager()->setPlayerPos(u, v);
MWBase::Environment::get().getWindowManager()->setPlayerDir(playerdirection.x, -playerdirection.z); MWBase::Environment::get().getWindowManager()->setPlayerDir(playerdirection.x, -playerdirection.z);
// explore radius (squared) // explore radius (squared)
const float sqrExploreRadius = 0.01 * sFogOfWarResolution*sFogOfWarResolution; 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 exploreRadiusUV = exploreRadius / sFogOfWarResolution; // explore radius from 0 to 1 (UV space)
int intExtMult = mInterior ? 1 : -1; // interior and exterior have reversed Y coordinates (interior: top to bottom)
// change the affected fog of war textures (in a 3x3 grid around the player)
for (int mx = -1; mx<2; ++mx)
{
for (int my = -1; my<2; ++my)
{
// is this texture affected at all?
bool affected = false;
if (mx == 0 && my == 0) // the player is always in the center of the 3x3 grid
affected = true;
else
{
bool affectsX = (mx > 0)? (u + exploreRadiusUV > 1) : (u - exploreRadiusUV < 0);
bool affectsY = (my > 0)? (v + exploreRadiusUV > 1) : (v - exploreRadiusUV < 0);
affected = (affectsX && (my == 0)) || (affectsY && mx == 0) || (affectsX && affectsY);
}
if (!affected)
continue;
std::string texName = texBaseName + coordStr(x+mx,y+my*intExtMult);
// get the appropriate fog of war texture
TexturePtr tex = TextureManager::getSingleton().getByName(texName+"_fog"); TexturePtr tex = TextureManager::getSingleton().getByName(texName+"_fog");
if (!tex.isNull()) if (!tex.isNull())
{ {
@ -339,7 +364,11 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
{ {
for (int texU = 0; texU<sFogOfWarResolution; ++texU) for (int texU = 0; texU<sFogOfWarResolution; ++texU)
{ {
float sqrDist = Math::Sqr(texU - u*sFogOfWarResolution) + Math::Sqr(texV - v*sFogOfWarResolution); // 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);
uint32 clr = mBuffers[texName][i]; uint32 clr = mBuffers[texName][i];
uint8 alpha = (clr >> 24); uint8 alpha = (clr >> 24);
alpha = std::min( alpha, (uint8) (std::max(0.f, std::min(1.f, (sqrDist/sqrExploreRadius)))*255) ); alpha = std::min( alpha, (uint8) (std::max(0.f, std::min(1.f, (sqrDist/sqrExploreRadius)))*255) );
@ -353,4 +382,6 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
memcpy(tex->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &mBuffers[texName][0], sFogOfWarResolution*sFogOfWarResolution*4); memcpy(tex->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &mBuffers[texName][0], sFogOfWarResolution*sFogOfWarResolution*4);
tex->getBuffer()->unlock(); tex->getBuffer()->unlock();
} }
}
}
} }

@ -528,7 +528,7 @@ void NpcAnimation::insertFootPart(int type, const std::string &mesh){
} }
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> NpcAnimation::insertFreePart(const std::string &mesh, const std::string suffix){ std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> NpcAnimation::insertFreePart(const std::string &mesh, const std::string& suffix){
std::string meshNumbered = mesh + getUniqueID(mesh + suffix) + suffix; std::string meshNumbered = mesh + getUniqueID(mesh + suffix) + suffix;
NIFLoader::load(meshNumbered); NIFLoader::load(meshNumbered);

@ -84,7 +84,7 @@ private:
NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv); NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv);
virtual ~NpcAnimation(); virtual ~NpcAnimation();
Ogre::Entity* insertBoundedPart(const std::string &mesh, std::string bonename); Ogre::Entity* insertBoundedPart(const std::string &mesh, std::string bonename);
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> insertFreePart(const std::string &mesh, const std::string suffix); std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> insertFreePart(const std::string &mesh, const std::string& suffix);
void insertFootPart(int type, const std::string &mesh); void insertFootPart(int type, const std::string &mesh);
virtual void runAnimation(float timepassed); virtual void runAnimation(float timepassed);
void updateParts(); void updateParts();

@ -39,7 +39,8 @@ struct LightInfo
LightInfo() : LightInfo() :
flickerVariation(0), resetTime(0.5), flickerVariation(0), resetTime(0.5),
flickerSlowVariation(0), time(0), interior(true) flickerSlowVariation(0), time(0), interior(true),
type(LT_Normal), radius(1.0)
{ {
} }
}; };
@ -68,7 +69,7 @@ class Objects{
///< Remove all movable objects from \a node. ///< Remove all movable objects from \a node.
public: public:
Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer) {} Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer), mIsStatic(false) {}
~Objects(){} ~Objects(){}
void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_); void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_);
void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh); void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh);

@ -6,4 +6,22 @@ namespace MWRender
Player::Player (Ogre::Camera *camera, Ogre::SceneNode* node) Player::Player (Ogre::Camera *camera, Ogre::SceneNode* node)
: mCamera (camera), mNode (node) : mCamera (camera), mNode (node)
{} {}
void Player::setRot(float x, float y, float z)
{
Ogre::SceneNode *sceneNode = mNode;
Ogre::Node* yawNode = sceneNode->getChildIterator().getNext();
Ogre::Node* pitchNode = yawNode->getChildIterator().getNext();
// we are only interested in X and Y rotation
// Rotate around X axis
Ogre::Quaternion xr(Ogre::Radian(x), Ogre::Vector3::UNIT_X);
// Rotate around Y axis
Ogre::Quaternion yr(Ogre::Radian(-z), Ogre::Vector3::UNIT_Y);
pitchNode->setOrientation(xr);
yawNode->setOrientation(yr);
}
} }

@ -23,6 +23,9 @@ namespace MWRender
Ogre::Camera *getCamera() { return mCamera; } Ogre::Camera *getCamera() { return mCamera; }
/// Set where the player is looking at. Uses Morrowind (euler) angles
void setRot(float x, float y, float z);
std::string getHandle() const { return mNode->getName(); } std::string getHandle() const { return mNode->getName(); }
Ogre::SceneNode* getNode() {return mNode;} Ogre::SceneNode* getNode() {return mNode;}
}; };

@ -11,6 +11,7 @@
#include "../mwworld/world.hpp" // these includes can be removed once the static-hack is gone #include "../mwworld/world.hpp" // these includes can be removed once the static-hack is gone
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/player.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include <components/esm/loadstat.hpp> #include <components/esm/loadstat.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
@ -21,6 +22,9 @@
#include "water.hpp" #include "water.hpp"
#include "compositors.hpp" #include "compositors.hpp"
#include "../mwgui/window_manager.hpp" // FIXME
#include "../mwinput/inputmanager.hpp" // FIXME
using namespace MWRender; using namespace MWRender;
using namespace Ogre; using namespace Ogre;
@ -30,6 +34,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
:mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0) :mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0)
{ {
mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5); mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5);
mRendering.setWindowEventListener(this);
mCompositors = new Compositors(mRendering.getViewport()); mCompositors = new Compositors(mRendering.getViewport());
@ -62,25 +67,13 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
// disable unsupported effects // disable unsupported effects
const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities(); const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities();
if (caps->getNumMultiRenderTargets() < 2 || !Settings::Manager::getBool("shaders", "Objects")) if (!waterShaderSupported())
Settings::Manager::setBool("shader", "Water", false); Settings::Manager::setBool("shader", "Water", false);
if ( !(caps->isShaderProfileSupported("fp40") || caps->isShaderProfileSupported("ps_4_0")) if ( !(caps->isShaderProfileSupported("fp40") || caps->isShaderProfileSupported("ps_4_0"))
|| !Settings::Manager::getBool("shaders", "Objects")) || !Settings::Manager::getBool("shaders", "Objects"))
Settings::Manager::setBool("enabled", "Shadows", false); Settings::Manager::setBool("enabled", "Shadows", false);
// note that the order is important here applyCompositors();
if (useMRT())
{
mCompositors->addCompositor("gbuffer", 0);
mCompositors->setCompositorEnabled("gbuffer", true);
mCompositors->addCompositor("Underwater", 1);
mCompositors->addCompositor("gbufferFinalizer", 2);
mCompositors->setCompositorEnabled("gbufferFinalizer", true);
}
else
{
mCompositors->addCompositor("UnderwaterNoMRT", 0);
}
// Turn the entire scene (represented by the 'root' node) -90 // Turn the entire scene (represented by the 'root' node) -90
// degrees around the x axis. This makes Z go upwards, and Y go into // degrees around the x axis. This makes Z go upwards, and Y go into
@ -104,7 +97,6 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
mTerrainManager = new TerrainManager(mRendering.getScene(), this); mTerrainManager = new TerrainManager(mRendering.getScene(), this);
//mSkyManager = 0;
mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera()); mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera());
mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode()); mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode());
@ -114,17 +106,24 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
mDebugging = new Debugging(mMwRoot, engine); mDebugging = new Debugging(mMwRoot, engine);
mLocalMap = new MWRender::LocalMap(&mRendering, this); mLocalMap = new MWRender::LocalMap(&mRendering, this);
setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI"));
} }
RenderingManager::~RenderingManager () RenderingManager::~RenderingManager ()
{ {
mRendering.removeWindowEventListener(this);
delete mPlayer; delete mPlayer;
delete mSkyManager; delete mSkyManager;
delete mDebugging; delete mDebugging;
delete mShaderHelper;
delete mShadows;
delete mTerrainManager; delete mTerrainManager;
delete mLocalMap; delete mLocalMap;
delete mOcclusionQuery; delete mOcclusionQuery;
delete mCompositors; delete mCompositors;
delete mWater;
} }
MWRender::SkyManager* RenderingManager::getSkyManager() MWRender::SkyManager* RenderingManager::getSkyManager()
@ -563,4 +562,119 @@ Compositors* RenderingManager::getCompositors()
return mCompositors; return mCompositors;
} }
void RenderingManager::processChangedSettings(const Settings::CategorySettingVector& settings)
{
bool changeRes = false;
for (Settings::CategorySettingVector::const_iterator it=settings.begin();
it != settings.end(); ++it)
{
if (it->second == "menu transparency" && it->first == "GUI")
{
setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI"));
}
else if (it->second == "max viewing distance" && it->first == "Viewing distance")
{
if (!MWBase::Environment::get().getWorld()->isCellExterior() && !MWBase::Environment::get().getWorld()->isCellQuasiExterior())
configureFog(*MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell());
}
else if (it->first == "Video" && (
it->second == "resolution x"
|| it->second == "resolution y"
|| it->second == "fullscreen"))
changeRes = true;
else if (it->second == "field of view" && it->first == "General")
mRendering.setFov(Settings::Manager::getFloat("field of view", "General"));
else if ((it->second == "texture filtering" && it->first == "General")
|| (it->second == "anisotropy" && it->first == "General"))
{
TextureFilterOptions tfo;
std::string filter = Settings::Manager::getString("texture filtering", "General");
if (filter == "anisotropic") tfo = TFO_ANISOTROPIC;
else if (filter == "trilinear") tfo = TFO_TRILINEAR;
else if (filter == "bilinear") tfo = TFO_BILINEAR;
else if (filter == "none") tfo = TFO_NONE;
MaterialManager::getSingleton().setDefaultTextureFiltering(tfo);
MaterialManager::getSingleton().setDefaultAnisotropy( (filter == "anisotropic") ? Settings::Manager::getInt("anisotropy", "General") : 1 );
}
else if (it->second == "shader" && it->first == "Water")
{
applyCompositors();
mShaderHelper->applyShaders();
}
}
if (changeRes)
{
unsigned int x = Settings::Manager::getInt("resolution x", "Video");
unsigned int y = Settings::Manager::getInt("resolution y", "Video");
if (x != mRendering.getWindow()->getWidth() || y != mRendering.getWindow()->getHeight())
{
mRendering.getWindow()->resize(x, y);
}
mRendering.getWindow()->setFullscreen(Settings::Manager::getBool("fullscreen", "Video"), x, y);
}
if (mWater)
mWater->processChangedSettings(settings);
}
void RenderingManager::setMenuTransparency(float val)
{
Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().getByName("transparent.png");
std::vector<Ogre::uint32> buffer;
buffer.resize(1);
buffer[0] = (int(255*val) << 24);
memcpy(tex->getBuffer()->lock(Ogre::HardwareBuffer::HBL_DISCARD), &buffer[0], 1*4);
tex->getBuffer()->unlock();
}
void RenderingManager::windowResized(Ogre::RenderWindow* rw)
{
Settings::Manager::setInt("resolution x", "Video", rw->getWidth());
Settings::Manager::setInt("resolution y", "Video", rw->getHeight());
mRendering.adjustViewport();
mCompositors->recreate();
mWater->assignTextures();
const Settings::CategorySettingVector& changed = Settings::Manager::apply();
MWBase::Environment::get().getInputManager()->processChangedSettings(changed); //FIXME
MWBase::Environment::get().getWindowManager()->processChangedSettings(changed); // FIXME
}
void RenderingManager::windowClosed(Ogre::RenderWindow* rw)
{
}
bool RenderingManager::waterShaderSupported()
{
const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities();
if (caps->getNumMultiRenderTargets() < 2 || !Settings::Manager::getBool("shaders", "Objects"))
return false;
return true;
}
void RenderingManager::applyCompositors()
{
mCompositors->removeAll();
if (useMRT())
{
mCompositors->addCompositor("gbuffer", 0);
mCompositors->setCompositorEnabled("gbuffer", true);
mCompositors->addCompositor("Underwater", 1);
mCompositors->addCompositor("gbufferFinalizer", 2);
mCompositors->setCompositorEnabled("gbufferFinalizer", true);
}
else
{
mCompositors->addCompositor("UnderwaterNoMRT", 0);
}
if (mWater)
mWater->assignTextures();
}
} // namespace } // namespace

@ -8,11 +8,15 @@
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include <OgreWindowEventUtilities.h>
#include <utility> #include <utility>
#include <openengine/ogre/renderer.hpp> #include <openengine/ogre/renderer.hpp>
#include <openengine/ogre/fader.hpp> #include <openengine/ogre/fader.hpp>
#include <openengine/bullet/physic.hpp> #include <openengine/bullet/physic.hpp>
#include <components/settings/settings.hpp>
#include <vector> #include <vector>
#include <string> #include <string>
@ -49,7 +53,7 @@ namespace MWRender
class Water; class Water;
class Compositors; class Compositors;
class RenderingManager: private RenderingInterface { class RenderingManager: private RenderingInterface, public Ogre::WindowEventListener {
private: private:
@ -157,10 +161,24 @@ class RenderingManager: private RenderingInterface {
///< transform the specified bounding box (in world coordinates) into screen coordinates. ///< transform the specified bounding box (in world coordinates) into screen coordinates.
/// @return packed vector4 (min_x, min_y, max_x, max_y) /// @return packed vector4 (min_x, min_y, max_x, max_y)
void processChangedSettings(const Settings::CategorySettingVector& settings);
Ogre::Viewport* getViewport() { return mRendering.getViewport(); }
static bool waterShaderSupported();
protected:
virtual void windowResized(Ogre::RenderWindow* rw);
virtual void windowClosed(Ogre::RenderWindow* rw);
private: private:
void setAmbientMode(); void setAmbientMode();
void setMenuTransparency(float val);
void applyCompositors();
bool mSunEnabled; bool mSunEnabled;
SkyManager* mSkyManager; SkyManager* mSkyManager;

@ -374,7 +374,7 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera)
, mSunGlare(NULL) , mSunGlare(NULL)
, mMasser(NULL) , mMasser(NULL)
, mSecunda(NULL) , mSecunda(NULL)
, mViewport(NULL) , mCamera(pCamera)
, mRootNode(NULL) , mRootNode(NULL)
, mSceneMgr(NULL) , mSceneMgr(NULL)
, mAtmosphereDay(NULL) , mAtmosphereDay(NULL)
@ -399,9 +399,8 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera)
, mSecundaEnabled(true) , mSecundaEnabled(true)
, mCreated(false) , mCreated(false)
{ {
mViewport = pCamera->getViewport();
mSceneMgr = pMwRoot->getCreator(); mSceneMgr = pMwRoot->getCreator();
mRootNode = pCamera->getParentSceneNode()->createChildSceneNode(); mRootNode = mCamera->getParentSceneNode()->createChildSceneNode();
mRootNode->pitch(Degree(-90)); // convert MW to ogre coordinates mRootNode->pitch(Degree(-90)); // convert MW to ogre coordinates
mRootNode->setInheritOrientation(false); mRootNode->setInheritOrientation(false);
} }
@ -741,7 +740,7 @@ void SkyManager::update(float duration)
// on how directly the player is looking at the sun // on how directly the player is looking at the sun
Vector3 sun = mSunGlare->getPosition(); Vector3 sun = mSunGlare->getPosition();
sun = Vector3(sun.x, sun.z, -sun.y); sun = Vector3(sun.x, sun.z, -sun.y);
Vector3 cam = mViewport->getCamera()->getRealDirection(); Vector3 cam = mCamera->getRealDirection();
const Degree angle = sun.angleBetween( cam ); const Degree angle = sun.angleBetween( cam );
float val = 1- (angle.valueDegrees() / 180.f); float val = 1- (angle.valueDegrees() / 180.f);
val = (val*val*val*val)*2; val = (val*val*val*val)*2;

@ -185,7 +185,7 @@ namespace MWRender
Moon* mMasser; Moon* mMasser;
Moon* mSecunda; Moon* mSecunda;
Ogre::Viewport* mViewport; Ogre::Camera* mCamera;
Ogre::SceneNode* mRootNode; Ogre::SceneNode* mRootNode;
Ogre::SceneManager* mSceneMgr; Ogre::SceneManager* mSceneMgr;

@ -22,30 +22,30 @@ namespace MWRender
TerrainManager::TerrainManager(Ogre::SceneManager* mgr, RenderingManager* rend) : TerrainManager::TerrainManager(Ogre::SceneManager* mgr, RenderingManager* rend) :
mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize)), mRendering(rend) mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize)), mRendering(rend)
{ {
mTerrainGlobals = OGRE_NEW TerrainGlobalOptions();
TerrainMaterialGeneratorPtr matGen; TerrainMaterialGeneratorPtr matGen;
TerrainMaterialGeneratorB* matGenP = new TerrainMaterialGeneratorB(); TerrainMaterialGeneratorB* matGenP = new TerrainMaterialGeneratorB();
matGen.bind(matGenP); matGen.bind(matGenP);
mTerrainGlobals.setDefaultMaterialGenerator(matGen); mTerrainGlobals->setDefaultMaterialGenerator(matGen);
TerrainMaterialGenerator::Profile* const activeProfile = TerrainMaterialGenerator::Profile* const activeProfile =
mTerrainGlobals.getDefaultMaterialGenerator() mTerrainGlobals->getDefaultMaterialGenerator()
->getActiveProfile(); ->getActiveProfile();
mActiveProfile = static_cast<TerrainMaterialGeneratorB::SM2Profile*>(activeProfile); mActiveProfile = static_cast<TerrainMaterialGeneratorB::SM2Profile*>(activeProfile);
//The pixel error should be as high as possible without it being noticed //The pixel error should be as high as possible without it being noticed
//as it governs how fast mesh quality decreases. //as it governs how fast mesh quality decreases.
mTerrainGlobals.setMaxPixelError(8); mTerrainGlobals->setMaxPixelError(8);
mTerrainGlobals.setLayerBlendMapSize(32); mTerrainGlobals->setLayerBlendMapSize(32);
mTerrainGlobals.setDefaultGlobalColourMapSize(65); mTerrainGlobals->setDefaultGlobalColourMapSize(65);
//10 (default) didn't seem to be quite enough //10 (default) didn't seem to be quite enough
mTerrainGlobals.setSkirtSize(128); mTerrainGlobals->setSkirtSize(128);
//due to the sudden flick between composite and non composite textures, //due to the sudden flick between composite and non composite textures,
//this seemed the distance where it wasn't too noticeable //this seemed the distance where it wasn't too noticeable
mTerrainGlobals.setCompositeMapDistance(mWorldSize*2); mTerrainGlobals->setCompositeMapDistance(mWorldSize*2);
mActiveProfile->setLightmapEnabled(false); mActiveProfile->setLightmapEnabled(false);
mActiveProfile->setLayerSpecularMappingEnabled(false); mActiveProfile->setLayerSpecularMappingEnabled(false);
@ -86,20 +86,21 @@ namespace MWRender
TerrainManager::~TerrainManager() TerrainManager::~TerrainManager()
{ {
OGRE_DELETE mTerrainGlobals;
} }
//---------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------
void TerrainManager::setDiffuse(const ColourValue& diffuse) void TerrainManager::setDiffuse(const ColourValue& diffuse)
{ {
mTerrainGlobals.setCompositeMapDiffuse(diffuse); mTerrainGlobals->setCompositeMapDiffuse(diffuse);
} }
//---------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------
void TerrainManager::setAmbient(const ColourValue& ambient) void TerrainManager::setAmbient(const ColourValue& ambient)
{ {
mTerrainGlobals.setCompositeMapAmbient(ambient); mTerrainGlobals->setCompositeMapAmbient(ambient);
} }
//---------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------

@ -33,7 +33,7 @@ namespace MWRender{
void cellAdded(MWWorld::Ptr::CellStore* store); void cellAdded(MWWorld::Ptr::CellStore* store);
void cellRemoved(MWWorld::Ptr::CellStore* store); void cellRemoved(MWWorld::Ptr::CellStore* store);
private: private:
Ogre::TerrainGlobalOptions mTerrainGlobals; Ogre::TerrainGlobalOptions* mTerrainGlobals;
Ogre::TerrainGroup mTerrainGroup; Ogre::TerrainGroup mTerrainGroup;
RenderingManager* mRendering; RenderingManager* mRendering;

@ -167,7 +167,7 @@ namespace Ogre
class ShaderHelper : public TerrainAlloc class ShaderHelper : public TerrainAlloc
{ {
public: public:
ShaderHelper() {} ShaderHelper() : mShadowSamplerStartHi(0), mShadowSamplerStartLo(0) {}
virtual ~ShaderHelper() {} virtual ~ShaderHelper() {}
virtual HighLevelGpuProgramPtr generateVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); virtual HighLevelGpuProgramPtr generateVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
virtual HighLevelGpuProgramPtr generateFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt); virtual HighLevelGpuProgramPtr generateFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);

@ -1,5 +1,5 @@
#include "water.hpp" #include "water.hpp"
#include <components/settings/settings.hpp>
#include "sky.hpp" #include "sky.hpp"
#include "renderingmanager.hpp" #include "renderingmanager.hpp"
#include "compositors.hpp" #include "compositors.hpp"
@ -10,7 +10,7 @@ namespace MWRender
{ {
Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cell) : Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cell) :
mCamera (camera), mViewport (camera->getViewport()), mSceneManager (camera->getSceneManager()), mCamera (camera), mSceneManager (camera->getSceneManager()),
mIsUnderwater(false), mVisibilityFlags(0), mIsUnderwater(false), mVisibilityFlags(0),
mReflectionTarget(0), mActive(1), mToggled(1), mReflectionTarget(0), mActive(1), mToggled(1),
mReflectionRenderActive(false), mRendering(rend) mReflectionRenderActive(false), mRendering(rend)
@ -30,13 +30,6 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel
mWater->setRenderQueueGroup(RQG_Water); mWater->setRenderQueueGroup(RQG_Water);
mWater->setCastShadows(false); mWater->setCastShadows(false);
mVisibilityFlags = RV_Terrain * Settings::Manager::getBool("reflect terrain", "Water")
+ RV_Statics * Settings::Manager::getBool("reflect statics", "Water")
+ RV_StaticsSmall * Settings::Manager::getBool("reflect small statics", "Water")
+ RV_Actors * Settings::Manager::getBool("reflect actors", "Water")
+ RV_Misc * Settings::Manager::getBool("reflect misc", "Water")
+ RV_Sky;
mWaterNode = mSceneManager->getRootSceneNode()->createChildSceneNode(); mWaterNode = mSceneManager->getRootSceneNode()->createChildSceneNode();
mWaterNode->setPosition(0, mTop, 0); mWaterNode->setPosition(0, mTop, 0);
@ -48,30 +41,9 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel
} }
mWaterNode->attachObject(mWater); mWaterNode->attachObject(mWater);
// Create rendertarget for reflection applyRTT();
int rttsize = Settings::Manager::getInt("rtt size", "Water"); applyVisibilityMask();
TexturePtr tex;
if (Settings::Manager::getBool("shader", "Water"))
{
tex = TextureManager::getSingleton().createManual("WaterReflection",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, rttsize, rttsize, 0, PF_FLOAT16_RGBA, TU_RENDERTARGET);
RenderTarget* rtt = tex->getBuffer()->getRenderTarget();
Viewport* vp = rtt->addViewport(mReflectionCamera);
vp->setOverlaysEnabled(false);
vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f));
vp->setShadowsEnabled(false);
vp->setVisibilityMask( mVisibilityFlags );
// use fallback techniques without shadows and without mrt (currently not implemented for sky and terrain)
//vp->setMaterialScheme("Fallback");
rtt->addListener(this);
rtt->setActive(true);
mReflectionTarget = rtt;
}
mCompositorName = RenderingManager::useMRT() ? "Underwater" : "UnderwaterNoMRT";
createMaterial(); createMaterial();
mWater->setMaterial(mMaterial); mWater->setMaterial(mMaterial);
@ -80,6 +52,8 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel
mSceneManager->addRenderQueueListener(this); mSceneManager->addRenderQueueListener(this);
assignTextures();
// ---------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------
// ---------------------------------- reflection debug overlay ---------------------------------- // ---------------------------------- reflection debug overlay ----------------------------------
@ -140,6 +114,9 @@ Water::~Water()
{ {
MeshManager::getSingleton().remove("water"); MeshManager::getSingleton().remove("water");
if (mReflectionTarget)
mReflectionTexture->getBuffer()->getRenderTarget()->removeListener(this);
mWaterNode->detachObject(mWater); mWaterNode->detachObject(mWater);
mSceneManager->destroyEntity(mWater); mSceneManager->destroyEntity(mWater);
mSceneManager->destroySceneNode(mWaterNode); mSceneManager->destroySceneNode(mWaterNode);
@ -249,7 +226,15 @@ void Water::postRenderTargetUpdate(const RenderTargetEvent& evt)
void Water::createMaterial() void Water::createMaterial()
{ {
if (mReflectionTarget == 0)
{
mMaterial = MaterialManager::getSingleton().getByName("Water_Fallback");
}
else
{
mMaterial = MaterialManager::getSingleton().getByName("Water"); mMaterial = MaterialManager::getSingleton().getByName("Water");
mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTexture(mReflectionTexture);
}
// these have to be set in code // these have to be set in code
std::string textureNames[32]; std::string textureNames[32];
@ -257,15 +242,20 @@ void Water::createMaterial()
{ {
textureNames[i] = "textures\\water\\water" + StringConverter::toString(i, 2, '0') + ".dds"; textureNames[i] = "textures\\water\\water" + StringConverter::toString(i, 2, '0') + ".dds";
} }
mMaterial->getTechnique(1)->getPass(0)->getTextureUnitState(0)->setAnimatedTextureName(textureNames, 32, 2); Ogre::Technique* tech;
// use technique without shaders if reflection is disabled
if (mReflectionTarget == 0) if (mReflectionTarget == 0)
mMaterial->removeTechnique(0); tech = mMaterial->getTechnique(0);
else
tech = mMaterial->getTechnique(1);
tech->getPass(0)->getTextureUnitState(0)->setAnimatedTextureName(textureNames, 32, 2);
}
void Water::assignTextures()
{
if (Settings::Manager::getBool("shader", "Water")) if (Settings::Manager::getBool("shader", "Water"))
{ {
CompositorInstance* compositor = CompositorManager::getSingleton().getCompositorChain(mViewport)->getCompositor("gbuffer"); CompositorInstance* compositor = CompositorManager::getSingleton().getCompositorChain(mRendering->getViewport())->getCompositor("gbuffer");
TexturePtr colorTexture = compositor->getTextureInstance("mrt_output", 0); TexturePtr colorTexture = compositor->getTextureInstance("mrt_output", 0);
TextureUnitState* tus = mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState("refractionMap"); TextureUnitState* tus = mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState("refractionMap");
@ -315,4 +305,84 @@ void Water::update()
{ {
} }
void Water::applyRTT()
{
if (mReflectionTarget)
{
TextureManager::getSingleton().remove("WaterReflection");
mReflectionTarget = 0;
}
// Create rendertarget for reflection
int rttsize = Settings::Manager::getInt("rtt size", "Water");
if (Settings::Manager::getBool("shader", "Water"))
{
mReflectionTexture = TextureManager::getSingleton().createManual("WaterReflection",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, rttsize, rttsize, 0, PF_FLOAT16_RGBA, TU_RENDERTARGET);
RenderTarget* rtt = mReflectionTexture->getBuffer()->getRenderTarget();
Viewport* vp = rtt->addViewport(mReflectionCamera);
vp->setOverlaysEnabled(false);
vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f));
vp->setShadowsEnabled(false);
// use fallback techniques without shadows and without mrt (currently not implemented for sky and terrain)
//vp->setMaterialScheme("Fallback");
rtt->addListener(this);
rtt->setActive(true);
mReflectionTarget = rtt;
}
mCompositorName = RenderingManager::useMRT() ? "Underwater" : "UnderwaterNoMRT";
}
void Water::applyVisibilityMask()
{
mVisibilityFlags = RV_Terrain * Settings::Manager::getBool("reflect terrain", "Water")
+ RV_Statics * Settings::Manager::getBool("reflect statics", "Water")
+ RV_StaticsSmall * Settings::Manager::getBool("reflect small statics", "Water")
+ RV_Actors * Settings::Manager::getBool("reflect actors", "Water")
+ RV_Misc * Settings::Manager::getBool("reflect misc", "Water")
+ RV_Sky;
if (mReflectionTarget)
{
mReflectionTexture->getBuffer()->getRenderTarget()->getViewport(0)->setVisibilityMask(mVisibilityFlags);
}
}
void Water::processChangedSettings(const Settings::CategorySettingVector& settings)
{
bool applyRT = false;
bool applyVisMask = false;
for (Settings::CategorySettingVector::const_iterator it=settings.begin();
it != settings.end(); ++it)
{
if ( it->first == "Water" && (
it->second == "shader"
|| it->second == "rtt size"))
applyRT = true;
if ( it->first == "Water" && (
it->second == "reflect actors"
|| it->second == "reflect terrain"
|| it->second == "reflect misc"
|| it->second == "reflect small statics"
|| it->second == "reflect statics"))
applyVisMask = true;
}
if(applyRT)
{
applyRTT();
applyVisibilityMask();
createMaterial();
mWater->setMaterial(mMaterial);
assignTextures();
}
if (applyVisMask)
applyVisibilityMask();
}
} // namespace } // namespace

@ -3,9 +3,11 @@
#include <Ogre.h> #include <Ogre.h>
#include <components/esm/loadcell.hpp> #include <components/esm/loadcell.hpp>
#include <components/settings/settings.hpp>
#include "renderconst.hpp" #include "renderconst.hpp"
namespace MWRender { namespace MWRender {
class SkyManager; class SkyManager;
@ -17,7 +19,6 @@ namespace MWRender {
static const int CELL_SIZE = 8192; static const int CELL_SIZE = 8192;
Ogre::Camera *mCamera; Ogre::Camera *mCamera;
Ogre::SceneManager *mSceneManager; Ogre::SceneManager *mSceneManager;
Ogre::Viewport *mViewport;
Ogre::Plane mWaterPlane; Ogre::Plane mWaterPlane;
Ogre::SceneNode *mWaterNode; Ogre::SceneNode *mWaterNode;
@ -39,6 +40,9 @@ namespace MWRender {
void renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation); void renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation);
void renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation); void renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation);
void applyRTT();
void applyVisibilityMask();
void updateVisible(); void updateVisible();
RenderingManager* mRendering; RenderingManager* mRendering;
@ -51,6 +55,7 @@ namespace MWRender {
Ogre::Camera* mReflectionCamera; Ogre::Camera* mReflectionCamera;
Ogre::TexturePtr mReflectionTexture;
Ogre::RenderTarget* mReflectionTarget; Ogre::RenderTarget* mReflectionTarget;
bool mUnderwaterEffect; bool mUnderwaterEffect;
@ -65,8 +70,12 @@ namespace MWRender {
void toggle(); void toggle();
void update(); void update();
void assignTextures();
void setViewportBackground(const Ogre::ColourValue& bg); void setViewportBackground(const Ogre::ColourValue& bg);
void processChangedSettings(const Settings::CategorySettingVector& settings);
void checkUnderwater(float y); void checkUnderwater(float y);
void changeCell(const ESM::Cell* cell); void changeCell(const ESM::Cell* cell);
void setHeight(const float height); void setHeight(const float height);

@ -146,4 +146,5 @@ op 0x200014f: ForceGreeting
op 0x2000150: ForceGreeting, explicit reference op 0x2000150: ForceGreeting, explicit reference
op 0x2000151: ToggleFullHelp op 0x2000151: ToggleFullHelp
op 0x2000152: Goodbye op 0x2000152: Goodbye
op 0x2000153: DontSaveObject (left unimplemented)
opcodes 0x2000154-0x3ffffff unused opcodes 0x2000154-0x3ffffff unused

@ -44,7 +44,7 @@ namespace MWScript
virtual void execute (Interpreter::Runtime& runtime) virtual void execute (Interpreter::Runtime& runtime)
{ {
MWBase::Environment::get().getInputManager()->setGuiMode(mDialogue); MWBase::Environment::get().getWindowManager()->pushGuiMode(mDialogue);
} }
}; };

@ -194,6 +194,17 @@ namespace MWScript
} }
}; };
class OpDontSaveObject : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
// We are ignoring the DontSaveObject statement for now. Probably not worth
/// bothering with. The incompatibility we are creating should be marginal at most.
}
};
const int opcodeXBox = 0x200000c; const int opcodeXBox = 0x200000c;
const int opcodeOnActivate = 0x200000d; const int opcodeOnActivate = 0x200000d;
const int opcodeActivate = 0x2000075; const int opcodeActivate = 0x2000075;
@ -208,6 +219,7 @@ namespace MWScript
const int opcodeFadeTo = 0x200013e; const int opcodeFadeTo = 0x200013e;
const int opcodeToggleWater = 0x2000144; const int opcodeToggleWater = 0x2000144;
const int opcodeTogglePathgrid = 0x2000146; const int opcodeTogglePathgrid = 0x2000146;
const int opcodeDontSaveObject = 0x2000153;
void registerExtensions (Compiler::Extensions& extensions) void registerExtensions (Compiler::Extensions& extensions)
{ {
@ -229,6 +241,7 @@ namespace MWScript
extensions.registerInstruction ("twa", "", opcodeToggleWater); extensions.registerInstruction ("twa", "", opcodeToggleWater);
extensions.registerInstruction ("togglepathgrid", "", opcodeTogglePathgrid); extensions.registerInstruction ("togglepathgrid", "", opcodeTogglePathgrid);
extensions.registerInstruction ("tpg", "", opcodeTogglePathgrid); extensions.registerInstruction ("tpg", "", opcodeTogglePathgrid);
extensions.registerInstruction ("dontsaveobject", "", opcodeDontSaveObject);
} }
void installOpcodes (Interpreter::Interpreter& interpreter) void installOpcodes (Interpreter::Interpreter& interpreter)
@ -247,6 +260,7 @@ namespace MWScript
interpreter.installSegment5 (opcodeFadeTo, new OpFadeTo); interpreter.installSegment5 (opcodeFadeTo, new OpFadeTo);
interpreter.installSegment5 (opcodeTogglePathgrid, new OpTogglePathgrid); interpreter.installSegment5 (opcodeTogglePathgrid, new OpTogglePathgrid);
interpreter.installSegment5 (opcodeToggleWater, new OpToggleWater); interpreter.installSegment5 (opcodeToggleWater, new OpToggleWater);
interpreter.installSegment5 (opcodeDontSaveObject, new OpDontSaveObject);
} }
} }
} }

@ -46,7 +46,7 @@ namespace MWSound
public: public:
virtual ~Sound_Output() { } virtual ~Sound_Output() { }
bool isInitialized() { return mInitialized; } bool isInitialized() const { return mInitialized; }
friend class OpenAL_Output; friend class OpenAL_Output;
friend class SoundManager; friend class SoundManager;

@ -7,7 +7,6 @@
#include <OgreRoot.h> #include <OgreRoot.h>
#include <components/esm_store/store.hpp> #include <components/esm_store/store.hpp>
#include <components/settings/settings.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
@ -53,6 +52,8 @@ namespace MWSound
, mMasterVolume(1.0f) , mMasterVolume(1.0f)
, mSFXVolume(1.0f) , mSFXVolume(1.0f)
, mMusicVolume(1.0f) , mMusicVolume(1.0f)
, mFootstepsVolume(1.0f)
, mVoiceVolume(1.0f)
{ {
if(!useSound) if(!useSound)
return; return;
@ -63,6 +64,10 @@ namespace MWSound
mSFXVolume = std::min(std::max(mSFXVolume, 0.0f), 1.0f); mSFXVolume = std::min(std::max(mSFXVolume, 0.0f), 1.0f);
mMusicVolume = Settings::Manager::getFloat("music volume", "Sound"); mMusicVolume = Settings::Manager::getFloat("music volume", "Sound");
mMusicVolume = std::min(std::max(mMusicVolume, 0.0f), 1.0f); mMusicVolume = std::min(std::max(mMusicVolume, 0.0f), 1.0f);
mVoiceVolume = Settings::Manager::getFloat("voice volume", "Sound");
mVoiceVolume = std::min(std::max(mVoiceVolume, 0.0f), 1.0f);
mFootstepsVolume = Settings::Manager::getFloat("footsteps volume", "Sound");
mFootstepsVolume = std::min(std::max(mFootstepsVolume, 0.0f), 1.0f);
std::cout << "Sound output: " << SOUND_OUT << std::endl; std::cout << "Sound output: " << SOUND_OUT << std::endl;
std::cout << "Sound decoder: " << SOUND_IN << std::endl; std::cout << "Sound decoder: " << SOUND_IN << std::endl;
@ -210,7 +215,7 @@ namespace MWSound
try try
{ {
// The range values are not tested // The range values are not tested
float basevol = mMasterVolume * mSFXVolume; float basevol = mMasterVolume * mVoiceVolume;
std::string filePath = "Sound/"+filename; std::string filePath = "Sound/"+filename;
const ESM::Position &pos = ptr.getCellRef().pos; const ESM::Position &pos = ptr.getCellRef().pos;
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]); const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
@ -234,7 +239,7 @@ namespace MWSound
return; return;
try try
{ {
float basevol = mMasterVolume * mSFXVolume; float basevol = mMasterVolume * mVoiceVolume;
std::string filePath = "Sound/"+filename; std::string filePath = "Sound/"+filename;
SoundPtr sound = mOutput->playSound(filePath, basevol, 1.0f, Play_Normal); SoundPtr sound = mOutput->playSound(filePath, basevol, 1.0f, Play_Normal);
@ -527,6 +532,39 @@ namespace MWSound
} }
void SoundManager::processChangedSettings(const Settings::CategorySettingVector& settings)
{
mMasterVolume = Settings::Manager::getFloat("master volume", "Sound");
mMusicVolume = Settings::Manager::getFloat("music volume", "Sound");
mSFXVolume = Settings::Manager::getFloat("sfx volume", "Sound");
mFootstepsVolume = Settings::Manager::getFloat("footsteps volume", "Sound");
mVoiceVolume = Settings::Manager::getFloat("voice volume", "Sound");
SoundMap::iterator snditer = mActiveSounds.begin();
while(snditer != mActiveSounds.end())
{
if(snditer->second.second != "_say_sound")
{
float basevol = mMasterVolume * mSFXVolume;
float min, max;
lookup(snditer->second.second, basevol, min, max);
snditer->first->mBaseVolume = basevol;
}
else
{
float basevol = mMasterVolume * mVoiceVolume;
snditer->first->mBaseVolume = basevol;
}
snditer->first->update();
snditer++;
}
if(mMusic)
{
mMusic->mBaseVolume = mMasterVolume * mMusicVolume;
mMusic->update();
}
}
// Default readAll implementation, for decoders that can't do anything // Default readAll implementation, for decoders that can't do anything
// better // better
void Sound_Decoder::readAll(std::vector<char> &output) void Sound_Decoder::readAll(std::vector<char> &output)

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save