Merge remote branch 'zini/master' into sound

actorid
Chris Robinson 13 years ago
commit 2f8056dfab

@ -15,7 +15,7 @@ include (OpenMWMacros)
# Version
set (OPENMW_VERSION_MAJOR 0)
set (OPENMW_VERSION_MINOR 14)
set (OPENMW_VERSION_MINOR 16)
set (OPENMW_VERSION_RELEASE 0)
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
@ -370,6 +370,10 @@ if(WIN32)
INSTALL(FILES
"${OpenMW_BINARY_DIR}/plugins.cfg"
"${OpenMW_SOURCE_DIR}/readme.txt"
"${OpenMW_SOURCE_DIR}/GPL3.txt"
"${OpenMW_SOURCE_DIR}/OFL.txt"
"${OpenMW_SOURCE_DIR}/Bitstream Vera License.txt"
"${OpenMW_SOURCE_DIR}/Daedric Font License.txt"
"${OpenMW_BINARY_DIR}/launcher.qss"
"${OpenMW_BINARY_DIR}/settings-default.cfg"
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg"
@ -391,8 +395,8 @@ if(WIN32)
!insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP
Delete \\\"$SMPROGRAMS\\\\$MUI_TEMP\\\\Readme.lnk\\\"
")
SET(CPACK_RESOURCE_FILE_README "${OpenMW_SOURCE_DIR}/readme.txt")
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/readme.txt")
SET(CPACK_RESOURCE_FILE_LICENSE "${OpenMW_SOURCE_DIR}/GPL3.txt")
SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
SET(CPACK_NSIS_DISPLAY_NAME "OpenMW")
SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.openmw.org")

@ -8,6 +8,7 @@ set(LAUNCHER
playpage.cpp
pluginsmodel.cpp
pluginsview.cpp
filedialog.cpp
launcher.rc
)
@ -22,6 +23,7 @@ set(LAUNCHER_HEADER
playpage.hpp
pluginsmodel.hpp
pluginsview.hpp
filedialog.hpp
)
# Headers that must be pre-processed
@ -34,6 +36,7 @@ set(LAUNCHER_HEADER_MOC
playpage.hpp
pluginsmodel.hpp
pluginsview.hpp
filedialog.hpp
)
source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER} ${LAUNCHER_HEADER_MOC})

@ -5,6 +5,7 @@
#include "datafilespage.hpp"
#include "lineedit.hpp"
#include "filedialog.hpp"
#include "naturalsort.hpp"
#include "pluginsmodel.hpp"
#include "pluginsview.hpp"
@ -139,7 +140,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, QWidget *parent)
createActions();
setupConfig();
setupDataFiles();
//setupDataFiles();
}
@ -188,7 +189,7 @@ void DataFilesPage::setupConfig()
}
void DataFilesPage::setupDataFiles()
bool DataFilesPage::setupDataFiles()
{
// We use the Configuration Manager to retrieve the configuration values
boost::program_options::variables_map variables;
@ -203,8 +204,7 @@ void DataFilesPage::setupDataFiles()
mCfgMgr.readConfiguration(variables, desc);
// Put the paths in a boost::filesystem vector to use with Files::Collections
Files::PathContainer dataDirs(variables["data"].as<Files::PathContainer>());
mDataDirs = dataDirs;
mDataDirs = Files::PathContainer(variables["data"].as<Files::PathContainer>());
// std::string local = variables["data-local"].as<std::string>();
// if (!local.empty()) {
@ -212,50 +212,50 @@ void DataFilesPage::setupDataFiles()
// dataDirs.push_back(Files::PathContainer::value_type(local));
// }
if (dataDirs.size()>1)
dataDirs.resize (1);
if (mDataDirs.size()>1)
mDataDirs.resize (1);
mCfgMgr.processPaths(dataDirs);
while (dataDirs.empty()) {
// No valid data files directory found
mCfgMgr.processPaths(mDataDirs);
while (mDataDirs.empty()) {
QMessageBox msgBox;
msgBox.setWindowTitle("Error detecting Morrowind installation");
msgBox.setIcon(QMessageBox::Warning);
msgBox.setStandardButtons(QMessageBox::Cancel);
msgBox.setText(tr("<br><b>Could not find the Data Files location</b><br><br> \
The directory containing the data files was not found.<br><br> \
Press \"Browse...\" to specify the location manually.<br>"));
The directory containing the data files was not found.<br><br> \
Press \"Browse...\" to specify the location manually.<br>"));
QAbstractButton *dirSelectButton =
msgBox.addButton(tr("B&rowse..."), QMessageBox::ActionRole);
msgBox.addButton(tr("B&rowse..."), QMessageBox::ActionRole);
msgBox.exec();
if (msgBox.clickedButton() == dirSelectButton) {
QString dataDir = QFileDialog::getExistingDirectory(
this, tr("Select Data Files Directory"),
"/home",
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
// Show a custom dir selection dialog which only accepts valid dirs
QString selectedDir = FileDialog::getExistingDirectory(
this, tr("Select Data Files Directory"),
QDir::currentPath(),
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
// Add the user selected data directory
if (!selectedDir.isEmpty()) {
mDataDirs.push_back(Files::PathContainer::value_type(selectedDir.toStdString()));
mCfgMgr.processPaths(mDataDirs);
} else {
// Cancel from within the dir selection dialog
return false;
}
dataDirs.push_back(Files::PathContainer::value_type(dataDir.toStdString()));
mDataDirs.push_back(Files::PathContainer::value_type(dataDir.toStdString()));
} else {
// Cancel
break;
return false;
}
}
// Check if cancel was clicked because we can't exit from while loop
if (dataDirs.empty()) {
QApplication::exit(1);
return;
}
// Create a file collection for the dataDirs
Files::Collections fileCollections(dataDirs, !variables["fs-strict"].as<bool>());
// Create a file collection for the data dirs
Files::Collections fileCollections(mDataDirs, !variables["fs-strict"].as<bool>());
// First we add all the master files
const Files::MultiDirCollection &esm = fileCollections.getCollection(".esm");
@ -356,6 +356,7 @@ void DataFilesPage::setupDataFiles()
}
readConfig();
return true;
}
void DataFilesPage::createActions()
@ -1057,8 +1058,25 @@ void DataFilesPage::writeConfig(QString profile)
return;
}
QString pathStr = QString::fromStdString(mCfgMgr.getUserPath().string());
QDir userPath(pathStr);
if (!userPath.exists()) {
if (!userPath.mkpath(pathStr)) {
QMessageBox msgBox;
msgBox.setWindowTitle("Error creating OpenMW configuration directory");
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setText(tr("<br><b>Could not create %0</b><br><br> \
Please make sure you have the right permissions and try again.<br>").arg(pathStr));
msgBox.exec();
qApp->quit();
return;
}
}
// Open the OpenMW config as a QFile
QFile file(QString::fromStdString((mCfgMgr.getUserPath() / "openmw.cfg").string()));
QFile file(pathStr.append("openmw.cfg"));
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
// File cannot be opened or created
@ -1067,10 +1085,10 @@ void DataFilesPage::writeConfig(QString profile)
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setText(tr("<br><b>Could not open or create %0</b><br><br> \
Please make sure you have the right permissions and try again.<br>").arg(file.fileName()));
Please make sure you have the right permissions and try again.<br>").arg(file.fileName()));
msgBox.exec();
qApp->exit(1);
qApp->quit();
return;
}
@ -1098,10 +1116,10 @@ void DataFilesPage::writeConfig(QString profile)
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setText(tr("<br><b>Could not write to %0</b><br><br> \
Please make sure you have the right permissions and try again.<br>").arg(file.fileName()));
Please make sure you have the right permissions and try again.<br>").arg(file.fileName()));
msgBox.exec();
qApp->exit(1);
qApp->quit();
return;
}

@ -34,6 +34,7 @@ public:
ComboBox *mProfilesComboBox;
void writeConfig(QString profile = QString());
bool setupDataFiles();
public slots:
void masterSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
@ -92,7 +93,6 @@ private:
void removePlugins(const QModelIndex &index);
void uncheckPlugins();
void createActions();
void setupDataFiles();
void setupConfig();
void readConfig();
void scrollToSelection();

@ -0,0 +1,57 @@
#include "filedialog.hpp"
#include <QDialogButtonBox>
#include <QPushButton>
FileDialog::FileDialog(QWidget *parent)
: QFileDialog(parent)
{
// Remove the default Choose button to prevent it being updated elsewhere
QDialogButtonBox *box = qFindChild<QDialogButtonBox*>(this);
Q_ASSERT(box);
box->removeButton(box->button(QDialogButtonBox::Open));
// Add our own button so we can disable/enable it
mChooseButton = new QPushButton(tr("&Choose"));
mChooseButton->setIcon(QIcon::fromTheme("document-open"));
mChooseButton->setEnabled(false);
box->addButton(mChooseButton, QDialogButtonBox::AcceptRole);
connect(this, SIGNAL(directoryEntered(const QString&)), this, SLOT(updateChooseButton(const QString&)));
emit directoryEntered(QDir::currentPath());
}
QString FileDialog::getExistingDirectory(QWidget *parent,
const QString &caption,
const QString &dir,
Options options)
{
// create a non-native file dialog
FileDialog dialog;
dialog.setFileMode(DirectoryOnly);
dialog.setOptions(options |= QFileDialog::DontUseNativeDialog | QFileDialog::ShowDirsOnly | QFileDialog::ReadOnly);
if (!caption.isEmpty())
dialog.setWindowTitle(caption);
if (!dir.isEmpty())
dialog.setDirectory(dir);
if (dialog.exec() == QDialog::Accepted) {
return dialog.selectedFiles().value(0);
}
return QString();
}
void FileDialog::updateChooseButton(const QString &directory)
{
QDir currentDir = QDir(directory);
currentDir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
currentDir.setNameFilters(QStringList() << "*.esm" << "*.esp");
if (!currentDir.entryList().isEmpty()) {
// There are data files in the current dir
mChooseButton->setEnabled(true);
} else {
mChooseButton->setEnabled(false);
}
}

@ -0,0 +1,28 @@
#ifndef FILEDIALOG_HPP
#define FILEDIALOG_HPP
#include <QFileDialog>
class QPushButton;
class FileDialog : public QFileDialog
{
Q_OBJECT
public:
FileDialog(QWidget *parent = 0);
static QString getExistingDirectory(QWidget *parent = 0,
const QString &caption = QString(),
const QString &dir = QString(),
Options options = ShowDirsOnly);
private slots:
void updateChooseButton(const QString &directory);
private:
QPushButton *mChooseButton;
};
#endif // FILEDIALOG_HPP

@ -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);
@ -44,118 +45,36 @@ GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent)
connect(mRendererComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(rendererChanged(const QString&)));
createPages();
setupConfig();
setupOgre();
readConfig();
}
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);
QWidget *main = new QWidget();
QGridLayout *grid = new QGridLayout(main);
OGLDisplayLayout->addItem(vSpacer2, 2, 1, 1, 1);
OGLDisplayLayout->addWidget(mOGLVSyncCheckBox, 3, 0, 1, 1);
OGLDisplayLayout->addWidget(mOGLFullScreenCheckBox, 6, 0, 1, 1);
mVSyncCheckBox = new QCheckBox(tr("Vertical Sync"), main);
grid->addWidget(mVSyncCheckBox, 0, 0, 1, 1);
// Direct3D rendering settings
QWidget *mD3DRendererPage = new QWidget();
mFullScreenCheckBox = new QCheckBox(tr("Full Screen"), main);
grid->addWidget(mFullScreenCheckBox, 1, 0, 1, 1);
QLabel *D3DRenderDeviceLabel = new QLabel(tr("Rendering Device:"), mD3DRendererPage);
mD3DRenderDeviceComboBox = 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 *D3DAntiAliasingLabel = new QLabel(tr("Antialiasing:"), mD3DRendererPage);
mD3DAntiAliasingComboBox = 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);
QLabel *D3DFloatingPointLabel = new QLabel(tr("Floating-point Mode:"), mD3DRendererPage);
mD3DFloatingPointComboBox = new QComboBox(mD3DRendererPage);
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);
mDisplayStackedWidget->addWidget(mOGLDisplayPage);
mDisplayStackedWidget->addWidget(mD3DDisplayPage);
}
QSpacerItem *vSpacer1 = new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Expanding);
grid->addItem(vSpacer1, 4, 0, 1, 1);
void GraphicsPage::setupConfig()
{
QString ogreCfg = mCfgMgr.getOgreConfigPath().string().c_str();
QFile file(ogreCfg);
mOgreConfig = new QSettings(ogreCfg, QSettings::IniFormat);
mDisplayStackedWidget->addWidget(main);
}
void GraphicsPage::setupOgre()
bool GraphicsPage::setupOgre()
{
QString pluginCfg = mCfgMgr.getPluginsConfigPath().string().c_str();
QFile file(pluginCfg);
@ -164,32 +83,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)
@ -206,9 +105,7 @@ void GraphicsPage::setupOgre()
msgBox.exec();
qCritical("Error creating Ogre::Root, the error reported was:\n %s", qPrintable(ogreError));
qApp->exit(1);
return;
return false;
}
#ifdef ENABLE_PLUGIN_GL
@ -228,11 +125,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));
@ -250,226 +155,86 @@ void GraphicsPage::setupOgre()
Please make sure the plugins.cfg file exists and contains a valid rendering plugin.<br>"));
msgBox.exec();
qApp->exit(1);
return;
return false;
}
// 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));
}
mAntiAliasingComboBox->clear();
mResolutionComboBox->clear();
mAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mSelectedRenderSystem));
mResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mSelectedRenderSystem));
// 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));
}
readConfig();
return true;
}
void GraphicsPage::readConfig()
{
// Read the config file settings
if (mOpenGLRenderSystem) {
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);
}
if (Settings::Manager::getBool("vsync", "Video"))
mVSyncCheckBox->setCheckState(Qt::Checked);
index = mOGLFrequencyComboBox->findText(getConfigValue("Display Frequency", mOpenGLRenderSystem));
if ( index != -1) {
mOGLFrequencyComboBox->setCurrentIndex(index);
}
// Now we do the same for the checkboxes
if (getConfigValue("VSync", mOpenGLRenderSystem) == QLatin1String("Yes")) {
mOGLVSyncCheckBox->setCheckState(Qt::Checked);
}
if (getConfigValue("Full Screen", mOpenGLRenderSystem) == QLatin1String("Yes")) {
mOGLFullScreenCheckBox->setCheckState(Qt::Checked);
}
}
if (mDirect3DRenderSystem) {
int index = mD3DRenderDeviceComboBox->findText(getConfigValue("Rendering Device", mDirect3DRenderSystem));
if ( index != -1) {
mD3DRenderDeviceComboBox->setCurrentIndex(index);
}
index = mD3DAntiAliasingComboBox->findText(getConfigValue("FSAA", mDirect3DRenderSystem));
if ( index != -1) {
mD3DAntiAliasingComboBox->setCurrentIndex(index);
}
index = mD3DFloatingPointComboBox->findText(getConfigValue("Floating-point mode", mDirect3DRenderSystem));
if ( index != -1) {
mD3DFloatingPointComboBox->setCurrentIndex(index);
}
index = mD3DResolutionComboBox->findText(getConfigValue("Video Mode", mDirect3DRenderSystem));
if ( index != -1) {
mD3DResolutionComboBox->setCurrentIndex(index);
}
if (getConfigValue("Allow NVPerfHUD", mDirect3DRenderSystem) == QLatin1String("Yes")) {
mD3DNvPerfCheckBox->setCheckState(Qt::Checked);
}
if (Settings::Manager::getBool("fullscreen", "Video"))
mFullScreenCheckBox->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;
}
Settings::Manager::setBool("vsync", "Video", mVSyncCheckBox->checkState());
Settings::Manager::setBool("fullscreen", "Video", mFullScreenCheckBox->checkState());
Settings::Manager::setString("antialiasing", "Video", mAntiAliasingComboBox->currentText().toStdString());
Settings::Manager::setString("render system", "Video", mRendererComboBox->currentText().toStdString());
// parse resolution x and y from a string like "800 x 600"
QString resolution = mResolutionComboBox->currentText();
QStringList tokens = resolution.split(" ", QString::SkipEmptyParts);
int resX = boost::lexical_cast<int>(tokens.at(0).toStdString());
int resY = boost::lexical_cast<int>(tokens.at(2).toStdString());
Settings::Manager::setInt("resolution x", "Video", resX);
Settings::Manager::setInt("resolution y", "Video", resY);
}
// Write the settings to the config file
QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer)
{
QStringList result;
uint row = 0;
Ogre::ConfigOptionMap options = renderer->getConfigOptions();
try
{
mOgre->saveConfig();
}
catch(Ogre::Exception &ex)
for (Ogre::ConfigOptionMap::iterator i = options.begin (); i != options.end (); i++, row++)
{
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));
Ogre::StringVector::iterator opt_it;
uint idx = 0;
for (opt_it = i->second.possibleValues.begin ();
opt_it != i->second.possibleValues.end (); opt_it++, idx++)
{
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();
}
}
qApp->exit(1);
return;
}
}
QString GraphicsPage::getConfigValue(const QString &key, Ogre::RenderSystem *renderer)
{
QString result;
mOgreConfig->beginGroup(renderer->getName().c_str());
result = mOgreConfig->value(key).toString();
mOgreConfig->endGroup();
return result;
}
QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSystem *renderer)
QStringList GraphicsPage::getAvailableResolutions(Ogre::RenderSystem *renderer)
{
QString key ("Video Mode");
QStringList result;
uint row = 0;
@ -477,15 +242,26 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy
for (Ogre::ConfigOptionMap::iterator i = options.begin (); i != options.end (); i++, row++)
{
if (key.toStdString() != i->first)
continue;
Ogre::StringVector::iterator opt_it;
uint idx = 0;
for (opt_it = i->second.possibleValues.begin ();
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();
}
opt_it != i->second.possibleValues.end (); opt_it++, idx++)
{
QString qval = QString::fromStdString(*opt_it).simplified();
// remove extra tokens after the resolution (for example bpp, can be there or not depending on rendersystem)
QStringList tokens = qval.split(" ", QString::SkipEmptyParts);
assert (tokens.size() >= 3);
QString resolutionStr = tokens.at(0) + QString(" x ") + tokens.at(2);
{
// do not add duplicate resolutions
if (!result.contains(resolutionStr))
result << resolutionStr;
}
}
}
@ -494,15 +270,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(getAvailableResolutions(mSelectedRenderSystem));
}

@ -30,6 +30,7 @@ class GraphicsPage : public QWidget
public:
GraphicsPage(Files::ConfigurationManager &cfg, QWidget *parent = 0);
bool setupOgre();
void writeConfig();
public slots:
@ -49,38 +50,19 @@ 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);
QStringList getAvailableResolutions(Ogre::RenderSystem *renderer);
void createPages();
void setupConfig();
void setupOgre();
void readConfig();
};

@ -1,12 +1,3 @@
/****************************************************************************
**
** Copyright (c) 2007 Trolltech ASA <info@trolltech.com>
**
** Use, modification and distribution is allowed without limitation,
** warranty, liability or support of any kind.
**
****************************************************************************/
#include "lineedit.hpp"
#include <QToolButton>
#include <QStyle>
@ -14,33 +5,33 @@
LineEdit::LineEdit(QWidget *parent)
: QLineEdit(parent)
{
clearButton = new QToolButton(this);
mClearButton = new QToolButton(this);
QPixmap pixmap(":images/clear.png");
clearButton->setIcon(QIcon(pixmap));
clearButton->setIconSize(pixmap.size());
clearButton->setCursor(Qt::ArrowCursor);
clearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }");
clearButton->hide();
connect(clearButton, SIGNAL(clicked()), this, SLOT(clear()));
mClearButton->setIcon(QIcon(pixmap));
mClearButton->setIconSize(pixmap.size());
mClearButton->setCursor(Qt::ArrowCursor);
mClearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }");
mClearButton->hide();
connect(mClearButton, SIGNAL(clicked()), this, SLOT(clear()));
connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(updateCloseButton(const QString&)));
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
setStyleSheet(QString("QLineEdit { padding-right: %1px; } ").arg(clearButton->sizeHint().width() + frameWidth + 1));
setStyleSheet(QString("QLineEdit { padding-right: %1px; } ").arg(mClearButton->sizeHint().width() + frameWidth + 1));
QSize msz = minimumSizeHint();
setMinimumSize(qMax(msz.width(), clearButton->sizeHint().height() + frameWidth * 2 + 2),
qMax(msz.height(), clearButton->sizeHint().height() + frameWidth * 2 + 2));
setMinimumSize(qMax(msz.width(), mClearButton->sizeHint().height() + frameWidth * 2 + 2),
qMax(msz.height(), mClearButton->sizeHint().height() + frameWidth * 2 + 2));
}
void LineEdit::resizeEvent(QResizeEvent *)
{
QSize sz = clearButton->sizeHint();
QSize sz = mClearButton->sizeHint();
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
clearButton->move(rect().right() - frameWidth - sz.width(),
mClearButton->move(rect().right() - frameWidth - sz.width(),
(rect().bottom() + 1 - sz.height())/2);
}
void LineEdit::updateCloseButton(const QString& text)
{
clearButton->setVisible(!text.isEmpty());
mClearButton->setVisible(!text.isEmpty());
}

@ -28,7 +28,7 @@ private slots:
void updateCloseButton(const QString &text);
private:
QToolButton *clearButton;
QToolButton *mClearButton;
};
#endif // LIENEDIT_H

@ -1,7 +1,6 @@
#include <QApplication>
#include <QDir>
#include <QFile>
#include <QtDebug>
#include "maindialog.hpp"
@ -31,8 +30,14 @@ int main(int argc, char *argv[])
QDir::setCurrent(dir.absolutePath());
MainDialog dialog;
return dialog.exec();
MainDialog mainWin;
if (mainWin.setup()) {
mainWin.show();
return app.exec();
}
return 0;
}

@ -7,7 +7,10 @@
MainDialog::MainDialog()
{
mIconWidget = new QListWidget;
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
mIconWidget = new QListWidget(centralWidget);
mIconWidget->setObjectName("IconWidget");
mIconWidget->setViewMode(QListView::IconMode);
mIconWidget->setWrapping(false);
@ -21,7 +24,7 @@ MainDialog::MainDialog()
mIconWidget->setCurrentRow(0);
mIconWidget->setFlow(QListView::LeftToRight);
QGroupBox *groupBox = new QGroupBox(this);
QGroupBox *groupBox = new QGroupBox(centralWidget);
QVBoxLayout *groupLayout = new QVBoxLayout(groupBox);
mPagesWidget = new QStackedWidget(groupBox);
@ -29,16 +32,15 @@ MainDialog::MainDialog()
QPushButton *playButton = new QPushButton(tr("Play"));
QDialogButtonBox *buttonBox = new QDialogButtonBox(this);
QDialogButtonBox *buttonBox = new QDialogButtonBox(centralWidget);
buttonBox->setStandardButtons(QDialogButtonBox::Close);
buttonBox->addButton(playButton, QDialogButtonBox::AcceptRole);
QVBoxLayout *dialogLayout = new QVBoxLayout(this);
QVBoxLayout *dialogLayout = new QVBoxLayout(centralWidget);
dialogLayout->addWidget(mIconWidget);
dialogLayout->addWidget(groupBox);
dialogLayout->addWidget(buttonBox);
setWindowTitle(tr("OpenMW Launcher"));
setWindowIcon(QIcon(":/images/openmw.png"));
// Remove what's this? button
@ -48,22 +50,22 @@ MainDialog::MainDialog()
// Install the stylesheet font
QFile file;
QFontDatabase fontDatabase;
const QStringList fonts = fontDatabase.families();
// Check if the font is installed
if (!fonts.contains("EB Garamond")) {
QString font = QString::fromStdString((mCfgMgr.getGlobalDataPath() / "resources/mygui/EBGaramond-Regular.ttf").string());
file.setFileName(font);
if (!file.exists()) {
font = QString::fromStdString((mCfgMgr.getLocalPath() / "resources/mygui/EBGaramond-Regular.ttf").string());
font = QString::fromStdString((mCfgMgr.getLocalPath() / "resources/mygui/EBGaramond-Regular.ttf").string());
}
fontDatabase.addApplicationFont(font);
}
// Load the stylesheet
QString config = QString::fromStdString((mCfgMgr.getGlobalDataPath() / "resources/launcher.qss").string());
file.setFileName(config);
@ -77,7 +79,6 @@ MainDialog::MainDialog()
qApp->setStyleSheet(styleSheet);
file.close();
connect(buttonBox, SIGNAL(rejected()), this, SLOT(close()));
connect(buttonBox, SIGNAL(accepted()), this, SLOT(play()));
@ -148,6 +149,53 @@ void MainDialog::createPages()
}
bool MainDialog::setup()
{
// Create the settings manager and load default settings file
const std::string localdefault = (mCfgMgr.getLocalPath() / "settings-default.cfg").string();
const std::string globaldefault = (mCfgMgr.getGlobalPath() / "settings-default.cfg").string();
// prefer local
if (boost::filesystem::exists(localdefault)) {
mSettings.loadDefault(localdefault);
} else if (boost::filesystem::exists(globaldefault)) {
mSettings.loadDefault(globaldefault);
} else {
QMessageBox msgBox;
msgBox.setWindowTitle("Error reading OpenMW configuration file");
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setText(tr("<br><b>Could not find %0</b><br><br> \
The problem may be due to an incomplete installation of OpenMW.<br> \
Reinstalling OpenMW may resolve the problem.").arg(QString::fromStdString(globaldefault)));
msgBox.exec();
return false;
}
// load user settings if they exist, otherwise just load the default settings as user settings
const std::string settingspath = (mCfgMgr.getUserPath() / "settings.cfg").string();
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);
// Setup the Graphics page
if (!mGraphicsPage->setupOgre()) {
return false;
}
// Setup the Data Files page
if (!mDataFilesPage->setupDataFiles()) {
return false;
}
return true;
}
void MainDialog::profileChanged(int index)
{
// Just to be sure, should always have a selection
@ -178,6 +226,12 @@ void MainDialog::closeEvent(QCloseEvent *event)
// Now write all config files
mDataFilesPage->writeConfig();
mGraphicsPage->writeConfig();
// Save user settings
const std::string settingspath = (mCfgMgr.getUserPath() / "settings.cfg").string();
qDebug() << QString::fromStdString(settingspath);
mSettings.saveUser(settingspath);
event->accept();
}
@ -219,7 +273,7 @@ void MainDialog::play()
if (!info.isExecutable()) {
QMessageBox msgBox;
msgBox.setWindowTitle("Error starting OpenMW");
msgBox.setIcon(QMessageBox::Critical);
msgBox.setIcon(QMessageBox::Warning);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setText(tr("<br><b>Could not start OpenMW</b><br><br> \
The OpenMW application is not executable.<br> \
@ -243,6 +297,7 @@ void MainDialog::play()
return;
} else {
close();
qApp->quit();
}
}

@ -1,9 +1,10 @@
#ifndef MAINDIALOG_H
#define MAINDIALOG_H
#include <QDialog>
#include <QMainWindow>
#include <components/files/configurationmanager.hpp>
#include <components/settings/settings.hpp>
class QListWidget;
class QListWidgetItem;
@ -16,7 +17,7 @@ class PlayPage;
class GraphicsPage;
class DataFilesPage;
class MainDialog : public QDialog
class MainDialog : public QMainWindow
{
Q_OBJECT
@ -27,6 +28,7 @@ public slots:
void changePage(QListWidgetItem *current, QListWidgetItem *previous);
void play();
void profileChanged(int index);
bool setup();
private:
void createIcons();
@ -41,6 +43,7 @@ private:
DataFilesPage *mDataFilesPage;
Files::ConfigurationManager mCfgMgr;
Settings::Manager mSettings;
};
#endif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

@ -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;
}
}

@ -16,6 +16,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
add_openmw_dir (mwrender
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects
renderinginterface localmap occlusionquery terrain terrainmaterial water shadows shaderhelper
compositors
)
add_openmw_dir (mwinput
@ -23,10 +24,11 @@ add_openmw_dir (mwinput
)
add_openmw_dir (mwgui
layouts text_input widgets race class birth review window_manager console dialogue
text_input widgets race class birth review window_manager console dialogue
dialogue_history window_base stats_window messagebox journalwindow charactercreation
map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list
formatting
formatting inventorywindow container hud countdialog tradewindow settingswindow
confirmationdialog alchemywindow referenceinterface spellwindow
)
add_openmw_dir (mwdialogue
@ -47,7 +49,8 @@ add_openmw_dir (mwsound
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 actionread
cells localscripts customdata weather inventorystore ptr actionopen actionread
actionequip timestamp actionalchemy
)
add_openmw_dir (mwclass
@ -57,6 +60,7 @@ add_openmw_dir (mwclass
add_openmw_dir (mwmechanics
mechanicsmanager stat creaturestats magiceffects movement actors drawstate spells
activespells
)
add_openmw_dir (mwbase

@ -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
@ -126,9 +126,9 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
// update GUI
Ogre::RenderWindow* window = mOgre->getWindow();
MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(),
window->getTriangleCount(),
window->getBatchCount());
unsigned int tri, batch;
MWBase::Environment::get().getWorld()->getTriangleBatchCount(tri, batch);
MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(), tri, batch);
MWBase::Environment::get().getWindowManager()->onFrame(evt.timeSinceLastFrame);
}
@ -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();

@ -79,7 +79,7 @@ namespace MWClass
ptr.get<ESM::Activator>();
MWGui::ToolTipInfo info;
info.caption = ref->base->name;
info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount());
std::string text;
if (MWBase::Environment::get().getWindowManager()->getFullHelp())

@ -9,6 +9,7 @@
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwworld/actionalchemy.hpp"
#include "../mwworld/world.hpp"
#include "../mwrender/objects.hpp"
@ -100,6 +101,14 @@ namespace MWClass
return std::string("Item Apparatus Down");
}
std::string Apparatus::getInventoryIcon (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref =
ptr.get<ESM::Apparatus>();
return ref->base->icon;
}
bool Apparatus::hasToolTip (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Apparatus, MWWorld::RefData> *ref =
@ -114,7 +123,7 @@ namespace MWClass
ptr.get<ESM::Apparatus>();
MWGui::ToolTipInfo info;
info.caption = ref->base->name;
info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount());
info.icon = ref->base->icon;
const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
@ -132,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());
}
}

@ -41,6 +41,13 @@ namespace MWClass
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const;
///< Return the put down sound Id
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"
@ -198,6 +199,14 @@ namespace MWClass
return std::string("Item Armor Heavy Down");
}
std::string Armor::getInventoryIcon (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
ptr.get<ESM::Armor>();
return ref->base->icon;
}
bool Armor::hasToolTip (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
@ -212,7 +221,7 @@ namespace MWClass
ptr.get<ESM::Armor>();
MWGui::ToolTipInfo info;
info.caption = ref->base->name;
info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount());
info.icon = ref->base->icon;
std::string text;
@ -248,4 +257,19 @@ namespace MWClass
return info;
}
std::string Armor::getEnchantment (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Armor, MWWorld::RefData> *ref =
ptr.get<ESM::Armor>();
return ref->base->enchant;
}
boost::shared_ptr<MWWorld::Action> Armor::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));
}
}

@ -55,6 +55,17 @@ namespace MWClass
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const;
///< Return the put down sound Id
virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const;
///< Return name of inventory icon.
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
///< @return the enchantment ID if the object is enchanted, otherwise an empty string
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
///< Generate action for using via inventory menu
};
}

@ -97,6 +97,14 @@ namespace MWClass
return std::string("Item Book Down");
}
std::string Book::getInventoryIcon (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =
ptr.get<ESM::Book>();
return ref->base->icon;
}
bool Book::hasToolTip (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =
@ -111,7 +119,7 @@ namespace MWClass
ptr.get<ESM::Book>();
MWGui::ToolTipInfo info;
info.caption = ref->base->name;
info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount());
info.icon = ref->base->icon;
const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
@ -132,4 +140,18 @@ namespace MWClass
return info;
}
std::string Book::getEnchantment (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =
ptr.get<ESM::Book>();
return ref->base->enchant;
}
boost::shared_ptr<MWWorld::Action> Book::use (const MWWorld::Ptr& ptr) const
{
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionRead(ptr));
}
}

@ -41,6 +41,15 @@ namespace MWClass
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const;
///< Return the put down sound Id
virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const;
///< Return name of inventory icon.
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
///< @return the enchantment ID if the object is enchanted, otherwise an empty string
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"
@ -166,6 +167,14 @@ namespace MWClass
return std::string("Item Clothes Down");
}
std::string Clothing::getInventoryIcon (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
ptr.get<ESM::Clothing>();
return ref->base->icon;
}
bool Clothing::hasToolTip (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
@ -180,7 +189,7 @@ namespace MWClass
ptr.get<ESM::Clothing>();
MWGui::ToolTipInfo info;
info.caption = ref->base->name;
info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount());
info.icon = ref->base->icon;
const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
@ -201,4 +210,19 @@ namespace MWClass
return info;
}
std::string Clothing::getEnchantment (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Clothing, MWWorld::RefData> *ref =
ptr.get<ESM::Clothing>();
return ref->base->enchant;
}
boost::shared_ptr<MWWorld::Action> Clothing::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));
}
}

@ -49,6 +49,16 @@ namespace MWClass
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const;
///< Return the put down sound Id
virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const;
///< Return name of inventory icon.
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
///< @return the enchantment ID if the object is enchanted, otherwise an empty string
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
///< Generate action for using via inventory menu
};
}

@ -17,6 +17,7 @@
#include "../mwgui/tooltips.hpp"
#include "../mwrender/objects.hpp"
#include "../mwworld/actionopen.hpp"
#include "../mwsound/soundmanager.hpp"
@ -86,6 +87,7 @@ namespace MWClass
const std::string lockedSound = "LockedChest";
const std::string trapActivationSound = "Disarm Trap Fail";
if (ptr.getCellRef().lockLevel>0)
{
// TODO check for key
@ -99,7 +101,8 @@ namespace MWClass
if(ptr.getCellRef().trap.empty())
{
// Not trapped, Inventory GUI goes here
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
//return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionOpen(ptr));
}
else
{
@ -176,4 +179,30 @@ namespace MWClass
return info;
}
float Container::getCapacity (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Container, MWWorld::RefData> *ref =
ptr.get<ESM::Container>();
return ref->base->weight;
}
float Container::getEncumbrance (const MWWorld::Ptr& ptr) const
{
return getContainerStore (ptr).getWeight();
}
void Container::lock (const MWWorld::Ptr& ptr, int lockLevel) const
{
if (lockLevel<0)
lockLevel = 0;
ptr.getCellRef().lockLevel = lockLevel;
}
void Container::unlock (const MWWorld::Ptr& ptr) const
{
ptr.getCellRef().lockLevel = 0;
}
}

@ -36,6 +36,20 @@ namespace MWClass
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr
virtual float getCapacity (const MWWorld::Ptr& ptr) const;
///< Return total weight that fits into the object. Throws an exception, if the object can't
/// hold other objects.
virtual float getEncumbrance (const MWWorld::Ptr& ptr) const;
///< Returns total weight of objects inside this object (including modifications from magic
/// effects). Throws an exception, if the object can't hold other objects.
virtual void lock (const MWWorld::Ptr& ptr, int lockLevel) const;
///< Lock object
virtual void unlock (const MWWorld::Ptr& ptr) const;
///< Unlock object
static void registerSelf();
};
}

@ -5,6 +5,7 @@
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/mechanicsmanager.hpp"
#include "../mwmechanics/magiceffects.hpp"
#include "../mwbase/environment.hpp"
@ -56,7 +57,10 @@ namespace MWClass
data->mCreatureStats.mLevel = ref->base->data.level;
// \todo add initial container content
data->mCreatureStats.mHello = ref->base->AI.hello;
data->mCreatureStats.mFight = ref->base->AI.fight;
data->mCreatureStats.mFlee = ref->base->AI.flee;
data->mCreatureStats.mAlarm = ref->base->AI.alarm;
// store
ptr.getRefData().setCustomData (data.release());
@ -82,24 +86,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.insertActorPhysics(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 =
@ -166,4 +161,26 @@ namespace MWClass
return info;
}
float Creature::getCapacity (const MWWorld::Ptr& ptr) const
{
const MWMechanics::CreatureStats& stats = getCreatureStats (ptr);
return stats.mAttributes[0].getModified()*5;
}
float Creature::getEncumbrance (const MWWorld::Ptr& ptr) const
{
float weight = getContainerStore (ptr).getWeight();
const MWMechanics::CreatureStats& stats = getCreatureStats (ptr);
weight -= stats.mMagicEffects.get (MWMechanics::EffectKey (8)).mMagnitude; // feather
weight += stats.mMagicEffects.get (MWMechanics::EffectKey (7)).mMagnitude; // burden
if (weight<0)
weight = 0;
return weight;
}
}

@ -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.
@ -52,6 +46,14 @@ namespace MWClass
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
///< Return name of the script attached to ptr
virtual float getCapacity (const MWWorld::Ptr& ptr) const;
///< Return total weight that fits into the object. Throws an exception, if the object can't
/// hold other objects.
virtual float getEncumbrance (const MWWorld::Ptr& ptr) const;
///< Returns total weight of objects inside this object (including modifications from magic
/// effects). Throws an exception, if the object can't hold other objects.
static void registerSelf();
};
}

@ -98,6 +98,14 @@ namespace MWClass
return std::string("Item Ingredient Down");
}
std::string Ingredient::getInventoryIcon (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =
ptr.get<ESM::Ingredient>();
return ref->base->icon;
}
bool Ingredient::hasToolTip (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Ingredient, MWWorld::RefData> *ref =
@ -112,7 +120,7 @@ namespace MWClass
ptr.get<ESM::Ingredient>();
MWGui::ToolTipInfo info;
info.caption = ref->base->name;
info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount());
info.icon = ref->base->icon;
const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
@ -127,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;

@ -41,6 +41,9 @@ namespace MWClass
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const;
///< Return the put down sound Id
virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const;
///< Return name of inventory icon.
};
}

@ -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())
{
@ -140,6 +135,15 @@ namespace MWClass
return std::string("Item Misc Down");
}
std::string Light::getInventoryIcon (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
ptr.get<ESM::Light>();
return ref->base->icon;
}
bool Light::hasToolTip (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
@ -154,7 +158,7 @@ namespace MWClass
ptr.get<ESM::Light>();
MWGui::ToolTipInfo info;
info.caption = ref->base->name;
info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount());
info.icon = ref->base->icon;
const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
@ -173,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.
@ -50,6 +45,13 @@ namespace MWClass
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const;
///< Return the put down sound Id
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"
@ -110,6 +111,14 @@ namespace MWClass
return std::string("Item Lockpick Down");
}
std::string Lockpick::getInventoryIcon (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref =
ptr.get<ESM::Tool>();
return ref->base->icon;
}
bool Lockpick::hasToolTip (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Tool, MWWorld::RefData> *ref =
@ -124,7 +133,7 @@ namespace MWClass
ptr.get<ESM::Tool>();
MWGui::ToolTipInfo info;
info.caption = ref->base->name;
info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount());
info.icon = ref->base->icon;
const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
@ -147,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));
}
}

@ -45,6 +45,13 @@ namespace MWClass
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const;
///< Return the put down sound Id
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
};
}

@ -1,6 +1,8 @@
#include "misc.hpp"
#include <boost/lexical_cast.hpp>
#include <components/esm/loadmisc.hpp>
#include <components/esm_store/cell_store.hpp>
@ -116,6 +118,14 @@ namespace MWClass
return std::string("Item Misc Down");
}
std::string Miscellaneous::getInventoryIcon (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
ptr.get<ESM::Miscellaneous>();
return ref->base->icon;
}
bool Miscellaneous::hasToolTip (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Miscellaneous, MWWorld::RefData> *ref =
@ -130,11 +140,24 @@ namespace MWClass
ptr.get<ESM::Miscellaneous>();
MWGui::ToolTipInfo info;
info.caption = ref->base->name;
info.icon = ref->base->icon;
const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
int count = ptr.getRefData().getCount();
bool isGold = (ref->base->name == store.gameSettings.search("sGold")->str);
if (isGold && count == 1)
count = ref->base->data.value;
std::string countString;
if (!isGold)
countString = MWGui::ToolTips::getCountString(count);
else // gold displays its count also if it's 1.
countString = " (" + boost::lexical_cast<std::string>(count) + ")";
info.caption = ref->base->name + countString;
info.icon = ref->base->icon;
if (ref->ref.soul != "")
{
const ESM::Creature *creature = store.creatures.search(ref->ref.soul);
@ -143,9 +166,7 @@ namespace MWClass
std::string text;
if (ref->base->name == store.gameSettings.search("sGold")->str)
info.caption += " (" + boost::lexical_cast<std::string>(ref->base->data.value) + ")";
else
if (!isGold)
{
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);

@ -41,6 +41,9 @@ namespace MWClass
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const;
///< Return the put down sound Id
virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const;
///< Return name of inventory icon.
};
}

@ -3,6 +3,8 @@
#include <memory>
#include <boost/algorithm/string.hpp>
#include <OgreSceneNode.h>
#include <components/esm/loadnpc.hpp>
@ -56,22 +58,24 @@ namespace MWClass
// NPC stats
if (!ref->base->faction.empty())
{
std::string faction = ref->base->faction;
boost::algorithm::to_lower(faction);
if(ref->base->npdt52.gold != -10)
{
data->mNpcStats.mFactionRank[ref->base->faction] = (int)ref->base->npdt52.rank;
data->mNpcStats.mFactionRank[faction] = (int)ref->base->npdt52.rank;
}
else
{
data->mNpcStats.mFactionRank[ref->base->faction] = (int)ref->base->npdt12.rank;
data->mNpcStats.mFactionRank[faction] = (int)ref->base->npdt12.rank;
}
}
// creature stats
if(ref->base->npdt52.gold != -10)
{
for (int i=0; i<27; ++i)
data->mNpcStats.mSkill[i].setBase (ref->base->npdt52.skills[i]);
// creature stats
data->mCreatureStats.mAttributes[0].set (ref->base->npdt52.strength);
data->mCreatureStats.mAttributes[1].set (ref->base->npdt52.intelligence);
data->mCreatureStats.mAttributes[2].set (ref->base->npdt52.willpower);
@ -88,10 +92,13 @@ namespace MWClass
}
else
{
//TODO: do something with npdt12 maybe:p
/// \todo do something with npdt12 maybe:p
}
// \todo add initial container content
data->mCreatureStats.mHello = ref->base->AI.hello;
data->mCreatureStats.mFight = ref->base->AI.fight;
data->mCreatureStats.mFlee = ref->base->AI.flee;
data->mCreatureStats.mAlarm = ref->base->AI.alarm;
// store
ptr.getRefData().setCustomData (data.release());
@ -108,44 +115,27 @@ 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 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.insertActorPhysics(ptr, smodel);
}
if(beast)
smodel = "meshes\\base_animkna.nif";
physics.insertActorPhysics(ptr, smodel);
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);
}
std::string Npc::getName (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
@ -325,4 +315,26 @@ namespace MWClass
return info;
}
float Npc::getCapacity (const MWWorld::Ptr& ptr) const
{
const MWMechanics::CreatureStats& stats = getCreatureStats (ptr);
return stats.mAttributes[0].getModified()*5;
}
float Npc::getEncumbrance (const MWWorld::Ptr& ptr) const
{
float weight = getContainerStore (ptr).getWeight();
const MWMechanics::CreatureStats& stats = getCreatureStats (ptr);
weight -= stats.mMagicEffects.get (MWMechanics::EffectKey (8)).mMagnitude; // feather
weight += stats.mMagicEffects.get (MWMechanics::EffectKey (7)).mMagnitude; // burden
if (weight<0)
weight = 0;
return weight;
}
}

@ -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.
@ -74,6 +68,14 @@ namespace MWClass
///< Return desired movement vector (determined based on movement settings,
/// stance and stats).
virtual float getCapacity (const MWWorld::Ptr& ptr) const;
///< Return total weight that fits into the object. Throws an exception, if the object can't
/// hold other objects.
virtual float getEncumbrance (const MWWorld::Ptr& ptr) const;
///< Returns total weight of objects inside this object (including modifications from magic
/// effects). Throws an exception, if the object can't hold other objects.
static void registerSelf();
};
}

@ -100,6 +100,14 @@ namespace MWClass
return std::string("Item Potion Down");
}
std::string Potion::getInventoryIcon (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref =
ptr.get<ESM::Potion>();
return ref->base->icon;
}
bool Potion::hasToolTip (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Potion, MWWorld::RefData> *ref =
@ -114,7 +122,7 @@ namespace MWClass
ptr.get<ESM::Potion>();
MWGui::ToolTipInfo info;
info.caption = ref->base->name;
info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount());
info.icon = ref->base->icon;
const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
@ -124,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");

@ -41,6 +41,9 @@ namespace MWClass
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const;
///< Return the put down sound Id
virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const;
///< Return name of inventory icon.
};
}

@ -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"
@ -109,6 +110,14 @@ namespace MWClass
return std::string("Item Probe Down");
}
std::string Probe::getInventoryIcon (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref =
ptr.get<ESM::Probe>();
return ref->base->icon;
}
bool Probe::hasToolTip (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Probe, MWWorld::RefData> *ref =
@ -123,7 +132,7 @@ namespace MWClass
ptr.get<ESM::Probe>();
MWGui::ToolTipInfo info;
info.caption = ref->base->name;
info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount());
info.icon = ref->base->icon;
const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
@ -146,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));
}
}

@ -45,6 +45,13 @@ namespace MWClass
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const;
///< Return the put down sound Id
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
};
}

@ -99,6 +99,14 @@ namespace MWClass
return std::string("Item Repair Down");
}
std::string Repair::getInventoryIcon (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref =
ptr.get<ESM::Repair>();
return ref->base->icon;
}
bool Repair::hasToolTip (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Repair, MWWorld::RefData> *ref =
@ -113,7 +121,7 @@ namespace MWClass
ptr.get<ESM::Repair>();
MWGui::ToolTipInfo info;
info.caption = ref->base->name;
info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount());
info.icon = ref->base->icon;
std::string text;

@ -41,6 +41,9 @@ namespace MWClass
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const;
///< Return the put down sound Id
virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const;
///< Return name of inventory icon.
};
}

@ -9,6 +9,7 @@
#include "../mwworld/ptr.hpp"
#include "../mwworld/actiontake.hpp"
#include "../mwworld/actionequip.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/world.hpp"
@ -250,6 +251,14 @@ namespace MWClass
return std::string("Item Misc Down");
}
std::string Weapon::getInventoryIcon (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
ptr.get<ESM::Weapon>();
return ref->base->icon;
}
bool Weapon::hasToolTip (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
@ -264,7 +273,7 @@ namespace MWClass
ptr.get<ESM::Weapon>();
MWGui::ToolTipInfo info;
info.caption = ref->base->name;
info.caption = ref->base->name + MWGui::ToolTips::getCountString(ptr.getRefData().getCount());
info.icon = ref->base->icon;
const ESMS::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
@ -339,4 +348,19 @@ namespace MWClass
return info;
}
std::string Weapon::getEnchantment (const MWWorld::Ptr& ptr) const
{
ESMS::LiveCellRef<ESM::Weapon, MWWorld::RefData> *ref =
ptr.get<ESM::Weapon>();
return ref->base->enchant;
}
boost::shared_ptr<MWWorld::Action> Weapon::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));
}
}

@ -55,6 +55,17 @@ namespace MWClass
virtual std::string getDownSoundId (const MWWorld::Ptr& ptr) const;
///< Return the put down sound Id
virtual std::string getInventoryIcon (const MWWorld::Ptr& ptr) const;
///< Return name of inventory icon.
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
///< @return the enchantment ID if the object is enchanted, otherwise an empty string
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
///< Generate action for using via inventory menu
};
}

@ -206,7 +206,7 @@ namespace MWDialogue
if(!NPCstats.mFactionRank.empty())
{
std::string NPCFaction = NPCstats.mFactionRank.begin()->first;
if(PCstats.mFactionRank.find(NPCFaction) != PCstats.mFactionRank.end()) sameFaction = 1;
if(PCstats.mFactionRank.find(toLower(NPCFaction)) != PCstats.mFactionRank.end()) sameFaction = 1;
}
if(!selectCompare<int,int>(comp,sameFaction,select.i)) return false;
}
@ -363,7 +363,7 @@ namespace MWDialogue
int sum = 0;
for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter)
if (iter->getCellRef().refID==name)
if (toLower(iter->getCellRef().refID) == toLower(name))
sum += iter->getRefData().getCount();
if(!selectCompare<int,int>(comp,sum,select.i)) return false;
}
@ -525,7 +525,7 @@ namespace MWDialogue
//MWWorld::Class npcClass = MWWorld::Class::get(actor);
MWMechanics::NpcStats stats = MWWorld::Class::get(actor).getNpcStats(actor);
std::map<std::string,int>::iterator it = stats.mFactionRank.find(info.npcFaction);
std::map<std::string,int>::iterator it = stats.mFactionRank.find(toLower(info.npcFaction));
if(it!=stats.mFactionRank.end())
{
//check rank
@ -542,7 +542,7 @@ namespace MWDialogue
if(!info.pcFaction.empty())
{
MWMechanics::NpcStats stats = MWWorld::Class::get(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()).getNpcStats(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
std::map<std::string,int>::iterator it = stats.mFactionRank.find(info.pcFaction);
std::map<std::string,int>::iterator it = stats.mFactionRank.find(toLower(info.pcFaction));
if(it!=stats.mFactionRank.end())
{
//check rank
@ -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,9 +635,9 @@ 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(MWWorld::Class::get (actor).getName (actor));
win->startDialogue(actor, MWWorld::Class::get (actor).getName (actor));
//setup the list of topics known by the actor. Topics who are also on the knownTopics list will be added to the GUI
updateTopics();
@ -767,6 +767,36 @@ namespace MWDialogue
}
}
// check the available services of this actor
int services = 0;
if (mActor.getTypeName() == typeid(ESM::NPC).name())
{
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* ref = mActor.get<ESM::NPC>();
if (ref->base->hasAI)
services = ref->base->AI.services;
}
else if (mActor.getTypeName() == typeid(ESM::Creature).name())
{
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData>* ref = mActor.get<ESM::Creature>();
if (ref->base->hasAI)
services = ref->base->AI.services;
}
if (services & ESM::NPC::Weapon
|| services & ESM::NPC::Armor
|| services & ESM::NPC::Clothing
|| services & ESM::NPC::Books
|| services & ESM::NPC::Ingredients
|| services & ESM::NPC::Picks
|| services & ESM::NPC::Probes
|| services & ESM::NPC::Lights
|| services & ESM::NPC::Apparatus
|| services & ESM::NPC::RepairItem
|| services & ESM::NPC::Misc)
win->setShowTrade(true);
else
win->setShowTrade(false);
// sort again, because the previous sort was case-sensitive
keywordList.sort(stringCompareNoCase);
win->setKeywords(keywordList);
@ -813,7 +843,7 @@ namespace MWDialogue
void DialogueManager::goodbyeSelected()
{
MWBase::Environment::get().getInputManager()->setGuiMode(MWGui::GM_Game);
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue);
}
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.removeGuiMode(GM_Alchemy);
mWindowManager.removeGuiMode(GM_Inventory);
}
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

@ -27,7 +27,6 @@ BirthDialog::BirthDialog(WindowManager& parWindowManager)
MyGUI::ButtonPtr backButton;
getWidget(backButton, "BackButton");
backButton->setCaption(mWindowManager.getGameSettingString("sBack", ""));
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onBackClicked);
MyGUI::ButtonPtr okButton;

@ -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;
@ -52,7 +53,7 @@ void BookWindow::open (MWWorld::Ptr book)
clearPages();
mCurrentPage = 0;
MWBase::Environment::get().getSoundManager()->playSound3D (book, "book open", 1.0, 1.0);
MWBase::Environment::get().getSoundManager()->playSound ("book open", 1.0, 1.0);
ESMS::LiveCellRef<ESM::Book, MWWorld::RefData> *ref =
mBook.get<ESM::Book>();
@ -77,23 +78,31 @@ void BookWindow::open (MWWorld::Ptr book)
}
updatePages();
setTakeButtonShow(true);
}
void BookWindow::setTakeButtonShow(bool show)
{
mTakeButton->setVisible(show);
}
void BookWindow::onCloseButtonClicked (MyGUI::Widget* _sender)
{
MWBase::Environment::get().getSoundManager()->playSound3D (mBook, "book close", 1.0, 1.0);
// 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.removeGuiMode(GM_Book);
}
void BookWindow::onTakeButtonClicked (MyGUI::Widget* _sender)
{
MWBase::Environment::get().getSoundManager()->playSound3D (mBook, "Item Book Up", 1.0, 1.0, MWSound::Play_NoTrack);
MWBase::Environment::get().getSoundManager()->playSound ("Item Book Up", 1.0, 1.0, MWSound::Play_NoTrack);
MWWorld::ActionTake take(mBook);
take.execute();
MWBase::Environment::get().getInputManager()->setGuiMode (GM_Game);
mWindowManager.removeGuiMode(GM_Book);
}
void BookWindow::onNextPageButtonClicked (MyGUI::Widget* _sender)

@ -11,7 +11,9 @@ namespace MWGui
{
public:
BookWindow(WindowManager& parWindowManager);
void open(MWWorld::Ptr book);
void setTakeButtonShow(bool show);
protected:
void 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)
@ -173,7 +223,6 @@ void CharacterCreation::spawnDialog(const char id)
mWM->removeDialog(mBirthSignDialog);
mBirthSignDialog = new BirthDialog(*mWM);
mBirthSignDialog->setNextButtonShow(mCreationStage >= CSE_BirthSignChosen);
mBirthSignDialog->setBirthId(mPlayerBirthSignId);
mBirthSignDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogDone);
mBirthSignDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogBack);
mBirthSignDialog->open();
@ -210,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);
@ -254,7 +305,7 @@ void CharacterCreation::onReviewDialogDone(WindowBase* parWindow)
if (mReviewDialog)
mWM->removeDialog(mReviewDialog);
mWM->setGuiMode(GM_Game);
mWM->popGuiMode();
}
void CharacterCreation::onReviewDialogBack()
@ -262,7 +313,7 @@ void CharacterCreation::onReviewDialogBack()
if (mReviewDialog)
mWM->removeDialog(mReviewDialog);
mWM->setGuiMode(GM_Birth);
mWM->pushGuiMode(GM_Birth);
}
void CharacterCreation::onReviewActivateDialog(int parDialog)
@ -271,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);
};
}
@ -305,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();
}
}
@ -325,7 +384,8 @@ void CharacterCreation::onPickClassDialogBack()
mWM->removeDialog(mPickClassDialog);
}
mWM->setGuiMode(GM_Class);
mWM->popGuiMode();
mWM->pushGuiMode(GM_Class);
}
void CharacterCreation::onClassChoice(int _index)
@ -335,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;
};
@ -364,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();
}
}
@ -384,7 +452,8 @@ void CharacterCreation::onRaceDialogBack()
mWM->removeDialog(mRaceDialog);
}
mWM->setGuiMode(GM_Name);
mWM->popGuiMode();
mWM->pushGuiMode(GM_Name);
}
void CharacterCreation::onRaceDialogDone(WindowBase* parWindow)
@ -399,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();
}
}
@ -414,18 +489,20 @@ void CharacterCreation::onBirthSignDialogDone(WindowBase* parWindow)
if (mBirthSignDialog)
{
mPlayerBirthSignId = mBirthSignDialog->getBirthId();
mWM->setBirthSign(mPlayerBirthSignId);
if (!mPlayerBirthSignId.empty())
MWBase::Environment::get().getMechanicsManager()->setPlayerBirthsign(mPlayerBirthSignId);
mWM->removeDialog(mBirthSignDialog);
}
if (mCreationStage >= CSE_BirthSignChosen)
mWM->setGuiMode(GM_Review);
{
mWM->popGuiMode();
mWM->pushGuiMode(GM_Review);
}
else
{
mCreationStage = CSE_BirthSignChosen;
mWM->setGuiMode(GM_Game);
mWM->popGuiMode();
}
}
@ -437,7 +514,8 @@ void CharacterCreation::onBirthSignDialogBack()
mWM->removeDialog(mBirthSignDialog);
}
mWM->setGuiMode(GM_Class);
mWM->popGuiMode();
mWM->pushGuiMode(GM_Class);
}
void CharacterCreation::onCreateClassDialogDone(WindowBase* parWindow)
@ -472,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();
}
}
@ -487,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)
@ -498,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;
}
@ -583,7 +669,8 @@ void CharacterCreation::showClassQuestionDialog()
if (mGenerateClassStep > sGenerateClassSteps.size())
{
mWM->setGuiMode(GM_Class);
mWM->popGuiMode();
mWM->pushGuiMode(GM_Class);
return;
}
@ -612,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,15 +708,24 @@ void CharacterCreation::onGenerateClassDone(WindowBase* parWindow)
if (mGenerateClassResultDialog)
mWM->removeDialog(mGenerateClassResultDialog);
MWBase::Environment::get().getMechanicsManager()->setPlayerClass(mGenerateClass);
const ESM::Class *klass = MWBase::Environment::get().getWorld()->getStore().classes.find(mGenerateClass);
mPlayerClass = *klass;
mWM->setPlayerClass(mPlayerClass);
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();
}
}
@ -636,7 +733,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
@ -28,7 +31,6 @@ GenerateClassResultDialog::GenerateClassResultDialog(WindowManager& parWindowMan
MyGUI::ButtonPtr backButton;
getWidget(backButton, "BackButton");
backButton->setCaption(mWindowManager.getGameSettingString("sBack", ""));
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &GenerateClassResultDialog::onBackClicked);
MyGUI::ButtonPtr okButton;
@ -80,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;
@ -111,7 +109,6 @@ PickClassDialog::PickClassDialog(WindowManager& parWindowManager)
MyGUI::ButtonPtr backButton;
getWidget(backButton, "BackButton");
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onBackClicked);
backButton->setCaption(mWindowManager.getGameSettingString("sBack", ""));
MyGUI::ButtonPtr okButton;
getWidget(okButton, "OKButton");
@ -233,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");
@ -389,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:"));
@ -432,7 +434,6 @@ CreateClassDialog::CreateClassDialog(WindowManager& parWindowManager)
MyGUI::ButtonPtr backButton;
getWidget(backButton, "BackButton");
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CreateClassDialog::onBackClicked);
backButton->setCaption(mWindowManager.getGameSettingString("sBack", ""));
MyGUI::ButtonPtr okButton;
getWidget(okButton, "OKButton");
@ -454,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()
@ -464,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();
@ -502,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;
}
@ -542,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);
@ -565,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);
@ -595,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);
@ -628,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)
@ -643,6 +687,7 @@ void CreateClassDialog::onDescriptionEntered(WindowBase* parWindow)
{
description = descDialog->getTextInput();
mWindowManager.removeDialog(descDialog);
descDialog = 0;
}
void CreateClassDialog::onOkClicked(MyGUI::Widget* _sender)
@ -668,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
@ -724,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;
@ -732,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
@ -813,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());
}
}
@ -822,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
@ -856,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

@ -34,7 +34,7 @@ namespace MWGui
typedef delegates::CMultiDelegate1<int> EventHandle_Int;
/** Event : Button was clicked.\n
signature : void method(MyGUI::WidgetPtr widget, int index)\n
signature : void method(int index)\n
*/
EventHandle_Int eventButtonSelected;
@ -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

@ -0,0 +1,681 @@
#include "container.hpp"
#include <cmath>
#include <algorithm>
#include <iterator>
#include <assert.h>
#include <iostream>
#include <boost/lexical_cast.hpp>
#include "../mwbase/environment.hpp"
#include "../mwworld/manualref.hpp"
#include "../mwworld/world.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
#include "../mwclass/container.hpp"
#include "../mwinput/inputmanager.hpp"
#include "../mwsound/soundmanager.hpp"
#include "window_manager.hpp"
#include "widgets.hpp"
#include "countdialog.hpp"
#include "tradewindow.hpp"
#include "inventorywindow.hpp"
using namespace MWGui;
using namespace Widgets;
namespace
{
bool compareType(std::string type1, std::string type2)
{
// this defines the sorting order of types. types that are first in the vector, appear before other types.
std::vector<std::string> mapping;
mapping.push_back( typeid(ESM::Weapon).name() );
mapping.push_back( typeid(ESM::Armor).name() );
mapping.push_back( typeid(ESM::Clothing).name() );
mapping.push_back( typeid(ESM::Potion).name() );
mapping.push_back( typeid(ESM::Ingredient).name() );
mapping.push_back( typeid(ESM::Apparatus).name() );
mapping.push_back( typeid(ESM::Book).name() );
mapping.push_back( typeid(ESM::Light).name() );
mapping.push_back( typeid(ESM::Miscellaneous).name() );
mapping.push_back( typeid(ESM::Tool).name() );
mapping.push_back( typeid(ESM::Repair).name() );
mapping.push_back( typeid(ESM::Probe).name() );
assert( std::find(mapping.begin(), mapping.end(), type1) != mapping.end() );
assert( std::find(mapping.begin(), mapping.end(), type2) != mapping.end() );
return std::find(mapping.begin(), mapping.end(), type1) < std::find(mapping.begin(), mapping.end(), type2);
}
bool sortItems(MWWorld::Ptr left, MWWorld::Ptr right)
{
if (left.getTypeName() == right.getTypeName())
{
int cmp = MWWorld::Class::get(left).getName(left).compare(
MWWorld::Class::get(right).getName(right));
return cmp < 0;
}
else
{
return compareType(left.getTypeName(), right.getTypeName());
}
}
}
ContainerBase::ContainerBase(DragAndDrop* dragAndDrop) :
mDragAndDrop(dragAndDrop),
mFilter(ContainerBase::Filter_All)
{
}
void ContainerBase::setWidgets(Widget* containerWidget, ScrollView* itemView)
{
mContainerWidget = containerWidget;
mItemView = itemView;
mContainerWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerBase::onContainerClicked);
mContainerWidget->eventMouseWheel += MyGUI::newDelegate(this, &ContainerWindow::onMouseWheel);
}
ContainerBase::~ContainerBase()
{
}
void ContainerBase::onSelectedItem(MyGUI::Widget* _sender)
{
mSelectedItem = _sender;
if (mDragAndDrop && !isTrading())
{
if(!mDragAndDrop->mIsOnDragAndDrop)
{
MWWorld::Ptr object = (*_sender->getUserData<MWWorld::Ptr>());
int count = object.getRefData().getCount();
if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1)
{
startDragItem(_sender, count);
}
else if (MyGUI::InputManager::getInstance().isControlPressed())
{
startDragItem(_sender, 1);
}
else
{
std::string message = MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTake")->str;
CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog();
dialog->open(MWWorld::Class::get(object).getName(object), message, count);
dialog->eventOkClicked.clear();
dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::startDragItem);
}
}
else
onContainerClicked(mContainerWidget);
}
else if (isTrading())
{
MWWorld::Ptr object = (*_sender->getUserData<MWWorld::Ptr>());
int count = object.getRefData().getCount();
if (isInventory())
{
// the player is trying to sell an item, check if the merchant accepts it
// also, don't allow selling gold (let's be better than Morrowind at this, can we?)
if (!MWBase::Environment::get().getWindowManager()->getTradeWindow()->npcAcceptsItem(object)
|| MWWorld::Class::get(object).getName(object) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str)
{
// user notification "i don't buy this item"
MWBase::Environment::get().getWindowManager()->
messageBox(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarterDialog4")->str, std::vector<std::string>());
return;
}
}
bool buying = isTradeWindow(); // buying or selling?
std::string message = buying ? MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sQuanityMenuMessage02")->str
: MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sQuanityMenuMessage01")->str;
if (std::find(mBoughtItems.begin(), mBoughtItems.end(), object) != mBoughtItems.end())
{
if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1)
{
sellAlreadyBoughtItem(NULL, count);
}
else if (MyGUI::InputManager::getInstance().isControlPressed())
{
sellAlreadyBoughtItem(NULL, 1);
}
else
{
CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog();
dialog->open(MWWorld::Class::get(object).getName(object), message, count);
dialog->eventOkClicked.clear();
dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::sellAlreadyBoughtItem);
}
}
else
{
if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1)
{
sellItem(NULL, count);
}
else if (MyGUI::InputManager::getInstance().isControlPressed())
{
sellItem(NULL, 1);
}
else
{
CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog();
dialog->open(MWWorld::Class::get(object).getName(object), message, count);
dialog->eventOkClicked.clear();
dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::sellItem);
}
}
}
else
{
onSelectedItemImpl(*_sender->getUserData<MWWorld::Ptr>());
}
}
void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count)
{
MWWorld::Ptr object = *mSelectedItem->getUserData<MWWorld::Ptr>();
if (isInventory())
{
MWBase::Environment::get().getWindowManager()->getTradeWindow()->addItem(object, count);
MWBase::Environment::get().getWindowManager()->getTradeWindow()->buyFromNpc(object, count);
MWBase::Environment::get().getWindowManager()->getTradeWindow()->drawItems();
}
else
{
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->addItem(object, count);
MWBase::Environment::get().getWindowManager()->getTradeWindow()->sellToNpc(object, count);
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems();
}
std::string sound = MWWorld::Class::get(object).getUpSoundId(object);
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
drawItems();
}
void ContainerBase::sellItem(MyGUI::Widget* _sender, int count)
{
MWWorld::Ptr object = *mSelectedItem->getUserData<MWWorld::Ptr>();
if (isInventory())
{
MWBase::Environment::get().getWindowManager()->getTradeWindow()->addBarteredItem(object, count);
MWBase::Environment::get().getWindowManager()->getTradeWindow()->buyFromNpc(object, count);
MWBase::Environment::get().getWindowManager()->getTradeWindow()->drawItems();
}
else
{
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->addBarteredItem(object, count);
MWBase::Environment::get().getWindowManager()->getTradeWindow()->sellToNpc(object, count);
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems();
}
std::string sound = MWWorld::Class::get(object).getUpSoundId(object);
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
drawItems();
}
void ContainerBase::startDragItem(MyGUI::Widget* _sender, int count)
{
mDragAndDrop->mIsOnDragAndDrop = true;
mSelectedItem->detachFromWidget();
mSelectedItem->attachToWidget(mDragAndDrop->mDragAndDropWidget);
MWWorld::Ptr object = *mSelectedItem->getUserData<MWWorld::Ptr>();
_unequipItem(object);
mDragAndDrop->mDraggedCount = count;
mDragAndDrop->mDraggedFrom = this;
std::string sound = MWWorld::Class::get(object).getUpSoundId(object);
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
mDragAndDrop->mDraggedWidget = mSelectedItem;
static_cast<MyGUI::ImageBox*>(mSelectedItem)->setImageTexture(""); // remove the background texture (not visible during drag)
static_cast<MyGUI::TextBox*>(mSelectedItem->getChildAt(0)->getChildAt(0))->setCaption(
getCountString(mDragAndDrop->mDraggedCount));
drawItems();
MWBase::Environment::get().getWindowManager()->setDragDrop(true);
}
void ContainerBase::onContainerClicked(MyGUI::Widget* _sender)
{
if (mDragAndDrop == NULL) return;
if(mDragAndDrop->mIsOnDragAndDrop) //drop item here
{
MWWorld::Ptr object = *mDragAndDrop->mDraggedWidget->getUserData<MWWorld::Ptr>();
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 (mPtr.getTypeName() == typeid(ESM::Container).name())
{
ESMS::LiveCellRef<ESM::Container, MWWorld::RefData>* ref = mPtr.get<ESM::Container>();
if (ref->base->flags & ESM::Container::Organic)
{
// user notification
MWBase::Environment::get().getWindowManager()->
messageBox(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sContentsMessage2")->str, std::vector<std::string>());
return;
}
}
int origCount = object.getRefData().getCount();
// check that we don't exceed the allowed weight (only for containers, not for inventory)
if (!isInventory())
{
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(mPtr).getEncumbrance(mPtr);
if (curWeight > capacity)
{
it->getRefData().setCount(0);
object.getRefData().setCount(origCount);
// user notification
MWBase::Environment::get().getWindowManager()->
messageBox(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sContentsMessage3")->str, std::vector<std::string>());
return;
}
else
{
object.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount);
}
std::cout << "container weight " << curWeight << "/" << capacity << std::endl;
}
else
{
object.getRefData().setCount (mDragAndDrop->mDraggedCount);
containerStore.add(object);
object.getRefData().setCount (origCount - mDragAndDrop->mDraggedCount);
}
}
mDragAndDrop->mIsOnDragAndDrop = false;
MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget);
drawItems();
mDragAndDrop->mDraggedFrom->drawItems();
MWBase::Environment::get().getWindowManager()->setDragDrop(false);
std::string sound = MWWorld::Class::get(object).getDownSoundId(object);
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
}
}
void ContainerBase::onMouseWheel(MyGUI::Widget* _sender, int _rel)
{
if (mItemView->getViewOffset().left + _rel*0.3 > 0)
mItemView->setViewOffset(MyGUI::IntPoint(0, 0));
else
mItemView->setViewOffset(MyGUI::IntPoint(mItemView->getViewOffset().left + _rel*0.3, 0));
}
void ContainerBase::setFilter(ContainerBase::Filter filter)
{
mFilter = filter;
drawItems();
}
void ContainerBase::openContainer(MWWorld::Ptr container)
{
mPtr = container;
}
void ContainerBase::drawItems()
{
while (mContainerWidget->getChildCount())
{
MyGUI::Gui::getInstance().destroyWidget(mContainerWidget->getChildAt(0));
}
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
int x = 0;
int y = 0;
int maxHeight = mItemView->getSize().height - 58;
bool onlyMagic = false;
int categories;
if (mFilter == Filter_All)
categories = MWWorld::ContainerStore::Type_All;
else if (mFilter == Filter_Weapon)
categories = MWWorld::ContainerStore::Type_Weapon;
else if (mFilter == Filter_Apparel)
categories = MWWorld::ContainerStore::Type_Clothing + MWWorld::ContainerStore::Type_Armor;
else if (mFilter == Filter_Magic)
{
categories = MWWorld::ContainerStore::Type_Clothing + MWWorld::ContainerStore::Type_Armor
+ MWWorld::ContainerStore::Type_Weapon + MWWorld::ContainerStore::Type_Book
+ MWWorld::ContainerStore::Type_Potion;
onlyMagic = true;
}
else if (mFilter == Filter_Misc)
{
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_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
std::vector< std::pair<MWWorld::Ptr, ItemState> > items;
std::vector<MWWorld::Ptr> equippedItems = getEquippedItems();
// add bought items (always at the beginning)
std::vector<MWWorld::Ptr> boughtItems;
for (MWWorld::ContainerStoreIterator it (mBoughtItems.begin()); it!=mBoughtItems.end(); ++it)
{
boughtItems.push_back(*it);
}
std::sort(boughtItems.begin(), boughtItems.end(), sortItems);
for (std::vector<MWWorld::Ptr>::iterator it=boughtItems.begin();
it != boughtItems.end(); ++it)
{
items.push_back( std::make_pair(*it, ItemState_Barter) );
}
// filter out the equipped items of categories we don't want
std::vector<MWWorld::Ptr> unwantedItems = equippedItems;
for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter)
{
std::vector<MWWorld::Ptr>::iterator found = std::find(unwantedItems.begin(), unwantedItems.end(), *iter);
if (found != unwantedItems.end())
{
unwantedItems.erase(found);
}
}
// now erase everything that's still in unwantedItems.
for (std::vector<MWWorld::Ptr>::iterator it=unwantedItems.begin();
it != unwantedItems.end(); ++it)
{
std::vector<MWWorld::Ptr>::iterator found = std::find(equippedItems.begin(), equippedItems.end(), *it);
assert(found != equippedItems.end());
equippedItems.erase(found);
}
// and add the items that are left (= have the correct category)
if (!ignoreEquippedItems())
{
for (std::vector<MWWorld::Ptr>::const_iterator it=equippedItems.begin();
it != equippedItems.end(); ++it)
{
items.push_back( std::make_pair(*it, ItemState_Equipped) );
}
}
std::vector<MWWorld::Ptr> ignoreItems = itemsToIgnore();
// now add the regular items
std::vector<MWWorld::Ptr> regularItems;
for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter)
{
if (std::find(equippedItems.begin(), equippedItems.end(), *iter) == equippedItems.end()
&& std::find(ignoreItems.begin(), ignoreItems.end(), *iter) == ignoreItems.end()
&& std::find(mBoughtItems.begin(), mBoughtItems.end(), *iter) == mBoughtItems.end())
regularItems.push_back(*iter);
}
// sort them and add
std::sort(regularItems.begin(), regularItems.end(), sortItems);
for (std::vector<MWWorld::Ptr>::const_iterator it=regularItems.begin(); it!=regularItems.end(); ++it)
{
items.push_back( std::make_pair(*it, ItemState_Normal) );
}
for (std::vector< std::pair<MWWorld::Ptr, ItemState> >::const_iterator it=items.begin();
it != items.end(); ++it)
{
const MWWorld::Ptr* iter = &((*it).first);
int displayCount = iter->getRefData().getCount();
if (mDragAndDrop != NULL && mDragAndDrop->mIsOnDragAndDrop && *iter == *mDragAndDrop->mDraggedWidget->getUserData<MWWorld::Ptr>())
{
displayCount -= mDragAndDrop->mDraggedCount;
}
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);
// background widget (for the "equipped" frame and magic item background image)
bool isMagic = (MWWorld::Class::get(*iter).getEnchantment(*iter) != "");
MyGUI::ImageBox* backgroundWidget = mContainerWidget->createWidget<ImageBox>("ImageBox", MyGUI::IntCoord(x, y, 42, 42), MyGUI::Align::Default);
backgroundWidget->setUserString("ToolTipType", "ItemPtr");
backgroundWidget->setUserData(*iter);
std::string backgroundTex = "textures\\menu_icon";
if (isMagic)
backgroundTex += "_magic";
if (it->second == ItemState_Normal)
{
if (!isMagic)
backgroundTex = "";
}
else if (it->second == ItemState_Equipped)
{
backgroundTex += "_equip";
}
else if (it->second == ItemState_Barter)
{
backgroundTex += "_barter";
}
if (backgroundTex != "")
backgroundTex += ".dds";
backgroundWidget->setImageTexture(backgroundTex);
if (it->second == ItemState_Barter && !isMagic)
backgroundWidget->setProperty("ImageCoord", "2 2 42 42");
else
backgroundWidget->setProperty("ImageCoord", "0 0 42 42");
backgroundWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerBase::onSelectedItem);
backgroundWidget->eventMouseWheel += MyGUI::newDelegate(this, &ContainerBase::onMouseWheel);
// image
ImageBox* image = backgroundWidget->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(displayCount));
y += 42;
if (y > maxHeight)
{
x += 42;
y = 0;
}
}
}
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)
{
if (count == 1)
return "";
if (count > 9999)
return boost::lexical_cast<std::string>(int(count/1000.f)) + "k";
else
return boost::lexical_cast<std::string>(count);
}
void ContainerBase::addBarteredItem(MWWorld::Ptr item, int count)
{
int origCount = item.getRefData().getCount();
item.getRefData().setCount(count);
MWWorld::ContainerStoreIterator it = mBoughtItems.add(item);
item.getRefData().setCount(origCount - count);
}
void ContainerBase::addItem(MWWorld::Ptr item, int count)
{
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
int origCount = item.getRefData().getCount();
item.getRefData().setCount(count);
MWWorld::ContainerStoreIterator it = containerStore.add(item);
item.getRefData().setCount(origCount - count);
}
void ContainerBase::transferBoughtItems()
{
MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
for (MWWorld::ContainerStoreIterator it(mBoughtItems.begin()); it != mBoughtItems.end(); ++it)
{
containerStore.add(*it);
}
}
void ContainerBase::returnBoughtItems(MWWorld::ContainerStore& store)
{
for (MWWorld::ContainerStoreIterator it(mBoughtItems.begin()); it != mBoughtItems.end(); ++it)
{
store.add(*it);
}
}
MWWorld::ContainerStore& ContainerBase::getContainerStore()
{
MWWorld::ContainerStore& store = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
return store;
}
// ------------------------------------------------------------------------------------------------
ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop)
: ContainerBase(dragAndDrop)
, WindowBase("openmw_container_window_layout.xml", parWindowManager)
{
getWidget(mTakeButton, "TakeButton");
getWidget(mCloseButton, "CloseButton");
MyGUI::ScrollView* itemView;
MyGUI::Widget* containerWidget;
getWidget(containerWidget, "Items");
getWidget(itemView, "ItemView");
setWidgets(containerWidget, itemView);
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onCloseButtonClicked);
mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked);
// adjust buttons size to fit text
int closeButtonWidth = mCloseButton->getTextSize().width+24;
int takeButtonWidth = mTakeButton->getTextSize().width+24;
mCloseButton->setCoord(600-20-closeButtonWidth, mCloseButton->getCoord().top, closeButtonWidth, mCloseButton->getCoord().height);
mTakeButton->setCoord(600-20-closeButtonWidth-takeButtonWidth-8, mTakeButton->getCoord().top, takeButtonWidth, mTakeButton->getCoord().height);
int w = MyGUI::RenderManager::getInstance().getViewSize().width;
//int h = MyGUI::RenderManager::getInstance().getViewSize().height;
static_cast<MyGUI::Window*>(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &ContainerWindow::onWindowResize);
setCoord(w-600,0,600,300);
}
ContainerWindow::~ContainerWindow()
{
}
void ContainerWindow::onWindowResize(MyGUI::Window* window)
{
drawItems();
}
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()->removeGuiMode(GM_Container);
}
}
void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender)
{
if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop)
{
// transfer everything into the player's inventory
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);
int i=0;
for (MWWorld::ContainerStoreIterator iter (containerStore.begin()); iter!=containerStore.end(); ++iter)
{
playerStore.add(*iter);
if (i==0)
{
// play the sound of the first object
std::string sound = MWWorld::Class::get(*iter).getUpSoundId(*iter);
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
}
++i;
}
containerStore.clear();
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
}
}
void ContainerWindow::onReferenceUnavailable()
{
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
}

@ -0,0 +1,147 @@
#ifndef MGUI_CONTAINER_H
#define MGUI_CONTAINER_H
#include <components/esm_store/store.hpp>
#include "window_base.hpp"
#include "referenceinterface.hpp"
#include "../mwclass/container.hpp"
#include "../mwworld/ptr.hpp"
#include "../mwworld/containerstore.hpp"
namespace MWWorld
{
class Environment;
}
namespace MyGUI
{
class Gui;
class Widget;
}
namespace MWGui
{
class WindowManager;
class ContainerWindow;
class ContainerBase;
}
namespace MWGui
{
class DragAndDrop
{
public:
bool mIsOnDragAndDrop;
MyGUI::Widget* mDraggedWidget;
MyGUI::Widget* mDragAndDropWidget;
ContainerBase* mDraggedFrom;
int mDraggedCount;
};
class ContainerBase : public ReferenceInterface
{
public:
ContainerBase(DragAndDrop* dragAndDrop);
virtual ~ContainerBase();
enum Filter
{
Filter_All = 0x01,
Filter_Weapon = 0x02,
Filter_Apparel = 0x03,
Filter_Magic = 0x04,
Filter_Misc = 0x05,
Filter_Ingredients = 0x06
};
enum ItemState
{
ItemState_Normal = 0x01,
ItemState_Equipped = 0x02,
ItemState_Barter = 0x03
};
void setWidgets(MyGUI::Widget* containerWidget, MyGUI::ScrollView* itemView); ///< only call once
void addBarteredItem(MWWorld::Ptr item, int count);
void addItem(MWWorld::Ptr item, int count);
void transferBoughtItems(); ///< transfer bought items into the inventory
void returnBoughtItems(MWWorld::ContainerStore& store); ///< return bought items into the specified ContainerStore
MWWorld::ContainerStore& getContainerStore();
MWWorld::ContainerStore& getBoughtItems() { return mBoughtItems; }
void openContainer(MWWorld::Ptr container);
void setFilter(Filter filter); ///< set category filter
void drawItems();
protected:
MyGUI::ScrollView* mItemView;
MyGUI::Widget* mContainerWidget;
MyGUI::Widget* mSelectedItem;
DragAndDrop* mDragAndDrop;
Filter mFilter;
// bought items are put in a separate ContainerStore so that they don't stack with other (not bought) items.
MWWorld::ContainerStore mBoughtItems;
void onSelectedItem(MyGUI::Widget* _sender);
void onContainerClicked(MyGUI::Widget* _sender);
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
/// start dragging an item (drag & drop)
void startDragItem(MyGUI::Widget* _sender, int count);
/// sell an item from this container
void sellItem(MyGUI::Widget* _sender, int count);
/// sell an item from this container, that was previously just bought
void sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count);
std::string getCountString(const int count);
virtual bool isTradeWindow() { return false; }
virtual bool isInventory() { return false; }
virtual std::vector<MWWorld::Ptr> getEquippedItems() { return std::vector<MWWorld::Ptr>(); }
virtual void _unequipItem(MWWorld::Ptr item) { ; }
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
{
public:
ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop);
virtual ~ContainerWindow();
void open(MWWorld::Ptr container);
protected:
MyGUI::Button* mTakeButton;
MyGUI::Button* mCloseButton;
void onWindowResize(MyGUI::Window* window);
void onCloseButtonClicked(MyGUI::Widget* _sender);
void onTakeAllButtonClicked(MyGUI::Widget* _sender);
virtual void onReferenceUnavailable();
};
}
#endif // CONTAINER_H

@ -0,0 +1,108 @@
#include "countdialog.hpp"
#include <boost/lexical_cast.hpp>
#include "../mwbase/environment.hpp"
#include "../mwworld/world.hpp"
namespace MWGui
{
CountDialog::CountDialog(WindowManager& parWindowManager) :
WindowBase("openmw_count_window_layout.xml", parWindowManager)
{
getWidget(mSlider, "CountSlider");
getWidget(mItemEdit, "ItemEdit");
getWidget(mItemText, "ItemText");
getWidget(mLabelText, "LabelText");
getWidget(mOkButton, "OkButton");
getWidget(mCancelButton, "CancelButton");
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onCancelButtonClicked);
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onOkButtonClicked);
mItemEdit->eventEditTextChange += MyGUI::newDelegate(this, &CountDialog::onEditTextChange);
mSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &CountDialog::onSliderMoved);
}
void CountDialog::open(const std::string& item, const std::string& message, const int maxCount)
{
setVisible(true);
mLabelText->setCaption(message);
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
mSlider->setScrollRange(maxCount);
mItemText->setCaption(item);
int width = std::max(mItemText->getTextSize().width + 128, 320);
setCoord(viewSize.width/2 - width/2,
viewSize.height/2 - mMainWidget->getHeight()/2,
width,
mMainWidget->getHeight());
// make other gui elements inaccessible while this dialog is open
MyGUI::InputManager::getInstance().addWidgetModal(mMainWidget);
MyGUI::InputManager::getInstance().setKeyFocusWidget(mItemEdit);
mSlider->setScrollPosition(maxCount-1);
mItemEdit->setCaption(boost::lexical_cast<std::string>(maxCount));
int okButtonWidth = mOkButton->getTextSize().width + 24;
mOkButton->setCoord(width - 30 - okButtonWidth,
mOkButton->getTop(),
okButtonWidth,
mOkButton->getHeight());
int cancelButtonWidth = mCancelButton->getTextSize().width + 24;
mCancelButton->setCoord(width - 30 - okButtonWidth - cancelButtonWidth - 8,
mCancelButton->getTop(),
cancelButtonWidth,
mCancelButton->getHeight());
}
void CountDialog::onCancelButtonClicked(MyGUI::Widget* _sender)
{
close();
}
void CountDialog::onOkButtonClicked(MyGUI::Widget* _sender)
{
eventOkClicked(NULL, mSlider->getScrollPosition()+1);
close();
}
void CountDialog::onEditTextChange(MyGUI::EditBox* _sender)
{
if (_sender->getCaption() == "")
return;
unsigned int count;
try
{
count = boost::lexical_cast<unsigned int>(_sender->getCaption());
}
catch (std::bad_cast&)
{
count = 1;
}
if (count > mSlider->getScrollRange())
{
count = mSlider->getScrollRange();
}
mSlider->setScrollPosition(count-1);
onSliderMoved(mSlider, count-1);
}
void CountDialog::onSliderMoved(MyGUI::ScrollBar* _sender, size_t _position)
{
mItemEdit->setCaption(boost::lexical_cast<std::string>(_position+1));
}
void CountDialog::close()
{
setVisible(false);
MyGUI::InputManager::getInstance().removeWidgetModal(mMainWidget);
}
}

@ -0,0 +1,39 @@
#ifndef MWGUI_COUNTDIALOG_H
#define MWGUI_COUNTDIALOG_H
#include "window_base.hpp"
namespace MWGui
{
class CountDialog : public WindowBase
{
public:
CountDialog(WindowManager& parWindowManager);
void open(const std::string& item, const std::string& message, const int maxCount);
typedef MyGUI::delegates::CMultiDelegate2<MyGUI::Widget*, int> EventHandle_WidgetInt;
/** Event : Ok button was clicked.\n
signature : void method(MyGUI::Widget* _sender, int _count)\n
*/
EventHandle_WidgetInt eventOkClicked;
private:
MyGUI::ScrollBar* mSlider;
MyGUI::EditBox* mItemEdit;
MyGUI::TextBox* mItemText;
MyGUI::TextBox* mLabelText;
MyGUI::Button* mOkButton;
MyGUI::Button* mCancelButton;
void onCancelButtonClicked(MyGUI::Widget* _sender);
void onOkButtonClicked(MyGUI::Widget* _sender);
void onEditTextChange(MyGUI::EditBox* _sender);
void onSliderMoved(MyGUI::ScrollBar* _sender, size_t _position);
void close();
};
}
#endif

@ -1,11 +1,4 @@
#include "dialogue.hpp"
#include "dialogue_history.hpp"
#include "window_manager.hpp"
#include "widgets.hpp"
#include "list.hpp"
#include "components/esm_store/store.hpp"
#include "../mwbase/environment.hpp"
#include "../mwdialogue/dialoguemanager.hpp"
#include <assert.h>
#include <iostream>
@ -14,6 +7,18 @@
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <components/esm_store/store.hpp>
#include "../mwbase/environment.hpp"
#include "../mwdialogue/dialoguemanager.hpp"
#include "dialogue_history.hpp"
#include "window_manager.hpp"
#include "widgets.hpp"
#include "list.hpp"
#include "tradewindow.hpp"
#include "inventorywindow.hpp"
using namespace MWGui;
using namespace Widgets;
@ -40,6 +45,7 @@ std::string::size_type find_str_ci(const std::string& str, const std::string& su
DialogueWindow::DialogueWindow(WindowManager& parWindowManager)
: WindowBase("openmw_dialogue_window_layout.xml", parWindowManager)
, mEnabled(true)
, mShowTrade(false)
{
// Centre dialog
center();
@ -58,14 +64,11 @@ DialogueWindow::DialogueWindow(WindowManager& parWindowManager)
//Topics list
getWidget(topicsList, "TopicsList");
//topicsList->eventListSelectAccept += MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
topicsList->eventItemSelected += MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
//topicsList->eventListChangePosition += MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
MyGUI::ButtonPtr byeButton;
getWidget(byeButton, "ByeButton");
byeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DialogueWindow::onByeClicked);
byeButton->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGoodbye")->str);
getWidget(pDispositionBar, "Disposition");
getWidget(pDispositionText,"DispositionText");
@ -109,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();
@ -127,24 +121,46 @@ void DialogueWindow::onSelectTopic(std::string topic)
{
if (!mEnabled) return;
MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_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.pushGuiMode(GM_Barter);
mWindowManager.getTradeWindow()->startTrade(mPtr);
}
else
MWBase::Environment::get().getDialogueManager()->keywordSelected(lower_string(topic));
}
void DialogueWindow::startDialogue(std::string npcName)
void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName)
{
mEnabled = true;
mPtr = actor;
topicsList->setEnabled(true);
static_cast<MyGUI::Window*>(mMainWidget)->setCaption(npcName);
adjustWindowCaption();
setTitle(npcName);
topicsList->clear();
history->eraseText(0,history->getTextLength());
updateOptions();
}
void DialogueWindow::setKeywords(std::list<std::string> keyWords)
{
topicsList->clear();
for(std::list<std::string>::iterator it = keyWords.begin(); it != keyWords.end(); it++)
bool anyService = mShowTrade;
if (mShowTrade)
topicsList->addItem(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarter")->str);
if (anyService)
topicsList->addSeparator();
for(std::list<std::string>::iterator it = keyWords.begin(); it != keyWords.end(); ++it)
{
topicsList->addItem(*it);
}
topicsList->adjustSize();
}
void DialogueWindow::removeKeyword(std::string keyWord)
@ -152,8 +168,8 @@ void DialogueWindow::removeKeyword(std::string keyWord)
if(topicsList->hasItem(keyWord))
{
topicsList->removeItem(keyWord);
pTopicsText.erase(keyWord);
}
topicsList->adjustSize();
}
void addColorInString(std::string& str, const std::string& keyword,std::string color1, std::string color2)
@ -189,10 +205,14 @@ void addColorInString(std::string& str, const std::string& keyword,std::string c
std::string DialogueWindow::parseText(std::string text)
{
bool separatorReached = false; // only parse topics that are below the separator (this prevents actions like "Barter" that are not topics from getting blue-colored)
for(unsigned int i = 0;i<topicsList->getItemCount();i++)
{
std::string keyWord = topicsList->getItemNameAt(i);
addColorInString(text,keyWord,"#686EBA","#B29154");
if (separatorReached && keyWord != "")
addColorInString(text,keyWord,"#686EBA","#B29154");
else
separatorReached = true;
}
return text;
}
@ -226,7 +246,6 @@ void DialogueWindow::updateOptions()
{
//Clear the list of topics
topicsList->clear();
pTopicsText.clear();
history->eraseText(0,history->getTextLength());
pDispositionBar->setProgressRange(100);
@ -241,3 +260,8 @@ void DialogueWindow::goodbye()
topicsList->setEnabled(false);
mEnabled = false;
}
void DialogueWindow::onReferenceUnavailable()
{
mWindowManager.removeGuiMode(GM_Dialogue);
}

@ -2,8 +2,11 @@
#define MWGUI_DIALOGE_H
#include "window_base.hpp"
#include "referenceinterface.hpp"
#include <boost/array.hpp>
#include "../mwworld/ptr.hpp"
namespace MWGui
{
class WindowManager;
@ -23,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;
@ -38,7 +39,7 @@ namespace MWGui
*/
EventHandle_Void eventBye;
void startDialogue(std::string npcName);
void startDialogue(MWWorld::Ptr actor, std::string npcName);
void stopDialogue();
void setKeywords(std::list<std::string> keyWord);
void removeKeyword(std::string keyWord);
@ -47,6 +48,10 @@ namespace MWGui
void askQuestion(std::string question);
void goodbye();
// various service button visibilities, depending if the npc/creature talked to has these services
// make sure to call these before setKeywords()
void setShowTrade(bool show) { mShowTrade = show; }
protected:
void onSelectTopic(std::string topic);
void onByeClicked(MyGUI::Widget* _sender);
@ -54,6 +59,8 @@ namespace MWGui
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
void onWindowResize(MyGUI::Window* _sender);
virtual void onReferenceUnavailable();
private:
void updateOptions();
/**
@ -61,13 +68,15 @@ namespace MWGui
*/
std::string parseText(std::string text);
// various service button visibilities, depending if the npc/creature talked to has these services
bool mShowTrade;
bool mEnabled;
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

@ -0,0 +1,516 @@
#include "hud.hpp"
#include <cmath>
#include <MyGUI.h>
#include <boost/lexical_cast.hpp>
#include "../mwbase/environment.hpp"
#include "../mwsound/soundmanager.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/world.hpp"
#include "../mwworld/player.hpp"
#include "inventorywindow.hpp"
#include "window_manager.hpp"
#include "container.hpp"
#include "console.hpp"
using namespace MWGui;
HUD::HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop)
: Layout("openmw_hud_layout.xml")
, health(NULL)
, magicka(NULL)
, stamina(NULL)
, weapImage(NULL)
, spellImage(NULL)
, weapStatus(NULL)
, spellStatus(NULL)
, effectBox(NULL)
, effect1(NULL)
, minimap(NULL)
, compass(NULL)
, crosshair(NULL)
, fpsbox(NULL)
, fpscounter(NULL)
, trianglecounter(NULL)
, batchcounter(NULL)
, hmsBaseLeft(0)
, weapBoxBaseLeft(0)
, spellBoxBaseLeft(0)
, 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 = 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 = viewSize.width - effectBox->getRight();
effectBox->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMagicClicked);
getWidget(minimapBox, "MiniMapBox");
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);
getWidget(trianglecounter, "TriangleCounter");
getWidget(batchcounter, "BatchCounter");
setEffect("icons\\s\\tx_s_chameleon.dds");
LocalMapBase::init(minimap, compass, this);
mMainWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onWorldClicked);
mMainWidget->eventMouseMove += MyGUI::newDelegate(this, &HUD::onWorldMouseOver);
mMainWidget->eventMouseLostFocus += MyGUI::newDelegate(this, &HUD::onWorldMouseLostFocus);
}
void HUD::setFpsLevel(int level)
{
fpscounter = 0;
MyGUI::Widget* fps;
getWidget(fps, "FPSBoxAdv");
fps->setVisible(false);
getWidget(fps, "FPSBox");
fps->setVisible(false);
if (level == 2)
{
getWidget(fpsbox, "FPSBoxAdv");
fpsbox->setVisible(true);
getWidget(fpscounter, "FPSCounterAdv");
}
else if (level == 1)
{
getWidget(fpsbox, "FPSBox");
fpsbox->setVisible(true);
getWidget(fpscounter, "FPSCounter");
}
}
void HUD::setFPS(float fps)
{
if (fpscounter)
fpscounter->setCaption(boost::lexical_cast<std::string>((int)fps));
}
void HUD::setTriangleCount(unsigned int count)
{
trianglecounter->setCaption(boost::lexical_cast<std::string>(count));
}
void HUD::setBatchCount(unsigned int count)
{
batchcounter->setCaption(boost::lexical_cast<std::string>(count));
}
void HUD::setEffect(const char *img)
{
effect1->setImageTexture(img);
}
void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<int>& value)
{
static const char *ids[] =
{
"HBar", "MBar", "FBar", 0
};
for (int i=0; ids[i]; ++i)
if (ids[i]==id)
{
MyGUI::Widget* w;
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
switch (i)
{
case 0:
health->setProgressRange (value.getModified());
health->setProgressPosition (value.getCurrent());
getWidget(w, "HealthFrame");
w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr);
break;
case 1:
magicka->setProgressRange (value.getModified());
magicka->setProgressPosition (value.getCurrent());
getWidget(w, "MagickaFrame");
w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr);
break;
case 2:
stamina->setProgressRange (value.getModified());
stamina->setProgressPosition (value.getCurrent());
getWidget(w, "FatigueFrame");
w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
break;
}
}
}
void HUD::setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible)
{
int weapDx = 0, spellDx = 0;
if (!hmsVisible)
spellDx = weapDx = weapBoxBaseLeft - hmsBaseLeft;
if (!weapVisible)
spellDx += spellBoxBaseLeft - weapBoxBaseLeft;
mWeaponVisible = weapVisible;
mSpellVisible = spellVisible;
if (!mWeaponVisible && !mSpellVisible)
mWeaponSpellBox->setVisible(false);
health->setVisible(hmsVisible);
stamina->setVisible(hmsVisible);
magicka->setVisible(hmsVisible);
weapBox->setPosition(weapBoxBaseLeft - weapDx, weapBox->getTop());
weapBox->setVisible(weapVisible);
spellBox->setPosition(spellBoxBaseLeft - spellDx, spellBox->getTop());
spellBox->setVisible(spellVisible);
}
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 = (viewSize.width - minimapBoxBaseRight) - (viewSize.width - effectBoxBaseRight);
mMapVisible = minimapBoxVisible;
minimapBox->setVisible(minimapBoxVisible);
effectBox->setPosition((viewSize.width - effectBoxBaseRight) - effectBox->getWidth() + effectsDx, effectBox->getTop());
effectBox->setVisible(effectBoxVisible);
}
void HUD::onWorldClicked(MyGUI::Widget* _sender)
{
if (mDragAndDrop->mIsOnDragAndDrop)
{
// drop item into the gameworld
MWWorld::Ptr object = *mDragAndDrop->mDraggedWidget->getUserData<MWWorld::Ptr>();
MWWorld::World* world = MWBase::Environment::get().getWorld();
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition();
float mouseX = cursorPosition.left / float(viewSize.width);
float mouseY = cursorPosition.top / float(viewSize.height);
int origCount = object.getRefData().getCount();
object.getRefData().setCount(mDragAndDrop->mDraggedCount);
if (world->canPlaceObject(mouseX, mouseY))
world->placeObject(object, mouseX, mouseY);
else
world->dropObjectOnGround(object);
MyGUI::PointerManager::getInstance().setPointer("arrow");
std::string sound = MWWorld::Class::get(object).getDownSoundId(object);
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
// remove object from the container it was coming from
object.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount);
mDragAndDrop->mIsOnDragAndDrop = false;
MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget);
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);
}
}
}
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);
float mouseY = cursorPosition.top / float(viewSize.height);
MWWorld::World* world = MWBase::Environment::get().getWorld();
// if we can't drop the object at the wanted position, show the "drop on ground" cursor.
bool canDrop = world->canPlaceObject(mouseX, mouseY);
if (!canDrop)
MyGUI::PointerManager::getInstance().setPointer("drop_ground");
else
MyGUI::PointerManager::getInstance().setPointer("arrow");
}
else
{
MyGUI::PointerManager::getInstance().setPointer("arrow");
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();
}

@ -0,0 +1,85 @@
#include "map_window.hpp"
#include <openengine/gui/layout.hpp>
#include "../mwmechanics/stat.hpp"
#include "../mwworld/ptr.hpp"
namespace MWGui
{
class DragAndDrop;
class HUD : public OEngine::GUI::Layout, public LocalMapBase
{
public:
HUD(int width, int height, int fpsLevel, DragAndDrop* dragAndDrop);
void setEffect(const char *img);
void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value);
void setFPS(float fps);
void setTriangleCount(unsigned int count);
void setBatchCount(unsigned int count);
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;
MyGUI::Widget *effectBox, *minimapBox;
MyGUI::ImageBox* effect1;
MyGUI::ScrollView* minimap;
MyGUI::ImageBox* compass;
MyGUI::ImageBox* crosshair;
MyGUI::TextBox* mCellNameBox;
MyGUI::TextBox* mWeaponSpellBox;
MyGUI::WidgetPtr fpsbox;
MyGUI::TextBox* fpscounter;
MyGUI::TextBox* trianglecounter;
MyGUI::TextBox* batchcounter;
private:
// bottom left elements
int hmsBaseLeft, weapBoxBaseLeft, spellBoxBaseLeft;
// bottom right elements
int minimapBoxBaseRight, effectBoxBaseRight;
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);
};
}

@ -0,0 +1,349 @@
#include "inventorywindow.hpp"
#include <cmath>
#include <algorithm>
#include <iterator>
#include <assert.h>
#include <iostream>
#include <boost/lexical_cast.hpp>
#include "../mwclass/container.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/world.hpp"
#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
{
std::string toLower (const std::string& name)
{
std::string lowerCase;
std::transform (name.begin(), name.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
return lowerCase;
}
}
namespace MWGui
{
InventoryWindow::InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop)
: ContainerBase(dragAndDrop)
, WindowPinnableBase("openmw_inventory_window_layout.xml", parWindowManager)
, mTrading(false)
{
static_cast<MyGUI::Window*>(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize);
getWidget(mAvatar, "Avatar");
getWidget(mEncumbranceBar, "EncumbranceBar");
getWidget(mEncumbranceText, "EncumbranceBarT");
getWidget(mFilterAll, "AllButton");
getWidget(mFilterWeapon, "WeaponButton");
getWidget(mFilterApparel, "ApparelButton");
getWidget(mFilterMagic, "MagicButton");
getWidget(mFilterMisc, "MiscButton");
getWidget(mLeftPane, "LeftPane");
getWidget(mRightPane, "RightPane");
mAvatar->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onAvatarClicked);
MyGUI::ScrollView* itemView;
MyGUI::Widget* containerWidget;
getWidget(containerWidget, "Items");
getWidget(itemView, "ItemView");
setWidgets(containerWidget, itemView);
// adjust size of buttons to fit text
int curX = 0;
mFilterAll->setSize( mFilterAll->getTextSize().width + 24, mFilterAll->getSize().height );
curX += mFilterAll->getTextSize().width + 24 + 4;
mFilterWeapon->setPosition(curX, mFilterWeapon->getPosition().top);
mFilterWeapon->setSize( mFilterWeapon->getTextSize().width + 24, mFilterWeapon->getSize().height );
curX += mFilterWeapon->getTextSize().width + 24 + 4;
mFilterApparel->setPosition(curX, mFilterApparel->getPosition().top);
mFilterApparel->setSize( mFilterApparel->getTextSize().width + 24, mFilterApparel->getSize().height );
curX += mFilterApparel->getTextSize().width + 24 + 4;
mFilterMagic->setPosition(curX, mFilterMagic->getPosition().top);
mFilterMagic->setSize( mFilterMagic->getTextSize().width + 24, mFilterMagic->getSize().height );
curX += mFilterMagic->getTextSize().width + 24 + 4;
mFilterMisc->setPosition(curX, mFilterMisc->getPosition().top);
mFilterMisc->setSize( mFilterMisc->getTextSize().width + 24, mFilterMisc->getSize().height );
mFilterAll->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
mFilterWeapon->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
mFilterApparel->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
mFilterMagic->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
mFilterMisc->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onFilterChanged);
mFilterAll->setStateSelected(true);
setCoord(0, 342, 498, 258);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
openContainer(player);
}
void InventoryWindow::open()
{
updateEncumbranceBar();
mTrading = false;
mBoughtItems.clear();
onWindowResize(static_cast<MyGUI::Window*>(mMainWidget));
}
void InventoryWindow::onWindowResize(MyGUI::Window* _sender)
{
const float aspect = 0.5; // fixed aspect ratio for the left pane
mLeftPane->setSize( (_sender->getSize().height-44) * aspect, _sender->getSize().height-44 );
mRightPane->setCoord( mLeftPane->getPosition().left + (_sender->getSize().height-44) * aspect + 4,
mRightPane->getPosition().top,
_sender->getSize().width - 12 - (_sender->getSize().height-44) * aspect - 15,
_sender->getSize().height-44 );
drawItems();
}
void InventoryWindow::onFilterChanged(MyGUI::Widget* _sender)
{
if (_sender == mFilterAll)
setFilter(ContainerBase::Filter_All);
else if (_sender == mFilterWeapon)
setFilter(ContainerBase::Filter_Weapon);
else if (_sender == mFilterApparel)
setFilter(ContainerBase::Filter_Apparel);
else if (_sender == mFilterMagic)
setFilter(ContainerBase::Filter_Magic);
else if (_sender == mFilterMisc)
setFilter(ContainerBase::Filter_Misc);
mFilterAll->setStateSelected(false);
mFilterWeapon->setStateSelected(false);
mFilterApparel->setStateSelected(false);
mFilterMagic->setStateSelected(false);
mFilterMisc->setStateSelected(false);
static_cast<MyGUI::Button*>(_sender)->setStateSelected(true);
}
void InventoryWindow::onPinToggled()
{
mWindowManager.setWeaponVisibility(!mPinned);
}
void InventoryWindow::onAvatarClicked(MyGUI::Widget* _sender)
{
if (mDragAndDrop->mIsOnDragAndDrop)
{
MWWorld::Ptr ptr = *mDragAndDrop->mDraggedWidget->getUserData<MWWorld::Ptr>();
if (mDragAndDrop->mDraggedFrom != this)
{
// add item to the player's inventory
MWWorld::ContainerStore& invStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
MWWorld::ContainerStoreIterator it = invStore.begin();
int origCount = ptr.getRefData().getCount();
ptr.getRefData().setCount(origCount - mDragAndDrop->mDraggedCount);
it = invStore.add(ptr);
(*it).getRefData().setCount(mDragAndDrop->mDraggedCount);
ptr = *it;
}
/// \todo scripts
boost::shared_ptr<MWWorld::Action> action = MWWorld::Class::get(ptr).use(ptr);
action->execute();
// this is necessary for books/scrolls: if they are already in the player's inventory,
// the "Take" button should not be visible.
// NOTE: the take button is "reset" when the window opens, so we can safely do the following
// without screwing up future book windows
if (mDragAndDrop->mDraggedFrom == this)
{
mWindowManager.getBookWindow()->setTakeButtonShow(false);
mWindowManager.getScrollWindow()->setTakeButtonShow(false);
}
mDragAndDrop->mIsOnDragAndDrop = false;
MyGUI::Gui::getInstance().destroyWidget(mDragAndDrop->mDraggedWidget);
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(mPtr).getInventoryStore(mPtr);
std::vector<MWWorld::Ptr> items;
for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot)
{
MWWorld::ContainerStoreIterator it = invStore.getSlot(slot);
if (it != invStore.end())
{
items.push_back(*it);
}
}
return items;
}
void InventoryWindow::_unequipItem(MWWorld::Ptr item)
{
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot)
{
MWWorld::ContainerStoreIterator it = invStore.getSlot(slot);
if (it != invStore.end() && *it == item)
{
invStore.equip(slot, invStore.end());
return;
}
}
}
void InventoryWindow::updateEncumbranceBar()
{
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
float capacity = MWWorld::Class::get(player).getCapacity(player);
float encumbrance = MWWorld::Class::get(player).getEncumbrance(player);
mEncumbranceBar->setProgressRange(capacity);
mEncumbranceBar->setProgressPosition(encumbrance);
mEncumbranceText->setCaption( boost::lexical_cast<std::string>(int(encumbrance)) + "/" + boost::lexical_cast<std::string>(int(capacity)) );
}
void InventoryWindow::onFrame()
{
if (!mMainWidget->getVisible())
return;
updateEncumbranceBar();
}
int InventoryWindow::getPlayerGold()
{
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
for (MWWorld::ContainerStoreIterator it = invStore.begin();
it != invStore.end(); ++it)
{
if (toLower(it->getCellRef().refID) == "gold_001")
return it->getRefData().getCount();
}
return 0;
}
void InventoryWindow::startTrade()
{
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;
}
}

@ -0,0 +1,60 @@
#ifndef MGUI_Inventory_H
#define MGUI_Inventory_H
#include "container.hpp"
#include "window_pinnable_base.hpp"
namespace MWGui
{
class InventoryWindow : public ContainerBase, public WindowPinnableBase
{
public:
InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop);
virtual void open();
/// start trading, disables item drag&drop
void startTrade();
void onFrame();
void pickUpObject (MWWorld::Ptr object);
int getPlayerGold();
protected:
MyGUI::Widget* mAvatar;
MyGUI::TextBox* mArmorRating;
MyGUI::ProgressBar* mEncumbranceBar;
MyGUI::TextBox* mEncumbranceText;
MyGUI::Widget* mLeftPane;
MyGUI::Widget* mRightPane;
MyGUI::Button* mFilterAll;
MyGUI::Button* mFilterWeapon;
MyGUI::Button* mFilterApparel;
MyGUI::Button* mFilterMagic;
MyGUI::Button* mFilterMisc;
bool mTrading;
void onWindowResize(MyGUI::Window* _sender);
void onFilterChanged(MyGUI::Widget* _sender);
void onAvatarClicked(MyGUI::Widget* _sender);
void onPinToggled();
void updateEncumbranceBar();
virtual bool isTrading() { return mTrading; }
virtual bool isInventory() { return true; }
virtual std::vector<MWWorld::Ptr> getEquippedItems();
virtual void _unequipItem(MWWorld::Ptr item);
virtual void onReferenceUnavailable() { ; }
virtual void notifyContentChanged();
};
}
#endif // Inventory_H

@ -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)
{

@ -1,332 +0,0 @@
#include "layouts.hpp"
#include "../mwmechanics/mechanicsmanager.hpp"
#include "window_manager.hpp"
#include <cmath>
#include <algorithm>
#include <iterator>
#undef min
#undef max
using namespace MWGui;
HUD::HUD(int width, int height, int fpsLevel)
: Layout("openmw_hud_layout.xml")
, health(NULL)
, magicka(NULL)
, stamina(NULL)
, weapImage(NULL)
, spellImage(NULL)
, weapStatus(NULL)
, spellStatus(NULL)
, effectBox(NULL)
, effect1(NULL)
, minimap(NULL)
, compass(NULL)
, crosshair(NULL)
, fpsbox(NULL)
, fpscounter(NULL)
, trianglecounter(NULL)
, batchcounter(NULL)
, hmsBaseLeft(0)
, weapBoxBaseLeft(0)
, spellBoxBaseLeft(0)
, effectBoxBaseRight(0)
, minimapBoxBaseRight(0)
{
setCoord(0,0, width, height);
// Energy bars
getWidget(health, "Health");
getWidget(magicka, "Magicka");
getWidget(stamina, "Stamina");
hmsBaseLeft = health->getLeft();
// Item and spell images and status bars
getWidget(weapBox, "WeapBox");
getWidget(weapImage, "WeapImage");
getWidget(weapStatus, "WeapStatus");
weapBoxBaseLeft = weapBox->getLeft();
getWidget(spellBox, "SpellBox");
getWidget(spellImage, "SpellImage");
getWidget(spellStatus, "SpellStatus");
spellBoxBaseLeft = spellBox->getLeft();
getWidget(effectBox, "EffectBox");
getWidget(effect1, "Effect1");
effectBoxBaseRight = effectBox->getRight();
getWidget(minimapBox, "MiniMapBox");
minimapBoxBaseRight = minimapBox->getRight();
getWidget(minimap, "MiniMap");
getWidget(compass, "Compass");
getWidget(crosshair, "Crosshair");
setFpsLevel(fpsLevel);
getWidget(trianglecounter, "TriangleCounter");
getWidget(batchcounter, "BatchCounter");
compass->setImageTexture("textures\\compass.dds");
crosshair->setImageTexture("textures\\target.dds");
// 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);
}
void HUD::setFpsLevel(int level)
{
MyGUI::Widget* fps;
getWidget(fps, "FPSBoxAdv");
fps->setVisible(false);
getWidget(fps, "FPSBox");
fps->setVisible(false);
if (level == 2)
{
getWidget(fpsbox, "FPSBoxAdv");
fpsbox->setVisible(true);
getWidget(fpscounter, "FPSCounterAdv");
}
else if (level == 1)
{
getWidget(fpsbox, "FPSBox");
fpsbox->setVisible(true);
getWidget(fpscounter, "FPSCounter");
}
}
void HUD::setFPS(float fps)
{
fpscounter->setCaption(boost::lexical_cast<std::string>((int)fps));
}
void HUD::setTriangleCount(size_t count)
{
trianglecounter->setCaption(boost::lexical_cast<std::string>(count));
}
void HUD::setBatchCount(size_t count)
{
batchcounter->setCaption(boost::lexical_cast<std::string>(count));
}
void HUD::setStats(int h, int hmax, int m, int mmax, int s, int smax)
{
health->setProgressRange(hmax);
health->setProgressPosition(h);
magicka->setProgressRange(mmax);
magicka->setProgressPosition(m);
stamina->setProgressRange(smax);
stamina->setProgressPosition(s);
}
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);
}
void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<int>& value)
{
static const char *ids[] =
{
"HBar", "MBar", "FBar", 0
};
for (int i=0; ids[i]; ++i)
if (ids[i]==id)
{
switch (i)
{
case 0:
health->setProgressRange (value.getModified());
health->setProgressPosition (value.getCurrent());
break;
case 1:
magicka->setProgressRange (value.getModified());
magicka->setProgressPosition (value.getCurrent());
break;
case 2:
stamina->setProgressRange (value.getModified());
stamina->setProgressPosition (value.getCurrent());
break;
}
}
}
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;
if (!hmsVisible)
spellDx = weapDx = weapBoxBaseLeft - hmsBaseLeft;
if (!weapVisible)
spellDx -= spellBoxBaseLeft - weapBoxBaseLeft;
health->setVisible(hmsVisible);
stamina->setVisible(hmsVisible);
magicka->setVisible(hmsVisible);
weapBox->setPosition(weapBoxBaseLeft - weapDx, weapBox->getTop());
weapBox->setVisible(weapVisible);
spellBox->setPosition(spellBoxBaseLeft - spellDx, spellBox->getTop());
spellBox->setVisible(spellVisible);
}
void HUD::setBottomRightVisibility(bool effectBoxVisible, bool minimapBoxVisible)
{
// effect box can have variable width -> variable left coordinate
int effectsDx = 0;
if (!minimapBoxVisible)
effectsDx = minimapBoxBaseRight - effectBoxBaseRight;
minimapBox->setVisible(minimapBoxVisible);
effectBox->setPosition(effectBoxBaseRight - effectBox->getWidth() + effectsDx, effectBox->getTop());
effectBox->setVisible(effectBoxVisible);
}
LocalMapBase::LocalMapBase()
: mCurX(0)
, mCurY(0)
, mInterior(false)
, mFogOfWar(true)
, mLocalMap(NULL)
, mPrefix()
, mChanged(true)
, mLayout(NULL)
, mLastPositionX(0.0f)
, mLastPositionY(0.0f)
, mLastDirectionX(0.0f)
, mLastDirectionY(0.0f)
{
}
void LocalMapBase::init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout)
{
mLocalMap = widget;
mLayout = layout;
}
void LocalMapBase::setCellPrefix(const std::string& prefix)
{
mPrefix = prefix;
mChanged = true;
}
void LocalMapBase::toggleFogOfWar()
{
mFogOfWar = !mFogOfWar;
applyFogOfWar();
}
void LocalMapBase::applyFogOfWar()
{
for (int mx=0; mx<3; ++mx)
{
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>(mCurX + (mx-1)) + "_"
+ boost::lexical_cast<std::string>(mCurY + (mInterior ? (my-1) : -1*(my-1)));
MyGUI::ImageBox* fog;
mLayout->getWidget(fog, name+"_fog");
fog->setImageTexture(mFogOfWar ?
((MyGUI::RenderManager::getInstance().getTexture(image+"_fog") != 0) ? image+"_fog"
: "black.png" )
: "");
}
}
}
void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
{
if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell
for (int mx=0; mx<3; ++mx)
{
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);
if (MyGUI::RenderManager::getInstance().getTexture(image) != 0)
box->setImageTexture(image);
else
box->setImageTexture("black.png");
}
}
mInterior = interior;
mCurX = x;
mCurY = y;
mChanged = false;
applyFogOfWar();
}

@ -1,236 +0,0 @@
#ifndef MWGUI_LAYOUTS_H
#define MWGUI_LAYOUTS_H
#include <components/esm_store/store.hpp>
#include <boost/array.hpp>
#include <boost/lexical_cast.hpp>
#include <sstream>
#include <set>
#include <string>
#include <utility>
#include "../mwmechanics/stat.hpp"
#include "window_base.hpp"
#include <cmath>
/*
This file contains classes corresponding to window layouts
defined in resources/mygui/ *.xml.
Each class inherites GUI::Layout and loads the XML file, and
provides some helper functions to manipulate the elements of the
window.
The windows are never created or destroyed (except at startup and
shutdown), they are only hid. You can control visibility with
setVisible().
*/
namespace MWGui
{
class LocalMapBase
{
public:
LocalMapBase();
void init(MyGUI::ScrollView* widget, OEngine::GUI::Layout* layout);
void setCellPrefix(const std::string& prefix);
void setActiveCell(const int x, const int y, bool interior=false);
void toggleFogOfWar();
protected:
int mCurX, mCurY;
bool mInterior;
MyGUI::ScrollView* mLocalMap;
std::string mPrefix;
bool mChanged;
bool mFogOfWar;
void applyFogOfWar();
OEngine::GUI::Layout* mLayout;
float mLastPositionX;
float mLastPositionY;
float mLastDirectionX;
float mLastDirectionY;
};
class HUD : public OEngine::GUI::Layout, public LocalMapBase
{
public:
HUD(int width, int height, int fpsLevel);
void setStats(int h, int hmax, int m, int mmax, int s, int smax);
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);
MyGUI::ProgressPtr health, magicka, stamina;
MyGUI::Widget *weapBox, *spellBox;
MyGUI::ImageBox *weapImage, *spellImage;
MyGUI::ProgressPtr weapStatus, spellStatus;
MyGUI::Widget *effectBox, *minimapBox;
MyGUI::ImageBox* effect1;
MyGUI::ScrollView* minimap;
MyGUI::ImageBox* compass;
MyGUI::ImageBox* crosshair;
MyGUI::WidgetPtr fpsbox;
MyGUI::TextBox* fpscounter;
MyGUI::TextBox* trianglecounter;
MyGUI::TextBox* batchcounter;
private:
// bottom left elements
int hmsBaseLeft, weapBoxBaseLeft, spellBoxBaseLeft;
// bottom right elements
int minimapBoxBaseRight, effectBoxBaseRight;
};
class MainMenu : public OEngine::GUI::Layout
{
public:
MainMenu(int w, int h)
: Layout("openmw_mainmenu_layout.xml")
{
setCoord(0,0,w,h);
}
};
#if 0
class InventoryWindow : public OEngine::GUI::Layout
{
public:
enum CategoryMode
{
CM_All = 0, // All items
CM_Weapon = 1, // Only weapons
CM_Apparel = 2, // Apparel
CM_Magic = 3, // Magic
CM_Misc = 4 // Misc
};
InventoryWindow ()
: Layout("openmw_inventory_window_layout.xml")
, categoryMode(CM_All)
// color should be fetched from skin
, activeColor(0, 0, 1)
, inactiveColor(0.7, 0.7, 0.7)
{
setCoord(0, 200, 600, 400);
// These are just demo values, you should replace these with
// real calls from outside the class later.
mMainWidget->setCaption("Glass Frostsword");
setText("EncumbranceBarT", "176/210");
MyGUI::ProgressPtr pt;
getWidget(pt, "EncumbranceBar");
pt->setProgressRange(210);
pt->setProgressPosition(176);
MyGUI::WidgetPtr avatar;
getWidget(avatar, "Avatar");
// Adjust armor rating text to bottom of avatar widget
MyGUI::TextBox* armor_rating;
getWidget(armor_rating, "ArmorRating");
armor_rating->setCaption("Armor: 11");
MyGUI::IntCoord coord = armor_rating->getCoord();
coord.top = avatar->getCoord().height - 4 - coord.height;
armor_rating->setCoord(coord);
names[0] = "All";
names[1] = "Weapon";
names[2] = "Apparel";
names[3] = "Magic";
names[4] = "Misc";
boost::array<CategoryMode, 5> categories = { {
CM_All, CM_Weapon, CM_Apparel, CM_Magic, CM_Misc
} };
// Initialize buttons with text and adjust sizes, also mark All as active button
int margin = 2;
int last_x = 0;
for (int i = 0; i < categories.size(); ++i)
{
CategoryMode mode = categories[i];
std::string name = names[mode];
name += "Button";
setText(name, names[mode]);
getWidget(buttons[mode], name);
MyGUI::ButtonPtr &button_pt = buttons[mode];
if (mode == CM_All)
button_pt->setTextColour(activeColor);
else
button_pt->setTextColour(inactiveColor);
MyGUI::IntCoord coord = button_pt->getCoord();
coord.left = last_x;
last_x += coord.width + margin;
button_pt->setCoord(coord);
button_pt->eventMouseButtonClick += MyGUI::newDelegate(this, &InventoryWindow::onCategorySelected);
}
}
void setCategory(CategoryMode mode)
{
MyGUI::ButtonPtr pt = getCategoryButton(categoryMode);
pt->setTextColour(inactiveColor);
pt = getCategoryButton(mode);
pt->setTextColour(activeColor);
categoryMode = mode;
}
MyGUI::ButtonPtr getCategoryButton(CategoryMode mode)
{
return buttons[mode];
}
void onCategorySelected(MyGUI::Widget *widget)
{
boost::array<CategoryMode, 5> categories = { {
CM_All, CM_Weapon, CM_Apparel, CM_Magic, CM_Misc
} };
for (int i = 0; i < categories.size(); ++i)
{
CategoryMode mode = categories[i];
if (widget == buttons[mode])
{
setCategory(mode);
return;
}
}
}
CategoryMode categoryMode; // Current category filter
MyGUI::ButtonPtr buttons[5]; // Button pointers
std::string names[5]; // Names of category buttons
MyGUI::Colour activeColor;
MyGUI::Colour inactiveColor;
};
#endif
}
#endif

@ -28,8 +28,11 @@ void MWList::initialiseOverride()
void MWList::addItem(const std::string& name)
{
mItems.push_back(name);
}
redraw();
void MWList::addSeparator()
{
mItems.push_back("");
}
void MWList::adjustSize()
@ -52,22 +55,33 @@ void MWList::redraw(bool scrollbarShown)
for (std::vector<std::string>::const_iterator it=mItems.begin();
it!=mItems.end(); ++it)
{
MyGUI::Button* button = mScrollView->createWidget<MyGUI::Button>(
"MW_ListLine", MyGUI::IntCoord(0, mItemHeight, mScrollView->getSize().width - scrollBarWidth - 2, 24),
MyGUI::Align::Left | MyGUI::Align::Top, getName() + "_item_" + (*it));
button->setCaption((*it));
button->getSubWidgetText()->setWordWrap(true);
button->getSubWidgetText()->setTextAlign(MyGUI::Align::Left);
button->eventMouseWheel += MyGUI::newDelegate(this, &MWList::onMouseWheel);
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWList::onItemSelected);
int height = button->getTextSize().height;
button->setSize(MyGUI::IntSize(button->getSize().width, height));
mItemHeight += height + spacing;
if (*it != "")
{
MyGUI::Button* button = mScrollView->createWidget<MyGUI::Button>(
"MW_ListLine", MyGUI::IntCoord(0, mItemHeight, mScrollView->getSize().width - scrollBarWidth - 2, 24),
MyGUI::Align::Left | MyGUI::Align::Top, getName() + "_item_" + (*it));
button->setCaption((*it));
button->getSubWidgetText()->setWordWrap(true);
button->getSubWidgetText()->setTextAlign(MyGUI::Align::Left);
button->eventMouseWheel += MyGUI::newDelegate(this, &MWList::onMouseWheel);
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWList::onItemSelected);
int height = button->getTextSize().height;
button->setSize(MyGUI::IntSize(button->getSize().width, height));
mItemHeight += height + spacing;
}
else
{
MyGUI::ImageBox* separator = mScrollView->createWidget<MyGUI::ImageBox>("MW_HLine",
MyGUI::IntCoord(2, mItemHeight, mScrollView->getWidth()-4, 18),
MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch);
separator->setNeedMouseFocus(false);
mItemHeight += 18 + spacing;
}
}
mScrollView->setCanvasSize(mClient->getSize().width + (_scrollBarWidth-scrollBarWidth), std::max(mItemHeight, mClient->getSize().height));
mScrollView->setViewOffset(MyGUI::IntPoint(0,0));
if (!scrollbarShown && mItemHeight > mClient->getSize().height)
redraw(true);
@ -93,15 +107,11 @@ void MWList::removeItem(const std::string& name)
{
assert( std::find(mItems.begin(), mItems.end(), name) != mItems.end() );
mItems.erase( std::find(mItems.begin(), mItems.end(), name) );
redraw();
}
void MWList::clear()
{
mItems.clear();
redraw();
}
void MWList::onMouseWheel(MyGUI::Widget* _sender, int _rel)

@ -26,15 +26,16 @@ namespace MWGui
EventHandle_String eventItemSelected;
/**
* Call after the size of the list changed
* Call after the size of the list changed, or items were inserted/removed
*/
void adjustSize();
void addItem(const std::string& name);
void addSeparator(); ///< add a seperator between the current and the next item.
void removeItem(const std::string& name);
bool hasItem(const std::string& name);
unsigned int getItemCount();
std::string getItemNameAt(unsigned int at);
std::string getItemNameAt(unsigned int at); ///< \attention if there are separators, this method will return "" at the place where the separator is
void clear();
protected:

@ -0,0 +1,16 @@
#include <openengine/gui/layout.hpp>
namespace MWGui
{
class MainMenu : public OEngine::GUI::Layout
{
public:
MainMenu(int w, int h)
: Layout("openmw_mainmenu_layout.xml")
{
setCoord(0,0,w,h);
}
};
}

@ -1,70 +1,148 @@
#include "map_window.hpp"
#include "window_manager.hpp"
/*
#include "../mwmechanics/mechanicsmanager.hpp"
#include <cmath>
#include <algorithm>
#include <iterator>
#include <boost/lexical_cast.hpp>
#undef min
#undef max
*/
using namespace MWGui;
MapWindow::MapWindow(WindowManager& parWindowManager) :
MWGui::WindowPinnableBase("openmw_map_window_layout.xml", parWindowManager),
mGlobal(false)
LocalMapBase::LocalMapBase()
: mCurX(0)
, mCurY(0)
, mInterior(false)
, mFogOfWar(true)
, mLocalMap(NULL)
, mMapDragAndDrop(false)
, mPrefix()
, mChanged(true)
, mLayout(NULL)
, mLastPositionX(0.0f)
, mLastPositionY(0.0f)
, mLastDirectionX(0.0f)
, mLastDirectionY(0.0f)
, mCompass(NULL)
{
setCoord(500,0,320,300);
setText("WorldButton", "World");
setImage("Compass", "textures\\compass.dds");
// Obviously you should override this later on
setCellName("No Cell Loaded");
}
getWidget(mLocalMap, "LocalMap");
getWidget(mGlobalMap, "GlobalMap");
getWidget(mPlayerArrow, "Compass");
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);
}
}
}
getWidget(mButton, "WorldButton");
mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked);
mButton->setCaption(mWindowManager.getGameSettingString("sWorld", ""));
int width = mButton->getTextSize().width + 24;
mButton->setCoord(mMainWidget->getSize().width - width - 22, mMainWidget->getSize().height - 64, width, 22);
void LocalMapBase::setCellPrefix(const std::string& prefix)
{
mPrefix = prefix;
mChanged = true;
}
MyGUI::Button* eventbox;
getWidget(eventbox, "EventBox");
eventbox->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
eventbox->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
void LocalMapBase::toggleFogOfWar()
{
mFogOfWar = !mFogOfWar;
applyFogOfWar();
}
LocalMapBase::init(mLocalMap, this);
void LocalMapBase::applyFogOfWar()
{
for (int mx=0; mx<3; ++mx)
{
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>(mCurX + (mx-1)) + "_"
+ boost::lexical_cast<std::string>(mCurY + (mInterior ? (my-1) : -1*(my-1)));
MyGUI::ImageBox* fog = mFogWidgets[my + 3*mx];
fog->setImageTexture(mFogOfWar ?
((MyGUI::RenderManager::getInstance().getTexture(image+"_fog") != 0) ? image+"_fog"
: "black.png" )
: "");
}
}
}
void MapWindow::setCellName(const std::string& cellName)
void LocalMapBase::setActiveCell(const int x, const int y, bool interior)
{
static_cast<MyGUI::Window*>(mMainWidget)->setCaption(cellName);
adjustWindowCaption();
if (x==mCurX && y==mCurY && mInterior==interior && !mChanged) return; // don't do anything if we're still in the same cell
for (int mx=0; mx<3; ++mx)
{
for (int my=0; my<3; ++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)));
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);
else
box->setImageTexture("black.png");
}
}
mInterior = interior;
mCurX = x;
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 MapWindow::setPlayerPos(const float x, const float y)
void LocalMapBase::setPlayerPos(const float x, const float y)
{
if (mGlobal || !mVisible || (x == mLastPositionX && y == mLastPositionY)) return;
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);
mPlayerArrow->setPosition(MyGUI::IntPoint(x*512-16, y*512-16));
mCompass->setPosition(MyGUI::IntPoint(512+x*512-16, 512+y*512-16));
mLastPositionX = x;
mLastPositionY = y;
}
void MapWindow::setPlayerDir(const float x, const float y)
void LocalMapBase::setPlayerDir(const float x, const float y)
{
if (!mVisible || (x == mLastDirectionX && y == mLastDirectionY)) return;
MyGUI::ISubWidget* main = mPlayerArrow->getSubWidgetMain();
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);
@ -74,6 +152,37 @@ void MapWindow::setPlayerDir(const float x, const float y)
mLastDirectionY = y;
}
// ------------------------------------------------------------------------------------------
MapWindow::MapWindow(WindowManager& parWindowManager) :
MWGui::WindowPinnableBase("openmw_map_window_layout.xml", parWindowManager),
mGlobal(false)
{
setCoord(500,0,320,300);
getWidget(mLocalMap, "LocalMap");
getWidget(mGlobalMap, "GlobalMap");
getWidget(mPlayerArrow, "Compass");
getWidget(mButton, "WorldButton");
mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked);
mButton->setCaptionWithReplacing("#{sWorld}");
int width = mButton->getTextSize().width + 24;
mButton->setCoord(mMainWidget->getSize().width - width - 22, mMainWidget->getSize().height - 64, width, 22);
MyGUI::Button* eventbox;
getWidget(eventbox, "EventBox");
eventbox->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
eventbox->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
LocalMapBase::init(mLocalMap, mPlayerArrow, this);
}
void MapWindow::setCellName(const std::string& cellName)
{
setTitle(cellName);
}
void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
{
if (_id!=MyGUI::MouseButton::Left) return;
@ -100,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);
}

@ -1,19 +1,53 @@
#ifndef MWGUI_MAPWINDOW_H
#define MWGUI_MAPWINDOW_H
#include "layouts.hpp"
#include "window_pinnable_base.hpp"
namespace MWGui
{
class LocalMapBase
{
public:
LocalMapBase();
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();
protected:
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;
float mLastDirectionY;
};
class MapWindow : public MWGui::WindowPinnableBase, public LocalMapBase
{
public:
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:

@ -15,6 +15,13 @@ void MessageBoxManager::onFrame (float frameDuration)
std::vector<MessageBoxManagerTimer>::iterator it;
for(it = mTimers.begin(); it != mTimers.end();)
{
// if this messagebox is already deleted, remove the timer and move on
if (std::find(mMessageBoxes.begin(), mMessageBoxes.end(), it->messageBox) == mMessageBoxes.end())
{
it = mTimers.erase(it);
continue;
}
it->current += frameDuration;
if(it->current >= it->max)
{
@ -51,7 +58,7 @@ void MessageBoxManager::onFrame (float frameDuration)
if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) {
delete mInterMessageBoxe;
mInterMessageBoxe = NULL;
mWindowManager->setNextMode(GM_Game);
mWindowManager->removeGuiMode(GM_InterMessageBox);
}
}
@ -79,13 +86,12 @@ void MessageBoxManager::createMessageBox (const std::string& message)
bool MessageBoxManager::createInteractiveMessageBox (const std::string& message, const std::vector<std::string>& buttons)
{
/// \todo Don't write this kind of error message to cout. Either discard the old message box
/// silently or throw an exception.
if(mInterMessageBoxe != NULL) {
std::cout << "there is a MessageBox already" << std::endl;
return false;
}
std::cout << "interactive MessageBox: " << message << " - ";
std::copy (buttons.begin(), buttons.end(), std::ostream_iterator<std::string> (std::cout, ", "));
std::cout << std::endl;
mInterMessageBoxe = new InteractiveMessageBox(*this, message, buttons);
@ -154,7 +160,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;
@ -259,11 +265,8 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan
if(buttonsWidth < fixedWidth)
{
// on one line
std::cout << "on one line" << std::endl;
if(textSize.width + 2*textPadding < buttonsWidth)
{
std::cout << "width = buttonsWidth" << std::endl;
mainWidgetSize.width = buttonsWidth;
}
else
@ -276,13 +279,9 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan
absCoord.left = (gameWindowSize.width - mainWidgetSize.width)/2;
absCoord.top = (gameWindowSize.height - mainWidgetSize.height)/2;
std::cout << "width " << mainWidgetSize.width << " height " << mainWidgetSize.height << std::endl;
std::cout << "left " << absCoord.left << " top " << absCoord.top << std::endl;
mMainWidget->setCoord(absCoord);
mMainWidget->setSize(mainWidgetSize);
MyGUI::IntCoord messageWidgetCoord;
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
messageWidgetCoord.top = textPadding;
@ -312,7 +311,6 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan
else
{
// among each other
if(biggestButtonWidth > textSize.width) {
mainWidgetSize.width = biggestButtonWidth + buttonTopPadding;
}
@ -321,8 +319,6 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan
}
mainWidgetSize.height = textSize.height + 2*textPadding + textButtonPadding + buttonHeight * buttons.size() + buttonMainPadding;
std::cout << "biggestButtonWidth " << biggestButtonWidth << " textSize.width " << textSize.width << std::endl;
std::cout << "width " << mainWidgetSize.width << " height " << mainWidgetSize.height << std::endl;
mMainWidget->setSize(mainWidgetSize);
MyGUI::IntCoord absCoord;
@ -377,7 +373,6 @@ void InteractiveMessageBox::mousePressed (MyGUI::Widget* pressed)
}
index++;
}
std::cout << "Cant be possible :/" << std::endl;
}
int InteractiveMessageBox::readPressedButton ()

@ -5,8 +5,9 @@ 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
GM_Console, // Console mode
@ -14,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);
@ -71,7 +74,6 @@ RaceDialog::RaceDialog(WindowManager& parWindowManager)
MyGUI::ButtonPtr backButton;
getWidget(backButton, "BackButton");
backButton->setCaption(mWindowManager.getGameSettingString("sBack", ""));
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onBackClicked);
MyGUI::ButtonPtr okButton;
@ -256,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);
@ -289,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
@ -27,25 +30,21 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager)
ButtonPtr button;
getWidget(nameWidget, "NameText");
getWidget(button, "NameButton");
button->setCaption(mWindowManager.getGameSettingString("sName", ""));
adjustButtonSize(button);
button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onNameClicked);;
getWidget(raceWidget, "RaceText");
getWidget(button, "RaceButton");
button->setCaption(mWindowManager.getGameSettingString("sRace", ""));
adjustButtonSize(button);
button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onRaceClicked);;
getWidget(classWidget, "ClassText");
getWidget(button, "ClassButton");
button->setCaption(mWindowManager.getGameSettingString("sClass", ""));
adjustButtonSize(button);
button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onClassClicked);;
getWidget(birthSignWidget, "SignText");
getWidget(button, "SignButton");
button->setCaption(mWindowManager.getGameSettingString("sBirthSign", ""));
adjustButtonSize(button);
button->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onBirthSignClicked);;
@ -78,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();
@ -92,7 +91,6 @@ ReviewDialog::ReviewDialog(WindowManager& parWindowManager)
MyGUI::ButtonPtr backButton;
getWidget(backButton, "BackButton");
backButton->setCaption(mWindowManager.getGameSettingString("sBack", ""));
backButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ReviewDialog::onBackClicked);
MyGUI::ButtonPtr okButton;
@ -142,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)
@ -156,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)
@ -200,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)
@ -219,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();
@ -233,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);
@ -240,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);
@ -261,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);
@ -302,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;
}
}
@ -335,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
@ -368,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) :
@ -25,7 +26,8 @@ ScrollWindow::ScrollWindow (WindowManager& parWindowManager) :
void ScrollWindow::open (MWWorld::Ptr scroll)
{
MWBase::Environment::get().getSoundManager()->playSound3D (scroll, "scroll", 1.0, 1.0);
// no 3d sounds because the object could be in a container.
MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0);
mScroll = scroll;
@ -41,21 +43,28 @@ void ScrollWindow::open (MWWorld::Ptr scroll)
mTextView->setCanvasSize(410, mTextView->getSize().height);
mTextView->setViewOffset(MyGUI::IntPoint(0,0));
setTakeButtonShow(true);
}
void ScrollWindow::setTakeButtonShow(bool show)
{
mTakeButton->setVisible(show);
}
void ScrollWindow::onCloseButtonClicked (MyGUI::Widget* _sender)
{
MWBase::Environment::get().getSoundManager()->playSound3D (mScroll, "scroll", 1.0, 1.0);
MWBase::Environment::get().getSoundManager()->playSound ("scroll", 1.0, 1.0);
MWBase::Environment::get().getInputManager()->setGuiMode (GM_Game);
mWindowManager.removeGuiMode(GM_Scroll);
}
void ScrollWindow::onTakeButtonClicked (MyGUI::Widget* _sender)
{
MWBase::Environment::get().getSoundManager()->playSound3D (mScroll, "Item Book Up", 1.0, 1.0, MWSound::Play_NoTrack);
MWBase::Environment::get().getSoundManager()->playSound ("Item Book Up", 1.0, 1.0, MWSound::Play_NoTrack);
MWWorld::ActionTake take(mScroll);
take.execute();
MWBase::Environment::get().getInputManager()->setGuiMode (GM_Game);
mWindowManager.removeGuiMode(GM_Scroll);
}

@ -11,7 +11,9 @@ namespace MWGui
{
public:
ScrollWindow (WindowManager& parWindowManager);
void open (MWWorld::Ptr scroll);
void setTakeButtonShow(bool show);
protected:
void onCloseButtonClicked (MyGUI::Widget* _sender);

@ -0,0 +1,349 @@
#include "settingswindow.hpp"
#include <OgreRoot.h>
#include <OgreRenderSystem.h>
#include <OgreString.h>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.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";
}
void parseResolution (int &x, int &y, const std::string& str)
{
std::vector<std::string> split;
boost::algorithm::split (split, str, boost::is_any_of("x@"));
assert (split.size() >= 2);
boost::trim(split[0]);
boost::trim(split[1]);
x = boost::lexical_cast<int> (split[0]);
y = boost::lexical_cast<int> (split[1]);
}
}
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)
{
int resX, resY;
parseResolution (resX, resY, *it);
std::string str = boost::lexical_cast<std::string>(resX) + " x " + boost::lexical_cast<std::string>(resY);
if (mResolutionList->findItemIndexWith(str) == MyGUI::ITEM_NONE)
mResolutionList->addItem(str);
}
// 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.removeGuiMode(GM_Settings);
}
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());
int resX, resY;
parseResolution (resX, resY, resStr);
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);
int resX, resY;
parseResolution (resX, resY, resStr);
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,461 @@
#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
|| spell->data.type == ESM::Spell::ST_Blight
|| spell->data.type == ESM::Spell::ST_Curse
|| spell->data.type == ESM::Spell::ST_Disease)
{
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

@ -1,13 +1,20 @@
#include "stats_window.hpp"
#include "../mwmechanics/mechanicsmanager.hpp"
#include "window_manager.hpp"
#include <cmath>
#include <algorithm>
#include <iterator>
#include <boost/lexical_cast.hpp>
#include "../mwmechanics/mechanicsmanager.hpp"
#include "../mwworld/world.hpp"
#include "../mwworld/player.hpp"
#include "../mwbase/environment.hpp"
#include "window_manager.hpp"
#include "tooltips.hpp"
using namespace MWGui;
const int StatsWindow::lineHeight = 18;
@ -24,11 +31,12 @@ StatsWindow::StatsWindow (WindowManager& parWindowManager)
, skillValues()
, skillWidgetMap()
, factionWidgetMap()
, factions()
, mFactions()
, birthSignId()
, reputation(0)
, bounty(0)
, skillWidgets()
, mChanged(true)
{
setCoord(0,0,498, 342);
@ -42,12 +50,6 @@ StatsWindow::StatsWindow (WindowManager& parWindowManager)
{ "Attrib6", "sAttributeEndurance" },
{ "Attrib7", "sAttributePersonality" },
{ "Attrib8", "sAttributeLuck" },
{ "Health_str", "sHealth" },
{ "Magicka_str", "sMagic" },
{ "Fatigue_str", "sFatigue" },
{ "Level_str", "sLevel" },
{ "Race_str", "sRace" },
{ "Class_str", "sClass" },
{ 0, 0 }
};
@ -60,6 +62,10 @@ StatsWindow::StatsWindow (WindowManager& parWindowManager)
getWidget(skillAreaWidget, "Skills");
getWidget(skillClientWidget, "SkillClient");
getWidget(skillScrollerWidget, "SkillScroller");
getWidget(mLeftPane, "LeftPane");
getWidget(mRightPane, "RightPane");
skillClientWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel);
skillScrollerWidget->eventScrollChangePosition += MyGUI::newDelegate(this, &StatsWindow::onScrollChangePosition);
updateScroller();
@ -72,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)
@ -91,8 +95,22 @@ void StatsWindow::onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos)
}
}
void StatsWindow::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());
}
void StatsWindow::onWindowResize(MyGUI::Window* window)
{
mLeftPane->setCoord( MyGUI::IntCoord(0, 0, 0.44*window->getSize().width, window->getSize().height) );
mRightPane->setCoord( MyGUI::IntCoord(0.44*window->getSize().width, 0, 0.56*window->getSize().width, window->getSize().height) );
updateScroller();
}
@ -153,11 +171,32 @@ void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicSta
};
for (int i=0; ids[i]; ++i)
{
if (ids[i]==id)
{
std::string id (ids[i]);
setBar (id, id + "T", value.getCurrent(), value.getModified());
// health, magicka, fatigue tooltip
MyGUI::Widget* w;
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
if (i==0)
{
getWidget(w, "Health");
w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr);
}
else if (i==1)
{
getWidget(w, "Magicka");
w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr);
}
else if (i==2)
{
getWidget(w, "Fatigue");
w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
}
}
}
}
void StatsWindow::setValue (const std::string& id, const std::string& value)
@ -216,16 +255,42 @@ 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 ()
{
if (mMainWidget->getVisible())
return;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWMechanics::NpcStats PCstats = MWWorld::Class::get(player).getNpcStats(player);
setFactions(PCstats.mFactionRank);
setBirthSign(MWBase::Environment::get().getWorld()->getPlayer().getBirthsign());
if (mChanged)
updateSkillArea();
}
void StatsWindow::setFactions (const std::vector<Faction>& factions)
void StatsWindow::setFactions (const FactionList& factions)
{
this->factions = factions;
if (mFactions != factions)
{
mFactions = factions;
mChanged = true;
}
}
void StatsWindow::setBirthSign (const std::string& signId)
{
birthSignId = signId;
if (signId != birthSignId)
{
birthSignId = signId;
mChanged = true;
}
}
void StatsWindow::addSeparator(MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
@ -233,6 +298,7 @@ void StatsWindow::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::Left | MyGUI::Align::Top | MyGUI::Align::HStretch);
separator->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel);
skillWidgets.push_back(separator);
coord1.top += separator->getHeight();
@ -245,26 +311,25 @@ void StatsWindow::addGroup(const std::string &label, MyGUI::IntCoord &coord1, My
MyGUI::IntCoord(0, coord1.top, coord1.width + coord2.width, coord1.height),
MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch);
groupWidget->setCaption(label);
groupWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel);
skillWidgets.push_back(groupWidget);
coord1.top += lineHeight;
coord2.top += lineHeight;
}
MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::string& tooltip, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::string &value, const std::string& state, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
{
MyGUI::TextBox *skillNameWidget, *skillValueWidget;
skillNameWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandText", coord1, MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch);
skillNameWidget->setCaption(text);
skillNameWidget->setUserString("ToolTipType", "Text");
skillNameWidget->setUserString("ToolTipText", tooltip);
skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel);
skillValueWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandTextRight", coord2, MyGUI::Align::Right | MyGUI::Align::Top);
skillValueWidget->setUserString("ToolTipType", "Text");
skillValueWidget->setUserString("ToolTipText", tooltip);
skillValueWidget->setCaption(value);
skillValueWidget->_setWidgetState(state);
skillValueWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel);
skillWidgets.push_back(skillNameWidget);
skillWidgets.push_back(skillValueWidget);
@ -275,17 +340,20 @@ MyGUI::TextBox* StatsWindow::addValueItem(const std::string& text, const std::st
return skillValueWidget;
}
void 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;
skillNameWidget = skillClientWidget->createWidget<MyGUI::TextBox>("SandText", coord1 + MyGUI::IntSize(coord2.width, 0), MyGUI::Align::Default);
skillNameWidget->setCaption(text);
skillNameWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel);
skillWidgets.push_back(skillNameWidget);
coord1.top += lineHeight;
coord2.top += lineHeight;
return skillNameWidget;
}
void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2)
@ -309,26 +377,55 @@ void StatsWindow::addSkills(const SkillList &skills, const std::string &titleId,
const MWMechanics::Stat<float> &stat = skillValues.find(skillId)->second;
float base = stat.getBase();
float modified = stat.getModified();
int progressPercent = (modified - float(static_cast<int>(modified))) * 100;
const ESM::Skill* skill = mWindowManager.getStore().skills.search(skillId);
assert(skill);
std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId];
const ESM::Attribute* attr = mWindowManager.getStore().attributes.search(skill->data.attribute);
assert(attr);
std::string state = "normal";
if (modified > base)
state = "increased";
else if (modified < base)
state = "decreased";
MyGUI::TextBox* widget = addValueItem(mWindowManager.getGameSettingString(skillNameId, skillNameId), "",
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)
{
skillWidgets[skillWidgets.size()-1-i]->setUserString("ToolTipType", "Layout");
skillWidgets[skillWidgets.size()-1-i]->setUserString("ToolTipLayout", "SkillToolTip");
skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_SkillName", "#{"+skillNameId+"}");
skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_SkillDescription", skill->description);
skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_SkillAttribute", "#{sGoverningAttribute}: #{" + attr->name + "}");
skillWidgets[skillWidgets.size()-1-i]->setUserString("ImageTexture_SkillImage", icon);
skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_SkillProgressText", boost::lexical_cast<std::string>(progressPercent)+"/100");
skillWidgets[skillWidgets.size()-1-i]->setUserString("Range_SkillProgress", "100");
skillWidgets[skillWidgets.size()-1-i]->setUserString("RangePosition_SkillProgress", boost::lexical_cast<std::string>(progressPercent));
}
skillWidgetMap[skillId] = widget;
}
}
void StatsWindow::updateSkillArea()
{
mChanged = false;
for (std::vector<MyGUI::WidgetPtr>::iterator it = skillWidgets.begin(); it != skillWidgets.end(); ++it)
{
MyGUI::Gui::getInstance().destroyWidget(*it);
}
skillWidgets.clear();
skillScrollerWidget->setScrollPosition(0);
onScrollChangePosition(skillScrollerWidget, 0);
clientHeight = 0;
const int valueSize = 40;
MyGUI::IntCoord coord1(10, 0, skillClientWidget->getWidth() - (10 + valueSize), 18);
MyGUI::IntCoord coord2(coord1.left + coord1.width, coord1.top, valueSize, coord1.height);
@ -344,19 +441,75 @@ void StatsWindow::updateSkillArea()
const ESMS::ESMStore &store = mWindowManager.getStore();
if (!factions.empty())
// race tooltip
const ESM::Race* playerRace = store.races.find (MWBase::Environment::get().getWorld()->getPlayer().getRace());
MyGUI::Widget* raceWidget;
getWidget(raceWidget, "RaceText");
ToolTips::createRaceToolTip(raceWidget, playerRace);
getWidget(raceWidget, "Race_str");
ToolTips::createRaceToolTip(raceWidget, playerRace);
// class tooltip
MyGUI::Widget* classWidget;
const ESM::Class& playerClass = MWBase::Environment::get().getWorld()->getPlayer().getClass();
getWidget(classWidget, "ClassText");
ToolTips::createClassToolTip(classWidget, playerClass);
getWidget(classWidget, "Class_str");
ToolTips::createClassToolTip(classWidget, playerClass);
if (!mFactions.empty())
{
// Add a line separator if there are items above
if (!skillWidgets.empty())
addSeparator(coord1, coord2);
addGroup(mWindowManager.getGameSettingString("sFaction", "Faction"), coord1, coord2);
FactionList::const_iterator end = factions.end();
for (FactionList::const_iterator it = factions.begin(); it != end; ++it)
FactionList::const_iterator end = mFactions.end();
for (FactionList::const_iterator it = mFactions.begin(); it != end; ++it)
{
const ESM::Faction *faction = store.factions.find(it->first);
addItem(faction->name, coord1, coord2);
// TODO: Faction rank should be placed in tooltip
MyGUI::Widget* w = addItem(faction->name, coord1, coord2);
std::string text;
text += std::string("#DDC79E") + faction->name;
text += std::string("\n#BF9959") + faction->ranks[it->second];
if (it->second < 9)
{
// player doesn't have max rank yet
text += std::string("\n\n#DDC79E#{sNextRank} ") + faction->ranks[it->second+1];
ESM::RankData rankData = faction->data.rankData[it->second+1];
const ESM::Attribute* attr1 = mWindowManager.getStore().attributes.search(faction->data.attribute1);
const ESM::Attribute* attr2 = mWindowManager.getStore().attributes.search(faction->data.attribute2);
assert(attr1 && attr2);
text += "\n#BF9959#{" + attr1->name + "}: " + boost::lexical_cast<std::string>(rankData.attribute1)
+ ", #{" + attr2->name + "}: " + boost::lexical_cast<std::string>(rankData.attribute2);
text += "\n\n#DDC79E#{sFavoriteSkills}";
text += "\n#BF9959";
for (int i=0; i<6; ++i)
{
const ESM::Skill* skill = mWindowManager.getStore().skills.search(faction->data.skillID[i]);
assert(skill);
text += "#{"+ESM::Skill::sSkillNameIds[faction->data.skillID[i]]+"}";
if (i<5)
text += ", ";
}
text += "\n";
if (rankData.skill1 > 0)
text += "\n#{sNeedOneSkill} " + boost::lexical_cast<std::string>(rankData.skill1);
if (rankData.skill2 > 0)
text += "\n#{sNeedTwoSkills} " + boost::lexical_cast<std::string>(rankData.skill2);
}
w->setUserString("ToolTipType", "Layout");
w->setUserString("ToolTipLayout", "TextToolTip");
w->setUserString("Caption_Text", text);
}
}
@ -366,9 +519,11 @@ void StatsWindow::updateSkillArea()
if (!skillWidgets.empty())
addSeparator(coord1, coord2);
addGroup(mWindowManager.getGameSettingString("sSign", "Sign"), coord1, coord2);
addGroup(mWindowManager.getGameSettingString("sBirthSign", "Sign"), coord1, coord2);
const ESM::BirthSign *sign = store.birthSigns.find(birthSignId);
addItem(sign->name, coord1, coord2);
MyGUI::Widget* w = addItem(sign->name, coord1, coord2);
ToolTips::createBirthsignToolTip(w, birthSignId);
}
// Add a line separator if there are items above
@ -376,12 +531,25 @@ void StatsWindow::updateSkillArea()
addSeparator(coord1, coord2);
addValueItem(mWindowManager.getGameSettingString("sReputation", "Reputation"),
mWindowManager.getGameSettingString("sSkillsMenuReputationHelp", ""),
boost::lexical_cast<std::string>(static_cast<int>(reputation)), "normal", coord1, coord2);
for (int i=0; i<2; ++i)
{
skillWidgets[skillWidgets.size()-1-i]->setUserString("ToolTipType", "Layout");
skillWidgets[skillWidgets.size()-1-i]->setUserString("ToolTipLayout", "TextToolTip");
skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_Text", "#{sSkillsMenuReputationHelp}");
}
addValueItem(mWindowManager.getGameSettingString("sBounty", "Bounty"),
mWindowManager.getGameSettingString("sCrimeHelp", ""),
boost::lexical_cast<std::string>(static_cast<int>(bounty)), "normal", coord1, coord2);
for (int i=0; i<2; ++i)
{
skillWidgets[skillWidgets.size()-1-i]->setUserString("ToolTipType", "Layout");
skillWidgets[skillWidgets.size()-1-i]->setUserString("ToolTipLayout", "TextToolTip");
skillWidgets[skillWidgets.size()-1-i]->setUserString("Caption_Text", "#{sCrimeHelp}");
}
clientHeight = coord1.top;
updateScroller();
}
@ -390,104 +558,11 @@ void StatsWindow::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() );
}
void StatsWindow::onPinToggled()
{
mWindowManager.setHMSVisibility(!mPinned);
}
void StatsWindow::setupToolTips()
{
const ESMS::ESMStore &store = mWindowManager.getStore();
MyGUI::Widget* widget;
getWidget(widget, "Attrib1");
widget->setUserString("ToolTipType", "ImageCaptionText");
widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeStrength")->str);
widget->setUserString("ToolTipText", store.gameSettings.find ("sStrDesc")->str);
widget->setUserString("ToolTipImage", "k\\attribute_strength.dds");
getWidget(widget, "AttribVal1");
widget->setUserString("ToolTipType", "ImageCaptionText");
widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeStrength")->str);
widget->setUserString("ToolTipText", store.gameSettings.find ("sStrDesc")->str);
widget->setUserString("ToolTipImage", "k\\attribute_strength.dds");
getWidget(widget, "Attrib2");
widget->setUserString("ToolTipType", "ImageCaptionText");
widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeIntelligence")->str);
widget->setUserString("ToolTipText", store.gameSettings.find ("sIntDesc")->str);
widget->setUserString("ToolTipImage", "k\\attribute_int.dds");
getWidget(widget, "AttribVal2");
widget->setUserString("ToolTipType", "ImageCaptionText");
widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeIntelligence")->str);
widget->setUserString("ToolTipText", store.gameSettings.find ("sIntDesc")->str);
widget->setUserString("ToolTipImage", "k\\attribute_int.dds");
getWidget(widget, "Attrib3");
widget->setUserString("ToolTipType", "ImageCaptionText");
widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeWillpower")->str);
widget->setUserString("ToolTipText", store.gameSettings.find ("sWilDesc")->str);
widget->setUserString("ToolTipImage", "k\\attribute_wilpower.dds");
getWidget(widget, "AttribVal3");
widget->setUserString("ToolTipType", "ImageCaptionText");
widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeWillpower")->str);
widget->setUserString("ToolTipText", store.gameSettings.find ("sWilDesc")->str);
widget->setUserString("ToolTipImage", "k\\attribute_wilpower.dds");
getWidget(widget, "Attrib4");
widget->setUserString("ToolTipType", "ImageCaptionText");
widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeAgility")->str);
widget->setUserString("ToolTipText", store.gameSettings.find ("sAgiDesc")->str);
widget->setUserString("ToolTipImage", "k\\attribute_agility.dds");
getWidget(widget, "AttribVal4");
widget->setUserString("ToolTipType", "ImageCaptionText");
widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeAgility")->str);
widget->setUserString("ToolTipText", store.gameSettings.find ("sAgiDesc")->str);
widget->setUserString("ToolTipImage", "k\\attribute_agility.dds");
getWidget(widget, "Attrib5");
widget->setUserString("ToolTipType", "ImageCaptionText");
widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeSpeed")->str);
widget->setUserString("ToolTipText", store.gameSettings.find ("sSpdDesc")->str);
widget->setUserString("ToolTipImage", "k\\attribute_speed.dds");
getWidget(widget, "AttribVal5");
widget->setUserString("ToolTipType", "ImageCaptionText");
widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeSpeed")->str);
widget->setUserString("ToolTipText", store.gameSettings.find ("sSpdDesc")->str);
widget->setUserString("ToolTipImage", "k\\attribute_speed.dds");
getWidget(widget, "Attrib6");
widget->setUserString("ToolTipType", "ImageCaptionText");
widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeEndurance")->str);
widget->setUserString("ToolTipText", store.gameSettings.find ("sEndDesc")->str);
widget->setUserString("ToolTipImage", "k\\attribute_endurance.dds");
getWidget(widget, "AttribVal6");
widget->setUserString("ToolTipType", "ImageCaptionText");
widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeEndurance")->str);
widget->setUserString("ToolTipText", store.gameSettings.find ("sEndDesc")->str);
widget->setUserString("ToolTipImage", "k\\attribute_endurance.dds");
getWidget(widget, "Attrib7");
widget->setUserString("ToolTipType", "ImageCaptionText");
widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributePersonality")->str);
widget->setUserString("ToolTipText", store.gameSettings.find ("sPerDesc")->str);
widget->setUserString("ToolTipImage", "k\\attribute_personality.dds");
getWidget(widget, "AttribVal7");
widget->setUserString("ToolTipType", "ImageCaptionText");
widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributePersonality")->str);
widget->setUserString("ToolTipText", store.gameSettings.find ("sPerDesc")->str);
widget->setUserString("ToolTipImage", "k\\attribute_personality.dds");
getWidget(widget, "Attrib8");
widget->setUserString("ToolTipType", "ImageCaptionText");
widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeLuck")->str);
widget->setUserString("ToolTipText", store.gameSettings.find ("sLucDesc")->str);
widget->setUserString("ToolTipImage", "k\\attribute_luck.dds");
getWidget(widget, "AttribVal8");
widget->setUserString("ToolTipType", "ImageCaptionText");
widget->setUserString("ToolTipCaption", store.gameSettings.find ("sAttributeLuck")->str);
widget->setUserString("ToolTipText", store.gameSettings.find ("sLucDesc")->str);
widget->setUserString("ToolTipImage", "k\\attribute_luck.dds");
}

@ -18,13 +18,15 @@ namespace MWGui
class StatsWindow : public WindowPinnableBase
{
public:
typedef std::pair<std::string, int> Faction;
typedef std::vector<Faction> FactionList;
typedef std::map<std::string, int> FactionList;
typedef std::vector<int> SkillList;
StatsWindow(WindowManager& parWindowManager);
/// automatically updates all the data in the stats window, but only if it has changed.
void onFrame();
void setBar(const std::string& name, const std::string& tname, int val, int max);
void setPlayerName(const std::string& playerName);
@ -36,8 +38,6 @@ namespace MWGui
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);
void configureSkills (const SkillList& major, const SkillList& minor);
void setFactions (const std::vector<Faction>& factions);
void setBirthSign (const std::string &signId);
void setReputation (int reputation) { this->reputation = reputation; }
void setBounty (int bounty) { this->bounty = bounty; }
void updateSkillArea();
@ -46,17 +46,22 @@ namespace MWGui
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& tooltip, 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);
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);
void onScrollChangePosition(MyGUI::ScrollBar* scroller, size_t pos);
void onWindowResize(MyGUI::Window* window);
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
static const int lineHeight;
MyGUI::Widget* mLeftPane;
MyGUI::Widget* mRightPane;
MyGUI::WidgetPtr skillAreaWidget, skillClientWidget;
MyGUI::ScrollBar* skillScrollerWidget;
int lastPos, clientHeight;
@ -65,11 +70,13 @@ namespace MWGui
std::map<int, MWMechanics::Stat<float> > skillValues;
std::map<int, MyGUI::TextBox*> skillWidgetMap;
std::map<std::string, MyGUI::WidgetPtr> factionWidgetMap;
FactionList factions; ///< Stores a list of factions and the current rank
FactionList mFactions; ///< Stores a list of factions and the current rank
std::string birthSignId;
int reputation, bounty;
std::vector<MyGUI::WidgetPtr> skillWidgets; //< Skills and other information
bool mChanged;
protected:
virtual void onPinToggled();
};

@ -8,6 +8,8 @@
#include <boost/lexical_cast.hpp>
#include <components/settings/settings.hpp>
using namespace MWGui;
using namespace MyGUI;
@ -16,6 +18,13 @@ ToolTips::ToolTips(WindowManager* windowManager) :
, mGameMode(true)
, mWindowManager(windowManager)
, mFullHelp(false)
, mEnabled(true)
, mFocusToolTipX(0.0)
, mFocusToolTipY(0.0)
, mDelay(0.0)
, mRemainingDelay(0.0)
, mLastMouseX(0)
, mLastMouseY(0)
{
getWidget(mDynamicToolTipBox, "DynamicToolTipBox");
@ -25,75 +34,225 @@ 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)
{
mEnabled = enabled;
}
void ToolTips::onFrame(float frameDuration)
{
/// \todo Store a MWWorld::Ptr in the widget user data, retrieve it here and construct a tooltip dynamically
while (mDynamicToolTipBox->getChildCount())
{
MyGUI::Gui::getInstance().destroyWidget(mDynamicToolTipBox->getChildAt(0));
}
MyGUI::Gui::getInstance().destroyWidget(mDynamicToolTipBox);
mDynamicToolTipBox = mMainWidget->createWidget<Widget>("HUD_Box",
IntCoord(0, 0, mMainWidget->getCoord().width, mMainWidget->getCoord().height),
Align::Stretch, "DynamicToolTipBox");
// start by hiding everything
for (unsigned int i=0; i < mMainWidget->getChildCount(); ++i)
{
mMainWidget->getChildAt(i)->setVisible(false);
}
const IntSize &viewSize = RenderManager::getInstance().getViewSize();
if (!mEnabled)
{
return;
}
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)))
{
mDynamicToolTipBox->setVisible(false);
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 == "")
{
mDynamicToolTipBox->setVisible(false);
return;
}
else if (type == "Text")
{
info.text = text;
}
else if (type == "CaptionText")
{
std::string caption = focus->getUserString("ToolTipCaption");
info.caption = caption;
info.text = text;
// 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 == "ImageCaptionText")
else
{
std::string caption = focus->getUserString("ToolTipCaption");
std::string image = focus->getUserString("ToolTipImage");
std::string sizeString = focus->getUserString("ToolTipImageSize");
const MyGUI::IntPoint& lastPressed = InputManager::getInstance().getLastPressedPosition(MyGUI::MouseButton::Left);
info.text = text;
info.caption = caption;
info.icon = image;
}
tooltipSize = createToolTip(info);
if (mousePos == lastPressed) // mouseclick makes tooltip disappear
return;
IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24);
if (mousePos.left == mLastMouseX && mousePos.top == mLastMouseY)
{
mRemainingDelay -= frameDuration;
}
else
{
mRemainingDelay = mDelay;
}
mLastMouseX = mousePos.left;
mLastMouseY = mousePos.top;
// 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;
}
if (mRemainingDelay > 0)
return;
setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height);
mDynamicToolTipBox->setVisible(true);
Widget* focus = InputManager::getInstance().getMouseFocusWidget();
if (focus == 0)
{
return;
}
IntSize tooltipSize;
// try to go 1 level up until there is a widget that has tooltip
// this is necessary because some skin elements are actually separate widgets
int i=0;
while (!focus->isUserString("ToolTipType"))
{
focus = focus->getParent();
if (!focus)
return;
++i;
}
std::string type = focus->getUserString("ToolTipType");
std::string text = focus->getUserString("ToolTipText");
if (type == "")
{
return;
}
else if (type == "ItemPtr")
{
mFocusObject = *focus->getUserData<MWWorld::Ptr>();
tooltipSize = getToolTipViaPtr(false);
}
else if (type == "Spell")
{
ToolTipInfo info;
const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().spells.find(focus->getUserString("Spell"));
info.caption = spell->name;
Widgets::SpellEffectList effects;
std::vector<ESM::ENAMstruct>::const_iterator end = spell->effects.list.end();
for (std::vector<ESM::ENAMstruct>::const_iterator it = spell->effects.list.begin(); it != end; ++it)
{
Widgets::SpellEffectParams params;
params.mEffectID = it->effectID;
params.mSkill = it->skill;
params.mAttribute = it->attribute;
params.mDuration = it->duration;
params.mMagnMin = it->magnMin;
params.mMagnMax = it->magnMax;
params.mRange = it->range;
params.mIsConstant = (spell->data.type == ESM::Spell::ST_Ability);
effects.push_back(params);
}
info.effects = effects;
tooltipSize = createToolTip(info);
}
else if (type == "Layout")
{
// 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
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)
{
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);
}
for (unsigned int i=0; i<tooltip->getChildCount(); ++i)
{
MyGUI::Widget* w = tooltip->getChildAt(i);
if (w->isUserString("AutoResizeHorizontal"))
{
MyGUI::TextBox* text = w->castType<MyGUI::TextBox>();
tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + text->getTextSize().width + 8);
}
else if (!tooltip->isUserString("DontResize"))
tooltipSize.width = std::max(tooltipSize.width, w->getLeft() + w->getWidth() + 8);
if (w->isUserString("AutoResizeVertical"))
{
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);
}
else
throw std::runtime_error ("unknown tooltip type");
IntPoint tooltipPosition = InputManager::getInstance().getMousePosition() + IntPoint(0, 24);
// make the tooltip stay completely in the viewport
if ((tooltipPosition.left + tooltipSize.width) > viewSize.width)
{
tooltipPosition.left = viewSize.width - tooltipSize.width;
}
if ((tooltipPosition.top + tooltipSize.height) > viewSize.height)
{
tooltipPosition.top = viewSize.height - tooltipSize.height;
}
setCoord(tooltipPosition.left, tooltipPosition.top, tooltipSize.width, tooltipSize.height);
}
}
else
{
@ -101,15 +260,13 @@ void ToolTips::onFrame(float frameDuration)
{
IntSize tooltipSize = getToolTipViaPtr();
// adjust tooltip size to fit its content, position it above the crosshair
/// \todo Slide the tooltip along the bounding box of the focused object (like in Morrowind)
setCoord(std::max(0, viewSize.width/2 - (tooltipSize.width)/2),
std::max(0, viewSize.height/2 - (tooltipSize.height) - 32),
setCoord(viewSize.width/2 - tooltipSize.width/2,
std::max(0, int(mFocusToolTipY*viewSize.height - tooltipSize.height)),
tooltipSize.width,
tooltipSize.height);
mDynamicToolTipBox->setVisible(true);
}
else
mDynamicToolTipBox->setVisible(false);
}
}
@ -128,7 +285,7 @@ void ToolTips::setFocusObject(const MWWorld::Ptr& focus)
mFocusObject = focus;
}
IntSize ToolTips::getToolTipViaPtr ()
IntSize ToolTips::getToolTipViaPtr (bool image)
{
// this the maximum width of the tooltip before it starts word-wrapping
setCoord(0, 0, 300, 300);
@ -145,6 +302,8 @@ IntSize ToolTips::getToolTipViaPtr ()
mDynamicToolTipBox->setVisible(true);
ToolTipInfo info = object.getToolTipInfo(mFocusObject);
if (!image)
info.icon = "";
tooltipSize = createToolTip(info);
}
@ -165,8 +324,10 @@ void ToolTips::findImageExtension(std::string& image)
}
}
IntSize ToolTips::createToolTip(const ToolTipInfo& info)
IntSize ToolTips::createToolTip(const MWGui::ToolTipInfo& info)
{
mDynamicToolTipBox->setVisible(true);
std::string caption = info.caption;
std::string image = info.icon;
int imageSize = (image != "") ? 32 : 0;
@ -221,7 +382,7 @@ IntSize ToolTips::createToolTip(const 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),
@ -241,7 +402,7 @@ IntSize ToolTips::createToolTip(const 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);
}
@ -257,7 +418,7 @@ IntSize ToolTips::createToolTip(const 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;
@ -275,10 +436,12 @@ IntSize ToolTips::createToolTip(const 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;
totalSize.width = std::max(totalSize.width, chargeAndTextWidth);
chargeText->setCoord((totalSize.width - chargeAndTextWidth)/2, coord.top+6, chargeTextWidth, 18);
IntCoord chargeCoord;
@ -350,6 +513,14 @@ std::string ToolTips::getMiscString(const std::string& text, const std::string&
return "\n" + prefix + ": " + text;
}
std::string ToolTips::getCountString(const int value)
{
if (value == 1)
return "";
else
return " (" + boost::lexical_cast<std::string>(value) + ")";
}
void ToolTips::toggleFullHelp()
{
mFullHelp = !mFullHelp;
@ -359,3 +530,162 @@ bool ToolTips::getFullHelp() const
{
return mFullHelp;
}
void ToolTips::setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y)
{
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
@ -39,10 +36,16 @@ namespace MWGui
void enterGameMode();
void enterGuiMode();
void setEnabled(bool enabled);
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
static std::string getValueString(const int value, const std::string& prefix);
///< @return "prefix: value" or "" if value is 0
@ -53,6 +56,18 @@ namespace MWGui
static std::string toString(const float value);
static std::string toString(const int value);
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;
@ -62,14 +77,25 @@ namespace MWGui
void findImageExtension(std::string& image);
MyGUI::IntSize getToolTipViaPtr ();
MyGUI::IntSize getToolTipViaPtr (bool image=true);
///< @return requested tooltip size
MyGUI::IntSize createToolTip(const ToolTipInfo& info);
///< @return requested tooltip size
float mFocusToolTipX;
float mFocusToolTipY;
float mDelay;
float mRemainingDelay; // remaining time until tooltip will show
int mLastMouseX;
int mLastMouseY;
bool mGameMode;
bool mEnabled;
bool mFullHelp;
};
}

@ -0,0 +1,370 @@
#include "tradewindow.hpp"
#include <boost/lexical_cast.hpp>
#include "../mwbase/environment.hpp"
#include "../mwworld/world.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/manualref.hpp"
#include "../mwsound/soundmanager.hpp"
#include "window_manager.hpp"
#include "inventorywindow.hpp"
namespace MWGui
{
TradeWindow::TradeWindow(WindowManager& parWindowManager) :
WindowBase("openmw_trade_window_layout.xml", parWindowManager)
, ContainerBase(NULL) // no drag&drop
, mCurrentBalance(0)
{
MyGUI::ScrollView* itemView;
MyGUI::Widget* containerWidget;
getWidget(containerWidget, "Items");
getWidget(itemView, "ItemView");
setWidgets(containerWidget, itemView);
getWidget(mFilterAll, "AllButton");
getWidget(mFilterWeapon, "WeaponButton");
getWidget(mFilterApparel, "ApparelButton");
getWidget(mFilterMagic, "MagicButton");
getWidget(mFilterMisc, "MiscButton");
getWidget(mMaxSaleButton, "MaxSaleButton");
getWidget(mCancelButton, "CancelButton");
getWidget(mOfferButton, "OfferButton");
getWidget(mPlayerGold, "PlayerGold");
getWidget(mMerchantGold, "MerchantGold");
getWidget(mIncreaseButton, "IncreaseButton");
getWidget(mDecreaseButton, "DecreaseButton");
getWidget(mTotalBalance, "TotalBalance");
getWidget(mTotalBalanceLabel, "TotalBalanceLabel");
getWidget(mBottomPane, "BottomPane");
// adjust size of buttons to fit text
int curX = 0;
mFilterAll->setSize( mFilterAll->getTextSize().width + 24, mFilterAll->getSize().height );
curX += mFilterAll->getTextSize().width + 24 + 4;
mFilterWeapon->setPosition(curX, mFilterWeapon->getPosition().top);
mFilterWeapon->setSize( mFilterWeapon->getTextSize().width + 24, mFilterWeapon->getSize().height );
curX += mFilterWeapon->getTextSize().width + 24 + 4;
mFilterApparel->setPosition(curX, mFilterApparel->getPosition().top);
mFilterApparel->setSize( mFilterApparel->getTextSize().width + 24, mFilterApparel->getSize().height );
curX += mFilterApparel->getTextSize().width + 24 + 4;
mFilterMagic->setPosition(curX, mFilterMagic->getPosition().top);
mFilterMagic->setSize( mFilterMagic->getTextSize().width + 24, mFilterMagic->getSize().height );
curX += mFilterMagic->getTextSize().width + 24 + 4;
mFilterMisc->setPosition(curX, mFilterMisc->getPosition().top);
mFilterMisc->setSize( mFilterMisc->getTextSize().width + 24, mFilterMisc->getSize().height );
mFilterAll->setStateSelected(true);
mFilterAll->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged);
mFilterWeapon->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged);
mFilterApparel->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged);
mFilterMagic->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged);
mFilterMisc->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged);
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onCancelButtonClicked);
mOfferButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onOfferButtonClicked);
mMaxSaleButton->setSize(MyGUI::IntSize(mMaxSaleButton->getTextSize().width + 24, mMaxSaleButton->getHeight()));
int cancelButtonWidth = mCancelButton->getTextSize().width + 24;
mCancelButton->setCoord(mBottomPane->getWidth()-cancelButtonWidth,
mCancelButton->getTop(),
cancelButtonWidth,
mCancelButton->getHeight());
int offerButtonWidth = mOfferButton->getTextSize().width + 24;
mOfferButton->setCoord(mBottomPane->getWidth()-cancelButtonWidth-offerButtonWidth-8,
mOfferButton->getTop(),
offerButtonWidth,
mOfferButton->getHeight());
setCoord(400, 0, 400, 300);
static_cast<MyGUI::Window*>(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &TradeWindow::onWindowResize);
}
void TradeWindow::startTrade(MWWorld::Ptr actor)
{
setTitle(MWWorld::Class::get(actor).getName(actor));
mCurrentBalance = 0;
mWindowManager.getInventoryWindow()->startTrade();
mBoughtItems.clear();
ContainerBase::openContainer(actor);
updateLabels();
drawItems();
}
void TradeWindow::onFilterChanged(MyGUI::Widget* _sender)
{
if (_sender == mFilterAll)
setFilter(ContainerBase::Filter_All);
else if (_sender == mFilterWeapon)
setFilter(ContainerBase::Filter_Weapon);
else if (_sender == mFilterApparel)
setFilter(ContainerBase::Filter_Apparel);
else if (_sender == mFilterMagic)
setFilter(ContainerBase::Filter_Magic);
else if (_sender == mFilterMisc)
setFilter(ContainerBase::Filter_Misc);
mFilterAll->setStateSelected(false);
mFilterWeapon->setStateSelected(false);
mFilterApparel->setStateSelected(false);
mFilterMagic->setStateSelected(false);
mFilterMisc->setStateSelected(false);
static_cast<MyGUI::Button*>(_sender)->setStateSelected(true);
}
void TradeWindow::onWindowResize(MyGUI::Window* _sender)
{
drawItems();
}
void TradeWindow::onOfferButtonClicked(MyGUI::Widget* _sender)
{
// were there any items traded at all?
MWWorld::ContainerStore& playerBought = mWindowManager.getInventoryWindow()->getBoughtItems();
MWWorld::ContainerStore& merchantBought = getBoughtItems();
if (playerBought.begin() == playerBought.end() && merchantBought.begin() == merchantBought.end())
{
// user notification
MWBase::Environment::get().getWindowManager()->
messageBox(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarterDialog11")->str, std::vector<std::string>());
return;
}
// check if the player can afford this
if (mCurrentBalance < 0 && mWindowManager.getInventoryWindow()->getPlayerGold() < std::abs(mCurrentBalance))
{
// user notification
MWBase::Environment::get().getWindowManager()->
messageBox(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarterDialog1")->str, std::vector<std::string>());
return;
}
// check if the merchant can afford this
int merchantgold;
if (mPtr.getTypeName() == typeid(ESM::NPC).name())
{
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* ref = mPtr.get<ESM::NPC>();
if (ref->base->npdt52.gold == -10)
merchantgold = ref->base->npdt12.gold;
else
merchantgold = ref->base->npdt52.gold;
}
else // ESM::Creature
{
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData>* ref = mPtr.get<ESM::Creature>();
merchantgold = ref->base->data.gold;
}
if (mCurrentBalance > 0 && merchantgold < mCurrentBalance)
{
// user notification
MWBase::Environment::get().getWindowManager()->
messageBox(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarterDialog2")->str, std::vector<std::string>());
return;
}
// success! make the item transfer.
transferBoughtItems();
mWindowManager.getInventoryWindow()->transferBoughtItems();
// add or remove gold from the player.
bool goldFound = false;
MWWorld::Ptr gold;
MWWorld::ContainerStore& playerStore = mWindowManager.getInventoryWindow()->getContainerStore();
for (MWWorld::ContainerStoreIterator it = playerStore.begin();
it != playerStore.end(); ++it)
{
if (MWWorld::Class::get(*it).getName(*it) == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sGold")->str)
{
goldFound = true;
gold = *it;
}
}
if (goldFound)
{
gold.getRefData().setCount(gold.getRefData().getCount() + mCurrentBalance);
}
else
{
assert(mCurrentBalance > 0);
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), "Gold_001");
ref.getPtr().getRefData().setCount(mCurrentBalance);
playerStore.add(ref.getPtr());
}
std::string sound = "Item Gold Up";
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
mWindowManager.removeGuiMode(GM_Barter);
}
void TradeWindow::onCancelButtonClicked(MyGUI::Widget* _sender)
{
// i give you back your stuff!
returnBoughtItems(mWindowManager.getInventoryWindow()->getContainerStore());
// now gimme back my stuff!
mWindowManager.getInventoryWindow()->returnBoughtItems(MWWorld::Class::get(mPtr).getContainerStore(mPtr));
mWindowManager.removeGuiMode(GM_Barter);
}
void TradeWindow::updateLabels()
{
mPlayerGold->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sYourGold")->str
+ " " + boost::lexical_cast<std::string>(mWindowManager.getInventoryWindow()->getPlayerGold()));
if (mCurrentBalance > 0)
{
mTotalBalanceLabel->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTotalSold")->str);
mTotalBalance->setCaption(boost::lexical_cast<std::string>(mCurrentBalance));
}
else
{
mTotalBalanceLabel->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sTotalCost")->str);
mTotalBalance->setCaption(boost::lexical_cast<std::string>(-mCurrentBalance));
}
int merchantgold;
if (mPtr.getTypeName() == typeid(ESM::NPC).name())
{
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* ref = mPtr.get<ESM::NPC>();
if (ref->base->npdt52.gold == -10)
merchantgold = ref->base->npdt12.gold;
else
merchantgold = ref->base->npdt52.gold;
}
else // ESM::Creature
{
ESMS::LiveCellRef<ESM::Creature, MWWorld::RefData>* ref = mPtr.get<ESM::Creature>();
merchantgold = ref->base->data.gold;
}
mMerchantGold->setCaption(MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sSellerGold")->str
+ " " + boost::lexical_cast<std::string>(merchantgold));
}
std::vector<MWWorld::Ptr> TradeWindow::getEquippedItems()
{
std::vector<MWWorld::Ptr> items;
if (mPtr.getTypeName() == typeid(ESM::Creature).name())
{
// creatures don't have equipment slots.
return items;
}
MWWorld::InventoryStore& invStore = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot)
{
MWWorld::ContainerStoreIterator it = invStore.getSlot(slot);
if (it != invStore.end())
{
items.push_back(*it);
}
}
return items;
}
bool TradeWindow::npcAcceptsItem(MWWorld::Ptr item)
{
int services = 0;
if (mPtr.getTypeName() == typeid(ESM::NPC).name())
{
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* ref = mPtr.get<ESM::NPC>();
if (ref->base->hasAI)
services = ref->base->AI.services;
}
else if (mPtr.getTypeName() == typeid(ESM::Creature).name())
{
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())
return services & ESM::NPC::Armor;
else if (item.getTypeName() == typeid(ESM::Clothing).name())
return services & ESM::NPC::Clothing;
else if (item.getTypeName() == typeid(ESM::Book).name())
return services & ESM::NPC::Books;
else if (item.getTypeName() == typeid(ESM::Ingredient).name())
return services & ESM::NPC::Ingredients;
else if (item.getTypeName() == typeid(ESM::Tool).name())
return services & ESM::NPC::Picks;
else if (item.getTypeName() == typeid(ESM::Probe).name())
return services & ESM::NPC::Probes;
else if (item.getTypeName() == typeid(ESM::Light).name())
return services & ESM::NPC::Lights;
else if (item.getTypeName() == typeid(ESM::Apparatus).name())
return services & ESM::NPC::Apparatus;
else if (item.getTypeName() == typeid(ESM::Repair).name())
return services & ESM::NPC::RepairItem;
else if (item.getTypeName() == typeid(ESM::Miscellaneous).name())
return services & ESM::NPC::Misc;
return false;
}
std::vector<MWWorld::Ptr> TradeWindow::itemsToIgnore()
{
std::vector<MWWorld::Ptr> items;
MWWorld::ContainerStore& invStore = MWWorld::Class::get(mPtr).getContainerStore(mPtr);
for (MWWorld::ContainerStoreIterator it = invStore.begin();
it != invStore.end(); ++it)
{
if (!npcAcceptsItem(*it))
items.push_back(*it);
}
return items;
}
void TradeWindow::sellToNpc(MWWorld::Ptr item, int count)
{
/// \todo price adjustment depending on merchantile skill
mCurrentBalance -= MWWorld::Class::get(item).getValue(item) * count;
updateLabels();
}
void TradeWindow::buyFromNpc(MWWorld::Ptr item, int count)
{
/// \todo price adjustment depending on merchantile skill
mCurrentBalance += MWWorld::Class::get(item).getValue(item) * count;
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);
}
}

@ -0,0 +1,77 @@
#ifndef MWGUI_TRADEWINDOW_H
#define MWGUI_TRADEWINDOW_H
#include "container.hpp"
#include "window_base.hpp"
#include "../mwworld/ptr.hpp"
namespace MyGUI
{
class Gui;
class Widget;
}
namespace MWGui
{
class WindowManager;
}
namespace MWGui
{
class TradeWindow : public ContainerBase, public WindowBase
{
public:
TradeWindow(WindowManager& parWindowManager);
void startTrade(MWWorld::Ptr actor);
void sellToNpc(MWWorld::Ptr item, int count); ///< only used for adjusting the gold balance
void buyFromNpc(MWWorld::Ptr item, int count); ///< only used for adjusting the gold balance
bool npcAcceptsItem(MWWorld::Ptr item);
protected:
MyGUI::Button* mFilterAll;
MyGUI::Button* mFilterWeapon;
MyGUI::Button* mFilterApparel;
MyGUI::Button* mFilterMagic;
MyGUI::Button* mFilterMisc;
MyGUI::Button* mIncreaseButton;
MyGUI::Button* mDecreaseButton;
MyGUI::TextBox* mTotalBalanceLabel;
MyGUI::TextBox* mTotalBalance;
MyGUI::Widget* mBottomPane;
MyGUI::Button* mMaxSaleButton;
MyGUI::Button* mCancelButton;
MyGUI::Button* mOfferButton;
MyGUI::TextBox* mPlayerGold;
MyGUI::TextBox* mMerchantGold;
int mCurrentBalance;
void onWindowResize(MyGUI::Window* _sender);
void onFilterChanged(MyGUI::Widget* _sender);
void onOfferButtonClicked(MyGUI::Widget* _sender);
void onCancelButtonClicked(MyGUI::Widget* _sender);
// don't show items that the NPC has equipped in his trade-window.
virtual bool ignoreEquippedItems() { return true; }
virtual std::vector<MWWorld::Ptr> getEquippedItems();
virtual bool isTrading() { return true; }
virtual bool isTradeWindow() { return true; }
virtual std::vector<MWWorld::Ptr> itemsToIgnore();
void updateLabels();
virtual void onReferenceUnavailable();
};
}
#endif

@ -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);

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

Loading…
Cancel
Save