Post merge

actorid
Jason Hooks 13 years ago
commit 20288de685

@ -1,7 +1,11 @@
#include "graphicspage.hpp"
#include <QtGui>
#include "graphicspage.hpp"
#include <boost/lexical_cast.hpp>
#include <components/files/configurationmanager.hpp>
#include <components/settings/settings.hpp>
GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent)
: QWidget(parent)
@ -17,12 +21,9 @@ GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent)
renderSystemLayout->addWidget(rendererLabel, 0, 0, 1, 1);
renderSystemLayout->addWidget(mRendererComboBox, 0, 1, 1, 1);
mRendererStackedWidget = new QStackedWidget(rendererGroup);
QVBoxLayout *rendererGroupLayout = new QVBoxLayout(rendererGroup);
rendererGroupLayout->addLayout(renderSystemLayout);
rendererGroupLayout->addWidget(mRendererStackedWidget);
// Display
QGroupBox *displayGroup = new QGroupBox(tr("Display"), this);
@ -52,107 +53,33 @@ GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent)
void GraphicsPage::createPages()
{
// OpenGL rendering settings
QWidget *mOGLRendererPage = new QWidget();
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);
QWidget *main = new QWidget();
QGridLayout *grid = new QGridLayout(main);
// Direct3D rendering settings
QWidget *mD3DRendererPage = new QWidget();
mVSyncCheckBox = new QCheckBox(tr("Vertical Sync"), main);
grid->addWidget(mVSyncCheckBox, 0, 0, 1, 1);
QLabel *D3DRenderDeviceLabel = new QLabel(tr("Rendering Device:"), mD3DRendererPage);
mD3DRenderDeviceComboBox = new QComboBox(mD3DRendererPage);
mFullScreenCheckBox = new QCheckBox(tr("Full Screen"), main);
grid->addWidget(mFullScreenCheckBox, 1, 0, 1, 1);
QLabel *D3DAntiAliasingLabel = new QLabel(tr("Antialiasing:"), mD3DRendererPage);
mD3DAntiAliasingComboBox = new QComboBox(mD3DRendererPage);
QLabel *antiAliasingLabel = new QLabel(tr("Antialiasing:"), main);
mAntiAliasingComboBox = new QComboBox(main);
grid->addWidget(antiAliasingLabel, 2, 0, 1, 1);
grid->addWidget(mAntiAliasingComboBox, 2, 1, 1, 1);
QLabel *D3DFloatingPointLabel = new QLabel(tr("Floating-point Mode:"), mD3DRendererPage);
mD3DFloatingPointComboBox = new QComboBox(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);
mD3DNvPerfCheckBox = new QCheckBox(tr("Allow NVPerfHUD"), mD3DRendererPage);
QGridLayout *D3DRendererLayout = new QGridLayout(mD3DRendererPage);
QSpacerItem *vSpacer3 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Minimum);
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);
QSpacerItem *vSpacer1 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Expanding);
grid->addItem(vSpacer1, 4, 0, 1, 1);
mDisplayStackedWidget->addWidget(mOGLDisplayPage);
mDisplayStackedWidget->addWidget(mD3DDisplayPage);
mDisplayStackedWidget->addWidget(main);
}
void GraphicsPage::setupConfig()
{
QString ogreCfg = mCfgMgr.getOgreConfigPath().string().c_str();
QFile file(ogreCfg);
mOgreConfig = new QSettings(ogreCfg, QSettings::IniFormat);
}
void GraphicsPage::setupOgre()
@ -164,32 +91,12 @@ void GraphicsPage::setupOgre()
Ogre::LogManager* logMgr = OGRE_NEW Ogre::LogManager;
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
{
#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
mOgre = new Ogre::Root(pluginCfg.toStdString(), file.fileName().toStdString(), "./launcherOgre.log");
mOgre = new Ogre::Root(pluginCfg.toStdString(), "", "./launcherOgre.log");
#endif
}
catch(Ogre::Exception &ex)
@ -228,11 +135,19 @@ void GraphicsPage::setupOgre()
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) {
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
QString openGLName = mRendererComboBox->itemText(mRendererComboBox->findText(QString("OpenGL"), Qt::MatchStartsWith));
@ -255,217 +170,44 @@ void GraphicsPage::setupOgre()
}
// Now fill the GUI elements
// OpenGL
if (mOpenGLRenderSystem) {
mOGLRTTComboBox->addItems(getAvailableOptions(QString("RTT Preferred Mode"), mOpenGLRenderSystem));
mOGLAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mOpenGLRenderSystem));
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));
}
mAntiAliasingComboBox->clear();
mResolutionComboBox->clear();
mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem));
mResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mSelectedRenderSystem));
}
void GraphicsPage::readConfig()
{
// Read the config file settings
if (mOpenGLRenderSystem) {
if (Settings::Manager::getBool("vsync", "Video"))
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);
}
if (Settings::Manager::getBool("fullscreen", "Video"))
mFullScreenCheckBox->setCheckState(Qt::Checked);
// 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")) {
mD3DNvPerfCheckBox->setCheckState(Qt::Checked);
}
if (getConfigValue("VSync", mDirect3DRenderSystem) == QLatin1String("Yes")) {
mD3DVSyncCheckBox->setCheckState(Qt::Checked);
}
int aaIndex = mAntiAliasingComboBox->findText(QString::fromStdString(Settings::Manager::getString("antialiasing", "Video")));
if (aaIndex != -1)
mAntiAliasingComboBox->setCurrentIndex(aaIndex);
if (getConfigValue("Full Screen", mDirect3DRenderSystem) == QLatin1String("Yes")) {
mD3DFullScreenCheckBox->setCheckState(Qt::Checked);
}
}
std::string resolution = boost::lexical_cast<std::string>(Settings::Manager::getInt("resolution x", "Video"))
+ " 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()
{
mOgre->setRenderSystem(mSelectedRenderSystem);
if (mDirect3DRenderSystem) {
// Nvidia Performance HUD
if (mD3DNvPerfCheckBox->checkState() == Qt::Checked) {
mDirect3DRenderSystem->setConfigOption("Allow NVPerfHUD", "Yes");
} else {
mDirect3DRenderSystem->setConfigOption("Allow NVPerfHUD", "No");
}
// Antialiasing
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;
Settings::Manager::setBool("vsync", "Video", mVSyncCheckBox->checkState());
Settings::Manager::setBool("fullscreen", "Video", mFullScreenCheckBox->checkState());
Settings::Manager::setString("antialiasing", "Video", mAntiAliasingComboBox->currentText().toStdString());
std::string resolution = mResolutionComboBox->currentText().toStdString();
// parse resolution x and y from a string like "800 x 600"
size_t xPos = resolution.find("x");
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);
Settings::Manager::setInt("resolution y", "Video", resY);
}
QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer)
@ -480,12 +222,17 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy
Ogre::StringVector::iterator opt_it;
uint idx = 0;
for (opt_it = i->second.possibleValues.begin ();
opt_it != i->second.possibleValues.end (); opt_it++, idx++)
{
opt_it != i->second.possibleValues.end (); opt_it++, idx++)
{
if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0)
result << QString::fromStdString((*opt_it).c_str()).simplified();
}
if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0)
{
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)
{
if (renderer.contains("Direct3D")) {
mRendererStackedWidget->setCurrentIndex(1);
mDisplayStackedWidget->setCurrentIndex(1);
}
mSelectedRenderSystem = mOgre->getRenderSystemByName(renderer.toStdString());
if (renderer.contains("OpenGL")) {
mRendererStackedWidget->setCurrentIndex(0);
mDisplayStackedWidget->setCurrentIndex(0);
}
mAntiAliasingComboBox->clear();
mResolutionComboBox->clear();
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;
QStackedWidget *mRendererStackedWidget;
QStackedWidget *mDisplayStackedWidget;
// OpenGL
QComboBox *mOGLRTTComboBox;
QComboBox *mOGLAntiAliasingComboBox;
QComboBox *mOGLResolutionComboBox;
QComboBox *mOGLFrequencyComboBox;
QCheckBox *mOGLVSyncCheckBox;
QCheckBox *mOGLFullScreenCheckBox;
// Direct3D
QComboBox *mD3DRenderDeviceComboBox;
QComboBox *mD3DAntiAliasingComboBox;
QComboBox *mD3DFloatingPointComboBox;
QComboBox *mD3DResolutionComboBox;
QCheckBox *mD3DNvPerfCheckBox;
QCheckBox *mD3DVSyncCheckBox;
QCheckBox *mD3DFullScreenCheckBox;
QSettings *mOgreConfig;
QComboBox *mAntiAliasingComboBox;
QComboBox *mResolutionComboBox;
QCheckBox *mVSyncCheckBox;
QCheckBox *mFullScreenCheckBox;
Files::ConfigurationManager &mCfgMgr;
QString getConfigValue(const QString &key, Ogre::RenderSystem *renderer);
QStringList getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer);
void createPages();

@ -7,6 +7,28 @@
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->setObjectName("IconWidget");
mIconWidget->setViewMode(QListView::IconMode);
@ -178,6 +200,11 @@ void MainDialog::closeEvent(QCloseEvent *event)
// Now write all config files
mDataFilesPage->writeConfig();
mGraphicsPage->writeConfig();
// Save user settings
const std::string settingspath = mCfgMgr.getUserPath().string() + "/settings.cfg";
mSettings.saveUser(settingspath);
event->accept();
}

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

@ -8,7 +8,9 @@
#include <algorithm>
#include <sstream>
MwIniImporter::MwIniImporter() {
MwIniImporter::MwIniImporter()
: mVerbose(false)
{
const char *map[][2] =
{
{ "fps", "General:Show FPS" },
@ -124,9 +126,9 @@ MwIniImporter::multistrmap MwIniImporter::loadCfgFile(std::string filename) {
void MwIniImporter::merge(multistrmap &cfg, multistrmap &ini) {
multistrmap::iterator cfgIt;
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()) {
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);
insertMultistrmap(cfg, it->first, *vc);
}
@ -139,9 +141,9 @@ void MwIniImporter::mergeFallback(multistrmap &cfg, multistrmap &ini) {
multistrmap::iterator cfgIt;
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()) {
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::replace( value.begin(), value.end(), ' ', '_' );
std::replace( value.begin(), value.end(), ':', '_' );
@ -176,7 +178,7 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, multistrmap &ini) {
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::transform(filetype.begin(), filetype.end(), filetype.begin(), ::tolower);
@ -194,22 +196,22 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, multistrmap &ini) {
cfg.erase("master");
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.erase("plugin");
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);
}
}
void MwIniImporter::writeToFile(boost::iostreams::stream<boost::iostreams::file_sink> &out, multistrmap &cfg) {
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(multistrmap::iterator it=cfg.begin(); it != cfg.end(); ++it) {
for(std::vector<std::string>::iterator entry=it->second.begin(); entry != it->second.end(); ++entry) {
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
dialogue_history window_base stats_window messagebox journalwindow charactercreation
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
@ -49,7 +50,7 @@ add_openmw_dir (mwworld
refdata world physicssystem scene globals class action nullaction actionteleport
containerstore actiontalk actiontake manualref player cellfunctors
cells localscripts customdata weather inventorystore ptr actionopen actionread
actionequip timestamp
actionequip timestamp actionalchemy
)
add_openmw_dir (mwclass

@ -105,7 +105,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
// frame.
// passing of time
if (MWBase::Environment::get().getWindowManager()->getMode()==MWGui::GM_Game)
if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
MWBase::Environment::get().getWorld()->advanceTime (
mEnvironment.getFrameDuration()*MWBase::Environment::get().getWorld()->getTimeScaleFactor()/3600);
@ -116,9 +116,9 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
// update actors
std::vector<std::pair<std::string, Ogre::Vector3> > movement;
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());
// update world
@ -268,15 +268,6 @@ void OMW::Engine::go()
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
Settings::Manager settings;
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"))
nifOverrides.loadTransparencyOverrides(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg");
mOgre->configure(!boost::filesystem::is_regular_file(mCfgMgr.getOgreConfigPath()),
mCfgMgr.getOgreConfigPath().string(),
std::string renderSystem = settings.getString("render system", "Video");
if (renderSystem == "")
{
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
renderSystem = "Direct3D9 Rendering Subsystem";
#else
renderSystem = "OpenGL Rendering Subsystem";
#endif
}
mOgre->configure(
mCfgMgr.getLogPath().string(),
mCfgMgr.getPluginsConfigPath().string(), false);
mCfgMgr.getPluginsConfigPath().string(),
renderSystem,
false);
// This has to be added BEFORE MyGUI is initialized, as it needs
// to find core.xml here.
@ -325,7 +326,14 @@ void OMW::Engine::go()
addZipResource(mResDir / "mygui" / "Obliviontt.zip");
// 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();
@ -413,7 +421,7 @@ void OMW::Engine::go()
void OMW::Engine::activate()
{
if (MWBase::Environment::get().getWindowManager()->getMode()!=MWGui::GM_Game)
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
return;
std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle();

@ -9,6 +9,7 @@
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwworld/actionalchemy.hpp"
#include "../mwworld/world.hpp"
#include "../mwrender/objects.hpp"
@ -140,4 +141,10 @@ namespace MWClass
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;
///< 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 =
ptr.get<ESM::Creature>();
const std::string &model = ref->base->model;
assert (ref->base != NULL);
if(!model.empty()){
physics.insertObjectPhysics(ptr, "meshes\\" + model);
}
}
void Creature::enable (const MWWorld::Ptr& ptr) const
{
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
{
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 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;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.

@ -135,6 +135,19 @@ namespace MWClass
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;
return info;

@ -9,6 +9,7 @@
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwworld/actionequip.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/world.hpp"
@ -55,12 +56,6 @@ namespace MWClass
if(!model.empty()){
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())
{
@ -182,4 +177,11 @@ namespace MWClass
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 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;
///< \return name (the one that is to be presented to the user; not the internal one);
/// can return an empty string.
@ -53,6 +48,10 @@ namespace MWClass
virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const;
///< 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/actiontake.hpp"
#include "../mwworld/actionequip.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/world.hpp"
#include "../mwgui/window_manager.hpp"
@ -155,4 +156,11 @@ namespace MWClass
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;
///< 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,42 +110,30 @@ namespace MWClass
void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
renderingInterface.getActors().insertNPC(ptr, getInventoryStore(ptr));
}
void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const
{
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
ptr.get<ESM::NPC>();
assert (ref->base != NULL);
std::string headID = ref->base->head;
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_";
std::string smodel = "meshes\\base_anim.nif";
if(beast)
smodel = "meshes\\base_animkna.nif";
//physics.insertObjectPhysics(ptr, smodel);
std::string headID = ref->base->head;
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_";
}
std::string smodel = "meshes\\base_anim.nif";
if(beast)
smodel = "meshes\\base_animkna.nif";
void Npc::enable (const MWWorld::Ptr& ptr) const
{
MWBase::Environment::get().getMechanicsManager()->addActor (ptr);
}
void Npc::disable (const MWWorld::Ptr& ptr) const
{
MWBase::Environment::get().getMechanicsManager()->removeActor (ptr);
MWBase::Environment::get().getMechanicsManager()->addActor (ptr);
}
std::string Npc::getName (const MWWorld::Ptr& ptr) const

@ -19,12 +19,6 @@ namespace MWClass
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;
///< \return name (the one that is to be presented to the user; not the internal one);
/// 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 += 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()) {
text += MWGui::ToolTips::getMiscString(ref->ref.owner, "Owner");

@ -9,6 +9,7 @@
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwworld/actionequip.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/world.hpp"
#include "../mwgui/window_manager.hpp"
@ -154,4 +155,11 @@ namespace MWClass
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;
///< 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)
{
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);
if(pos !=std::string::npos)
@ -635,7 +635,7 @@ namespace MWDialogue
actorKnownTopics.clear();
//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();
win->startDialogue(actor, MWWorld::Class::get (actor).getName (actor));
@ -843,7 +843,7 @@ namespace MWDialogue
void DialogueManager::goodbyeSelected()
{
MWBase::Environment::get().getInputManager()->setGuiMode(MWGui::GM_Game);
MWBase::Environment::get().getWindowManager()->popGuiMode();
}
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 "formatting.hpp"
#include <boost/lexical_cast.hpp>
#include "../mwbase/environment.hpp"
#include "../mwinput/inputmanager.hpp"
#include "../mwsound/soundmanager.hpp"
#include "../mwworld/actiontake.hpp"
#include <boost/lexical_cast.hpp>
#include "formatting.hpp"
#include "window_manager.hpp"
using namespace MWGui;
@ -91,7 +92,7 @@ void BookWindow::onCloseButtonClicked (MyGUI::Widget* _sender)
// no 3d sounds because the object could be in a container.
MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0);
MWBase::Environment::get().getInputManager()->setGuiMode(MWGui::GM_Game);
mWindowManager.popGuiMode();
}
void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender)
@ -101,7 +102,7 @@ void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender)
MWWorld::ActionTake take(mBook);
take.execute();
MWBase::Environment::get().getInputManager()->setGuiMode (GM_Game);
mWindowManager.popGuiMode();
}
void BookWindow::onNextPageButtonClicked (MyGUI::Widget* _sender)

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

@ -42,11 +42,15 @@ namespace MWGui
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:
//Dialogs
TextInputDialog* mNameDialog;
RaceDialog* mRaceDialog;
DialogueWindow* mDialogueWindow;
ClassChoiceDialog* mClassChoiceDialog;
InfoBoxDialog* mGenerateClassQuestionDialog;
GenerateClassResultDialog* mGenerateClassResultDialog;
@ -62,9 +66,6 @@ namespace MWGui
std::string mPlayerRaceId;
std::string mPlayerBirthSignId;
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> mPlayerMagicka;
MWMechanics::DynamicStat<int> mPlayerFatigue;

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

@ -139,6 +139,7 @@ namespace MWGui
{
public:
SelectSpecializationDialog(WindowManager& parWindowManager);
~SelectSpecializationDialog();
ESM::Class::Specialization getSpecializationId() const { return specializationId; }
@ -169,6 +170,7 @@ namespace MWGui
{
public:
SelectAttributeDialog(WindowManager& parWindowManager);
~SelectAttributeDialog();
ESM::Attribute::AttributeID getAttributeId() const { return attributeId; }
Widgets::MWAttributePtr getAffectedWidget() const { return affectedWidget; }
@ -201,6 +203,7 @@ namespace MWGui
{
public:
SelectSkillDialog(WindowManager& parWindowManager);
~SelectSkillDialog();
ESM::Skill::SkillEnum getSkillId() const { return skillId; }
Widgets::MWSkillPtr getAffectedWidget() const { return affectedWidget; }
@ -236,6 +239,7 @@ namespace MWGui
{
public:
DescriptionDialog(WindowManager& parWindowManager);
~DescriptionDialog();
std::string getTextInput() const { return textEdit ? textEdit->getOnlyText() : ""; }
void setTextInput(const std::string &text) { if (textEdit) textEdit->setOnlyText(text); }
@ -285,6 +289,10 @@ namespace MWGui
void onDescriptionEntered(WindowBase* parWindow);
void onDialogCancel();
void setSpecialization(int id);
void update();
private:
MyGUI::EditPtr editName;
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()
{
setVisible(false);
setSelectedObject(MWWorld::Ptr());
// Remove keyboard focus from the console input whenever the
// console is turned off
MyGUI::InputManager::getInstance().setKeyFocusWidget(NULL);
@ -240,7 +241,7 @@ namespace MWGui
{
try
{
ConsoleInterpreterContext interpreterContext (*this, MWWorld::Ptr());
ConsoleInterpreterContext interpreterContext (*this, mPtr);
Interpreter::Interpreter interpreter;
MWScript::installOpcodes (interpreter);
std::vector<Interpreter::Type_Code> code;
@ -267,7 +268,7 @@ namespace MWGui
/* Are there quotation marks? */
if( tmp.find('"') != string::npos ) {
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 == '"' )
numquotes++;
}
@ -310,7 +311,7 @@ namespace MWGui
}
/* 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;
/* Is the string shorter than the input string? If yes skip it. */
@ -358,7 +359,7 @@ namespace MWGui
int i = tmp.length();
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) ) {
/* Append the longest match to the end of the output string*/
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. */
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/interpretercontext.hpp"
#include "referenceinterface.hpp"
namespace MWGui
{
class Console : private OEngine::GUI::Layout, private Compiler::ErrorHandler
class Console : private OEngine::GUI::Layout, private Compiler::ErrorHandler, public ReferenceInterface
{
private:
@ -39,7 +41,17 @@ namespace MWGui
/// \note The list may contain duplicates (if a name is a keyword and an identifier at the same
/// time).
public:
public:
void setSelectedObject(const MWWorld::Ptr& object);
///< Set the implicit object for script execution
protected:
virtual void onReferenceUnavailable();
public:
MyGUI::EditPtr command;
MyGUI::EditPtr history;
@ -58,6 +70,8 @@ namespace MWGui
void setFont(const std::string &fntName);
void onResChange(int width, int height);
void clearHistory();
// Print a message to the console. Messages may contain color

@ -119,7 +119,7 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender)
else
onContainerClicked(mContainerWidget);
}
else
else if (isTrading())
{
MWWorld::Ptr object = (*_sender->getUserData<MWWorld::Ptr>());
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)
@ -260,16 +264,16 @@ void ContainerBase::onContainerClicked(MyGUI::Widget* _sender)
if(mDragAndDrop->mIsOnDragAndDrop) //drop item here
{
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)
{
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
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)
{
// 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)
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.
object.getRefData().setCount(mDragAndDrop->mDraggedCount);
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)
{
it->getRefData().setCount(0);
@ -342,8 +346,7 @@ void ContainerBase::setFilter(ContainerBase::Filter filter)
void ContainerBase::openContainer(MWWorld::Ptr container)
{
mContainer = container;
drawItems();
mPtr = container;
}
void ContainerBase::drawItems()
@ -352,15 +355,12 @@ void ContainerBase::drawItems()
{
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 y = 0;
int maxHeight = mItemView->getSize().height - 58;
int index = 0;
bool onlyMagic = false;
int categories;
if (mFilter == Filter_All)
@ -381,8 +381,10 @@ void ContainerBase::drawItems()
categories = MWWorld::ContainerStore::Type_Miscellaneous + MWWorld::ContainerStore::Type_Book
+ MWWorld::ContainerStore::Type_Ingredient + MWWorld::ContainerStore::Type_Repair
+ 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
@ -454,7 +456,6 @@ void ContainerBase::drawItems()
for (std::vector< std::pair<MWWorld::Ptr, ItemState> >::const_iterator it=items.begin();
it != items.end(); ++it)
{
index++;
const MWWorld::Ptr* iter = &((*it).first);
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()))
{
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)
bool isMagic = (MWWorld::Class::get(*iter).getEnchantment(*iter) != "");
@ -514,6 +515,7 @@ void ContainerBase::drawItems()
text->setNeedMouseFocus(false);
text->setTextShadow(true);
text->setTextShadowColour(MyGUI::Colour(0,0,0));
text->setCaption(getCountString(displayCount));
y += 42;
if (y > maxHeight)
@ -522,13 +524,14 @@ void ContainerBase::drawItems()
y = 0;
}
text->setCaption(getCountString(displayCount));
}
}
MyGUI::IntSize size = MyGUI::IntSize(std::max(mItemView->getSize().width, x+42), mItemView->getSize().height);
mItemView->setCanvasSize(size);
mContainerWidget->setSize(size);
notifyContentChanged();
}
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)
{
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer);
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
int origCount = item.getRefData().getCount();
@ -563,7 +566,7 @@ void ContainerBase::addItem(MWWorld::Ptr item, int count)
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)
{
@ -581,7 +584,7 @@ void ContainerBase::returnBoughtItems(MWWorld::ContainerStore& store)
MWWorld::ContainerStore& ContainerBase::getContainerStore()
{
MWWorld::ContainerStore& store = MWWorld::Class::get(mContainer).getContainerStore(mContainer);
MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
return store;
}
@ -630,13 +633,14 @@ void ContainerWindow::open(MWWorld::Ptr container)
{
openContainer(container);
setTitle(MWWorld::Class::get(container).getName(container));
drawItems();
}
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
{
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)
{
// 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::ContainerStore& playerStore = MWWorld::Class::get(player).getContainerStore(player);
@ -667,6 +671,11 @@ void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender)
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
#include <components/esm_store/store.hpp>
#include "../mwclass/container.hpp"
#include <sstream>
#include <set>
#include <string>
#include <utility>
#include "window_base.hpp"
#include "referenceinterface.hpp"
#include "../mwclass/container.hpp"
#include "../mwworld/ptr.hpp"
#include "../mwworld/containerstore.hpp"
#include <vector>
namespace MWWorld
{
@ -43,7 +42,7 @@ namespace MWGui
int mDraggedCount;
};
class ContainerBase
class ContainerBase : public ReferenceInterface
{
public:
ContainerBase(DragAndDrop* dragAndDrop);
@ -55,7 +54,9 @@ namespace MWGui
Filter_Weapon = 0x02,
Filter_Apparel = 0x03,
Filter_Magic = 0x04,
Filter_Misc = 0x05
Filter_Misc = 0x05,
Filter_Ingredients = 0x06
};
enum ItemState
@ -87,7 +88,6 @@ namespace MWGui
MyGUI::Widget* mSelectedItem;
DragAndDrop* mDragAndDrop;
MWWorld::Ptr mContainer;
Filter mFilter;
@ -116,8 +116,12 @@ namespace MWGui
virtual bool isTrading() { return false; }
virtual void onSelectedItemImpl(MWWorld::Ptr item) { ; }
virtual bool ignoreEquippedItems() { return false; }
virtual std::vector<MWWorld::Ptr> itemsToIgnore() { return std::vector<MWWorld::Ptr>(); }
virtual void notifyContentChanged() { ; }
};
class ContainerWindow : public ContainerBase, public WindowBase
@ -136,6 +140,8 @@ namespace MWGui
void onWindowResize(MyGUI::Window* window);
void onCloseButtonClicked(MyGUI::Widget* _sender);
void onTakeAllButtonClicked(MyGUI::Widget* _sender);
virtual void onReferenceUnavailable();
};
}
#endif // CONTAINER_H

@ -17,9 +17,6 @@ namespace MWGui
getWidget(mOkButton, "OkButton");
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);
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onOkButtonClicked);
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);
}
void DialogueWindow::open()
{
topicsList->clear();
pTopicsText.clear();
history->eraseText(0,history->getTextLength());
updateOptions();
setVisible(true);
}
void DialogueWindow::onByeClicked(MyGUI::Widget* _sender)
{
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)
{
/// \todo check if the player is allowed to trade with this actor (e.g. faction rank high enough)?
mWindowManager.setGuiMode(GM_Barter);
mWindowManager.getTradeWindow()->startTrade(mActor);
mWindowManager.pushGuiMode(GM_Barter);
mWindowManager.getTradeWindow()->startTrade(mPtr);
}
else
@ -144,9 +135,13 @@ void DialogueWindow::onSelectTopic(std::string topic)
void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName)
{
mEnabled = true;
mActor = actor;
mPtr = actor;
topicsList->setEnabled(true);
setTitle(npcName);
topicsList->clear();
history->eraseText(0,history->getTextLength());
updateOptions();
}
void DialogueWindow::setKeywords(std::list<std::string> keyWords)
@ -161,7 +156,7 @@ void DialogueWindow::setKeywords(std::list<std::string> keyWords)
if (anyService)
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);
}
@ -173,7 +168,6 @@ void DialogueWindow::removeKeyword(std::string keyWord)
if(topicsList->hasItem(keyWord))
{
topicsList->removeItem(keyWord);
pTopicsText.erase(keyWord);
}
topicsList->adjustSize();
}
@ -249,7 +243,6 @@ void DialogueWindow::updateOptions()
{
//Clear the list of topics
topicsList->clear();
pTopicsText.clear();
history->eraseText(0,history->getTextLength());
pDispositionBar->setProgressRange(100);
@ -264,3 +257,8 @@ void DialogueWindow::goodbye()
topicsList->setEnabled(false);
mEnabled = false;
}
void DialogueWindow::onReferenceUnavailable()
{
mWindowManager.removeGuiMode(GM_Dialogue);
}

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

@ -12,8 +12,10 @@
#include "../mwworld/world.hpp"
#include "../mwworld/player.hpp"
#include "inventorywindow.hpp"
#include "window_manager.hpp"
#include "container.hpp"
#include "console.hpp"
using namespace MWGui;
@ -41,35 +43,60 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop)
, effectBoxBaseRight(0)
, minimapBoxBaseRight(0)
, mDragAndDrop(dragAndDrop)
, mCellNameTimer(0.0f)
, mCellNameBox(NULL)
, mMapVisible(true)
, mWeaponVisible(true)
, mSpellVisible(true)
, mWorldMouseOver(false)
{
setCoord(0,0, width, height);
// Energy bars
getWidget(mHealthFrame, "HealthFrame");
getWidget(health, "Health");
getWidget(magicka, "Magicka");
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
getWidget(weapBox, "WeapBox");
getWidget(weapImage, "WeapImage");
getWidget(weapStatus, "WeapStatus");
weapBoxBaseLeft = weapBox->getLeft();
weapBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWeaponClicked);
getWidget(spellBox, "SpellBox");
getWidget(spellImage, "SpellImage");
getWidget(spellStatus, "SpellStatus");
spellBoxBaseLeft = spellBox->getLeft();
spellBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked);
getWidget(effectBox, "EffectBox");
getWidget(effect1, "Effect1");
effectBoxBaseRight = effectBox->getRight();
effectBoxBaseRight = viewSize.width - effectBox->getRight();
effectBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked);
getWidget(minimapBox, "MiniMapBox");
minimapBoxBaseRight = minimapBox->getRight();
minimapBoxBaseRight = viewSize.width - minimapBox->getRight();
minimapBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked);
getWidget(minimap, "MiniMap");
getWidget(compass, "Compass");
getWidget(mCellNameBox, "CellName");
getWidget(mWeaponSpellBox, "WeaponSpellName");
getWidget(crosshair, "Crosshair");
setFpsLevel(fpsLevel);
@ -77,15 +104,9 @@ HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop)
getWidget(trianglecounter, "TriangleCounter");
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");
LocalMapBase::init(minimap, this);
LocalMapBase::init(minimap, compass, this);
mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked);
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)
{
fpscounter = 0;
MyGUI::Widget* fps;
getWidget(fps, "FPSBoxAdv");
fps->setVisible(false);
@ -116,7 +139,8 @@ void HUD::setFpsLevel(int level)
void HUD::setFPS(float fps)
{
fpscounter->setCaption(boost::lexical_cast<std::string>((int)fps));
if (fpscounter)
fpscounter->setCaption(boost::lexical_cast<std::string>((int)fps));
}
void HUD::setTriangleCount(size_t count)
@ -129,28 +153,6 @@ void HUD::setBatchCount(size_t 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)
{
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)
{
int weapDx = 0, spellDx = 0;
@ -228,7 +201,12 @@ void HUD::setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellV
spellDx = weapDx = weapBoxBaseLeft - hmsBaseLeft;
if (!weapVisible)
spellDx -= spellBoxBaseLeft - weapBoxBaseLeft;
spellDx += spellBoxBaseLeft - weapBoxBaseLeft;
mWeaponVisible = weapVisible;
mSpellVisible = spellVisible;
if (!mWeaponVisible && !mSpellVisible)
mWeaponSpellBox->setVisible(false);
health->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)
{
const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize();
// effect box can have variable width -> variable left coordinate
int effectsDx = 0;
if (!minimapBoxVisible)
effectsDx = minimapBoxBaseRight - effectBoxBaseRight;
effectsDx = (viewSize.width - minimapBoxBaseRight) - (viewSize.width - effectBoxBaseRight);
mMapVisible = 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);
}
@ -286,6 +267,33 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender)
mDragAndDrop->mDraggedWidget = 0;
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)
{
mWorldMouseOver = false;
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition();
float mouseX = cursorPosition.left / float(viewSize.width);
@ -312,11 +322,195 @@ void HUD::onWorldMouseOver(MyGUI::Widget* _sender, int x, int y)
else
{
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)
{
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 "../mwmechanics/stat.hpp"
#include "../mwworld/ptr.hpp"
namespace MWGui
{
@ -12,22 +13,30 @@ namespace MWGui
{
public:
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 setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value);
void setFPS(float fps);
void setTriangleCount(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 setBottomRightVisibility(bool effectBoxVisible, bool minimapVisible);
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::Widget* mHealthFrame;
MyGUI::Widget *weapBox, *spellBox;
MyGUI::ImageBox *weapImage, *spellImage;
MyGUI::ProgressPtr weapStatus, spellStatus;
@ -36,6 +45,8 @@ namespace MWGui
MyGUI::ScrollView* minimap;
MyGUI::ImageBox* compass;
MyGUI::ImageBox* crosshair;
MyGUI::TextBox* mCellNameBox;
MyGUI::TextBox* mWeaponSpellBox;
MyGUI::WidgetPtr fpsbox;
MyGUI::TextBox* fpscounter;
@ -50,8 +61,25 @@ namespace MWGui
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 onWorldMouseOver(MyGUI::Widget* _sender, int x, int y);
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 "../mwbase/environment.hpp"
#include "../mwworld/manualref.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwsound/soundmanager.hpp"
#include "window_manager.hpp"
#include "widgets.hpp"
#include "bookwindow.hpp"
#include "scrollwindow.hpp"
#include "spellwindow.hpp"
namespace
{
@ -91,13 +94,13 @@ namespace MWGui
mFilterAll->setStateSelected(true);
setCoord(0, 342, 600, 258);
setCoord(0, 342, 498, 258);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
openContainer(player);
}
void InventoryWindow::openInventory()
void InventoryWindow::open()
{
updateEncumbranceBar();
@ -155,7 +158,7 @@ namespace MWGui
if (mDragAndDrop->mDraggedFrom != this)
{
// 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();
int origCount = ptr.getRefData().getCount();
@ -187,12 +190,21 @@ namespace MWGui
mWindowManager.setDragDrop(false);
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()
{
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mContainer).getInventoryStore(mContainer);
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
std::vector<MWWorld::Ptr> items;
@ -210,7 +222,7 @@ namespace MWGui
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)
{
@ -244,7 +256,7 @@ namespace MWGui
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();
it != invStore.end(); ++it)
@ -259,4 +271,79 @@ namespace MWGui
{
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:
InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop);
void openInventory();
virtual void open();
/// start trading, disables item drag&drop
void startTrade();
void onFrame();
void pickUpObject (MWWorld::Ptr object);
int getPlayerGold();
protected:
@ -48,6 +50,10 @@ namespace MWGui
virtual bool isInventory() { return true; }
virtual std::vector<MWWorld::Ptr> getEquippedItems();
virtual void _unequipItem(MWWorld::Ptr item);
virtual void onReferenceUnavailable() { ; }
virtual void notifyContentChanged();
};
}

@ -131,7 +131,7 @@ void MWGui::JournalWindow::open()
book journal;
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());
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::list<std::string> journal = formatText(a,10,20,1);
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)
{

@ -11,6 +11,7 @@ LocalMapBase::LocalMapBase()
, mInterior(false)
, mFogOfWar(true)
, mLocalMap(NULL)
, mMapDragAndDrop(false)
, mPrefix()
, mChanged(true)
, mLayout(NULL)
@ -18,13 +19,41 @@ LocalMapBase::LocalMapBase()
, mLastPositionY(0.0f)
, mLastDirectionX(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;
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)
@ -47,10 +76,10 @@ void LocalMapBase::applyFogOfWar()
{
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>(mCurX + (mx-1)) + "_"
+ boost::lexical_cast<std::string>(mCurY + (mInterior ? (my-1) : -1*(my-1)));
MyGUI::ImageBox* fog;
mLayout->getWidget(fog, name+"_fog");
MyGUI::ImageBox* fog = mFogWidgets[my + 3*mx];
fog->setImageTexture(mFogOfWar ?
((MyGUI::RenderManager::getInstance().getTexture(image+"_fog") != 0) ? image+"_fog"
: "black.png" )
@ -66,14 +95,13 @@ void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
{
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)) + "_"
+ boost::lexical_cast<std::string>(y + (interior ? (my-1) : -1*(my-1)));
MyGUI::ImageBox* box;
mLayout->getWidget(box, name);
std::string name = "Map_" + boost::lexical_cast<std::string>(mx) + "_"
+ boost::lexical_cast<std::string>(my);
MyGUI::ImageBox* box = mMapWidgets[my + 3*mx];
if (MyGUI::RenderManager::getInstance().getTexture(image) != 0)
box->setImageTexture(image);
@ -86,6 +114,42 @@ void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
mCurY = y;
mChanged = false;
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");
mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked);
mButton->setCaption(mWindowManager.getGameSettingString("sWorld", ""));
mButton->setCaptionWithReplacing("#{sWorld}");
int width = mButton->getTextSize().width + 24;
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->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
LocalMapBase::init(mLocalMap, this);
LocalMapBase::init(mLocalMap, mPlayerArrow, this);
}
void MapWindow::setCellName(const std::string& cellName)
@ -119,33 +183,6 @@ void MapWindow::setCellName(const std::string& 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)
{
if (_id!=MyGUI::MouseButton::Left) return;
@ -172,8 +209,8 @@ void MapWindow::onWorldButtonClicked(MyGUI::Widget* _sender)
mGlobalMap->setVisible(mGlobal);
mLocalMap->setVisible(!mGlobal);
mButton->setCaption( mGlobal ? mWindowManager.getGameSettingString("sWorld", "") :
mWindowManager.getGameSettingString("sLocal", ""));
mButton->setCaptionWithReplacing( mGlobal ? "#{sLocal}" :
"#{sWorld}");
int width = mButton->getTextSize().width + 24;
mButton->setCoord(mMainWidget->getSize().width - width - 22, mMainWidget->getSize().height - 64, width, 22);
}

@ -9,10 +9,12 @@ namespace MWGui
{
public:
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 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();
@ -20,14 +22,20 @@ namespace MWGui
int mCurX, mCurY;
bool mInterior;
MyGUI::ScrollView* mLocalMap;
MyGUI::ImageBox* mCompass;
std::string mPrefix;
bool mChanged;
bool mFogOfWar;
std::vector<MyGUI::ImageBox*> mMapWidgets;
std::vector<MyGUI::ImageBox*> mFogWidgets;
void applyFogOfWar();
OEngine::GUI::Layout* mLayout;
bool mMapDragAndDrop;
float mLastPositionX;
float mLastPositionY;
float mLastDirectionX;
@ -40,8 +48,6 @@ namespace MWGui
MapWindow(WindowManager& parWindowManager);
virtual ~MapWindow(){}
void setPlayerPos(const float x, const float y);
void setPlayerDir(const float x, const float y);
void setCellName(const std::string& cellName);
private:

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

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

@ -1,7 +1,4 @@
#include "race.hpp"
#include "window_manager.hpp"
#include "widgets.hpp"
#include "components/esm_store/store.hpp"
#include <assert.h>
#include <iostream>
@ -10,6 +7,12 @@
#include <boost/algorithm/string.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 Widgets;
@ -51,7 +54,7 @@ RaceDialog::RaceDialog(WindowManager& parWindowManager)
prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousFace);
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(nextButton, "NextHairButton");
prevButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onSelectPreviousHair);
@ -255,6 +258,8 @@ void RaceDialog::updateSkills()
skillWidget->setWindowManager(&mWindowManager);
skillWidget->setSkillNumber(skillId);
skillWidget->setSkillValue(MWSkill::SkillValue(race->data.bonus[i].bonus));
ToolTips::createSkillToolTip(skillWidget, skillId);
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->setWindowManager(&mWindowManager);
spellPowerWidget->setSpellId(spellpower);
spellPowerWidget->setUserString("ToolTipType", "Spell");
spellPowerWidget->setUserString("Spell", spellpower);
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 "window_manager.hpp"
#include "widgets.hpp"
#include "components/esm_store/store.hpp"
#include <cmath>
#include <boost/algorithm/string.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 max
@ -74,7 +77,7 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager)
getWidget(skillAreaWidget, "Skills");
getWidget(skillClientWidget, "SkillClient");
getWidget(skillScrollerWidget, "SkillScroller");
skillClientWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel);
skillScrollerWidget->eventScrollChangePosition += MyGUI::newDelegate(this, &ReviewDialog::onScrollChangePosition);
updateScroller();
@ -137,13 +140,17 @@ void ReviewDialog::setRace(const std::string &raceId_)
raceId = raceId_;
const ESM::Race *race = mWindowManager.getStore().races.search(raceId);
if (race)
{
ToolTips::createRaceToolTip(raceWidget, race);
raceWidget->setCaption(race->name);
}
}
void ReviewDialog::setClass(const ESM::Class& class_)
{
klass = class_;
classWidget->setCaption(klass.name);
ToolTips::createClassToolTip(classWidget, klass);
}
void ReviewDialog::setBirthSign(const std::string& signId)
@ -151,22 +158,31 @@ void ReviewDialog::setBirthSign(const std::string& signId)
birthSignId = signId;
const ESM::BirthSign *sign = mWindowManager.getStore().birthSigns.search(birthSignId);
if (sign)
{
birthSignWidget->setCaption(sign->name);
ToolTips::createBirthsignToolTip(birthSignWidget, birthSignId);
}
}
void ReviewDialog::setHealth(const MWMechanics::DynamicStat<int>& value)
{
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)
{
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)
{
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)
@ -195,6 +211,7 @@ void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanic
widget->setCaption(text);
widget->_setWidgetState(state);
}
}
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())
miscSkills.push_back(skill);
}
updateSkillArea();
}
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);
separator->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel);
skillWidgets.push_back(separator);
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)
{
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);
skillWidgets.push_back(groupWidget);
@ -235,17 +257,19 @@ void ReviewDialog::addGroup(const std::string &label, MyGUI::IntCoord &coord1, M
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* skillValueWidget;
skillNameWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandText", coord1, MyGUI::Align::Default);
skillNameWidget->setCaption(text);
skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel);
skillValueWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandTextRight", coord2, MyGUI::Align::Top | MyGUI::Align::Right);
skillValueWidget->setCaption(value);
skillValueWidget->_setWidgetState(state);
skillValueWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel);
skillWidgets.push_back(skillNameWidget);
skillWidgets.push_back(skillValueWidget);
@ -256,12 +280,13 @@ MyGUI::TextBox* ReviewDialog::addValueItem(const std::string text, const std::st
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;
skillNameWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default);
skillNameWidget->setCaption(text);
skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &ReviewDialog::onMouseWheel);
skillWidgets.push_back(skillNameWidget);
@ -297,6 +322,12 @@ void ReviewDialog::addSkills(const SkillList &skills, const std::string &titleId
else if (modified < base)
state = "decreased";
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;
}
}
@ -330,6 +361,8 @@ void ReviewDialog::updateScroller()
{
skillScrollerWidget->setScrollRange(std::max(clientHeight - skillClientWidget->getHeight(), 0));
skillScrollerWidget->setScrollPage(std::max(skillClientWidget->getHeight() - lineHeight, 0));
if (clientHeight != 0)
skillScrollerWidget->setTrackSize( (skillAreaWidget->getHeight() / float(clientHeight)) * skillScrollerWidget->getLineSize() );
}
// widget controls
@ -363,3 +396,15 @@ void ReviewDialog::onBirthSignClicked(MyGUI::Widget* _sender)
{
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 onBirthSignClicked(MyGUI::Widget* _sender);
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
private:
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 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);
void addItem(const std::string text, 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 updateScroller();
void updateSkillArea();

@ -1,12 +1,13 @@
#include "scrollwindow.hpp"
#include "formatting.hpp"
#include "../mwbase/environment.hpp"
#include "../mwinput/inputmanager.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwsound/soundmanager.hpp"
#include "formatting.hpp"
#include "window_manager.hpp"
using namespace MWGui;
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().getInputManager()->setGuiMode (GM_Game);
mWindowManager.popGuiMode();
}
void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender)
@ -65,5 +66,5 @@ void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender)
MWWorld::ActionTake take(mScroll);
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 "window_manager.hpp"
#include "tooltips.hpp"
using namespace MWGui;
@ -77,8 +78,6 @@ StatsWindow::StatsWindow (WindowManager& parWindowManager)
MyGUI::WindowPtr t = static_cast<MyGUI::WindowPtr>(mMainWidget);
t->eventWindowChangeCoord += MyGUI::newDelegate(this, &StatsWindow::onWindowResize);
setupToolTips();
}
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())
miscSkills.push_back(skill);
}
updateSkillArea();
}
void StatsWindow::onFrame ()
@ -339,7 +340,7 @@ MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::st
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;
@ -444,32 +445,17 @@ void StatsWindow::updateSkillArea()
const ESM::Race* playerRace = store.races.find (MWBase::Environment::get().getWorld()->getPlayer().getRace());
MyGUI::Widget* raceWidget;
getWidget(raceWidget, "RaceText");
raceWidget->setUserString("Caption_CenteredCaption", playerRace->name);
raceWidget->setUserString("Caption_CenteredCaptionText", playerRace->description);
ToolTips::createRaceToolTip(raceWidget, playerRace);
getWidget(raceWidget, "Race_str");
raceWidget->setUserString("Caption_CenteredCaption", playerRace->name);
raceWidget->setUserString("Caption_CenteredCaptionText", playerRace->description);
ToolTips::createRaceToolTip(raceWidget, playerRace);
// class tooltip
MyGUI::Widget* classWidget;
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");
classWidget->setUserString("Caption_ClassName", playerClass.name);
classWidget->setUserString("Caption_ClassDescription", playerClass.description);
classWidget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr);
ToolTips::createClassToolTip(classWidget, playerClass);
getWidget(classWidget, "Class_str");
classWidget->setUserString("Caption_ClassName", playerClass.name);
classWidget->setUserString("Caption_ClassDescription", playerClass.description);
classWidget->setUserString("Caption_ClassSpecialisation", "#{sSpecialization}: " + specStr);
ToolTips::createClassToolTip(classWidget, playerClass);
if (!mFactions.empty())
{
@ -536,61 +522,8 @@ void StatsWindow::updateSkillArea()
addGroup(mWindowManager.getGameSettingString("sBirthSign", "Sign"), coord1, coord2);
const ESM::BirthSign *sign = store.birthSigns.find(birthSignId);
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;
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);
ToolTips::createBirthsignToolTip(w, birthSignId);
}
// Add a line separator if there are items above
@ -633,116 +566,3 @@ void StatsWindow::onPinToggled()
{
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 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::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 setupToolTips();
void setFactions (const FactionList& factions);
void setBirthSign (const std::string &signId);

@ -8,6 +8,8 @@
#include <boost/lexical_cast.hpp>
#include <components/settings/settings.hpp>
using namespace MWGui;
using namespace MyGUI;
@ -19,6 +21,10 @@ ToolTips::ToolTips(WindowManager* windowManager) :
, mEnabled(true)
, mFocusToolTipX(0.0)
, mFocusToolTipY(0.0)
, mDelay(0.0)
, mRemainingDelay(0.0)
, mLastMouseX(0)
, mLastMouseY(0)
{
getWidget(mDynamicToolTipBox, "DynamicToolTipBox");
@ -28,6 +34,9 @@ ToolTips::ToolTips(WindowManager* windowManager) :
// even if the mouse is over the tooltip
mDynamicToolTipBox->setNeedMouseFocus(false);
mMainWidget->setNeedMouseFocus(false);
mDelay = Settings::Manager::getFloat("tooltip delay", "GUI");
mRemainingDelay = mDelay;
}
void ToolTips::setEnabled(bool enabled)
@ -37,10 +46,10 @@ void ToolTips::setEnabled(bool enabled)
void ToolTips::onFrame(float frameDuration)
{
MyGUI::Gui::getInstance().destroyWidget(mDynamicToolTipBox);
mDynamicToolTipBox = mMainWidget->createWidget<Widget>("HUD_Box",
IntCoord(0, 0, mMainWidget->getCoord().width, mMainWidget->getCoord().height),
Align::Stretch, "DynamicToolTipBox");
while (mDynamicToolTipBox->getChildCount())
{
MyGUI::Gui::getInstance().destroyWidget(mDynamicToolTipBox->getChildAt(0));
}
// start by hiding everything
for (unsigned int i=0; i < mMainWidget->getChildCount(); ++i)
@ -57,105 +66,193 @@ void ToolTips::onFrame(float frameDuration)
if (!mGameMode)
{
Widget* focus = InputManager::getInstance().getMouseFocusWidget();
if (focus == 0)
const MyGUI::IntPoint& mousePos = InputManager::getInstance().getMousePosition();
if (mWindowManager->getWorldMouseOver() && ((mWindowManager->getMode() == GM_Console)
|| (mWindowManager->getMode() == GM_Container)
|| (mWindowManager->getMode() == GM_Inventory)))
{
return;
}
std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle();
try
{
mFocusObject = MWBase::Environment::get().getWorld()->getPtrViaHandle(handle);
}
catch (std::exception& e)
{
return;
}
IntSize tooltipSize;
MyGUI::IntSize tooltipSize = getToolTipViaPtr(true);
std::string type = focus->getUserString("ToolTipType");
std::string text = focus->getUserString("ToolTipText");
IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24);
ToolTipInfo info;
if (type == "")
{
return;
}
else if (type == "ItemPtr")
{
mFocusObject = *focus->getUserData<MWWorld::Ptr>();
tooltipSize = getToolTipViaPtr(false);
// 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 if (type == "Layout")
else
{
// tooltip defined in the layout
MyGUI::Widget* tooltip;
getWidget(tooltip, focus->getUserString("ToolTipLayout"));
const MyGUI::IntPoint& lastPressed = InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left);
tooltip->setVisible(true);
if (!tooltip->isUserString("DontResize"))
{
tooltip->setCoord(0, 0, 450, 300); // this is the maximum width of the tooltip before it starts word-wrapping
if (mousePos == lastPressed) // mouseclick makes tooltip disappear
return;
tooltipSize = MyGUI::IntSize(0, tooltip->getSize().height);
if (mousePos.left == mLastMouseX && mousePos.top == mLastMouseY)
{
mRemainingDelay -= frameDuration;
}
else
tooltipSize = tooltip->getSize();
std::map<std::string, std::string> userStrings = focus->getUserStrings();
for (std::map<std::string, std::string>::iterator it = userStrings.begin();
it != userStrings.end(); ++it)
{
if (it->first == "ToolTipType"
|| it->first == "ToolTipLayout")
continue;
mRemainingDelay = mDelay;
}
mLastMouseX = mousePos.left;
mLastMouseY = mousePos.top;
if (mRemainingDelay > 0)
return;
Widget* focus = InputManager::getInstance().getMouseFocusWidget();
if (focus == 0)
{
return;
}
size_t underscorePos = it->first.find("_");
std::string propertyKey = it->first.substr(0, underscorePos);
std::string widgetName = it->first.substr(underscorePos+1, it->first.size()-(underscorePos+1));
IntSize tooltipSize;
MyGUI::Widget* w;
getWidget(w, widgetName);
w->setProperty(propertyKey, it->second);
// 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;
}
for (unsigned int i=0; i<tooltip->getChildCount(); ++i)
std::string type = focus->getUserString("ToolTipType");
std::string text = focus->getUserString("ToolTipText");
if (type == "")
{
return;
}
else if (type == "ItemPtr")
{
mFocusObject = *focus->getUserData<MWWorld::Ptr>();
tooltipSize = getToolTipViaPtr(false);
}
else if (type == "Spell")
{
MyGUI::Widget* w = tooltip->getChildAt(i);
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")
{
// tooltip defined in the layout
MyGUI::Widget* tooltip;
getWidget(tooltip, focus->getUserString("ToolTipLayout"));
tooltip->setVisible(true);
if (!tooltip->isUserString("DontResize"))
{
tooltip->setCoord(0, 0, 450, 300); // this is the maximum width of the tooltip before it starts word-wrapping
if (w->isUserString("AutoResizeHorizontal"))
tooltipSize = MyGUI::IntSize(0, tooltip->getSize().height);
}
else
tooltipSize = tooltip->getSize();
std::map<std::string, std::string> userStrings = focus->getUserStrings();
for (std::map<std::string, std::string>::iterator it = userStrings.begin();
it != userStrings.end(); ++it)
{
MyGUI::TextBox* text = w->castType<MyGUI::TextBox>();
tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + text->getTextSize().width + 8);
if (it->first == "ToolTipType"
|| it->first == "ToolTipLayout")
continue;
size_t underscorePos = it->first.find("_");
std::string propertyKey = it->first.substr(0, underscorePos);
std::string widgetName = it->first.substr(underscorePos+1, it->first.size()-(underscorePos+1));
MyGUI::Widget* w;
getWidget(w, widgetName);
w->setProperty(propertyKey, it->second);
}
else if (!tooltip->isUserString("DontResize"))
tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + w->getWidth() + 8);
if (w->isUserString("AutoResizeVertical"))
for (unsigned int i=0; i<tooltip->getChildCount(); ++i)
{
MyGUI::TextBox* text = w->castType<MyGUI::TextBox>();
int height = text->getTextSize().height;
if (height > w->getHeight())
MyGUI::Widget* w = tooltip->getChildAt(i);
if (w->isUserString("AutoResizeHorizontal"))
{
tooltipSize += MyGUI::IntSize(0, height - w->getHeight());
MyGUI::TextBox* text = w->castType<MyGUI::TextBox>();
tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + text->getTextSize().width + 8);
}
if (height < w->getHeight())
else if (!tooltip->isUserString("DontResize"))
tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + w->getWidth() + 8);
if (w->isUserString("AutoResizeVertical"))
{
tooltipSize -= MyGUI::IntSize(0, w->getHeight() - height);
MyGUI::TextBox* text = w->castType<MyGUI::TextBox>();
int height = text->getTextSize().height;
if (height > w->getHeight())
{
tooltipSize += MyGUI::IntSize(0, height - w->getHeight());
}
if (height < w->getHeight())
{
tooltipSize -= MyGUI::IntSize(0, w->getHeight() - height);
}
}
}
tooltip->setCoord(0, 0, tooltipSize.width, tooltipSize.height);
}
tooltip->setCoord(0, 0, tooltipSize.width, tooltipSize.height);
}
else
throw std::runtime_error ("unknown tooltip type");
else
throw std::runtime_error ("unknown tooltip type");
IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24);
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;
}
// 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);
setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height);
}
}
else
{
@ -285,7 +382,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
IntSize totalSize = IntSize( std::max(textSize.width, captionSize.width + ((image != "") ? imageCaptionHPadding : 0)),
((text != "") ? textSize.height + imageCaptionVPadding : 0) + captionHeight );
if (info.effects != 0)
if (!info.effects.empty())
{
Widget* effectArea = mDynamicToolTipBox->createWidget<Widget>("",
IntCoord(0, totalSize.height, 300, 300-totalSize.height),
@ -305,7 +402,7 @@ IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
effectsWidget->setEffectList(info.effects);
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.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>
("MW_StatName", coord, Align::Default, "ToolTipEnchantWidget");
enchantWidget->setWindowManager(mWindowManager);
enchantWidget->setEffectList(&enchant->effects);
enchantWidget->setEffectList(Widgets::MWEffectList::effectListFromESM(&enchant->effects));
std::vector<MyGUI::WidgetPtr> enchantEffectItems;
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");
chargeText->setCaption(store.gameSettings.search("sCharges")->str);
chargeText->setProperty("Static", "true");
const int chargeTextWidth = chargeText->getTextSize().width + 5;
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;
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 "../mwworld/ptr.hpp"
#include "widgets.hpp"
namespace MWGui
{
class WindowManager;
@ -13,11 +15,6 @@ namespace MWGui
struct ToolTipInfo
{
public:
ToolTipInfo() :
effects(0)
{
};
std::string caption;
std::string text;
std::string icon;
@ -26,7 +23,7 @@ namespace MWGui
std::string enchant;
// effects (for potions, ingredients)
const ESM::EffectList* effects;
Widgets::SpellEffectList effects;
};
class ToolTips : public OEngine::GUI::Layout
@ -44,6 +41,8 @@ namespace MWGui
void toggleFullHelp(); ///< show extra info in item tooltips (owner, script)
bool getFullHelp() const;
void setDelay(float delay);
void setFocusObject(const MWWorld::Ptr& focus);
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
@ -60,6 +59,15 @@ namespace MWGui
static std::string getCountString(const int 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:
MyGUI::Widget* mDynamicToolTipBox;
@ -78,6 +86,12 @@ namespace MWGui
float mFocusToolTipX;
float mFocusToolTipY;
float mDelay;
float mRemainingDelay; // remaining time until tooltip will show
int mLastMouseX;
int mLastMouseY;
bool mGameMode;
bool mEnabled;

@ -104,6 +104,8 @@ namespace MWGui
ContainerBase::openContainer(actor);
updateLabels();
drawItems();
}
void TradeWindow::onFilterChanged(MyGUI::Widget* _sender)
@ -157,9 +159,9 @@ namespace MWGui
// check if the merchant can afford this
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)
merchantgold = ref->base->npdt12.gold;
else
@ -167,7 +169,7 @@ namespace MWGui
}
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;
}
if (mCurrentBalance > 0 && merchantgold < mCurrentBalance)
@ -210,7 +212,7 @@ namespace MWGui
std::string sound = "Item Gold Up";
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
mWindowManager.setGuiMode(GM_Game);
mWindowManager.popGuiMode();
}
void TradeWindow::onCancelButtonClicked(MyGUI::Widget* _sender)
@ -218,9 +220,9 @@ namespace MWGui
// i give you back your stuff!
returnBoughtItems(mWindowManager.getInventoryWindow()->getContainerStore());
// 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()
@ -240,9 +242,9 @@ namespace MWGui
}
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)
merchantgold = ref->base->npdt12.gold;
else
@ -250,7 +252,7 @@ namespace MWGui
}
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;
}
@ -262,13 +264,13 @@ namespace MWGui
{
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.
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)
{
@ -285,19 +287,21 @@ namespace MWGui
bool TradeWindow::npcAcceptsItem(MWWorld::Ptr item)
{
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)
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)
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())
return services & ESM::NPC::Weapon;
else if (item.getTypeName() == typeid(ESM::Armor).name())
@ -327,7 +331,7 @@ namespace MWGui
std::vector<MWWorld::Ptr> TradeWindow::itemsToIgnore()
{
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();
it != invStore.end(); ++it)
@ -356,4 +360,11 @@ namespace MWGui
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();
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->setWindowManager(mWindowManager);
effect->setFlags(flags);
effect->setSpellEffect(*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;
params.mIsConstant = (flags & MWEffectList::EF_Constant);
params.mNoTarget = (flags & MWEffectList::EF_NoTarget);
effect->setSpellEffect(params);
effects.push_back(effect);
coord.top += effect->getHeight();
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;
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)
{
// 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;
std::vector<ESM::ENAMstruct>::const_iterator end = mEffectList->list.end();
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->setWindowManager(mWindowManager);
effect->setFlags(flags);
it->mIsConstant = (flags & EF_Constant) || it->mIsConstant;
it->mNoTarget = (flags & EF_NoTarget) || it->mNoTarget;
effect->setSpellEffect(*it);
effects.push_back(effect);
if (effect->getRequestedWidth() > maxwidth)
maxwidth = effect->getRequestedWidth();
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)
{
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()
@ -341,13 +370,12 @@ MWSpellEffect::MWSpellEffect()
, imageWidget(nullptr)
, textWidget(nullptr)
, mRequestedWidth(0)
, mFlags(0)
{
}
void MWSpellEffect::setSpellEffect(SpellEffectValue value)
void MWSpellEffect::setSpellEffect(const SpellEffectParams& params)
{
effect = value;
mEffectParams = params;
updateWidgets();
}
@ -357,74 +385,71 @@ void MWSpellEffect::updateWidgets()
return;
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 (magicEffect)
std::string pt = mWindowManager->getGameSettingString("spoint", "");
std::string pts = mWindowManager->getGameSettingString("spoints", "");
std::string to = " " + mWindowManager->getGameSettingString("sTo", "") + " ";
std::string sec = " " + mWindowManager->getGameSettingString("ssecond", "");
std::string secs = " " + mWindowManager->getGameSettingString("sseconds", "");
std::string effectIDStr = effectIDToString(mEffectParams.mEffectID);
std::string spellLine = mWindowManager->getGameSettingString(effectIDStr, "");
if (effectInvolvesSkill(effectIDStr) && mEffectParams.mSkill >= 0 && mEffectParams.mSkill < ESM::Skill::Length)
{
std::string pt = mWindowManager->getGameSettingString("spoint", "");
std::string pts = mWindowManager->getGameSettingString("spoints", "");
std::string to = " " + mWindowManager->getGameSettingString("sTo", "") + " ";
std::string sec = " " + mWindowManager->getGameSettingString("ssecond", "");
std::string secs = " " + mWindowManager->getGameSettingString("sseconds", "");
std::string effectIDStr = effectIDToString(effect.effectID);
std::string spellLine = mWindowManager->getGameSettingString(effectIDStr, "");
if (effect.skill >= 0 && effect.skill < ESM::Skill::Length)
{
spellLine += " " + mWindowManager->getGameSettingString(ESM::Skill::sSkillNameIds[effect.skill], "");
}
if (effect.attribute >= 0 && effect.attribute < 8)
spellLine += " " + mWindowManager->getGameSettingString(ESM::Skill::sSkillNameIds[mEffectParams.mSkill], "");
}
if (effectInvolvesAttribute(effectIDStr) && mEffectParams.mAttribute >= 0 && mEffectParams.mAttribute < 8)
{
static const char *attributes[8] = {
"sAttributeStrength",
"sAttributeIntelligence",
"sAttributeWillpower",
"sAttributeAgility",
"sAttributeSpeed",
"sAttributeEndurance",
"sAttributePersonality",
"sAttributeLuck"
};
spellLine += " " + mWindowManager->getGameSettingString(attributes[mEffectParams.mAttribute], "");
}
if ((mEffectParams.mMagnMin >= 0 || mEffectParams.mMagnMax >= 0) && effectHasMagnitude(effectIDStr))
{
if (mEffectParams.mMagnMin == mEffectParams.mMagnMax)
spellLine += " " + boost::lexical_cast<std::string>(mEffectParams.mMagnMin) + " " + ((mEffectParams.mMagnMin == 1) ? pt : pts);
else
{
static const char *attributes[8] = {
"sAttributeStrength",
"sAttributeIntelligence",
"sAttributeWillpower",
"sAttributeAgility",
"sAttributeSpeed",
"sAttributeEndurance",
"sAttributePersonality",
"sAttributeLuck"
};
spellLine += " " + mWindowManager->getGameSettingString(attributes[effect.attribute], "");
spellLine += " " + boost::lexical_cast<std::string>(mEffectParams.mMagnMin) + to + boost::lexical_cast<std::string>(mEffectParams.mMagnMax) + " " + pts;
}
}
if ((effect.magnMin >= 0 || effect.magnMax >= 0) && effectHasMagnitude(effectIDStr))
// constant effects have no duration and no target
if (!mEffectParams.mIsConstant)
{
if (mEffectParams.mDuration >= 0 && effectHasDuration(effectIDStr))
{
if (effect.magnMin == effect.magnMax)
spellLine += " " + boost::lexical_cast<std::string>(effect.magnMin) + " " + ((effect.magnMin == 1) ? pt : pts);
else
{
spellLine += " " + boost::lexical_cast<std::string>(effect.magnMin) + to + boost::lexical_cast<std::string>(effect.magnMax) + " " + pts;
}
spellLine += " " + mWindowManager->getGameSettingString("sfor", "") + " " + boost::lexical_cast<std::string>(mEffectParams.mDuration) + ((mEffectParams.mDuration == 1) ? sec : secs);
}
// constant effects have no duration and no target
if (!(mFlags & MWEffectList::EF_Constant))
// potions have no target
if (!mEffectParams.mNoTarget)
{
if (effect.duration >= 0 && effectHasDuration(effectIDStr))
{
spellLine += " " + mWindowManager->getGameSettingString("sfor", "") + " " + boost::lexical_cast<std::string>(effect.duration) + ((effect.duration == 1) ? sec : secs);
}
// potions have no target
if (!(mFlags & MWEffectList::EF_Potion))
{
std::string on = mWindowManager->getGameSettingString("sonword", "");
if (effect.range == ESM::RT_Self)
spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeSelf", "");
else if (effect.range == ESM::RT_Touch)
spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTouch", "");
else if (effect.range == ESM::RT_Target)
spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTarget", "");
}
std::string on = mWindowManager->getGameSettingString("sonword", "");
if (mEffectParams.mRange == ESM::RT_Self)
spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeSelf", "");
else if (mEffectParams.mRange == ESM::RT_Touch)
spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTouch", "");
else if (mEffectParams.mRange == ESM::RT_Target)
spellLine += " " + on + " " + mWindowManager->getGameSettingString("sRangeTarget", "");
}
static_cast<MyGUI::TextBox*>(textWidget)->setCaption(spellLine);
mRequestedWidth = textWidget->getTextSize().width + 24;
}
else
static_cast<MyGUI::TextBox*>(textWidget)->setCaption("");
static_cast<MyGUI::TextBox*>(textWidget)->setCaption(spellLine);
mRequestedWidth = textWidget->getTextSize().width + 24;
}
if (imageWidget)
{
@ -677,6 +702,24 @@ bool MWSpellEffect::effectHasMagnitude(const std::string& effect)
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()
{
}
@ -724,7 +767,7 @@ void MWDynamicStat::setValue(int cur, int max_)
static_cast<MyGUI::TextBox*>(barTextWidget)->setCaption("");
}
}
void MWDynamicStat::setTitle(const std::string text)
void MWDynamicStat::setTitle(const std::string& text)
{
if (textWidget)
static_cast<MyGUI::TextBox*>(textWidget)->setCaption(text);

@ -21,8 +21,58 @@ namespace MWGui
namespace Widgets
{
class MWEffectList;
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
{
MYGUI_RTTI_DERIVED( MWSkill );
@ -108,6 +158,9 @@ namespace MWGui
};
typedef MWAttribute* MWAttributePtr;
/**
* @todo remove this class and use MWEffectList instead
*/
class MWSpellEffect;
class MYGUI_EXPORT MWSpell : public Widget
{
@ -155,12 +208,14 @@ namespace MWGui
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
};
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
@ -180,7 +235,7 @@ namespace MWGui
void updateWidgets();
WindowManager* mWindowManager;
const ESM::EffectList* mEffectList;
SpellEffectList mEffectList;
};
typedef MWEffectList* MWEffectListPtr;
@ -193,14 +248,13 @@ namespace MWGui
typedef ESM::ENAMstruct SpellEffectValue;
void setWindowManager(WindowManager* parWindowManager) { mWindowManager = parWindowManager; }
void setSpellEffect(SpellEffectValue value);
void setFlags(int flags) { mFlags = flags; }
void setSpellEffect(const SpellEffectParams& params);
std::string effectIDToString(const short effectID);
bool effectHasMagnitude (const std::string& effect);
bool effectHasDuration (const std::string& effect);
const SpellEffectValue &getSpellEffect() const { return effect; }
bool effectInvolvesAttribute (const std::string& effect);
bool effectInvolvesSkill (const std::string& effect);
int getRequestedWidth() const { return mRequestedWidth; }
@ -214,8 +268,7 @@ namespace MWGui
void updateWidgets();
WindowManager* mWindowManager;
SpellEffectValue effect;
int mFlags;
SpellEffectParams mEffectParams;
MyGUI::ImageBox* imageWidget;
MyGUI::TextBox* textWidget;
int mRequestedWidth;
@ -229,7 +282,7 @@ namespace MWGui
MWDynamicStat();
void setValue(int value, int max);
void setTitle(const std::string text);
void setTitle(const std::string& text);
int getValue() const { return value; }
int getMax() const { return max; }
@ -247,7 +300,6 @@ namespace MWGui
MyGUI::TextBox* barTextWidget;
};
typedef MWDynamicStat* MWDynamicStatPtr;
}
}

@ -1,6 +1,8 @@
#include "window_base.hpp"
#include "window_manager.hpp"
#include <components/settings/settings.hpp>
using namespace MWGui;
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()
{
// 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();
coord.left = (gameWindowSize.width - coord.width)/2;
coord.top = (gameWindowSize.height - coord.height)/2;

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

@ -16,6 +16,10 @@
#include "mainmenu.hpp"
#include "countdialog.hpp"
#include "tradewindow.hpp"
#include "settingswindow.hpp"
#include "confirmationdialog.hpp"
#include "alchemywindow.hpp"
#include "spellwindow.hpp"
#include "../mwmechanics/mechanicsmanager.hpp"
#include "../mwinput/inputmanager.hpp"
@ -35,7 +39,7 @@
using namespace MWGui;
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)
, hud(NULL)
, map(NULL)
@ -45,11 +49,15 @@ WindowManager::WindowManager(
, mMessageBoxManager(NULL)
, console(NULL)
, mJournal(NULL)
, mDialogueWindow(nullptr)
, mDialogueWindow(NULL)
, mBookWindow(NULL)
, mScrollWindow(NULL)
, mCountDialog(NULL)
, mTradeWindow(NULL)
, mSettingsWindow(NULL)
, mConfirmationDialog(NULL)
, mAlchemyWindow(NULL)
, mSpellWindow(NULL)
, mCharGen(NULL)
, playerClass()
, playerName()
@ -62,9 +70,6 @@ WindowManager::WindowManager(
, playerMagicka()
, playerFatigue()
, gui(NULL)
, mode(GM_Game)
, nextMode(GM_Game)
, needModeChange(false)
, garbageDialogs()
, shown(GW_ALL)
, allowed(newGame ? GW_None : GW_ALL)
@ -118,6 +123,10 @@ WindowManager::WindowManager(
mScrollWindow = new ScrollWindow(*this);
mBookWindow = new BookWindow(*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
hud->setVisible(true);
@ -135,6 +144,9 @@ WindowManager::WindowManager(
playerSkillValues.insert(std::make_pair(ESM::Skill::skillIds[i], MWMechanics::Stat<float>()));
}
unsetSelectedSpell();
unsetSelectedWeapon();
// Set up visibility
updateVisible();
}
@ -158,6 +170,10 @@ WindowManager::~WindowManager()
delete mBookWindow;
delete mScrollWindow;
delete mTradeWindow;
delete mSettingsWindow;
delete mConfirmationDialog;
delete mAlchemyWindow;
delete mSpellWindow;
cleanupGarbage();
}
@ -178,29 +194,10 @@ void WindowManager::cleanupGarbage()
void WindowManager::update()
{
cleanupGarbage();
if (needModeChange)
{
needModeChange = false;
MWBase::Environment::get().getInputManager()->setGuiMode(nextMode);
nextMode = GM_Game;
}
if (showFPSLevel > 0)
{
hud->setFPS(mFPS);
hud->setTriangleCount(mTriangleCount);
hud->setBatchCount(mBatchCount);
}
}
void WindowManager::setNextMode(GuiMode newMode)
{
nextMode = newMode;
needModeChange = true;
}
void WindowManager::setGuiMode(GuiMode newMode)
{
MWBase::Environment::get().getInputManager()->setGuiMode(newMode);
hud->setFPS(mFPS);
hud->setTriangleCount(mTriangleCount);
hud->setBatchCount(mBatchCount);
}
void WindowManager::updateVisible()
@ -217,22 +214,38 @@ void WindowManager::updateVisible()
mScrollWindow->setVisible(false);
mBookWindow->setVisible(false);
mTradeWindow->setVisible(false);
mSettingsWindow->setVisible(false);
mAlchemyWindow->setVisible(false);
mSpellWindow->setVisible(false);
// Mouse is visible whenever we're not in game mode
MyGUI::PointerManager::getInstance().setVisible(isGuiMode());
if (mode == GM_Game)
bool gameMode = !isGuiMode();
if (gameMode)
mToolTips->enterGameMode();
else
mToolTips->enterGuiMode();
setMinimapVisibility((allowed & GW_Map) && !map->pinned());
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 (gameMode)
return;
GuiMode mode = mGuiModes.back();
switch(mode) {
case GM_Game:
// If in game mode, don't show anything.
break;
case GM_MainMenu:
menu->setVisible(true);
break;
case GM_Settings:
mSettingsWindow->setVisible(true);
break;
case GM_Console:
console->enable();
break;
@ -242,6 +255,9 @@ void WindowManager::updateVisible()
case GM_Book:
mBookWindow->setVisible(true);
break;
case GM_Alchemy:
mAlchemyWindow->setVisible(true);
break;
case GM_Name:
case GM_Race:
case GM_Class:
@ -261,29 +277,24 @@ void WindowManager::updateVisible()
int eff = shown & allowed;
// Show the windows we want
map -> setVisible( (eff & GW_Map) != 0 );
mStatsWindow -> setVisible( (eff & GW_Stats) != 0 );
mInventoryWindow->setVisible(true);
mInventoryWindow->openInventory();
map -> setVisible(eff & GW_Map);
mStatsWindow -> setVisible(eff & GW_Stats);
mInventoryWindow->setVisible(eff & GW_Inventory);
mSpellWindow->setVisible(eff & GW_Magic);
break;
}
case GM_Container:
mContainerWindow->setVisible(true);
mInventoryWindow->setVisible(true);
mInventoryWindow->openInventory();
break;
case GM_Dialogue:
mDialogueWindow->open();
mDialogueWindow->setVisible(true);
break;
case GM_Barter:
mInventoryWindow->setVisible(true);
mInventoryWindow->openInventory();
mTradeWindow->setVisible(true);
break;
case GM_InterMessageBox:
if(!mMessageBoxManager->isInteractiveMessageBox()) {
setGuiMode(GM_Game);
}
break;
case GM_Journal:
mJournal->setVisible(true);
@ -291,9 +302,6 @@ void WindowManager::updateVisible()
break;
default:
// 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;
}
}
@ -301,6 +309,7 @@ void WindowManager::updateVisible()
void WindowManager::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
{
mStatsWindow->setValue (id, value);
mCharGen->setValue(id, value);
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)
{
mStatsWindow->setValue(parSkill, value);
mCharGen->setValue(parSkill, value);
playerSkillValues[parSkill] = value;
}
@ -338,6 +348,7 @@ void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicS
{
mStatsWindow->setValue (id, value);
hud->setValue (id, value);
mCharGen->setValue(id, value);
if (id == "HBar")
{
playerHealth = value;
@ -390,6 +401,7 @@ void WindowManager::setPlayerClass (const ESM::Class &class_)
void WindowManager::configureSkills (const SkillList& major, const SkillList& minor)
{
mStatsWindow->configureSkills (major, minor);
mCharGen->configureSkills(major, minor);
playerMajorSkills = major;
playerMinorSkills = minor;
}
@ -427,7 +439,7 @@ void WindowManager::messageBox (const std::string& message, const std::vector<st
else
{
mMessageBoxManager->createInteractiveMessageBox(message, buttons);
setGuiMode(GM_InterMessageBox);
pushGuiMode(GM_InterMessageBox);
}
}
@ -452,7 +464,7 @@ void WindowManager::onDialogueWindowBye()
//removeDialog(dialogueWindow);
mDialogueWindow->setVisible(false);
}
setGuiMode(GM_Game);
popGuiMode();
}
void WindowManager::onFrame (float frameDuration)
@ -469,6 +481,13 @@ void WindowManager::onFrame (float frameDuration)
mInventoryWindow->onFrame();
mStatsWindow->onFrame();
hud->onFrame(frameDuration);
mDialogueWindow->checkReferenceAvailable();
mTradeWindow->checkReferenceAvailable();
mContainerWindow->checkReferenceAvailable();
console->checkReferenceAvailable();
}
const ESMS::ESMStore& WindowManager::getStore() const
@ -493,6 +512,7 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell)
}
map->setCellName( name );
hud->setCellName( name );
map->setCellPrefix("Cell");
hud->setCellPrefix("Cell");
@ -502,6 +522,7 @@ void WindowManager::changeCell(MWWorld::Ptr::CellStore* cell)
else
{
map->setCellName( cell->cell->name );
hud->setCellName( cell->cell->name );
map->setCellPrefix( cell->cell->name );
hud->setCellPrefix( cell->cell->name );
}
@ -542,14 +563,6 @@ void WindowManager::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)
{
mToolTips->setFocusObject(focus);
@ -572,12 +585,13 @@ bool WindowManager::getFullHelp() const
void WindowManager::setWeaponVisibility(bool visible)
{
hud->weapBox->setVisible(visible);
hud->setBottomLeftVisibility(hud->health->getVisible(), visible, hud->spellBox->getVisible());
}
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)
@ -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);
if (setting && setting->type == ESM::VT_String)
_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 <components/esm_store/store.hpp>
#include <components/settings/settings.hpp>
#include <openengine/ogre/renderer.hpp>
#include <openengine/gui/manager.hpp>
@ -77,6 +78,10 @@ namespace MWGui
class MessageBoxManager;
class CountDialog;
class TradeWindow;
class SettingsWindow;
class ConfirmationDialog;
class AlchemyWindow;
class SpellWindow;
struct ClassPoint
{
@ -93,11 +98,9 @@ namespace MWGui
typedef std::vector<Faction> FactionList;
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();
void setGuiMode(GuiMode newMode);
/**
* Should be called each frame to update windows/gui elements.
* This could mean updating sizes of gui elements or opening
@ -105,19 +108,24 @@ namespace MWGui
*/
void update();
void setMode(GuiMode newMode)
{
if (newMode==GM_Inventory && allowed==GW_None)
return;
void pushGuiMode(GuiMode mode);
void popGuiMode();
void removeGuiMode(GuiMode mode); ///< can be anywhere in the stack
mode = newMode;
updateVisible();
GuiMode getMode() const
{
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
void disallowAll()
@ -133,13 +141,21 @@ namespace MWGui
updateVisible();
}
bool isAllowed(GuiWindow wnd) const
{
return allowed & wnd;
}
MWGui::DialogueWindow* getDialogueWindow() {return mDialogueWindow;}
MWGui::ContainerWindow* getContainerWindow() {return mContainerWindow;}
MWGui::InventoryWindow* getInventoryWindow() {return mInventoryWindow;}
MWGui::BookWindow* getBookWindow() {return mBookWindow;}
MWGui::ScrollWindow* getScrollWindow() {return mScrollWindow;}
MWGui::CountDialog* getCountDialog() {return mCountDialog;}
MWGui::ConfirmationDialog* getConfirmationDialog() {return mConfirmationDialog;}
MWGui::TradeWindow* getTradeWindow() {return mTradeWindow;}
MWGui::SpellWindow* getSpellWindow() {return mSpellWindow;}
MWGui::Console* getConsole() {return console;}
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 setMouseVisible(bool visible);
void getMousePosition(int &x, int &y);
void getMousePosition(float &x, float &y);
void setDragDrop(bool dragDrop);
bool getWorldMouseOver();
void toggleFogOfWar();
void toggleFullHelp(); ///< show extra info in item tooltips (owner, script)
bool getFullHelp() const;
int toggleFps();
///< toggle fps display @return resulting fps level
void setInteriorMapTexture(const int x, const int y);
///< set the index of the map texture that should be used (for interiors)
@ -192,6 +208,12 @@ namespace MWGui
void setWeaponVisibility(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>
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.
@ -201,6 +223,11 @@ namespace MWGui
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
* ID or it is not a string the default string is returned.
@ -212,6 +239,8 @@ namespace MWGui
const ESMS::ESMStore& getStore() const;
void processChangedSettings(const Settings::CategorySettingVector& changed);
private:
OEngine::GUI::MyGUIManager *mGuiManager;
HUD *hud;
@ -230,6 +259,10 @@ namespace MWGui
BookWindow* mBookWindow;
CountDialog* mCountDialog;
TradeWindow* mTradeWindow;
SettingsWindow* mSettingsWindow;
ConfirmationDialog* mConfirmationDialog;
AlchemyWindow* mAlchemyWindow;
SpellWindow* mSpellWindow;
CharacterCreation* mCharGen;
@ -244,9 +277,7 @@ namespace MWGui
MyGUI::Gui *gui; // Gui
GuiMode mode; // Current gui mode
GuiMode nextMode; // Next mode to activate in update()
bool needModeChange; //Whether a mode change is needed in update() [will use nextMode]
std::vector<GuiMode> mGuiModes;
std::vector<OEngine::GUI::Layout*> garbageDialogs;
void cleanupGarbage();
@ -257,9 +288,6 @@ namespace MWGui
the start of the game, when windows are enabled one by one
through script commands. You can manipulate this through using
allow() and disableAll().
The setting should also affect visibility of certain HUD
elements, but this is not done yet.
*/
GuiWindow allowed;

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

@ -69,7 +69,7 @@ namespace MWInput
A_ToggleWeapon,
A_ToggleSpell,
A_ToggleFps, // Toggle FPS display (this is temporary)
A_Settings, // Temporary hotkey
A_LAST // Marker for the last item
};
@ -92,12 +92,12 @@ namespace MWInput
/* InputImpl Methods */
void toggleFps()
public:
void adjustMouseRegion(int width, int height)
{
windows.toggleFps();
input.adjustMouseClippingSize(width, height);
}
private:
void toggleSpell()
{
if (windows.isGuiMode()) return;
@ -140,23 +140,32 @@ namespace MWInput
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. */
void toggleInventory()
{
using namespace MWGui;
using namespace MWGui;
if (mDragDrop)
return;
if (mDragDrop)
return;
GuiMode mode = windows.getMode();
bool gameMode = !windows.isGuiMode();
// Toggle between game mode and inventory mode
if(mode == GM_Game)
setGuiMode(GM_Inventory);
else if(mode == GM_Inventory)
setGuiMode(GM_Game);
// Toggle between game mode and inventory mode
if(gameMode)
windows.pushGuiMode(GM_Inventory);
else if(windows.getMode() == GM_Inventory)
windows.popGuiMode();
// .. but don't touch any other mode.
// .. but don't touch any other mode.
}
// Toggle console
@ -167,28 +176,33 @@ namespace MWInput
if (mDragDrop)
return;
GuiMode mode = windows.getMode();
bool gameMode = !windows.isGuiMode();
// Switch to console mode no matter what mode we are currently
// in, except of course if we are already in console mode
if(mode == GM_Console)
setGuiMode(GM_Game);
else setGuiMode(GM_Console);
if (!gameMode)
{
if (windows.getMode() == GM_Console)
windows.popGuiMode();
else
windows.pushGuiMode(GM_Console);
}
else
windows.pushGuiMode(GM_Console);
}
void toggleJournal()
{
using namespace MWGui;
GuiMode mode = windows.getMode();
using namespace MWGui;
// Toggle between game mode and journal mode
if(mode == GM_Game)
setGuiMode(GM_Journal);
else if(mode == GM_Journal)
setGuiMode(GM_Game);
// Toggle between game mode and journal mode
bool gameMode = !windows.isGuiMode();
// .. but don't touch any other mode.
if(gameMode)
windows.pushGuiMode(GM_Journal);
else if(windows.getMode() == GM_Journal)
windows.popGuiMode();
// .. but don't touch any other mode.
}
void activate()
@ -259,8 +273,8 @@ namespace MWInput
"Draw Weapon");
disp->funcs.bind(A_ToggleSpell,boost::bind(&InputImpl::toggleSpell,this),
"Ready hands");
disp->funcs.bind(A_ToggleFps, boost::bind(&InputImpl::toggleFps, this),
"Toggle FPS display");
disp->funcs.bind(A_Settings, boost::bind(&InputImpl::showSettings, this),
"Show settings window");
// Add the exit listener
ogre.getRoot()->addFrameListener(&exit);
@ -282,8 +296,7 @@ namespace MWInput
lst->add(guiEvents,Event::EV_ALL);
}
// Start out in game mode
setGuiMode(MWGui::GM_Game);
changeInputMode(false);
/**********************************
Key binding section
@ -307,7 +320,7 @@ namespace MWInput
disp->bind(A_ToggleWalk, KC_C);
disp->bind(A_ToggleWeapon,KC_F);
disp->bind(A_ToggleSpell,KC_R);
disp->bind(A_ToggleFps, KC_F10);
disp->bind(A_Settings, KC_F2);
// Key bindings for polled keys
// NOTE: These keys are constantly being polled. Only add keys that must be checked each frame.
@ -348,6 +361,7 @@ namespace MWInput
windows.update();
// Disable movement in Gui mode
if (windows.isGuiMode()) return;
// 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
// 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?
if(windows.isGuiMode())
if(guiMode)
{
// Disable mouse look
mouse->setCamera(NULL);
@ -431,11 +441,6 @@ namespace MWInput
delete impl;
}
void MWInputManager::setGuiMode(MWGui::GuiMode mode)
{
impl->setGuiMode(mode);
}
void MWInputManager::update()
{
impl->update();
@ -445,4 +450,25 @@ namespace MWInput
{
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 <components/settings/settings.hpp>
namespace OEngine
{
namespace Render
@ -50,9 +52,11 @@ namespace MWInput
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

@ -71,7 +71,10 @@ namespace MWMechanics
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)

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

@ -30,6 +30,15 @@ namespace MWMechanics
for (int i=0; i<27; ++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
if (mRaceSelected)
{

@ -28,7 +28,7 @@ namespace MWMechanics
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);
}

@ -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;
}
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)
{
int id = 0;
@ -47,3 +62,10 @@ void Compositors::setCompositorEnabled (const std::string& name, const bool enab
mCompositors[name].first = enabled;
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 setViewport(Ogre::Viewport* vp) { mViewport = vp; }
/// recreate compositors (call this after viewport size changes)
void recreate();
bool toggle() { setEnabled(!mEnabled); return mEnabled; }
/**
@ -39,6 +44,8 @@ namespace MWRender
*/
void addCompositor (const std::string& name, const int priority);
void removeAll ();
protected:
/// maps compositor name to its "enabled" state
CompositorMap mCompositors;

@ -68,7 +68,7 @@ ManualObject *Debugging::createPathgridLines(const ESM::Pathgrid *pathgrid)
result->begin(PATHGRID_LINE_MATERIAL, RenderOperation::OT_LINE_LIST);
for(ESM::Pathgrid::EdgeList::const_iterator it = pathgrid->edges.begin();
it != pathgrid->edges.end();
it++)
++it)
{
const ESM::Pathgrid::Edge &edge = *it;
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
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);
}
@ -205,7 +205,7 @@ void Debugging::togglePathgrid()
else
{
// 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);
}

@ -307,50 +307,81 @@ void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaterni
// convert from world coordinates to texture UV coordinates
float u,v;
std::string texName;
std::string texBaseName;
if (!mInterior)
{
u = std::abs((pos.x - (sSize*x))/sSize);
v = 1-std::abs((pos.y + (sSize*y))/sSize);
texName = "Cell_"+coordStr(x,y);
texBaseName = "Cell_";
}
else
{
u = (pos.x - min.x - sSize*x)/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()->setPlayerDir(playerdirection.x, -playerdirection.z);
// 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)
// get the appropriate fog of war texture
TexturePtr tex = TextureManager::getSingleton().getByName(texName+"_fog");
if (!tex.isNull())
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)
{
// get its buffer
if (mBuffers.find(texName) == mBuffers.end()) return;
int i=0;
for (int texV = 0; texV<sFogOfWarResolution; ++texV)
for (int my = -1; my<2; ++my)
{
for (int texU = 0; texU<sFogOfWarResolution; ++texU)
// 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
{
float sqrDist = Math::Sqr(texU - u*sFogOfWarResolution) + Math::Sqr(texV - v*sFogOfWarResolution);
uint32 clr = mBuffers[texName][i];
uint8 alpha = (clr >> 24);
alpha = std::min( alpha, (uint8) (std::max(0.f, std::min(1.f, (sqrDist/sqrExploreRadius)))*255) );
mBuffers[texName][i] = (uint32) (alpha << 24);
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;
++i;
std::string texName = texBaseName + coordStr(x+mx,y+my*intExtMult);
TexturePtr tex = TextureManager::getSingleton().getByName(texName+"_fog");
if (!tex.isNull())
{
// get its buffer
if (mBuffers.find(texName) == mBuffers.end()) return;
int i=0;
for (int texV = 0; texV<sFogOfWarResolution; ++texV)
{
for (int texU = 0; texU<sFogOfWarResolution; ++texU)
{
// fix into range of 0 ... sFogOfWarResolution
int _texU = texU * (float(sFogOfWarResolution+1) / float(sFogOfWarResolution));
int _texV = texV * (float(sFogOfWarResolution+1) / float(sFogOfWarResolution));
float sqrDist = Math::Sqr((_texU + mx*sFogOfWarResolution) - u*sFogOfWarResolution) + Math::Sqr((_texV + my*sFogOfWarResolution) - v*sFogOfWarResolution);
uint32 clr = mBuffers[texName][i];
uint8 alpha = (clr >> 24);
alpha = std::min( alpha, (uint8) (std::max(0.f, std::min(1.f, (sqrDist/sqrExploreRadius)))*255) );
mBuffers[texName][i] = (uint32) (alpha << 24);
++i;
}
}
// copy to the texture
memcpy(tex->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &mBuffers[texName][0], sFogOfWarResolution*sFogOfWarResolution*4);
tex->getBuffer()->unlock();
}
}
// copy to the texture
memcpy(tex->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &mBuffers[texName][0], sFogOfWarResolution*sFogOfWarResolution*4);
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;
NIFLoader::load(meshNumbered);

@ -84,7 +84,7 @@ private:
NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv);
virtual ~NpcAnimation();
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);
virtual void runAnimation(float timepassed);
void updateParts();

@ -39,7 +39,8 @@ struct LightInfo
LightInfo() :
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.
public:
Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer) {}
Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer), mIsStatic(false) {}
~Objects(){}
void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_);
void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh);

@ -6,4 +6,22 @@ namespace MWRender
Player::Player (Ogre::Camera *camera, Ogre::SceneNode* 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; }
/// 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(); }
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/ptr.hpp"
#include "../mwworld/player.hpp"
#include "../mwbase/environment.hpp"
#include <components/esm/loadstat.hpp>
#include <components/settings/settings.hpp>
@ -21,6 +22,9 @@
#include "water.hpp"
#include "compositors.hpp"
#include "../mwgui/window_manager.hpp" // FIXME
#include "../mwinput/inputmanager.hpp" // FIXME
using namespace MWRender;
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.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5);
mRendering.setWindowEventListener(this);
mCompositors = new Compositors(mRendering.getViewport());
@ -62,25 +67,13 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
// disable unsupported effects
const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities();
if (caps->getNumMultiRenderTargets() < 2 || !Settings::Manager::getBool("shaders", "Objects"))
if (!waterShaderSupported())
Settings::Manager::setBool("shader", "Water", false);
if ( !(caps->isShaderProfileSupported("fp40") || caps->isShaderProfileSupported("ps_4_0"))
|| !Settings::Manager::getBool("shaders", "Objects"))
Settings::Manager::setBool("enabled", "Shadows", false);
// note that the order is important here
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);
}
applyCompositors();
// Turn the entire scene (represented by the 'root' node) -90
// 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);
//mSkyManager = 0;
mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera());
mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode());
@ -114,17 +106,24 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
mDebugging = new Debugging(mMwRoot, engine);
mLocalMap = new MWRender::LocalMap(&mRendering, this);
setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI"));
}
RenderingManager::~RenderingManager ()
{
mRendering.removeWindowEventListener(this);
delete mPlayer;
delete mSkyManager;
delete mDebugging;
delete mShaderHelper;
delete mShadows;
delete mTerrainManager;
delete mLocalMap;
delete mOcclusionQuery;
delete mCompositors;
delete mWater;
}
MWRender::SkyManager* RenderingManager::getSkyManager()
@ -563,4 +562,119 @@ Compositors* RenderingManager::getCompositors()
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

@ -8,11 +8,15 @@
#include "../mwworld/class.hpp"
#include <OgreWindowEventUtilities.h>
#include <utility>
#include <openengine/ogre/renderer.hpp>
#include <openengine/ogre/fader.hpp>
#include <openengine/bullet/physic.hpp>
#include <components/settings/settings.hpp>
#include <vector>
#include <string>
@ -49,7 +53,7 @@ namespace MWRender
class Water;
class Compositors;
class RenderingManager: private RenderingInterface {
class RenderingManager: private RenderingInterface, public Ogre::WindowEventListener {
private:
@ -157,10 +161,24 @@ class RenderingManager: private RenderingInterface {
///< transform the specified bounding box (in world coordinates) into screen coordinates.
/// @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:
void setAmbientMode();
void setMenuTransparency(float val);
void applyCompositors();
bool mSunEnabled;
SkyManager* mSkyManager;

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

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

@ -22,30 +22,30 @@ namespace MWRender
TerrainManager::TerrainManager(Ogre::SceneManager* mgr, RenderingManager* rend) :
mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize)), mRendering(rend)
{
mTerrainGlobals = OGRE_NEW TerrainGlobalOptions();
TerrainMaterialGeneratorPtr matGen;
TerrainMaterialGeneratorB* matGenP = new TerrainMaterialGeneratorB();
matGen.bind(matGenP);
mTerrainGlobals.setDefaultMaterialGenerator(matGen);
mTerrainGlobals->setDefaultMaterialGenerator(matGen);
TerrainMaterialGenerator::Profile* const activeProfile =
mTerrainGlobals.getDefaultMaterialGenerator()
mTerrainGlobals->getDefaultMaterialGenerator()
->getActiveProfile();
mActiveProfile = static_cast<TerrainMaterialGeneratorB::SM2Profile*>(activeProfile);
//The pixel error should be as high as possible without it being noticed
//as it governs how fast mesh quality decreases.
mTerrainGlobals.setMaxPixelError(8);
mTerrainGlobals->setMaxPixelError(8);
mTerrainGlobals.setLayerBlendMapSize(32);
mTerrainGlobals.setDefaultGlobalColourMapSize(65);
mTerrainGlobals->setLayerBlendMapSize(32);
mTerrainGlobals->setDefaultGlobalColourMapSize(65);
//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,
//this seemed the distance where it wasn't too noticeable
mTerrainGlobals.setCompositeMapDistance(mWorldSize*2);
mTerrainGlobals->setCompositeMapDistance(mWorldSize*2);
mActiveProfile->setLightmapEnabled(false);
mActiveProfile->setLayerSpecularMappingEnabled(false);
@ -86,20 +86,21 @@ namespace MWRender
TerrainManager::~TerrainManager()
{
OGRE_DELETE mTerrainGlobals;
}
//----------------------------------------------------------------------------------------------
void TerrainManager::setDiffuse(const ColourValue& diffuse)
{
mTerrainGlobals.setCompositeMapDiffuse(diffuse);
mTerrainGlobals->setCompositeMapDiffuse(diffuse);
}
//----------------------------------------------------------------------------------------------
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 cellRemoved(MWWorld::Ptr::CellStore* store);
private:
Ogre::TerrainGlobalOptions mTerrainGlobals;
Ogre::TerrainGlobalOptions* mTerrainGlobals;
Ogre::TerrainGroup mTerrainGroup;
RenderingManager* mRendering;

@ -167,7 +167,7 @@ namespace Ogre
class ShaderHelper : public TerrainAlloc
{
public:
ShaderHelper() {}
ShaderHelper() : mShadowSamplerStartHi(0), mShadowSamplerStartLo(0) {}
virtual ~ShaderHelper() {}
virtual HighLevelGpuProgramPtr generateVertexProgram(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 <components/settings/settings.hpp>
#include "sky.hpp"
#include "renderingmanager.hpp"
#include "compositors.hpp"
@ -10,7 +10,7 @@ namespace MWRender
{
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),
mReflectionTarget(0), mActive(1), mToggled(1),
mReflectionRenderActive(false), mRendering(rend)
@ -30,13 +30,6 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel
mWater->setRenderQueueGroup(RQG_Water);
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->setPosition(0, mTop, 0);
@ -48,30 +41,9 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel
}
mWaterNode->attachObject(mWater);
// Create rendertarget for reflection
int rttsize = Settings::Manager::getInt("rtt size", "Water");
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;
}
applyRTT();
applyVisibilityMask();
mCompositorName = RenderingManager::useMRT() ? "Underwater" : "UnderwaterNoMRT";
createMaterial();
mWater->setMaterial(mMaterial);
@ -80,6 +52,8 @@ Water::Water (Ogre::Camera *camera, RenderingManager* rend, const ESM::Cell* cel
mSceneManager->addRenderQueueListener(this);
assignTextures();
// ----------------------------------------------------------------------------------------------
// ---------------------------------- reflection debug overlay ----------------------------------
@ -140,6 +114,9 @@ Water::~Water()
{
MeshManager::getSingleton().remove("water");
if (mReflectionTarget)
mReflectionTexture->getBuffer()->getRenderTarget()->removeListener(this);
mWaterNode->detachObject(mWater);
mSceneManager->destroyEntity(mWater);
mSceneManager->destroySceneNode(mWaterNode);
@ -249,7 +226,15 @@ void Water::postRenderTargetUpdate(const RenderTargetEvent& evt)
void Water::createMaterial()
{
mMaterial = MaterialManager::getSingleton().getByName("Water");
if (mReflectionTarget == 0)
{
mMaterial = MaterialManager::getSingleton().getByName("Water_Fallback");
}
else
{
mMaterial = MaterialManager::getSingleton().getByName("Water");
mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTexture(mReflectionTexture);
}
// these have to be set in code
std::string textureNames[32];
@ -257,15 +242,20 @@ void Water::createMaterial()
{
textureNames[i] = "textures\\water\\water" + StringConverter::toString(i, 2, '0') + ".dds";
}
mMaterial->getTechnique(1)->getPass(0)->getTextureUnitState(0)->setAnimatedTextureName(textureNames, 32, 2);
// use technique without shaders if reflection is disabled
Ogre::Technique* tech;
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"))
{
CompositorInstance* compositor = CompositorManager::getSingleton().getCompositorChain(mViewport)->getCompositor("gbuffer");
CompositorInstance* compositor = CompositorManager::getSingleton().getCompositorChain(mRendering->getViewport())->getCompositor("gbuffer");
TexturePtr colorTexture = compositor->getTextureInstance("mrt_output", 0);
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

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

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

@ -44,7 +44,7 @@ namespace MWScript
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 opcodeOnActivate = 0x200000d;
const int opcodeActivate = 0x2000075;
@ -208,6 +219,7 @@ namespace MWScript
const int opcodeFadeTo = 0x200013e;
const int opcodeToggleWater = 0x2000144;
const int opcodeTogglePathgrid = 0x2000146;
const int opcodeDontSaveObject = 0x2000153;
void registerExtensions (Compiler::Extensions& extensions)
{
@ -229,6 +241,7 @@ namespace MWScript
extensions.registerInstruction ("twa", "", opcodeToggleWater);
extensions.registerInstruction ("togglepathgrid", "", opcodeTogglePathgrid);
extensions.registerInstruction ("tpg", "", opcodeTogglePathgrid);
extensions.registerInstruction ("dontsaveobject", "", opcodeDontSaveObject);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -247,6 +260,7 @@ namespace MWScript
interpreter.installSegment5 (opcodeFadeTo, new OpFadeTo);
interpreter.installSegment5 (opcodeTogglePathgrid, new OpTogglePathgrid);
interpreter.installSegment5 (opcodeToggleWater, new OpToggleWater);
interpreter.installSegment5 (opcodeDontSaveObject, new OpDontSaveObject);
}
}
}

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

@ -7,7 +7,6 @@
#include <OgreRoot.h>
#include <components/esm_store/store.hpp>
#include <components/settings/settings.hpp>
#include "../mwbase/environment.hpp"
@ -53,6 +52,8 @@ namespace MWSound
, mMasterVolume(1.0f)
, mSFXVolume(1.0f)
, mMusicVolume(1.0f)
, mFootstepsVolume(1.0f)
, mVoiceVolume(1.0f)
{
if(!useSound)
return;
@ -63,6 +64,10 @@ namespace MWSound
mSFXVolume = std::min(std::max(mSFXVolume, 0.0f), 1.0f);
mMusicVolume = Settings::Manager::getFloat("music volume", "Sound");
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 decoder: " << SOUND_IN << std::endl;
@ -210,7 +215,7 @@ namespace MWSound
try
{
// The range values are not tested
float basevol = mMasterVolume * mSFXVolume;
float basevol = mMasterVolume * mVoiceVolume;
std::string filePath = "Sound/"+filename;
const ESM::Position &pos = ptr.getCellRef().pos;
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
@ -234,7 +239,7 @@ namespace MWSound
return;
try
{
float basevol = mMasterVolume * mSFXVolume;
float basevol = mMasterVolume * mVoiceVolume;
std::string filePath = "Sound/"+filename;
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
// better
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