Merge branch 'next' of https://github.com/zinnschlag/openmw into graphics

actorid
scrawl 12 years ago
commit 32b837ebd4

@ -391,11 +391,11 @@ if(WIN32)
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".") INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".")
SET(CPACK_GENERATOR "NSIS") SET(CPACK_GENERATOR "NSIS")
SET(CPACK_PACKAGE_NAME "OpenMW") SET(CPACK_PACKAGE_NAME "OpenMW ${OPENMW_VERSION}")
SET(CPACK_PACKAGE_VENDOR "OpenMW.org") SET(CPACK_PACKAGE_VENDOR "OpenMW.org")
SET(CPACK_PACKAGE_VERSION ${OPENMW_VERSION}) SET(CPACK_PACKAGE_VERSION ${OPENMW_VERSION})
SET(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR}) SET(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR})
SET(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO}) SET(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINOR})
SET(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE}) SET(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW;omwlauncher;OpenMW Launcher") SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW;omwlauncher;OpenMW Launcher")
SET(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Readme.lnk' '\$INSTDIR\\\\readme.txt'") SET(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Readme.lnk' '\$INSTDIR\\\\readme.txt'")

@ -16,7 +16,7 @@
#include <iostream> #include <iostream>
#include <boost/format.hpp> #include <boost/format.hpp>
std::string bodyPartLabel(char idx) std::string bodyPartLabel(int idx)
{ {
const char *bodyPartLabels[] = { const char *bodyPartLabels[] = {
"Head", "Head",
@ -47,14 +47,14 @@ std::string bodyPartLabel(char idx)
"Weapon", "Weapon",
"Tail" "Tail"
}; };
if ((int)idx >= 0 && (int)(idx) <= 26) if (idx >= 0 && idx <= 26)
return bodyPartLabels[(int)(idx)]; return bodyPartLabels[idx];
else else
return "Invalid"; return "Invalid";
} }
std::string meshPartLabel(char idx) std::string meshPartLabel(int idx)
{ {
const char *meshPartLabels[] = { const char *meshPartLabels[] = {
"Head", "Head",
@ -73,25 +73,25 @@ std::string meshPartLabel(char idx)
"Clavicle", "Clavicle",
"Tail" "Tail"
}; };
if ((int)(idx) >= 0 && (int)(idx) <= ESM::BodyPart::MP_Tail) if (idx >= 0 && idx <= ESM::BodyPart::MP_Tail)
return meshPartLabels[(int)(idx)]; return meshPartLabels[idx];
else else
return "Invalid"; return "Invalid";
} }
std::string meshTypeLabel(char idx) std::string meshTypeLabel(int idx)
{ {
const char *meshTypeLabels[] = { const char *meshTypeLabels[] = {
"Skin", "Skin",
"Clothing", "Clothing",
"Armor" "Armor"
}; };
if ((int)(idx) >= 0 && (int)(idx) <= ESM::BodyPart::MT_Armor) if (idx >= 0 && idx <= ESM::BodyPart::MT_Armor)
return meshTypeLabels[(int)(idx)]; return meshTypeLabels[idx];
else else
return "Invalid"; return "Invalid";
} }
std::string clothingTypeLabel(int idx) std::string clothingTypeLabel(int idx)
@ -108,7 +108,7 @@ std::string clothingTypeLabel(int idx)
"Ring", "Ring",
"Amulet" "Amulet"
}; };
if (idx >= 0 && idx <= 9) if (idx >= 0 && idx <= 9)
return clothingTypeLabels[idx]; return clothingTypeLabels[idx];
else else

@ -3,9 +3,9 @@
#include <string> #include <string>
std::string bodyPartLabel(char idx); std::string bodyPartLabel(int idx);
std::string meshPartLabel(char idx); std::string meshPartLabel(int idx);
std::string meshTypeLabel(char idx); std::string meshTypeLabel(int idx);
std::string clothingTypeLabel(int idx); std::string clothingTypeLabel(int idx);
std::string armorTypeLabel(int idx); std::string armorTypeLabel(int idx);
std::string dialogTypeLabel(int idx); std::string dialogTypeLabel(int idx);

@ -59,7 +59,7 @@ opencs_units (view/world
) )
opencs_units_noqt (view/world opencs_units_noqt (view/world
dialoguesubview util subviews dialoguesubview util subviews enumdelegate vartypedelegate
) )
@ -75,7 +75,7 @@ opencs_units_noqt (view/tools
set (OPENCS_US set (OPENCS_US
) )
set (OPENCS_RES set (OPENCS_RES ../../files/opencs/resources.qrc
) )
source_group (opencs FILES ${OPENCS_SRC} ${OPENCS_HDR}) source_group (opencs FILES ${OPENCS_SRC} ${OPENCS_HDR})
@ -104,4 +104,4 @@ target_link_libraries(opencs
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${QT_LIBRARIES} ${QT_LIBRARIES}
components components
) )

@ -5,6 +5,7 @@
#include <iostream> #include <iostream>
#include <QtGui/QApplication> #include <QtGui/QApplication>
#include <QIcon>
class Application : public QApplication class Application : public QApplication
{ {
@ -31,9 +32,12 @@ class Application : public QApplication
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
Q_INIT_RESOURCE (resources);
Application mApplication (argc, argv); Application mApplication (argc, argv);
mApplication.setWindowIcon (QIcon (":./opencs.png"));
CS::Editor editor; CS::Editor editor;
return editor.run(); return editor.run();
} }

@ -18,6 +18,136 @@ void CSMDoc::Document::load (const std::vector<boost::filesystem::path>::const_i
if (lastAsModified) if (lastAsModified)
getData().loadFile (*end2, false); getData().loadFile (*end2, false);
addOptionalGmsts();
}
void CSMDoc::Document::addOptionalGmsts()
{
static const char *sFloats[] =
{
"fCombatDistanceWerewolfMod",
"fFleeDistance",
"fWereWolfAcrobatics",
"fWereWolfAgility",
"fWereWolfAlchemy",
"fWereWolfAlteration",
"fWereWolfArmorer",
"fWereWolfAthletics",
"fWereWolfAxe",
"fWereWolfBlock",
"fWereWolfBluntWeapon",
"fWereWolfConjuration",
"fWereWolfDestruction",
"fWereWolfEnchant",
"fWereWolfEndurance",
"fWereWolfFatigue",
"fWereWolfHandtoHand",
"fWereWolfHealth",
"fWereWolfHeavyArmor",
"fWereWolfIllusion",
"fWereWolfIntellegence",
"fWereWolfLightArmor",
"fWereWolfLongBlade",
"fWereWolfLuck",
"fWereWolfMagicka",
"fWereWolfMarksman",
"fWereWolfMediumArmor",
"fWereWolfMerchantile",
"fWereWolfMysticism",
"fWereWolfPersonality",
"fWereWolfRestoration",
"fWereWolfRunMult",
"fWereWolfSecurity",
"fWereWolfShortBlade",
"fWereWolfSilverWeaponDamageMult",
"fWereWolfSneak",
"fWereWolfSpear",
"fWereWolfSpeechcraft",
"fWereWolfSpeed",
"fWereWolfStrength",
"fWereWolfUnarmored",
"fWereWolfWillPower",
0
};
static const char *sIntegers[] =
{
"iWereWolfBounty",
"iWereWolfFightMod",
"iWereWolfFleeMod",
"iWereWolfLevelToAttack",
0
};
static const char *sStrings[] =
{
"sCompanionShare",
"sCompanionWarningButtonOne",
"sCompanionWarningButtonTwo",
"sCompanionWarningMessage",
"sDeleteNote",
"sEditNote",
"sEffectSummonCreature01",
"sEffectSummonCreature02",
"sEffectSummonCreature03",
"sEffectSummonCreature04",
"sEffectSummonCreature05",
"sEffectSummonFabricant",
"sLevitateDisabled",
"sMagicCreature01ID",
"sMagicCreature02ID",
"sMagicCreature03ID",
"sMagicCreature04ID",
"sMagicCreature05ID",
"sMagicFabricantID",
"sMaxSale",
"sProfitValue",
"sTeleportDisabled",
"sWerewolfAlarmMessage",
"sWerewolfPopup",
"sWerewolfRefusal",
"sWerewolfRestMessage",
0
};
for (int i=0; sFloats[i]; ++i)
{
ESM::GameSetting gmst;
gmst.mId = sFloats[i];
gmst.mF = 0;
gmst.mType = ESM::VT_Float;
addOptionalGmst (gmst);
}
for (int i=0; sIntegers[i]; ++i)
{
ESM::GameSetting gmst;
gmst.mId = sIntegers[i];
gmst.mI = 0;
gmst.mType = ESM::VT_Long;
addOptionalGmst (gmst);
}
for (int i=0; sStrings[i]; ++i)
{
ESM::GameSetting gmst;
gmst.mId = sStrings[i];
gmst.mStr = "<no text>";
gmst.mType = ESM::VT_String;
addOptionalGmst (gmst);
}
}
void CSMDoc::Document::addOptionalGmst (const ESM::GameSetting& gmst)
{
if (getData().getGmsts().searchId (gmst.mId)==-1)
{
CSMWorld::Record<ESM::GameSetting> record;
record.mBase = gmst;
record.mState = CSMWorld::RecordBase::State_BaseOnly;
getData().getGmsts().appendRecord (record);
}
} }
void CSMDoc::Document::createBase() void CSMDoc::Document::createBase()

@ -17,6 +17,11 @@
class QAbstractItemModel; class QAbstractItemModel;
namespace ESM
{
struct GameSetting;
}
namespace CSMDoc namespace CSMDoc
{ {
class Document : public QObject class Document : public QObject
@ -46,6 +51,10 @@ namespace CSMDoc
void createBase(); void createBase();
void addOptionalGmsts();
void addOptionalGmst (const ESM::GameSetting& gmst);
public: public:
Document (const std::vector<boost::filesystem::path>& files, bool new_); Document (const std::vector<boost::filesystem::path>& files, bool new_);

@ -29,7 +29,8 @@ namespace CSMWorld
Display_String, Display_String,
Display_Integer, Display_Integer,
Display_Float, Display_Float,
Display_Var Display_Var,
Display_VarType
}; };
std::string mTitle; std::string mTitle;

@ -79,7 +79,7 @@ namespace CSMWorld
int mType; int mType;
FixedRecordTypeColumn (int type) FixedRecordTypeColumn (int type)
: Column<ESXRecordT> ("Type", ColumnBase::Display_Integer, 0), mType (type) {} : Column<ESXRecordT> ("Record Type", ColumnBase::Display_Integer, 0), mType (type) {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
@ -92,10 +92,11 @@ namespace CSMWorld
} }
}; };
/// \attention A var type column must be immediately followed by a suitable value column.
template<typename ESXRecordT> template<typename ESXRecordT>
struct VarTypeColumn : public Column<ESXRecordT> struct VarTypeColumn : public Column<ESXRecordT>
{ {
VarTypeColumn() : Column<ESXRecordT> ("Type", ColumnBase::Display_Integer) {} VarTypeColumn() : Column<ESXRecordT> ("Type", ColumnBase::Display_VarType) {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {

@ -54,6 +54,16 @@ CSMWorld::IdCollection<ESM::Global>& CSMWorld::Data::getGlobals()
return mGlobals; return mGlobals;
} }
const CSMWorld::IdCollection<ESM::GameSetting>& CSMWorld::Data::getGmsts() const
{
return mGmsts;
}
CSMWorld::IdCollection<ESM::GameSetting>& CSMWorld::Data::getGmsts()
{
return mGmsts;
}
QAbstractTableModel *CSMWorld::Data::getTableModel (const UniversalId& id) QAbstractTableModel *CSMWorld::Data::getTableModel (const UniversalId& id)
{ {
std::map<UniversalId::Type, QAbstractTableModel *>::iterator iter = mModelIndex.find (id.getType()); std::map<UniversalId::Type, QAbstractTableModel *>::iterator iter = mModelIndex.find (id.getType());
@ -72,7 +82,11 @@ void CSMWorld::Data::merge()
void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base) void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
{ {
ESM::ESMReader reader; ESM::ESMReader reader;
/// \todo set encoder
/// \todo set encoding properly, once config implementation has been fixed.
ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding ("win1252"));
reader.setEncoder (&encoder);
reader.open (path.string()); reader.open (path.string());
// Note: We do not need to send update signals here, because at this point the model is not connected // Note: We do not need to send update signals here, because at this point the model is not connected

@ -40,6 +40,10 @@ namespace CSMWorld
IdCollection<ESM::Global>& getGlobals(); IdCollection<ESM::Global>& getGlobals();
const IdCollection<ESM::GameSetting>& getGmsts() const;
IdCollection<ESM::GameSetting>& getGmsts();
QAbstractTableModel *getTableModel (const UniversalId& id); QAbstractTableModel *getTableModel (const UniversalId& id);
///< If no table model is available for \a id, an exception is thrown. ///< If no table model is available for \a id, an exception is thrown.
/// ///

@ -3,19 +3,19 @@
CSMWorld::RecordBase::~RecordBase() {} CSMWorld::RecordBase::~RecordBase() {}
bool CSMWorld::RecordBase::RecordBase::isDeleted() const bool CSMWorld::RecordBase::isDeleted() const
{ {
return mState==State_Deleted || mState==State_Erased; return mState==State_Deleted || mState==State_Erased;
} }
bool CSMWorld::RecordBase::RecordBase::isErased() const bool CSMWorld::RecordBase::isErased() const
{ {
return mState==State_Erased; return mState==State_Erased;
} }
bool CSMWorld::RecordBase::RecordBase::isModified() const bool CSMWorld::RecordBase::isModified() const
{ {
return mState==State_Modified || mState==State_ModifiedOnly; return mState==State_Modified || mState==State_ModifiedOnly;
} }

@ -10,48 +10,48 @@ OpenDialog::OpenDialog(QWidget * parent) : QDialog(parent)
QVBoxLayout *layout = new QVBoxLayout(this); QVBoxLayout *layout = new QVBoxLayout(this);
mFileSelector = new DataFilesList(mCfgMgr, this); mFileSelector = new DataFilesList(mCfgMgr, this);
layout->addWidget(mFileSelector); layout->addWidget(mFileSelector);
//FIXME - same as DataFilesPage::setupDataFiles /// \todo move config to Editor class and add command line options.
// We use the Configuration Manager to retrieve the configuration values // We use the Configuration Manager to retrieve the configuration values
boost::program_options::variables_map variables; boost::program_options::variables_map variables;
boost::program_options::options_description desc; boost::program_options::options_description desc;
desc.add_options() desc.add_options()
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken()) ("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken())
("data-local", boost::program_options::value<std::string>()->default_value("")) ("data-local", boost::program_options::value<std::string>()->default_value(""))
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false)) ("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
("encoding", boost::program_options::value<std::string>()->default_value("win1252")); ("encoding", boost::program_options::value<std::string>()->default_value("win1252"));
boost::program_options::notify(variables); boost::program_options::notify(variables);
mCfgMgr.readConfiguration(variables, desc); mCfgMgr.readConfiguration(variables, desc);
Files::PathContainer mDataDirs, mDataLocal; Files::PathContainer mDataDirs, mDataLocal;
if (!variables["data"].empty()) { if (!variables["data"].empty()) {
mDataDirs = Files::PathContainer(variables["data"].as<Files::PathContainer>()); mDataDirs = Files::PathContainer(variables["data"].as<Files::PathContainer>());
} }
std::string local = variables["data-local"].as<std::string>(); std::string local = variables["data-local"].as<std::string>();
if (!local.empty()) { if (!local.empty()) {
mDataLocal.push_back(Files::PathContainer::value_type(local)); mDataLocal.push_back(Files::PathContainer::value_type(local));
} }
mCfgMgr.processPaths(mDataDirs); mCfgMgr.processPaths(mDataDirs);
mCfgMgr.processPaths(mDataLocal); mCfgMgr.processPaths(mDataLocal);
// Set the charset for reading the esm/esp files // Set the charset for reading the esm/esp files
QString encoding = QString::fromStdString(variables["encoding"].as<std::string>()); QString encoding = QString::fromStdString(variables["encoding"].as<std::string>());
Files::PathContainer dataDirs; Files::PathContainer dataDirs;
dataDirs.insert(dataDirs.end(), mDataDirs.begin(), mDataDirs.end()); dataDirs.insert(dataDirs.end(), mDataDirs.begin(), mDataDirs.end());
dataDirs.insert(dataDirs.end(), mDataLocal.begin(), mDataLocal.end()); dataDirs.insert(dataDirs.end(), mDataLocal.begin(), mDataLocal.end());
mFileSelector->setupDataFiles(dataDirs, encoding); mFileSelector->setupDataFiles(dataDirs, encoding);
buttonBox = new QDialogButtonBox(QDialogButtonBox::Open | QDialogButtonBox::Cancel, Qt::Horizontal, this); buttonBox = new QDialogButtonBox(QDialogButtonBox::Open | QDialogButtonBox::Cancel, Qt::Horizontal, this);
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
layout->addWidget(buttonBox); layout->addWidget(buttonBox);
setLayout(layout); setLayout(layout);
setWindowTitle(tr("Open")); setWindowTitle(tr("Open"));
} }

@ -35,7 +35,7 @@ void CSVDoc::Operation::updateLabel (int threads)
CSVDoc::Operation::Operation (int type) : mType (type), mStalling (false) CSVDoc::Operation::Operation (int type) : mType (type), mStalling (false)
{ {
/// \todo Add a cancel button or a pop up menu with a cancel item /// \todo Add a cancel button or a pop up menu with a cancel item
setBarColor( type);
updateLabel(); updateLabel();
/// \todo assign different progress bar colours to allow the user to distinguish easily between operation types /// \todo assign different progress bar colours to allow the user to distinguish easily between operation types
@ -51,4 +51,70 @@ void CSVDoc::Operation::setProgress (int current, int max, int threads)
int CSVDoc::Operation::getType() const int CSVDoc::Operation::getType() const
{ {
return mType; return mType;
} }
void CSVDoc::Operation::setBarColor (int type)
{
QString style ="QProgressBar {"
"text-align: center;"
"}"
"QProgressBar::chunk {"
"background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 %1, stop:.50 %2 stop: .51 %3 stop:1 %4);"
"text-align: center;"
"margin: 2px 1px 1p 2px;"
"}";
// "QProgressBar::chunk {background-color: %1;}";
QString topColor = "#F2F6F8";
QString bottomColor = "#E0EFF9";
QString midTopColor = "#D8E1E7";
QString midBottomColor = "#B5C6D0"; // default gray gloss
// colors inspired by samples from:
// http://www.colorzilla.com/gradient-editor/
switch (type)
{
case CSMDoc::State_Saving:
topColor = "#FECCB1";
midTopColor = "#F17432";
midBottomColor = "#EA5507";
bottomColor = "#FB955E"; // red gloss #2
//break;
case CSMDoc::State_Searching:
topColor = "#EBF1F6";
midTopColor = "#ABD3EE";
midBottomColor = "#89C3EB";
bottomColor = "#D5EBFB"; //blue gloss #4
//break;
case CSMDoc::State_Verifying:
topColor = "#BFD255";
midTopColor = "#8EB92A";
midBottomColor = "#72AA00";
bottomColor = "#9ECB2D"; //green gloss
//break;
case CSMDoc::State_Compiling:
topColor = "#F3E2C7";
midTopColor = "#C19E67";
midBottomColor = "#B68D4C";
bottomColor = "#E9D4B3"; //l Brown 3D
//break;
default:
topColor = "#F2F6F8";
bottomColor = "#E0EFF9";
midTopColor = "#D8E1E7";
midBottomColor = "#B5C6D0"; // gray gloss for undefined ops
}
setStyleSheet(style.arg(topColor).arg(midTopColor).arg(midBottomColor).arg(bottomColor));
}

@ -25,7 +25,11 @@ namespace CSVDoc
void setProgress (int current, int max, int threads); void setProgress (int current, int max, int threads);
int getType() const; int getType() const;
private:
void setBarColor (int type);
}; };
} }
#endif #endif

@ -6,6 +6,10 @@
#include "../../model/doc/documentmanager.hpp" #include "../../model/doc/documentmanager.hpp"
#include "../../model/doc/document.hpp" #include "../../model/doc/document.hpp"
#include "../world/util.hpp"
#include "../world/enumdelegate.hpp"
#include "../world/vartypedelegate.hpp"
#include "view.hpp" #include "view.hpp"
void CSVDoc::ViewManager::updateIndices() void CSVDoc::ViewManager::updateIndices()
@ -29,11 +33,16 @@ void CSVDoc::ViewManager::updateIndices()
CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
: mDocumentManager (documentManager) : mDocumentManager (documentManager)
{ {
mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection;
mDelegateFactories->add (CSMWorld::ColumnBase::Display_VarType,
new CSVWorld::VarTypeDelegateFactory (ESM::VT_None, ESM::VT_String, ESM::VT_Int, ESM::VT_Float));
} }
CSVDoc::ViewManager::~ViewManager() CSVDoc::ViewManager::~ViewManager()
{ {
delete mDelegateFactories;
for (std::vector<View *>::iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) for (std::vector<View *>::iterator iter (mViews.begin()); iter!=mViews.end(); ++iter)
delete *iter; delete *iter;
} }

@ -11,6 +11,11 @@ namespace CSMDoc
class DocumentManager; class DocumentManager;
} }
namespace CSVWorld
{
class CommandDelegateFactoryCollection;
}
namespace CSVDoc namespace CSVDoc
{ {
class View; class View;
@ -21,6 +26,7 @@ namespace CSVDoc
CSMDoc::DocumentManager& mDocumentManager; CSMDoc::DocumentManager& mDocumentManager;
std::vector<View *> mViews; std::vector<View *> mViews;
CSVWorld::CommandDelegateFactoryCollection *mDelegateFactories;
// not implemented // not implemented
ViewManager (const ViewManager&); ViewManager (const ViewManager&);

@ -0,0 +1,101 @@
#include "enumdelegate.hpp"
#include <stdexcept>
#include <QComboBox>
#include <QApplication>
#include <QUndoStack>
#include "../../model/world/commands.hpp"
void CSVWorld::EnumDelegate::setModelDataImp (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const
{
if (QComboBox *comboBox = dynamic_cast<QComboBox *> (editor))
{
QString value = comboBox->currentText();
for (std::vector<std::pair<int, QString> >::const_iterator iter (mValues.begin());
iter!=mValues.end(); ++iter)
if (iter->second==value)
{
addCommands (model, index, iter->first);
break;
}
}
}
void CSVWorld::EnumDelegate::addCommands (QAbstractItemModel *model,
const QModelIndex& index, int type) const
{
getUndoStack().push (new CSMWorld::ModifyCommand (*model, index, type));
}
CSVWorld::EnumDelegate::EnumDelegate (const std::vector<std::pair<int, QString> >& values,
QUndoStack& undoStack, QObject *parent)
: CommandDelegate (undoStack, parent), mValues (values)
{
}
QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem& option,
const QModelIndex& index) const
{
QComboBox *comboBox = new QComboBox (parent);
for (std::vector<std::pair<int, QString> >::const_iterator iter (mValues.begin());
iter!=mValues.end(); ++iter)
comboBox->addItem (iter->second);
return comboBox;
}
void CSVWorld::EnumDelegate::setEditorData (QWidget *editor, const QModelIndex& index) const
{
if (QComboBox *comboBox = dynamic_cast<QComboBox *> (editor))
{
int value = index.data (Qt::EditRole).toInt();
std::size_t size = mValues.size();
for (std::size_t i=0; i<size; ++i)
if (mValues[i].first==value)
{
comboBox->setCurrentIndex (i);
break;
}
}
}
void CSVWorld::EnumDelegate::paint (QPainter *painter, const QStyleOptionViewItem& option,
const QModelIndex& index) const
{
QStyleOptionViewItemV4 option2 (option);
int value = index.data().toInt();
for (std::vector<std::pair<int, QString> >::const_iterator iter (mValues.begin());
iter!=mValues.end(); ++iter)
if (iter->first==value)
{
option2.text = iter->second;
QApplication::style()->drawControl (QStyle::CE_ItemViewItem, &option2, painter);
break;
}
}
CSVWorld::CommandDelegate *CSVWorld::EnumDelegateFactory::makeDelegate (QUndoStack& undoStack,
QObject *parent) const
{
return new EnumDelegate (mValues, undoStack, parent);
}
void CSVWorld::EnumDelegateFactory::add (int value, const QString& name)
{
mValues.push_back (std::make_pair (value, name));
}

@ -0,0 +1,57 @@
#ifndef CSV_WORLD_ENUMDELEGATE_H
#define CSV_WORLD_ENUMDELEGATE_H
#include <vector>
#include <QString>
#include <components/esm/defs.hpp>
#include "util.hpp"
namespace CSVWorld
{
/// \brief Integer value that represents an enum and is interacted with via a combobox
class EnumDelegate : public CommandDelegate
{
std::vector<std::pair<int, QString> > mValues;
private:
virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const;
virtual void addCommands (QAbstractItemModel *model,
const QModelIndex& index, int type) const;
public:
EnumDelegate (const std::vector<std::pair<int, QString> >& values,
QUndoStack& undoStack, QObject *parent);
virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem& option,
const QModelIndex& index) const;
virtual void setEditorData (QWidget *editor, const QModelIndex& index) const;
virtual void paint (QPainter *painter, const QStyleOptionViewItem& option,
const QModelIndex& index) const;
};
class EnumDelegateFactory : public CommandDelegateFactory
{
std::vector<std::pair<int, QString> > mValues;
public:
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.
void add (int value, const QString& name);
};
}
#endif

@ -102,7 +102,12 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q
if (flags & CSMWorld::ColumnBase::Flag_Table) if (flags & CSMWorld::ColumnBase::Flag_Table)
{ {
CommandDelegate *delegate = new CommandDelegate (undoStack, this); CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display> (
mModel->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
CommandDelegate *delegate = CommandDelegateFactoryCollection::get().makeDelegate (display,
undoStack, this);
mDelegates.push_back (delegate); mDelegates.push_back (delegate);
setItemDelegateForColumn (i, delegate); setItemDelegateForColumn (i, delegate);
} }

@ -1,6 +1,8 @@
#include "util.hpp" #include "util.hpp"
#include <stdexcept>
#include <QUndoStack> #include <QUndoStack>
#include "../../model/world/commands.hpp" #include "../../model/world/commands.hpp"
@ -35,6 +37,70 @@ QVariant CSVWorld::NastyTableModelHack::getData() const
return mData; return mData;
} }
CSVWorld::CommandDelegateFactory::~CommandDelegateFactory() {}
CSVWorld::CommandDelegateFactoryCollection *CSVWorld::CommandDelegateFactoryCollection::sThis = 0;
CSVWorld::CommandDelegateFactoryCollection::CommandDelegateFactoryCollection()
{
if (sThis)
throw std::logic_error ("multiple instances of CSVWorld::CommandDelegateFactoryCollection");
sThis = this;
}
CSVWorld::CommandDelegateFactoryCollection::~CommandDelegateFactoryCollection()
{
sThis = 0;
for (std::map<CSMWorld::ColumnBase::Display, CommandDelegateFactory *>::iterator iter (
mFactories.begin());
iter!=mFactories.end(); ++iter)
delete iter->second;
}
void CSVWorld::CommandDelegateFactoryCollection::add (CSMWorld::ColumnBase::Display display,
CommandDelegateFactory *factory)
{
mFactories.insert (std::make_pair (display, factory));
}
CSVWorld::CommandDelegate *CSVWorld::CommandDelegateFactoryCollection::makeDelegate (
CSMWorld::ColumnBase::Display display, QUndoStack& undoStack, QObject *parent) const
{
std::map<CSMWorld::ColumnBase::Display, CommandDelegateFactory *>::const_iterator iter =
mFactories.find (display);
if (iter!=mFactories.end())
return iter->second->makeDelegate (undoStack, parent);
return new CommandDelegate (undoStack, parent);
}
const CSVWorld::CommandDelegateFactoryCollection& CSVWorld::CommandDelegateFactoryCollection::get()
{
if (!sThis)
throw std::logic_error ("no instance of CSVWorld::CommandDelegateFactoryCollection");
return *sThis;
}
QUndoStack& CSVWorld::CommandDelegate::getUndoStack() const
{
return mUndoStack;
}
void CSVWorld::CommandDelegate::setModelDataImp (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const
{
NastyTableModelHack hack (*model);
QStyledItemDelegate::setModelData (editor, &hack, index);
mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData()));
}
CSVWorld::CommandDelegate::CommandDelegate (QUndoStack& undoStack, QObject *parent) CSVWorld::CommandDelegate::CommandDelegate (QUndoStack& undoStack, QObject *parent)
: QStyledItemDelegate (parent), mUndoStack (undoStack), mEditLock (false) : QStyledItemDelegate (parent), mUndoStack (undoStack), mEditLock (false)
{} {}
@ -44,14 +110,18 @@ void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemMode
{ {
if (!mEditLock) if (!mEditLock)
{ {
NastyTableModelHack hack (*model); setModelDataImp (editor, model, index);
QStyledItemDelegate::setModelData (editor, &hack, index);
mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData()));
} }
///< \todo provide some kind of feedback to the user, indicating that editing is currently not possible. ///< \todo provide some kind of feedback to the user, indicating that editing is currently not possible.
} }
void CSVWorld::CommandDelegate::setEditLock (bool locked) void CSVWorld::CommandDelegate::setEditLock (bool locked)
{ {
mEditLock = locked; mEditLock = locked;
}
bool CSVWorld::CommandDelegate::isEditLocked() const
{
return mEditLock;
} }

@ -1,9 +1,13 @@
#ifndef CSV_WORLD_UTIL_H #ifndef CSV_WORLD_UTIL_H
#define CSV_WORLD_UTIL_H #define CSV_WORLD_UTIL_H
#include <map>
#include <QAbstractTableModel> #include <QAbstractTableModel>
#include <QStyledItemDelegate> #include <QStyledItemDelegate>
#include "../../model/world/columnbase.hpp"
class QUndoStack; class QUndoStack;
namespace CSVWorld namespace CSVWorld
@ -31,19 +35,73 @@ namespace CSVWorld
QVariant getData() const; QVariant getData() const;
}; };
class CommandDelegate;
class CommandDelegateFactory
{
public:
virtual ~CommandDelegateFactory();
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const = 0;
///< The ownership of the returned CommandDelegate is transferred to the caller.
};
class CommandDelegateFactoryCollection
{
static CommandDelegateFactoryCollection *sThis;
std::map<CSMWorld::ColumnBase::Display, CommandDelegateFactory *> mFactories;
private:
// not implemented
CommandDelegateFactoryCollection (const CommandDelegateFactoryCollection&);
CommandDelegateFactoryCollection& operator= (const CommandDelegateFactoryCollection&);
public:
CommandDelegateFactoryCollection();
~CommandDelegateFactoryCollection();
void add (CSMWorld::ColumnBase::Display display, CommandDelegateFactory *factory);
///< The ownership of \æ factory is transferred to *this.
///
/// This function must not be called more than once per value of \æ display.
CommandDelegate *makeDelegate (CSMWorld::ColumnBase::Display display, QUndoStack& undoStack,
QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.
///
/// If no factory is registered for \a display, a CommandDelegate will be returned.
static const CommandDelegateFactoryCollection& get();
};
///< \brief Use commands instead of manipulating the model directly ///< \brief Use commands instead of manipulating the model directly
class CommandDelegate : public QStyledItemDelegate class CommandDelegate : public QStyledItemDelegate
{ {
QUndoStack& mUndoStack; QUndoStack& mUndoStack;
bool mEditLock; bool mEditLock;
protected:
QUndoStack& getUndoStack() const;
virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const;
public: public:
CommandDelegate (QUndoStack& undoStack, QObject *parent); CommandDelegate (QUndoStack& undoStack, QObject *parent);
void setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const; virtual void setModelData (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const;
void setEditLock (bool locked); void setEditLock (bool locked);
bool isEditLocked() const;
}; };
} }

@ -0,0 +1,103 @@
#include "vartypedelegate.hpp"
#include <QUndoStack>
#include "../../model/world/commands.hpp"
void CSVWorld::VarTypeDelegate::addCommands (QAbstractItemModel *model, const QModelIndex& index, int type)
const
{
QModelIndex next = model->index (index.row(), index.column()+1);
QVariant old = model->data (next);
QVariant value;
switch (type)
{
case ESM::VT_Short:
case ESM::VT_Int:
case ESM::VT_Long:
value = old.toInt();
break;
case ESM::VT_Float:
value = old.toFloat();
break;
case ESM::VT_String:
value = old.toString();
break;
default: break; // ignore the rest
}
getUndoStack().beginMacro (
"Modify " + model->headerData (index.column(), Qt::Horizontal, Qt::DisplayRole).toString());
getUndoStack().push (new CSMWorld::ModifyCommand (*model, index, type));
getUndoStack().push (new CSMWorld::ModifyCommand (*model, next, value));
getUndoStack().endMacro();
}
CSVWorld::VarTypeDelegate::VarTypeDelegate (const std::vector<std::pair<int, QString> >& values,
QUndoStack& undoStack, QObject *parent)
: EnumDelegate (values, undoStack, parent)
{}
CSVWorld::VarTypeDelegateFactory::VarTypeDelegateFactory (ESM::VarType type0,
ESM::VarType type1, ESM::VarType type2, ESM::VarType type3)
{
if (type0!=ESM::VT_Unknown)
add (type0);
if (type1!=ESM::VT_Unknown)
add (type1);
if (type2!=ESM::VT_Unknown)
add (type2);
if (type3!=ESM::VT_Unknown)
add (type3);
}
CSVWorld::CommandDelegate *CSVWorld::VarTypeDelegateFactory::makeDelegate (QUndoStack& undoStack,
QObject *parent) const
{
return new VarTypeDelegate (mValues, undoStack, parent);
}
void CSVWorld::VarTypeDelegateFactory::add (ESM::VarType type)
{
struct Name
{
ESM::VarType mType;
const char *mName;
};
static const Name sNames[] =
{
{ ESM::VT_None, "empty" },
{ ESM::VT_Short, "short" },
{ ESM::VT_Int, "long" },
{ ESM::VT_Long, "long" },
{ ESM::VT_Float, "float" },
{ ESM::VT_String, "string" },
{ ESM::VT_Unknown, 0 } // end marker
};
for (int i=0; sNames[i].mName; ++i)
if (sNames[i].mType==type)
{
mValues.push_back (std::make_pair (type, sNames[i].mName));
return;
}
throw std::logic_error ("Unsupported variable type");
}

@ -0,0 +1,38 @@
#ifndef CSV_WORLD_VARTYPEDELEGATE_H
#define CSV_WORLD_VARTYPEDELEGATE_H
#include "enumdelegate.hpp"
namespace CSVWorld
{
class VarTypeDelegate : public EnumDelegate
{
private:
virtual void addCommands (QAbstractItemModel *model,
const QModelIndex& index, int type) const;
public:
VarTypeDelegate (const std::vector<std::pair<int, QString> >& values,
QUndoStack& undoStack, QObject *parent);
};
class VarTypeDelegateFactory : public CommandDelegateFactory
{
std::vector<std::pair<int, QString> > mValues;
public:
VarTypeDelegateFactory (ESM::VarType type0 = ESM::VT_Unknown,
ESM::VarType type1 = ESM::VT_Unknown, ESM::VarType type2 = ESM::VT_Unknown,
ESM::VarType type3 = ESM::VT_Unknown);
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.
void add (ESM::VarType type);
};
}
#endif

@ -125,6 +125,12 @@ if(APPLE)
find_library(COCOA_FRAMEWORK Cocoa) find_library(COCOA_FRAMEWORK Cocoa)
find_library(IOKIT_FRAMEWORK IOKit) find_library(IOKIT_FRAMEWORK IOKit)
target_link_libraries(openmw ${CARBON_FRAMEWORK} ${COCOA_FRAMEWORK} ${IOKIT_FRAMEWORK}) target_link_libraries(openmw ${CARBON_FRAMEWORK} ${COCOA_FRAMEWORK} ${IOKIT_FRAMEWORK})
if (FFMPEG_FOUND)
find_library(COREVIDEO_FRAMEWORK CoreVideo)
find_library(VDA_FRAMEWORK VideoDecodeAcceleration)
target_link_libraries(openmw ${COREVIDEO_FRAMEWORK} ${VDA_FRAMEWORK})
endif()
endif(APPLE) endif(APPLE)
if(DPKG_PROGRAM) if(DPKG_PROGRAM)

@ -199,6 +199,7 @@ namespace MWBase
///< Hides dialog and schedules dialog to be deleted. ///< Hides dialog and schedules dialog to be deleted.
virtual void messageBox (const std::string& message, const std::vector<std::string>& buttons) = 0; virtual void messageBox (const std::string& message, const std::vector<std::string>& buttons) = 0;
virtual void enterPressed () = 0;
virtual int readPressedButton() = 0; virtual int readPressedButton() = 0;
///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox) ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox)

@ -12,6 +12,7 @@
#include "../mwworld/actionalchemy.hpp" #include "../mwworld/actionalchemy.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp" #include "../mwworld/physicssystem.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwrender/renderinginterface.hpp" #include "../mwrender/renderinginterface.hpp"
@ -61,6 +62,9 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Apparatus::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Apparatus::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor) const const MWWorld::Ptr& actor) const
{ {
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction ());
boost::shared_ptr<MWWorld::Action> action( boost::shared_ptr<MWWorld::Action> action(
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));

@ -15,6 +15,7 @@
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp" #include "../mwworld/physicssystem.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwrender/renderinginterface.hpp" #include "../mwrender/renderinginterface.hpp"
@ -64,6 +65,9 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Armor::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Armor::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor) const const MWWorld::Ptr& actor) const
{ {
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction ());
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTake (ptr)); boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTake (ptr));
action->setSound(getUpSoundId(ptr)); action->setSound(getUpSoundId(ptr));

@ -13,6 +13,7 @@
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp" #include "../mwworld/physicssystem.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
@ -62,6 +63,9 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Clothing::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Clothing::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor) const const MWWorld::Ptr& actor) const
{ {
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction ());
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTake (ptr)); boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTake (ptr));
action->setSound(getUpSoundId(ptr)); action->setSound(getUpSoundId(ptr));

@ -9,6 +9,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/failedaction.hpp" #include "../mwworld/failedaction.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwworld/containerstore.hpp" #include "../mwworld/containerstore.hpp"
#include "../mwworld/customdata.hpp" #include "../mwworld/customdata.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
@ -85,6 +86,9 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Container::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Container::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor) const const MWWorld::Ptr& actor) const
{ {
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction ());
const std::string lockedSound = "LockedChest"; const std::string lockedSound = "LockedChest";
const std::string trapActivationSound = "Disarm Trap Fail"; const std::string trapActivationSound = "Disarm Trap Fail";

@ -13,6 +13,7 @@
#include "../mwworld/physicssystem.hpp" #include "../mwworld/physicssystem.hpp"
#include "../mwworld/actioneat.hpp" #include "../mwworld/actioneat.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/npcstats.hpp"
@ -72,6 +73,9 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Ingredient::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Ingredient::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor) const const MWWorld::Ptr& actor) const
{ {
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction ());
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTake (ptr)); boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTake (ptr));
action->setSound(getUpSoundId(ptr)); action->setSound(getUpSoundId(ptr));

@ -88,6 +88,9 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Light::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Light::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor) const const MWWorld::Ptr& actor) const
{ {
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction ());
MWWorld::LiveCellRef<ESM::Light> *ref = MWWorld::LiveCellRef<ESM::Light> *ref =
ptr.get<ESM::Light>(); ptr.get<ESM::Light>();

@ -13,6 +13,7 @@
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp" #include "../mwworld/physicssystem.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
@ -62,6 +63,9 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Lockpick::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Lockpick::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor) const const MWWorld::Ptr& actor) const
{ {
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction ());
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTake (ptr)); boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTake (ptr));
action->setSound(getUpSoundId(ptr)); action->setSound(getUpSoundId(ptr));

@ -14,6 +14,7 @@
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp" #include "../mwworld/physicssystem.hpp"
#include "../mwworld/manualref.hpp" #include "../mwworld/manualref.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
@ -65,6 +66,9 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Miscellaneous::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Miscellaneous::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor) const const MWWorld::Ptr& actor) const
{ {
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction ());
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTake (ptr)); boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTake (ptr));
action->setSound(getUpSoundId(ptr)); action->setSound(getUpSoundId(ptr));
@ -210,6 +214,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
newRef.getPtr().get<ESM::Miscellaneous>(); newRef.getPtr().get<ESM::Miscellaneous>();
newPtr = MWWorld::Ptr(&cell.mMiscItems.insert(*ref), &cell); newPtr = MWWorld::Ptr(&cell.mMiscItems.insert(*ref), &cell);
newPtr.getRefData ().setCount(goldAmount);
} else { } else {
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref = MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
ptr.get<ESM::Miscellaneous>(); ptr.get<ESM::Miscellaneous>();

@ -13,6 +13,7 @@
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp" #include "../mwworld/physicssystem.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
@ -62,6 +63,9 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Potion::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Potion::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor) const const MWWorld::Ptr& actor) const
{ {
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction ());
boost::shared_ptr<MWWorld::Action> action( boost::shared_ptr<MWWorld::Action> action(
new MWWorld::ActionTake (ptr)); new MWWorld::ActionTake (ptr));

@ -13,6 +13,7 @@
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp" #include "../mwworld/physicssystem.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
@ -61,6 +62,9 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Probe::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Probe::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor) const const MWWorld::Ptr& actor) const
{ {
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction ());
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTake (ptr)); boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTake (ptr));
action->setSound(getUpSoundId(ptr)); action->setSound(getUpSoundId(ptr));

@ -11,6 +11,7 @@
#include "../mwworld/actiontake.hpp" #include "../mwworld/actiontake.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp" #include "../mwworld/physicssystem.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
@ -60,6 +61,9 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Repair::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Repair::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor) const const MWWorld::Ptr& actor) const
{ {
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction ());
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTake (ptr)); boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTake (ptr));
action->setSound(getUpSoundId(ptr)); action->setSound(getUpSoundId(ptr));

@ -13,6 +13,7 @@
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp" #include "../mwworld/physicssystem.hpp"
#include "../mwworld/nullaction.hpp"
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
@ -62,6 +63,9 @@ namespace MWClass
boost::shared_ptr<MWWorld::Action> Weapon::activate (const MWWorld::Ptr& ptr, boost::shared_ptr<MWWorld::Action> Weapon::activate (const MWWorld::Ptr& ptr,
const MWWorld::Ptr& actor) const const MWWorld::Ptr& actor) const
{ {
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction ());
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTake (ptr)); boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTake (ptr));
action->setSound(getUpSoundId(ptr)); action->setSound(getUpSoundId(ptr));

@ -48,7 +48,6 @@ BirthDialog::BirthDialog(MWBase::WindowManager& parWindowManager)
getWidget(okButton, "OKButton"); getWidget(okButton, "OKButton");
okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); okButton->setCaption(mWindowManager.getGameSettingString("sOK", ""));
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onOkClicked); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BirthDialog::onOkClicked);
okButton->setEnabled(false);
updateBirths(); updateBirths();
updateSpells(); updateSpells();
@ -85,7 +84,6 @@ void BirthDialog::setBirthId(const std::string &birthId)
mBirthList->setIndexSelected(i); mBirthList->setIndexSelected(i);
MyGUI::ButtonPtr okButton; MyGUI::ButtonPtr okButton;
getWidget(okButton, "OKButton"); getWidget(okButton, "OKButton");
okButton->setEnabled(true);
break; break;
} }
} }
@ -114,7 +112,6 @@ void BirthDialog::onSelectBirth(MyGUI::ListBox* _sender, size_t _index)
MyGUI::ButtonPtr okButton; MyGUI::ButtonPtr okButton;
getWidget(okButton, "OKButton"); getWidget(okButton, "OKButton");
okButton->setEnabled(true);
const std::string *birthId = mBirthList->getItemDataAt<std::string>(_index); const std::string *birthId = mBirthList->getItemDataAt<std::string>(_index);
if (boost::iequals(mCurrentBirthId, *birthId)) if (boost::iequals(mCurrentBirthId, *birthId))
@ -133,8 +130,6 @@ void BirthDialog::updateBirths()
const MWWorld::Store<ESM::BirthSign> &signs = const MWWorld::Store<ESM::BirthSign> &signs =
MWBase::Environment::get().getWorld()->getStore().get<ESM::BirthSign>(); MWBase::Environment::get().getWorld()->getStore().get<ESM::BirthSign>();
int index = 0;
// sort by name // sort by name
std::vector < std::pair<std::string, const ESM::BirthSign*> > birthSigns; std::vector < std::pair<std::string, const ESM::BirthSign*> > birthSigns;
@ -145,12 +140,20 @@ void BirthDialog::updateBirths()
} }
std::sort(birthSigns.begin(), birthSigns.end(), sortBirthSigns); std::sort(birthSigns.begin(), birthSigns.end(), sortBirthSigns);
for (std::vector < std::pair<std::string, const ESM::BirthSign*> >::const_iterator it2 = birthSigns.begin(); it2 != birthSigns.end(); ++it2) int index = 0;
for (std::vector<std::pair<std::string, const ESM::BirthSign*> >::const_iterator it2 = birthSigns.begin();
it2 != birthSigns.end(); ++it2, ++index)
{ {
mBirthList->addItem(it2->second->mName, it2->first); mBirthList->addItem(it2->second->mName, it2->first);
if (boost::iequals(it2->first, mCurrentBirthId)) if (mCurrentBirthId.empty())
{
mBirthList->setIndexSelected(index); mBirthList->setIndexSelected(index);
++index; mCurrentBirthId = it2->first;
}
else if (boost::iequals(it2->first, mCurrentBirthId))
{
mBirthList->setIndexSelected(index);
}
} }
} }

@ -14,8 +14,10 @@
using namespace MWGui; using namespace MWGui;
BookWindow::BookWindow (MWBase::WindowManager& parWindowManager) : BookWindow::BookWindow (MWBase::WindowManager& parWindowManager)
WindowBase("openmw_book.layout", parWindowManager) : WindowBase("openmw_book.layout", parWindowManager)
, mTakeButtonShow(true)
, mTakeButtonAllowed(true)
{ {
getWidget(mCloseButton, "CloseButton"); getWidget(mCloseButton, "CloseButton");
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BookWindow::onCloseButtonClicked); mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BookWindow::onCloseButtonClicked);
@ -85,7 +87,14 @@ void BookWindow::open (MWWorld::Ptr book)
void BookWindow::setTakeButtonShow(bool show) void BookWindow::setTakeButtonShow(bool show)
{ {
mTakeButton->setVisible(show); mTakeButtonShow = show;
mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed);
}
void BookWindow::setInventoryAllowed(bool allowed)
{
mTakeButtonAllowed = allowed;
mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed);
} }
void BookWindow::onCloseButtonClicked (MyGUI::Widget* sender) void BookWindow::onCloseButtonClicked (MyGUI::Widget* sender)

@ -17,6 +17,8 @@ namespace MWGui
void open(MWWorld::Ptr book); void open(MWWorld::Ptr book);
void setTakeButtonShow(bool show); void setTakeButtonShow(bool show);
void setInventoryAllowed(bool allowed);
protected: protected:
void onNextPageButtonClicked (MyGUI::Widget* sender); void onNextPageButtonClicked (MyGUI::Widget* sender);
void onPrevPageButtonClicked (MyGUI::Widget* sender); void onPrevPageButtonClicked (MyGUI::Widget* sender);
@ -40,6 +42,9 @@ namespace MWGui
std::vector<MyGUI::Widget*> mPages; std::vector<MyGUI::Widget*> mPages;
MWWorld::Ptr mBook; MWWorld::Ptr mBook;
bool mTakeButtonShow;
bool mTakeButtonAllowed;
}; };
} }

@ -104,7 +104,6 @@ PickClassDialog::PickClassDialog(MWBase::WindowManager& parWindowManager)
MyGUI::ButtonPtr okButton; MyGUI::ButtonPtr okButton;
getWidget(okButton, "OKButton"); getWidget(okButton, "OKButton");
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onOkClicked); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PickClassDialog::onOkClicked);
okButton->setEnabled(false);
updateClasses(); updateClasses();
updateStats(); updateStats();
@ -140,7 +139,6 @@ void PickClassDialog::setClassId(const std::string &classId)
mClassList->setIndexSelected(i); mClassList->setIndexSelected(i);
MyGUI::ButtonPtr okButton; MyGUI::ButtonPtr okButton;
getWidget(okButton, "OKButton"); getWidget(okButton, "OKButton");
okButton->setEnabled(true);
break; break;
} }
} }
@ -169,7 +167,6 @@ void PickClassDialog::onSelectClass(MyGUI::ListBox* _sender, size_t _index)
MyGUI::ButtonPtr okButton; MyGUI::ButtonPtr okButton;
getWidget(okButton, "OKButton"); getWidget(okButton, "OKButton");
okButton->setEnabled(true);
const std::string *classId = mClassList->getItemDataAt<std::string>(_index); const std::string *classId = mClassList->getItemDataAt<std::string>(_index);
if (boost::iequals(mCurrentClassId, *classId)) if (boost::iequals(mCurrentClassId, *classId))
@ -197,8 +194,15 @@ void PickClassDialog::updateClasses()
const std::string &id = it->mId; const std::string &id = it->mId;
mClassList->addItem(it->mName, id); mClassList->addItem(it->mName, id);
if (boost::iequals(id, mCurrentClassId)) if (mCurrentClassId.empty())
{
mCurrentClassId = id;
mClassList->setIndexSelected(index); mClassList->setIndexSelected(index);
}
else if (boost::iequals(id, mCurrentClassId))
{
mClassList->setIndexSelected(index);
}
++index; ++index;
} }
} }

@ -6,7 +6,9 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <OgreUTFString.h>
using namespace MWGui; using namespace MWGui;
@ -67,118 +69,135 @@ namespace
return value; return value;
} }
Ogre::UTFString::unicode_char unicodeCharFromChar(char ch)
{
std::string s;
s += ch;
Ogre::UTFString string(s);
return string.getChar(0);
}
} }
std::vector<std::string> BookTextParser::split(std::string text, const int width, const int height) std::vector<std::string> BookTextParser::split(std::string utf8Text, const int width, const int height)
{ {
using Ogre::UTFString;
std::vector<std::string> result; std::vector<std::string> result;
MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor
text = Interpreter::fixDefinesBook(text, interpreterContext); utf8Text = Interpreter::fixDefinesBook(utf8Text, interpreterContext);
boost::algorithm::replace_all(text, "<BR>", "\n"); boost::algorithm::replace_all(utf8Text, "\n", "");
boost::algorithm::replace_all(text, "<P>", "\n\n"); boost::algorithm::replace_all(utf8Text, "<BR>", "\n");
boost::algorithm::replace_all(utf8Text, "<P>", "\n\n");
UTFString text(utf8Text);
const int spacing = 48; const int spacing = 48;
while (text.size() > 0) const UTFString::unicode_char LEFT_ANGLE = unicodeCharFromChar('<');
const UTFString::unicode_char NEWLINE = unicodeCharFromChar('\n');
const UTFString::unicode_char SPACE = unicodeCharFromChar(' ');
while (!text.empty())
{ {
// read in characters until we have exceeded the size, or run out of text // read in characters until we have exceeded the size, or run out of text
int currentWidth = 0; int currentWidth = 0;
int currentHeight = 0; int currentHeight = 0;
std::string currentText;
std::string currentWord;
unsigned int i=0; size_t currentWordStart = 0;
while (currentHeight <= height-spacing && i<text.size()) size_t index = 0;
while (currentHeight <= height - spacing && index < text.size())
{ {
if (text[i] == '<') const UTFString::unicode_char ch = text.getChar(index);
if (ch == LEFT_ANGLE)
{ {
if (text.find('>', i) == std::string::npos) const size_t tagStart = index + 1;
const size_t tagEnd = text.find('>', tagStart);
if (tagEnd == UTFString::npos)
throw std::runtime_error("BookTextParser Error: Tag is not terminated"); throw std::runtime_error("BookTextParser Error: Tag is not terminated");
const std::string tag = text.substr(tagStart, tagEnd - tagStart).asUTF8();
if (text.size() > i+4 && text.substr(i, 4) == "<IMG") if (boost::algorithm::starts_with(tag, "IMG"))
{ {
int h = mHeight; const int h = mHeight;
parseImage(text.substr(i, text.find('>', i)-i), false); parseImage(tag, false);
currentHeight += (mHeight-h); currentHeight += (mHeight - h);
currentWidth = 0; currentWidth = 0;
} }
else if (text.size() > i+5 && text.substr(i, 5) == "<FONT") else if (boost::algorithm::starts_with(tag, "FONT"))
{ {
parseFont(text.substr(i, text.find('>', i)-i)); parseFont(tag);
currentHeight += 18; // keep this in sync with the font size if (currentWidth != 0) {
currentHeight += currentFontHeight();
currentWidth = 0;
}
currentWidth = 0; currentWidth = 0;
} }
else if (text.size() > i+4 && text.substr(i, 4) == "<DIV") else if (boost::algorithm::starts_with(tag, "DIV"))
{ {
parseDiv(text.substr(i, text.find('>', i)-i)); parseDiv(tag);
currentHeight += 18; // keep this in sync with the font size if (currentWidth != 0) {
currentWidth = 0; currentHeight += currentFontHeight();
currentWidth = 0;
}
} }
index = tagEnd;
currentText += text.substr(i, text.find('>', i)-i+1);
i = text.find('>', i);
} }
else if (text[i] == '\n') else if (ch == NEWLINE)
{ {
currentHeight += 18; // keep this in sync with the font size currentHeight += currentFontHeight();
currentWidth = 0; currentWidth = 0;
currentWord = ""; currentWordStart = index;
currentText += text[i];
} }
else if (text[i] == ' ') else if (ch == SPACE)
{ {
currentWidth += 3; // keep this in sync with the font's SpaceWidth property currentWidth += 3; // keep this in sync with the font's SpaceWidth property
currentWord = ""; currentWordStart = index;
currentText += text[i];
} }
else else
{ {
currentWidth += currentWidth += widthForCharGlyph(ch);
MyGUI::FontManager::getInstance().getByName (mTextStyle.mFont == "Default" ? "EB Garamond" : mTextStyle.mFont)
->getGlyphInfo(static_cast<unsigned int>(text[i]))->width;
currentWord += text[i];
currentText += text[i];
} }
if (currentWidth > width) if (currentWidth > width)
{ {
currentHeight += 18; // keep this in sync with the font size currentHeight += currentFontHeight();
currentWidth = 0; currentWidth = 0;
// add size of the current word // add size of the current word
unsigned int j=0; UTFString word = text.substr(currentWordStart, index - currentWordStart);
while (j<currentWord.size()) for (UTFString::const_iterator it = word.begin(), end = word.end(); it != end; ++it)
{ currentWidth += widthForCharGlyph(it.getCharacter());
currentWidth +=
MyGUI::FontManager::getInstance().getByName (mTextStyle.mFont == "Default" ? "EB Garamond" : mTextStyle.mFont)
->getGlyphInfo(static_cast<unsigned int>(currentWord[j]))->width;
++j;
}
} }
index += UTFString::_utf16_char_length(ch);
++i;
}
if (currentHeight > height-spacing)
{
// remove the last word
currentText.erase(currentText.size()-currentWord.size(), currentText.size());
} }
const size_t pageEnd = (currentHeight > height - spacing && currentWordStart != 0)
? currentWordStart : index;
result.push_back(currentText); result.push_back(text.substr(0, pageEnd).asUTF8());
text.erase(0, currentText.size()); text.erase(0, pageEnd);
} }
return result; return result;
} }
float BookTextParser::widthForCharGlyph(unsigned unicodeChar) const
{
std::string fontName(mTextStyle.mFont == "Default" ? "EB Garamond" : mTextStyle.mFont);
return MyGUI::FontManager::getInstance().getByName(fontName)
->getGlyphInfo(unicodeChar)->width;
}
float BookTextParser::currentFontHeight() const
{
std::string fontName(mTextStyle.mFont == "Default" ? "EB Garamond" : mTextStyle.mFont);
return MyGUI::FontManager::getInstance().getByName(fontName)->getDefaultHeight();
}
MyGUI::IntSize BookTextParser::parse(std::string text, MyGUI::Widget* parent, const int width) MyGUI::IntSize BookTextParser::parse(std::string text, MyGUI::Widget* parent, const int width)
{ {
MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor
text = Interpreter::fixDefinesBook(text, interpreterContext); text = Interpreter::fixDefinesBook(text, interpreterContext);
mParent = parent; mParent = parent;
mWidth = width; mWidth = width;
mHeight = 0; mHeight = 0;
@ -189,12 +208,13 @@ MyGUI::IntSize BookTextParser::parse(std::string text, MyGUI::Widget* parent, co
MyGUI::Gui::getInstance().destroyWidget(mParent->getChildAt(0)); MyGUI::Gui::getInstance().destroyWidget(mParent->getChildAt(0));
} }
boost::algorithm::replace_all(text, "\n", "");
boost::algorithm::replace_all(text, "<BR>", "\n"); boost::algorithm::replace_all(text, "<BR>", "\n");
boost::algorithm::replace_all(text, "<P>", "\n\n"); boost::algorithm::replace_all(text, "<P>", "\n\n");
// remove leading newlines // remove leading newlines
//while (text[0] == '\n') // while (text[0] == '\n')
// text.erase(0); // text.erase(0);
// remove trailing " // remove trailing "
if (text[text.size()-1] == '\"') if (text[text.size()-1] == '\"')
@ -279,28 +299,30 @@ void BookTextParser::parseSubText(std::string text)
{ {
if (text[0] == '<') if (text[0] == '<')
{ {
if (text.find('>') == std::string::npos) const size_t tagStart = 1;
const size_t tagEnd = text.find('>', tagStart);
if (tagEnd == std::string::npos)
throw std::runtime_error("BookTextParser Error: Tag is not terminated"); throw std::runtime_error("BookTextParser Error: Tag is not terminated");
const std::string tag = text.substr(tagStart, tagEnd - tagStart);
if (text.size() > 4 && text.substr(0, 4) == "<IMG") if (boost::algorithm::starts_with(tag, "IMG"))
parseImage(text.substr(0, text.find('>'))); parseImage(tag);
else if (text.size() > 5 && text.substr(0, 5) == "<FONT") if (boost::algorithm::starts_with(tag, "FONT"))
parseFont(text.substr(0, text.find('>'))); parseFont(tag);
else if (text.size() > 4 && text.substr(0, 4) == "<DIV") if (boost::algorithm::starts_with(tag, "DOV"))
parseDiv(text.substr(0, text.find('>'))); parseDiv(tag);
text.erase(0, text.find('>')+1); text.erase(0, tagEnd + 1);
} }
bool tagFound = false; size_t tagStart = std::string::npos;
std::string realText; // real text, without tags std::string realText; // real text, without tags
unsigned int i=0; for (size_t i = 0; i<text.size(); ++i)
for (; i<text.size(); ++i)
{ {
char c = text[i]; char c = text[i];
if (c == '<') if (c == '<')
{ {
if (text[i+1] == '/') // ignore closing tags if ((i + 1 < text.size()) && text[i+1] == '/') // ignore closing tags
{ {
while (c != '>') while (c != '>')
{ {
@ -313,7 +335,7 @@ void BookTextParser::parseSubText(std::string text)
} }
else else
{ {
tagFound = true; tagStart = i;
break; break;
} }
} }
@ -336,8 +358,8 @@ void BookTextParser::parseSubText(std::string text)
box->setSize(box->getSize().width, box->getTextSize().height); box->setSize(box->getSize().width, box->getTextSize().height);
mHeight += box->getTextSize().height; mHeight += box->getTextSize().height;
if (tagFound) if (tagStart != std::string::npos)
{ {
parseSubText(text.substr(i, text.size())); parseSubText(text.substr(tagStart, text.size()));
} }
} }

@ -40,6 +40,8 @@ namespace MWGui
std::vector<std::string> split(std::string text, const int width, const int height); std::vector<std::string> split(std::string text, const int width, const int height);
protected: protected:
float widthForCharGlyph(unsigned unicodeChar) const;
float currentFontHeight() const;
void parseSubText(std::string text); void parseSubText(std::string text);
void parseImage(std::string tag, bool createWidget=true); void parseImage(std::string tag, bool createWidget=true);

@ -1,3 +1,5 @@
#include <components/misc/stringops.hpp>
#include "messagebox.hpp" #include "messagebox.hpp"
using namespace MWGui; using namespace MWGui;
@ -133,6 +135,10 @@ void MessageBoxManager::setMessageBoxSpeed (int speed)
mMessageBoxSpeed = speed; mMessageBoxSpeed = speed;
} }
void MessageBoxManager::enterPressed ()
{
mInterMessageBoxe->enterPressed();
}
int MessageBoxManager::readPressedButton () int MessageBoxManager::readPressedButton ()
{ {
@ -359,7 +365,28 @@ InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxMan
} }
} }
void InteractiveMessageBox::enterPressed()
{
std::string ok = Misc::StringUtils::lowerCase(MyGUI::LanguageManager::getInstance().replaceTags("#{sOK}"));
std::vector<MyGUI::ButtonPtr>::const_iterator button;
for(button = mButtons.begin(); button != mButtons.end(); ++button)
{
if(Misc::StringUtils::lowerCase((*button)->getCaption()) == ok)
{
buttonActivated(*button);
break;
}
}
}
void InteractiveMessageBox::mousePressed (MyGUI::Widget* pressed) void InteractiveMessageBox::mousePressed (MyGUI::Widget* pressed)
{
buttonActivated (pressed);
}
void InteractiveMessageBox::buttonActivated (MyGUI::Widget* pressed)
{ {
mMarkedToDelete = true; mMarkedToDelete = true;
int index = 0; int index = 0;

@ -34,7 +34,8 @@ namespace MWGui
void removeMessageBox (float time, MessageBox *msgbox); void removeMessageBox (float time, MessageBox *msgbox);
bool removeMessageBox (MessageBox *msgbox); bool removeMessageBox (MessageBox *msgbox);
void setMessageBoxSpeed (int speed); void setMessageBoxSpeed (int speed);
void enterPressed();
int readPressedButton (); int readPressedButton ();
MWBase::WindowManager *mWindowManager; MWBase::WindowManager *mWindowManager;
@ -70,12 +71,15 @@ namespace MWGui
{ {
public: public:
InteractiveMessageBox (MessageBoxManager& parMessageBoxManager, const std::string& message, const std::vector<std::string>& buttons); InteractiveMessageBox (MessageBoxManager& parMessageBoxManager, const std::string& message, const std::vector<std::string>& buttons);
void enterPressed ();
void mousePressed (MyGUI::Widget* _widget); void mousePressed (MyGUI::Widget* _widget);
int readPressedButton (); int readPressedButton ();
bool mMarkedToDelete; bool mMarkedToDelete;
private: private:
void buttonActivated (MyGUI::Widget* _widget);
MessageBoxManager& mMessageBoxManager; MessageBoxManager& mMessageBoxManager;
MyGUI::EditPtr mMessageWidget; MyGUI::EditPtr mMessageWidget;
MyGUI::WidgetPtr mButtonsWidget; MyGUI::WidgetPtr mButtonsWidget;

@ -81,7 +81,6 @@ RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager)
getWidget(okButton, "OKButton"); getWidget(okButton, "OKButton");
okButton->setCaption(mWindowManager.getGameSettingString("sOK", "")); okButton->setCaption(mWindowManager.getGameSettingString("sOK", ""));
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onOkClicked); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &RaceDialog::onOkClicked);
okButton->setEnabled(false);
updateRaces(); updateRaces();
updateSkills(); updateSkills();
@ -135,7 +134,6 @@ void RaceDialog::setRaceId(const std::string &raceId)
mRaceList->setIndexSelected(i); mRaceList->setIndexSelected(i);
MyGUI::ButtonPtr okButton; MyGUI::ButtonPtr okButton;
getWidget(okButton, "OKButton"); getWidget(okButton, "OKButton");
okButton->setEnabled(true);
break; break;
} }
} }
@ -258,7 +256,6 @@ void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index)
MyGUI::ButtonPtr okButton; MyGUI::ButtonPtr okButton;
getWidget(okButton, "OKButton"); getWidget(okButton, "OKButton");
okButton->setEnabled(true);
const std::string *raceId = mRaceList->getItemDataAt<std::string>(_index); const std::string *raceId = mRaceList->getItemDataAt<std::string>(_index);
if (boost::iequals(mCurrentRaceId, *raceId)) if (boost::iequals(mCurrentRaceId, *raceId))
return; return;

@ -12,8 +12,10 @@
using namespace MWGui; using namespace MWGui;
ScrollWindow::ScrollWindow (MWBase::WindowManager& parWindowManager) : ScrollWindow::ScrollWindow (MWBase::WindowManager& parWindowManager)
WindowBase("openmw_scroll.layout", parWindowManager) : WindowBase("openmw_scroll.layout", parWindowManager)
, mTakeButtonShow(true)
, mTakeButtonAllowed(true)
{ {
getWidget(mTextView, "TextView"); getWidget(mTextView, "TextView");
@ -50,7 +52,14 @@ void ScrollWindow::open (MWWorld::Ptr scroll)
void ScrollWindow::setTakeButtonShow(bool show) void ScrollWindow::setTakeButtonShow(bool show)
{ {
mTakeButton->setVisible(show); mTakeButtonShow = show;
mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed);
}
void ScrollWindow::setInventoryAllowed(bool allowed)
{
mTakeButtonAllowed = allowed;
mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed);
} }
void ScrollWindow::onCloseButtonClicked (MyGUI::Widget* _sender) void ScrollWindow::onCloseButtonClicked (MyGUI::Widget* _sender)

@ -15,6 +15,7 @@ namespace MWGui
void open (MWWorld::Ptr scroll); void open (MWWorld::Ptr scroll);
void setTakeButtonShow(bool show); void setTakeButtonShow(bool show);
void setInventoryAllowed(bool allowed);
protected: protected:
void onCloseButtonClicked (MyGUI::Widget* _sender); void onCloseButtonClicked (MyGUI::Widget* _sender);
@ -26,6 +27,10 @@ namespace MWGui
MyGUI::ScrollView* mTextView; MyGUI::ScrollView* mTextView;
MWWorld::Ptr mScroll; MWWorld::Ptr mScroll;
bool mTakeButtonShow;
bool mTakeButtonAllowed;
}; };
} }

@ -19,12 +19,17 @@
#include "inventorywindow.hpp" #include "inventorywindow.hpp"
static const float BALANCE_CHANGE_INITIAL_PAUSE = 0.5; // in seconds
static const float BALANCE_CHANGE_INTERVAL = 0.1; // in seconds
namespace MWGui namespace MWGui
{ {
TradeWindow::TradeWindow(MWBase::WindowManager& parWindowManager) : TradeWindow::TradeWindow(MWBase::WindowManager& parWindowManager) :
WindowBase("openmw_trade_window.layout", parWindowManager) WindowBase("openmw_trade_window.layout", parWindowManager)
, ContainerBase(NULL) // no drag&drop , ContainerBase(NULL) // no drag&drop
, mCurrentBalance(0) , mCurrentBalance(0)
, mBalanceButtonsState(BBS_None)
, mBalanceChangePause(0.0)
{ {
MyGUI::ScrollView* itemView; MyGUI::ScrollView* itemView;
MyGUI::Widget* containerWidget; MyGUI::Widget* containerWidget;
@ -59,8 +64,10 @@ namespace MWGui
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onCancelButtonClicked); mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onCancelButtonClicked);
mOfferButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onOfferButtonClicked); mOfferButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onOfferButtonClicked);
mIncreaseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onIncreaseButtonClicked); mIncreaseButton->eventMouseButtonPressed += MyGUI::newDelegate(this, &TradeWindow::onIncreaseButtonPressed);
mDecreaseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onDecreaseButtonClicked); mIncreaseButton->eventMouseButtonReleased += MyGUI::newDelegate(this, &TradeWindow::onBalanceButtonReleased);
mDecreaseButton->eventMouseButtonPressed += MyGUI::newDelegate(this, &TradeWindow::onDecreaseButtonPressed);
mDecreaseButton->eventMouseButtonReleased += MyGUI::newDelegate(this, &TradeWindow::onBalanceButtonReleased);
setCoord(400, 0, 400, 300); setCoord(400, 0, 400, 300);
@ -143,6 +150,21 @@ namespace MWGui
} }
} }
void TradeWindow::onFrame(float frameDuration)
{
if (!mMainWidget->getVisible() || mBalanceButtonsState == BBS_None)
return;
mBalanceChangePause -= frameDuration;
if (mBalanceChangePause < 0.0) {
mBalanceChangePause += BALANCE_CHANGE_INTERVAL;
if (mBalanceButtonsState == BBS_Increase)
onIncreaseButtonTriggered();
else if (mBalanceButtonsState == BBS_Decrease)
onDecreaseButtonTriggered();
}
}
void TradeWindow::onOfferButtonClicked(MyGUI::Widget* _sender) void TradeWindow::onOfferButtonClicked(MyGUI::Widget* _sender)
{ {
const MWWorld::Store<ESM::GameSetting> &gmst = const MWWorld::Store<ESM::GameSetting> &gmst =
@ -242,7 +264,7 @@ namespace MWGui
//skill use! //skill use!
MWWorld::Class::get(playerPtr).skillUsageSucceeded(playerPtr, ESM::Skill::Mercantile, 0); MWWorld::Class::get(playerPtr).skillUsageSucceeded(playerPtr, ESM::Skill::Mercantile, 0);
} }
int iBarterSuccessDisposition = gmst.find("iBarterSuccessDisposition")->getInt(); int iBarterSuccessDisposition = gmst.find("iBarterSuccessDisposition")->getInt();
MWBase::Environment::get().getDialogueManager()->applyTemporaryDispositionChange(iBarterSuccessDisposition); MWBase::Environment::get().getDialogueManager()->applyTemporaryDispositionChange(iBarterSuccessDisposition);
@ -271,14 +293,33 @@ namespace MWGui
mWindowManager.removeGuiMode(GM_Barter); mWindowManager.removeGuiMode(GM_Barter);
} }
void TradeWindow::onIncreaseButtonClicked(MyGUI::Widget* _sender) void TradeWindow::onIncreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
{
mBalanceButtonsState = BBS_Increase;
mBalanceChangePause = BALANCE_CHANGE_INITIAL_PAUSE;
onIncreaseButtonTriggered();
}
void TradeWindow::onDecreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
{
mBalanceButtonsState = BBS_Decrease;
mBalanceChangePause = BALANCE_CHANGE_INITIAL_PAUSE;
onDecreaseButtonTriggered();
}
void TradeWindow::onBalanceButtonReleased(MyGUI::Widget *_sender, int _left, int _top, MyGUI::MouseButton _id)
{
mBalanceButtonsState = BBS_None;
}
void TradeWindow::onIncreaseButtonTriggered()
{ {
if(mCurrentBalance<=-1) mCurrentBalance -= 1; if(mCurrentBalance<=-1) mCurrentBalance -= 1;
if(mCurrentBalance>=1) mCurrentBalance += 1; if(mCurrentBalance>=1) mCurrentBalance += 1;
updateLabels(); updateLabels();
} }
void TradeWindow::onDecreaseButtonClicked(MyGUI::Widget* _sender) void TradeWindow::onDecreaseButtonTriggered()
{ {
if(mCurrentBalance<-1) mCurrentBalance += 1; if(mCurrentBalance<-1) mCurrentBalance += 1;
if(mCurrentBalance>1) mCurrentBalance -= 1; if(mCurrentBalance>1) mCurrentBalance -= 1;

@ -34,6 +34,8 @@ namespace MWGui
void addOrRemoveGold(int gold); void addOrRemoveGold(int gold);
void onFrame(float frameDuration);
protected: protected:
MyGUI::Button* mFilterAll; MyGUI::Button* mFilterAll;
MyGUI::Button* mFilterWeapon; MyGUI::Button* mFilterWeapon;
@ -57,12 +59,24 @@ namespace MWGui
int mCurrentBalance; int mCurrentBalance;
int mCurrentMerchantOffer; int mCurrentMerchantOffer;
enum BalanceButtonsState {
BBS_None,
BBS_Increase,
BBS_Decrease
} mBalanceButtonsState;
/// pause before next balance change will trigger while user holds +/- button pressed
float mBalanceChangePause;
void onWindowResize(MyGUI::Window* _sender); void onWindowResize(MyGUI::Window* _sender);
void onFilterChanged(MyGUI::Widget* _sender); void onFilterChanged(MyGUI::Widget* _sender);
void onOfferButtonClicked(MyGUI::Widget* _sender); void onOfferButtonClicked(MyGUI::Widget* _sender);
void onCancelButtonClicked(MyGUI::Widget* _sender); void onCancelButtonClicked(MyGUI::Widget* _sender);
void onIncreaseButtonClicked(MyGUI::Widget* _sender); void onIncreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
void onDecreaseButtonClicked(MyGUI::Widget* _sender); void onDecreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
void onBalanceButtonReleased(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
void onIncreaseButtonTriggered();
void onDecreaseButtonTriggered();
// don't show items that the NPC has equipped in his trade-window. // don't show items that the NPC has equipped in his trade-window.
virtual bool ignoreEquippedItems() { return true; } virtual bool ignoreEquippedItems() { return true; }

@ -132,6 +132,8 @@ namespace MWGui
if (mWindowManager.getInventoryWindow()->getPlayerGold()<price) if (mWindowManager.getInventoryWindow()->getPlayerGold()<price)
return; return;
mWindowManager.getTradeWindow ()->addOrRemoveGold (-price);
MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(1); MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(1);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
ESM::Position pos = *_sender->getUserData<ESM::Position>(); ESM::Position pos = *_sender->getUserData<ESM::Position>();

@ -1,5 +1,7 @@
#include "waitdialog.hpp" #include "waitdialog.hpp"
#include <cmath>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <libs/openengine/ogre/fader.hpp> #include <libs/openengine/ogre/fader.hpp>
@ -14,6 +16,7 @@
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/npcstats.hpp"
#include "widgets.hpp" #include "widgets.hpp"
@ -132,21 +135,62 @@ namespace MWGui
void WaitDialog::onUntilHealedButtonClicked(MyGUI::Widget* sender) void WaitDialog::onUntilHealedButtonClicked(MyGUI::Widget* sender)
{ {
startWaiting(); // we need to sleep for a specific time, and since that isn't calculated yet, we'll do it here
// I'm making the assumption here that the # of hours rested is calculated when rest is started
// TODO: the rougher logic here (calculating the hourly deltas) should really go into helper funcs elsewhere
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWMechanics::CreatureStats stats = MWWorld::Class::get(player).getCreatureStats(player);
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
float hourlyHealthDelta = stats.getAttribute(ESM::Attribute::Endurance).getModified() * 0.1;
bool stunted = (stats.getMagicEffects().get(MWMechanics::EffectKey(136)).mMagnitude > 0);
float fRestMagicMult = store.get<ESM::GameSetting>().find("fRestMagicMult")->getFloat();
float hourlyMagickaDelta = fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified();
// this massive duplication is why it has to be put into helper functions instead
float fFatigueReturnBase = store.get<ESM::GameSetting>().find("fFatigueReturnBase")->getFloat();
float fFatigueReturnMult = store.get<ESM::GameSetting>().find("fFatigueReturnMult")->getFloat();
float fEndFatigueMult = store.get<ESM::GameSetting>().find("fEndFatigueMult")->getFloat();
float capacity = MWWorld::Class::get(player).getCapacity(player);
float encumbrance = MWWorld::Class::get(player).getEncumbrance(player);
float normalizedEncumbrance = (capacity == 0 ? 1 : encumbrance/capacity);
if (normalizedEncumbrance > 1)
normalizedEncumbrance = 1;
float hourlyFatigueDelta = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance);
hourlyFatigueDelta *= 3600 * fEndFatigueMult * stats.getAttribute(ESM::Attribute::Endurance).getModified();
float healthHours = hourlyHealthDelta >= 0.0
? (stats.getHealth().getBase() - stats.getHealth().getCurrent()) / hourlyHealthDelta
: 1.0f;
float magickaHours = stunted ? 0.0 :
hourlyMagickaDelta >= 0.0
? (stats.getMagicka().getBase() - stats.getMagicka().getCurrent()) / hourlyMagickaDelta
: 1.0f;
float fatigueHours = hourlyFatigueDelta >= 0.0
? (stats.getFatigue().getBase() - stats.getFatigue().getCurrent()) / hourlyFatigueDelta
: 1.0f;
int autoHours = int(std::ceil( std::max(std::max(healthHours, magickaHours), std::max(fatigueHours, 1.0f)) )); // this should use a variadic max if possible
startWaiting(autoHours);
} }
void WaitDialog::onWaitButtonClicked(MyGUI::Widget* sender) void WaitDialog::onWaitButtonClicked(MyGUI::Widget* sender)
{ {
startWaiting(); startWaiting(mManualHours);
} }
void WaitDialog::startWaiting () void WaitDialog::startWaiting(int hoursToWait)
{ {
MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0.2); MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0.2);
setVisible(false); setVisible(false);
mProgressBar.setVisible (true); mProgressBar.setVisible (true);
mWaiting = true; mWaiting = true;
mCurHour = 0; mCurHour = 0;
mHours = hoursToWait;
mRemainingTime = 0.05; mRemainingTime = 0.05;
mProgressBar.setProgress (0, mHours); mProgressBar.setProgress (0, mHours);
} }
@ -159,7 +203,7 @@ namespace MWGui
void WaitDialog::onHourSliderChangedPosition(MyGUI::ScrollBar* sender, size_t position) void WaitDialog::onHourSliderChangedPosition(MyGUI::ScrollBar* sender, size_t position)
{ {
mHourText->setCaptionWithReplacing (boost::lexical_cast<std::string>(position+1) + " #{sRestMenu2}"); mHourText->setCaptionWithReplacing (boost::lexical_cast<std::string>(position+1) + " #{sRestMenu2}");
mHours = position+1; mManualHours = position+1;
} }
void WaitDialog::setCanRest (bool canRest) void WaitDialog::setCanRest (bool canRest)
@ -181,9 +225,9 @@ namespace MWGui
mRemainingTime -= dt; mRemainingTime -= dt;
if (mRemainingTime < 0) while (mRemainingTime < 0)
{ {
mRemainingTime = 0.05; mRemainingTime += 0.05;
++mCurHour; ++mCurHour;
mProgressBar.setProgress (mCurHour, mHours); mProgressBar.setProgress (mCurHour, mHours);
@ -197,6 +241,7 @@ namespace MWGui
if (mCurHour > mHours) if (mCurHour > mHours)
stopWaiting(); stopWaiting();
} }
void WaitDialog::stopWaiting () void WaitDialog::stopWaiting ()

@ -47,6 +47,7 @@ namespace MWGui
bool mSleeping; bool mSleeping;
int mCurHour; int mCurHour;
int mHours; int mHours;
int mManualHours; // stores the hours to rest selected via slider
float mRemainingTime; float mRemainingTime;
WaitDialogProgressBar mProgressBar; WaitDialogProgressBar mProgressBar;
@ -58,7 +59,7 @@ namespace MWGui
void setCanRest(bool canRest); void setCanRest(bool canRest);
void startWaiting(); void startWaiting(int hoursToWait);
void stopWaiting(); void stopWaiting();
}; };

@ -110,7 +110,6 @@ WindowManager::WindowManager(
, mHudEnabled(true) , mHudEnabled(true)
, mTranslationDataStorage (translationDataStorage) , mTranslationDataStorage (translationDataStorage)
{ {
// Set up the GUI system // Set up the GUI system
mGuiManager = new OEngine::GUI::MyGUIManager(mRendering->getWindow(), mRendering->getScene(), false, logpath); mGuiManager = new OEngine::GUI::MyGUIManager(mRendering->getWindow(), mRendering->getScene(), false, logpath);
mGui = mGuiManager->getGui(); mGui = mGuiManager->getGui();
@ -196,6 +195,9 @@ WindowManager::WindowManager(
unsetSelectedSpell(); unsetSelectedSpell();
unsetSelectedWeapon(); unsetSelectedWeapon();
if (newGame)
disallowAll ();
// Set up visibility // Set up visibility
updateVisible(); updateVisible();
} }
@ -560,6 +562,11 @@ void WindowManager::messageBox (const std::string& message, const std::vector<st
} }
} }
void WindowManager::enterPressed ()
{
mMessageBoxManager->enterPressed();
}
int WindowManager::readPressedButton () int WindowManager::readPressedButton ()
{ {
return mMessageBoxManager->readPressedButton(); return mMessageBoxManager->readPressedButton();
@ -608,6 +615,7 @@ void WindowManager::onFrame (float frameDuration)
mHud->onFrame(frameDuration); mHud->onFrame(frameDuration);
mTrainingWindow->onFrame (frameDuration); mTrainingWindow->onFrame (frameDuration);
mTradeWindow->onFrame(frameDuration);
mTrainingWindow->checkReferenceAvailable(); mTrainingWindow->checkReferenceAvailable();
mDialogueWindow->checkReferenceAvailable(); mDialogueWindow->checkReferenceAvailable();
@ -945,12 +953,23 @@ bool WindowManager::isAllowed (GuiWindow wnd) const
void WindowManager::allow (GuiWindow wnd) void WindowManager::allow (GuiWindow wnd)
{ {
mAllowed = (GuiWindow)(mAllowed | wnd); mAllowed = (GuiWindow)(mAllowed | wnd);
if (wnd & GW_Inventory)
{
mBookWindow->setInventoryAllowed (true);
mScrollWindow->setInventoryAllowed (true);
}
updateVisible(); updateVisible();
} }
void WindowManager::disallowAll() void WindowManager::disallowAll()
{ {
mAllowed = GW_None; mAllowed = GW_None;
mBookWindow->setInventoryAllowed (false);
mScrollWindow->setInventoryAllowed (false);
updateVisible(); updateVisible();
} }

@ -189,6 +189,7 @@ namespace MWGui
virtual void removeDialog(OEngine::GUI::Layout* dialog); ///< Hides dialog and schedules dialog to be deleted. virtual void removeDialog(OEngine::GUI::Layout* dialog); ///< Hides dialog and schedules dialog to be deleted.
virtual void messageBox (const std::string& message, const std::vector<std::string>& buttons); virtual void messageBox (const std::string& message, const std::vector<std::string>& buttons);
virtual void enterPressed ();
virtual int readPressedButton (); ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox) virtual int readPressedButton (); ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox)
virtual void onFrame (float frameDuration); virtual void onFrame (float frameDuration);

@ -253,7 +253,7 @@ namespace MWInput
// update values of channels (as a result of pressed keys) // update values of channels (as a result of pressed keys)
if (!loading) if (!loading)
mInputCtrl->update(dt); mInputCtrl->update(dt);
// Update windows/gui as a result of input events // Update windows/gui as a result of input events
// For instance this could mean opening a new window/dialog, // For instance this could mean opening a new window/dialog,
// by doing this after the input events are handled we // by doing this after the input events are handled we
@ -428,6 +428,14 @@ namespace MWInput
bool InputManager::keyPressed( const OIS::KeyEvent &arg ) bool InputManager::keyPressed( const OIS::KeyEvent &arg )
{ {
if(arg.key == OIS::KC_RETURN
&& MWBase::Environment::get().getWindowManager()->isGuiMode()
&& MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_InterMessageBox )
{
// Pressing enter when a messagebox is prompting for "ok" will activate the ok button
MWBase::Environment::get().getWindowManager()->enterPressed();
}
mInputCtrl->keyPressed (arg); mInputCtrl->keyPressed (arg);
unsigned int text = arg.text; unsigned int text = arg.text;
#ifdef __APPLE__ // filter \016 symbol for F-keys on OS X #ifdef __APPLE__ // filter \016 symbol for F-keys on OS X
@ -581,10 +589,14 @@ namespace MWInput
// Toggle between game mode and inventory mode // Toggle between game mode and inventory mode
if(gameMode) if(gameMode)
mWindows.pushGuiMode(MWGui::GM_Inventory); mWindows.pushGuiMode(MWGui::GM_Inventory);
else if(mWindows.getMode() == MWGui::GM_Inventory) else
mWindows.popGuiMode(); {
MWGui::GuiMode mode = mWindows.getMode();
if(mode == MWGui::GM_Inventory || mode == MWGui::GM_Container)
mWindows.popGuiMode();
}
// .. but don't touch any other mode. // .. but don't touch any other mode, except container.
} }
void InputManager::toggleConsole() void InputManager::toggleConsole()
@ -625,11 +637,14 @@ namespace MWInput
{ {
if (!mWindows.isGuiMode ()) if (!mWindows.isGuiMode ())
mWindows.pushGuiMode (MWGui::GM_QuickKeysMenu); mWindows.pushGuiMode (MWGui::GM_QuickKeysMenu);
else if (mWindows.getMode () == MWGui::GM_QuickKeysMenu)
mWindows.removeGuiMode (MWGui::GM_QuickKeysMenu);
} }
void InputManager::activate() void InputManager::activate()
{ {
mEngine.activate(); if (mControlSwitch["playercontrols"])
mEngine.activate();
} }
void InputManager::toggleAutoMove() void InputManager::toggleAutoMove()

@ -17,6 +17,11 @@
#include "../mwsound/sound_decoder.hpp" #include "../mwsound/sound_decoder.hpp"
#include "../mwsound/sound.hpp" #include "../mwsound/sound.hpp"
#ifdef _WIN32
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif
namespace MWRender namespace MWRender
{ {
@ -361,7 +366,11 @@ class MovieAudioDecoder : public MWSound::Sound_Decoder
} }
void open(const std::string&) void open(const std::string&)
#ifdef _WIN32
{ fail(std::string("Invalid call to ")+__FUNCSIG__); }
#else
{ fail(std::string("Invalid call to ")+__PRETTY_FUNCTION__); } { fail(std::string("Invalid call to ")+__PRETTY_FUNCTION__); }
#endif
void close() { } void close() { }

@ -21,6 +21,7 @@
#include "../mwworld/containerstore.hpp" #include "../mwworld/containerstore.hpp"
#include "../mwworld/actionequip.hpp" #include "../mwworld/actionequip.hpp"
#include "../mwworld/inventorystore.hpp" #include "../mwworld/inventorystore.hpp"
#include "../mwworld/player.hpp"
#include "interpretercontext.hpp" #include "interpretercontext.hpp"
#include "ref.hpp" #include "ref.hpp"
@ -47,6 +48,10 @@ namespace MWScript
if (count<0) if (count<0)
throw std::runtime_error ("second argument for AddItem must be non-negative"); throw std::runtime_error ("second argument for AddItem must be non-negative");
// no-op
if (count == 0)
return;
MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), item); MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), item);
ref.getPtr().getRefData().setCount (count); ref.getPtr().getRefData().setCount (count);
@ -60,6 +65,26 @@ namespace MWScript
} }
MWWorld::Class::get (ptr).getContainerStore (ptr).add (ref.getPtr()); MWWorld::Class::get (ptr).getContainerStore (ptr).add (ref.getPtr());
// Spawn a messagebox (only for items added to player's inventory)
if (ptr == MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer())
{
// The two GMST entries below expand to strings informing the player of what, and how many of it has been added to their inventory
std::string msgBox;
std::string itemName = MWWorld::Class::get(ref.getPtr()).getName(ref.getPtr());
if (count == 1)
{
msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage60}");
msgBox = boost::str(boost::format(msgBox) % itemName);
}
else
{
msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage61}");
msgBox = boost::str(boost::format(msgBox) % count % itemName);
}
MWBase::Environment::get().getWindowManager()->messageBox(msgBox, std::vector<std::string>());
}
} }
}; };
@ -101,13 +126,19 @@ namespace MWScript
Interpreter::Type_Integer count = runtime[0].mInteger; Interpreter::Type_Integer count = runtime[0].mInteger;
runtime.pop(); runtime.pop();
if (count<0) if (count<0)
throw std::runtime_error ("second argument for RemoveItem must be non-negative"); throw std::runtime_error ("second argument for RemoveItem must be non-negative");
// no-op
if (count == 0)
return;
MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr); MWWorld::ContainerStore& store = MWWorld::Class::get (ptr).getContainerStore (ptr);
std::string itemName = ""; std::string itemName = "";
// originalCount holds the total number of items to remove, count holds the remaining number of items to remove
Interpreter::Type_Integer originalCount = count; Interpreter::Type_Integer originalCount = count;
for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end() && count; for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end() && count;
@ -130,28 +161,26 @@ namespace MWScript
} }
} }
/* The two GMST entries below expand to strings informing the player of what, and how many of it has been removed from their inventory */ // Spawn a messagebox (only for items added to player's inventory)
std::string msgBox; if (ptr == MWBase::Environment::get().getWorld ()->getPlayer ().getPlayer())
if(originalCount - count > 1)
{ {
msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage63}"); // The two GMST entries below expand to strings informing the player of what, and how many of it has been removed from their inventory
std::stringstream temp; std::string msgBox;
temp << boost::format(msgBox) % (originalCount - count) % itemName; int numRemoved = (originalCount - count);
msgBox = temp.str(); if(numRemoved > 1)
} {
else msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage63}");
{ msgBox = boost::str (boost::format(msgBox) % numRemoved % itemName);
msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage62}"); }
std::stringstream temp; else
temp << boost::format(msgBox) % itemName; {
msgBox = temp.str(); msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage62}");
} msgBox = boost::str (boost::format(msgBox) % itemName);
}
if(originalCount - count > 0)
MWBase::Environment::get().getWindowManager()->messageBox(msgBox, std::vector<std::string>());
// To be fully compatible with original Morrowind, we would need to check if if (numRemoved > 0)
// count is >= 0 here and throw an exception. But let's be tollerant instead. MWBase::Environment::get().getWindowManager()->messageBox(msgBox, std::vector<std::string>());
}
} }
}; };

@ -160,6 +160,7 @@ void FFmpeg_Decoder::open(const std::string &fname)
{ {
if(mFormatCtx->streams[j]->codec->codec_type == AVMEDIA_TYPE_AUDIO) if(mFormatCtx->streams[j]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
{ {
mFormatCtx->streams[j]->codec->request_sample_fmt = AV_SAMPLE_FMT_S16;
mStream = &mFormatCtx->streams[j]; mStream = &mFormatCtx->streams[j];
break; break;
} }

@ -14,9 +14,6 @@ namespace MWWorld
void ActionTake::executeImp (const Ptr& actor) void ActionTake::executeImp (const Ptr& actor)
{ {
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
return;
// insert into player's inventory // insert into player's inventory
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPtr ("player", true); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPtr ("player", true);

@ -3,7 +3,7 @@
#include <set> #include <set>
#include <iostream> #include <iostream>
#include <boost/filesystem/v3/operations.hpp> #include <boost/filesystem/operations.hpp>
namespace MWWorld namespace MWWorld
{ {

@ -77,8 +77,8 @@ public:
std::string mKey, mTrap; // Key and trap ID names, if any std::string mKey, mTrap; // Key and trap ID names, if any
// No idea - occurs ONCE in Morrowind.esm, for an activator // No idea - occurs ONCE in Morrowind.esm, for an activator
char mUnam; signed char mUnam;
// Track deleted references. 0 - not deleted, 1 - deleted, but respawns, 2 - deleted and does not respawn. // Track deleted references. 0 - not deleted, 1 - deleted, but respawns, 2 - deleted and does not respawn.
int mDeleted; int mDeleted;
@ -164,14 +164,14 @@ struct Cell
bool mWaterInt; bool mWaterInt;
int mMapColor; int mMapColor;
int mNAM0; int mNAM0;
// References "leased" from another cell (i.e. a different cell // References "leased" from another cell (i.e. a different cell
// introduced this ref, and it has been moved here by a plugin) // introduced this ref, and it has been moved here by a plugin)
CellRefTracker mLeasedRefs; CellRefTracker mLeasedRefs;
MovedCellRefTracker mMovedRefs; MovedCellRefTracker mMovedRefs;
void load(ESMReader &esm, MWWorld::ESMStore &store); void load(ESMReader &esm, MWWorld::ESMStore &store);
// This method is left in for compatibility with esmtool. Parsing moved references currently requires // This method is left in for compatibility with esmtool. Parsing moved references currently requires
// passing ESMStore, bit it does not know about this parameter, so we do it this way. // passing ESMStore, bit it does not know about this parameter, so we do it this way.
void load(ESMReader &esm) {}; void load(ESMReader &esm) {};
@ -209,7 +209,7 @@ struct Cell
reuse one memory location without blanking it between calls. reuse one memory location without blanking it between calls.
*/ */
static bool getNextRef(ESMReader &esm, CellRef &ref); static bool getNextRef(ESMReader &esm, CellRef &ref);
/* This fetches an MVRF record, which is used to track moved references. /* This fetches an MVRF record, which is used to track moved references.
* Since they are comparably rare, we use a separate method for this. * Since they are comparably rare, we use a separate method for this.
*/ */

@ -30,7 +30,7 @@ struct Dialogue
}; };
std::string mId; std::string mId;
char mType; signed char mType;
std::vector<DialInfo> mInfo; std::vector<DialInfo> mInfo;
void load(ESMReader &esm); void load(ESMReader &esm);

@ -8,7 +8,7 @@ namespace ToUTF8
/// Central European and Eastern European languages that use Latin script, /// Central European and Eastern European languages that use Latin script,
/// such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian, /// such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian,
/// Serbian (Latin script), Romanian and Albanian. /// Serbian (Latin script), Romanian and Albanian.
static char windows_1250[] = static signed char windows_1250[] =
{ {
1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
@ -270,7 +270,7 @@ static char windows_1250[] =
/// Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic /// Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic
/// and other languages /// and other languages
static char windows_1251[] = static signed char windows_1251[] =
{ {
1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
@ -531,7 +531,7 @@ static char windows_1251[] =
}; };
/// Latin alphabet used by English and some other Western languages /// Latin alphabet used by English and some other Western languages
static char windows_1252[] = static signed char windows_1252[] =
{ {
1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,

@ -216,7 +216,7 @@ void Utf8Encoder::copyFromArray(unsigned char ch, char* &out)
return; return;
} }
const char *in = translationArray + ch*6; const signed char *in = translationArray + ch*6;
int len = *(in++); int len = *(in++);
for (int i=0; i<len; i++) for (int i=0; i<len; i++)
*(out++) = *(in++); *(out++) = *(in++);

@ -47,7 +47,7 @@ namespace ToUTF8
void copyFromArray2(const char*& chp, char* &out); void copyFromArray2(const char*& chp, char* &out);
std::vector<char> mOutput; std::vector<char> mOutput;
char* translationArray; signed char* translationArray;
}; };
} }

@ -26,6 +26,7 @@ gugus / gus
Jacob Essex (Yacoby) Jacob Essex (Yacoby)
Jannik Heller (scrawl) Jannik Heller (scrawl)
Jason Hooks (jhooks) Jason Hooks (jhooks)
Joel Graff (graffy)
Karl-Felix Glatzer (k1ll) Karl-Felix Glatzer (k1ll)
lazydev lazydev
Leon Saunders (emoose) Leon Saunders (emoose)

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/">
<file>opencs.png</file>
</qresource>
</RCC>
Loading…
Cancel
Save