forked from teamnwah/openmw-tes3coop
Merge pull request #305 from TES3MP/master
Add master commits up to 6 Oct 2017
This commit is contained in:
commit
7a38a0b223
222 changed files with 4351 additions and 1828 deletions
|
@ -6,5 +6,5 @@ brew outdated cmake || brew upgrade cmake
|
||||||
brew outdated pkgconfig || brew upgrade pkgconfig
|
brew outdated pkgconfig || brew upgrade pkgconfig
|
||||||
brew install $macos_qt_formula
|
brew install $macos_qt_formula
|
||||||
|
|
||||||
curl https://downloads.openmw.org/osx/dependencies/openmw-deps-5e144e2.zip -o ~/openmw-deps.zip
|
curl https://downloads.openmw.org/osx/dependencies/openmw-deps-c40905f.zip -o ~/openmw-deps.zip
|
||||||
unzip ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null
|
unzip ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null
|
||||||
|
|
|
@ -3,7 +3,7 @@ TES3MP
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/TES3MP/openmw-tes3mp.svg?branch=master)](https://travis-ci.org/TES3MP/openmw-tes3mp)
|
[![Build Status](https://travis-ci.org/TES3MP/openmw-tes3mp.svg?branch=master)](https://travis-ci.org/TES3MP/openmw-tes3mp)
|
||||||
|
|
||||||
TES3MP is a project aiming to add multiplayer functionality to [OpenMW](https://github.com/OpenMW/openmw), a free and open source recreation of the popular Bethesda Softworks game "The Elder Scrolls III: Morrowind".
|
TES3MP is a project aiming to add multiplayer functionality to [OpenMW](https://github.com/OpenMW/openmw), a free and open source engine recreation of the popular Bethesda Softworks game "The Elder Scrolls III: Morrowind".
|
||||||
|
|
||||||
* Version: 0.7-alpha
|
* Version: 0.7-alpha
|
||||||
* License: GPLv3 (see docs/license/GPL3.txt for more information)
|
* License: GPLv3 (see docs/license/GPL3.txt for more information)
|
||||||
|
@ -25,17 +25,17 @@ Contributing
|
||||||
|
|
||||||
Development has been relatively fast, but any contribution regarding [code](https://github.com/TES3MP/openmw-tes3mp/blob/master/CONTRIBUTING.md), documentation, bug hunting or video showcases is greatly appreciated.
|
Development has been relatively fast, but any contribution regarding [code](https://github.com/TES3MP/openmw-tes3mp/blob/master/CONTRIBUTING.md), documentation, bug hunting or video showcases is greatly appreciated.
|
||||||
|
|
||||||
Test sessions are often advertised in [our Steam group](https://steamcommunity.com/groups/mwmulti) or [our Discord server](https://discord.gg/H8zhhuk).
|
Test sessions are often advertised in [our Steam group](https://steamcommunity.com/groups/mwmulti) or [our Discord server](https://discord.gg/ECJk293).
|
||||||
|
|
||||||
Feel free to contact the [team members](https://github.com/TES3MP/openmw-tes3mp/blob/master/tes3mp-credits.md) for any questions you might have.
|
Feel free to contact the [team members](https://github.com/TES3MP/openmw-tes3mp/blob/master/tes3mp-credits.md) for any questions you might have.
|
||||||
|
|
||||||
Getting Started
|
Getting Started
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
* [Quickstart guide](https://github.com/TES3MP/openmw-tes3mp/wiki/Quickstart-guide)
|
||||||
|
* [Steam group](https://steamcommunity.com/groups/mwmulti) and its [detailed FAQ](http://steamcommunity.com/groups/mwmulti/discussions/1/353916184342480541/)
|
||||||
* [TES3MP section on OpenMW forums](https://forum.openmw.org/viewforum.php?f=44)
|
* [TES3MP section on OpenMW forums](https://forum.openmw.org/viewforum.php?f=44)
|
||||||
* [Steam group](https://steamcommunity.com/groups/mwmulti)
|
|
||||||
* [Subreddit](https://www.reddit.com/r/tes3mp)
|
* [Subreddit](https://www.reddit.com/r/tes3mp)
|
||||||
* [Installation and build instructions](https://github.com/TES3MP/openmw-tes3mp/wiki/Installation-and-build-instructions)
|
|
||||||
* [Known issues and bug reports](https://github.com/TES3MP/openmw-tes3mp/issues)
|
* [Known issues and bug reports](https://github.com/TES3MP/openmw-tes3mp/issues)
|
||||||
|
|
||||||
Donations
|
Donations
|
||||||
|
|
|
@ -18,7 +18,7 @@ opencs_hdrs_noqt (model/doc
|
||||||
|
|
||||||
|
|
||||||
opencs_units (model/world
|
opencs_units (model/world
|
||||||
idtable idtableproxymodel regionmap data commanddispatcher idtablebase resourcetable nestedtableproxymodel idtree infotableproxymodel
|
idtable idtableproxymodel regionmap data commanddispatcher idtablebase resourcetable nestedtableproxymodel idtree infotableproxymodel landtexturetableproxymodel
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ opencs_units (view/world
|
||||||
cellcreator pathgridcreator referenceablecreator startscriptcreator referencecreator scenesubview
|
cellcreator pathgridcreator referenceablecreator startscriptcreator referencecreator scenesubview
|
||||||
infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable nestedtable
|
infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable nestedtable
|
||||||
dialoguespinbox recordbuttonbar tableeditidaction scripterrortable extendedcommandconfigurator
|
dialoguespinbox recordbuttonbar tableeditidaction scripterrortable extendedcommandconfigurator
|
||||||
bodypartcreator
|
bodypartcreator landtexturecreator landcreator
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units_noqt (view/world
|
opencs_units_noqt (view/world
|
||||||
|
|
|
@ -240,6 +240,8 @@ void CSMPrefs::State::declare()
|
||||||
declareShortcut ("document-world-cells", "Open Cell List", QKeySequence());
|
declareShortcut ("document-world-cells", "Open Cell List", QKeySequence());
|
||||||
declareShortcut ("document-world-referencables", "Open Object List", QKeySequence());
|
declareShortcut ("document-world-referencables", "Open Object List", QKeySequence());
|
||||||
declareShortcut ("document-world-references", "Open Instance List", QKeySequence());
|
declareShortcut ("document-world-references", "Open Instance List", QKeySequence());
|
||||||
|
declareShortcut ("document-world-lands", "Open Lands List", QKeySequence());
|
||||||
|
declareShortcut ("document-world-landtextures", "Open Land Textures List", QKeySequence());
|
||||||
declareShortcut ("document-world-pathgrid", "Open Pathgrid List", QKeySequence());
|
declareShortcut ("document-world-pathgrid", "Open Pathgrid List", QKeySequence());
|
||||||
declareShortcut ("document-world-regionmap", "Open Region Map", QKeySequence());
|
declareShortcut ("document-world-regionmap", "Open Region Map", QKeySequence());
|
||||||
declareShortcut ("document-mechanics-globals", "Open Global List", QKeySequence());
|
declareShortcut ("document-mechanics-globals", "Open Global List", QKeySequence());
|
||||||
|
@ -276,6 +278,7 @@ void CSMPrefs::State::declare()
|
||||||
declareShortcut ("table-edit", "Edit Record", QKeySequence());
|
declareShortcut ("table-edit", "Edit Record", QKeySequence());
|
||||||
declareShortcut ("table-add", "Add Row/Record", QKeySequence(Qt::ShiftModifier | Qt::Key_A));
|
declareShortcut ("table-add", "Add Row/Record", QKeySequence(Qt::ShiftModifier | Qt::Key_A));
|
||||||
declareShortcut ("table-clone", "Clone Record", QKeySequence(Qt::ShiftModifier | Qt::Key_D));
|
declareShortcut ("table-clone", "Clone Record", QKeySequence(Qt::ShiftModifier | Qt::Key_D));
|
||||||
|
declareShortcut ("touch-record", "Touch Record", QKeySequence());
|
||||||
declareShortcut ("table-revert", "Revert Record", QKeySequence());
|
declareShortcut ("table-revert", "Revert Record", QKeySequence());
|
||||||
declareShortcut ("table-remove", "Remove Row/Record", QKeySequence(Qt::Key_Delete));
|
declareShortcut ("table-remove", "Remove Row/Record", QKeySequence(Qt::Key_Delete));
|
||||||
declareShortcut ("table-moveup", "Move Record Up", QKeySequence());
|
declareShortcut ("table-moveup", "Move Record Up", QKeySequence());
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
@ -13,8 +14,9 @@
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
#include "columnbase.hpp"
|
#include "columnbase.hpp"
|
||||||
|
|
||||||
#include "collectionbase.hpp"
|
#include "collectionbase.hpp"
|
||||||
|
#include "land.hpp"
|
||||||
|
#include "landtexture.hpp"
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
|
@ -22,15 +24,14 @@ namespace CSMWorld
|
||||||
template<typename ESXRecordT>
|
template<typename ESXRecordT>
|
||||||
struct IdAccessor
|
struct IdAccessor
|
||||||
{
|
{
|
||||||
std::string& getId (ESXRecordT& record);
|
void setId(ESXRecordT& record, const std::string& id) const;
|
||||||
|
|
||||||
const std::string getId (const ESXRecordT& record) const;
|
const std::string getId (const ESXRecordT& record) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ESXRecordT>
|
template<typename ESXRecordT>
|
||||||
std::string& IdAccessor<ESXRecordT>::getId (ESXRecordT& record)
|
void IdAccessor<ESXRecordT>::setId(ESXRecordT& record, const std::string& id) const
|
||||||
{
|
{
|
||||||
return record.mId;
|
record.mId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ESXRecordT>
|
template<typename ESXRecordT>
|
||||||
|
@ -39,6 +40,39 @@ namespace CSMWorld
|
||||||
return record.mId;
|
return record.mId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void IdAccessor<Land>::setId (Land& record, const std::string& id) const
|
||||||
|
{
|
||||||
|
int x=0, y=0;
|
||||||
|
|
||||||
|
Land::parseUniqueRecordId(id, x, y);
|
||||||
|
record.mX = x;
|
||||||
|
record.mY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void IdAccessor<LandTexture>::setId (LandTexture& record, const std::string& id) const
|
||||||
|
{
|
||||||
|
int plugin = 0;
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
LandTexture::parseUniqueRecordId(id, plugin, index);
|
||||||
|
record.mPluginIndex = plugin;
|
||||||
|
record.mIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline const std::string IdAccessor<Land>::getId (const Land& record) const
|
||||||
|
{
|
||||||
|
return Land::createUniqueRecordId(record.mX, record.mY);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline const std::string IdAccessor<LandTexture>::getId (const LandTexture& record) const
|
||||||
|
{
|
||||||
|
return LandTexture::createUniqueRecordId(record.mPluginIndex, record.mIndex);
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Single-type record collection
|
/// \brief Single-type record collection
|
||||||
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
|
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
|
||||||
class Collection : public CollectionBase
|
class Collection : public CollectionBase
|
||||||
|
@ -69,6 +103,13 @@ namespace CSMWorld
|
||||||
///
|
///
|
||||||
/// \return Success?
|
/// \return Success?
|
||||||
|
|
||||||
|
int cloneRecordImp (const std::string& origin, const std::string& dest,
|
||||||
|
UniversalId::Type type);
|
||||||
|
///< Returns the index of the clone.
|
||||||
|
|
||||||
|
int touchRecordImp (const std::string& id);
|
||||||
|
///< Returns the index of the record on success, -1 on failure.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Collection();
|
Collection();
|
||||||
|
@ -108,6 +149,10 @@ namespace CSMWorld
|
||||||
const std::string& destination,
|
const std::string& destination,
|
||||||
const UniversalId::Type type);
|
const UniversalId::Type type);
|
||||||
|
|
||||||
|
virtual bool touchRecord(const std::string& id);
|
||||||
|
///< Change the state of a record from base to modified, if it is not already.
|
||||||
|
/// \return True if the record was changed.
|
||||||
|
|
||||||
virtual int searchId (const std::string& id) const;
|
virtual int searchId (const std::string& id) const;
|
||||||
////< Search record with \a id.
|
////< Search record with \a id.
|
||||||
/// \return index of record (if found) or -1 (not found)
|
/// \return index of record (if found) or -1 (not found)
|
||||||
|
@ -206,16 +251,71 @@ namespace CSMWorld
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ESXRecordT, typename IdAccessorT>
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
void Collection<ESXRecordT, IdAccessorT>::cloneRecord(const std::string& origin,
|
int Collection<ESXRecordT, IdAccessorT>::cloneRecordImp(const std::string& origin,
|
||||||
const std::string& destination,
|
const std::string& destination, UniversalId::Type type)
|
||||||
const UniversalId::Type type)
|
|
||||||
{
|
{
|
||||||
Record<ESXRecordT> copy;
|
Record<ESXRecordT> copy;
|
||||||
copy.mModified = getRecord(origin).get();
|
copy.mModified = getRecord(origin).get();
|
||||||
copy.mState = RecordBase::State_ModifiedOnly;
|
copy.mState = RecordBase::State_ModifiedOnly;
|
||||||
copy.get().mId = destination;
|
IdAccessorT().setId(copy.get(), destination);
|
||||||
|
|
||||||
insertRecord(copy, getAppendIndex(destination, type));
|
int index = getAppendIndex(destination, type);
|
||||||
|
insertRecord(copy, getAppendIndex(destination, type));
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
int Collection<ESXRecordT, IdAccessorT>::touchRecordImp(const std::string& id)
|
||||||
|
{
|
||||||
|
int index = getIndex(id);
|
||||||
|
Record<ESXRecordT>& record = mRecords.at(index);
|
||||||
|
if (record.isDeleted())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("attempt to touch deleted record");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!record.isModified())
|
||||||
|
{
|
||||||
|
record.setModified(record.get());
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
void Collection<ESXRecordT, IdAccessorT>::cloneRecord(const std::string& origin,
|
||||||
|
const std::string& destination, const UniversalId::Type type)
|
||||||
|
{
|
||||||
|
cloneRecordImp(origin, destination, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void Collection<Land, IdAccessor<Land> >::cloneRecord(const std::string& origin,
|
||||||
|
const std::string& destination, const UniversalId::Type type)
|
||||||
|
{
|
||||||
|
int index = cloneRecordImp(origin, destination, type);
|
||||||
|
mRecords.at(index).get().mPlugin = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
bool Collection<ESXRecordT, IdAccessorT>::touchRecord(const std::string& id)
|
||||||
|
{
|
||||||
|
return touchRecordImp(id) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline bool Collection<Land, IdAccessor<Land> >::touchRecord(const std::string& id)
|
||||||
|
{
|
||||||
|
int index = touchRecordImp(id);
|
||||||
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
mRecords.at(index).get().mPlugin = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ESXRecordT, typename IdAccessorT>
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
@ -366,7 +466,7 @@ namespace CSMWorld
|
||||||
UniversalId::Type type)
|
UniversalId::Type type)
|
||||||
{
|
{
|
||||||
ESXRecordT record;
|
ESXRecordT record;
|
||||||
IdAccessorT().getId (record) = id;
|
IdAccessorT().setId(record, id);
|
||||||
record.blank();
|
record.blank();
|
||||||
|
|
||||||
Record<ESXRecordT> record2;
|
Record<ESXRecordT> record2;
|
||||||
|
|
|
@ -78,6 +78,8 @@ namespace CSMWorld
|
||||||
const std::string& destination,
|
const std::string& destination,
|
||||||
const UniversalId::Type type) = 0;
|
const UniversalId::Type type) = 0;
|
||||||
|
|
||||||
|
virtual bool touchRecord(const std::string& id) = 0;
|
||||||
|
|
||||||
virtual const RecordBase& getRecord (const std::string& id) const = 0;
|
virtual const RecordBase& getRecord (const std::string& id) const = 0;
|
||||||
|
|
||||||
virtual const RecordBase& getRecord (int index) const = 0;
|
virtual const RecordBase& getRecord (int index) const = 0;
|
||||||
|
|
|
@ -1,28 +1,341 @@
|
||||||
#include "columnimp.hpp"
|
#include "columnimp.hpp"
|
||||||
|
|
||||||
CSMWorld::BodyPartRaceColumn::BodyPartRaceColumn(const MeshTypeColumn<ESM::BodyPart> *meshType)
|
#include <stdexcept>
|
||||||
: mMeshType(meshType)
|
#include <QVector>
|
||||||
{}
|
|
||||||
|
|
||||||
QVariant CSMWorld::BodyPartRaceColumn::get(const Record<ESM::BodyPart> &record) const
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
if (mMeshType != NULL && mMeshType->get(record) == ESM::BodyPart::MT_Skin)
|
/* LandTextureNicknameColumn */
|
||||||
|
LandTextureNicknameColumn::LandTextureNicknameColumn()
|
||||||
|
: Column<LandTexture>(Columns::ColumnId_TextureNickname, ColumnBase::Display_String)
|
||||||
{
|
{
|
||||||
return QString::fromUtf8(record.get().mRace.c_str());
|
|
||||||
}
|
}
|
||||||
return QVariant(QVariant::UserType);
|
|
||||||
}
|
QVariant LandTextureNicknameColumn::get(const Record<LandTexture>& record) const
|
||||||
|
{
|
||||||
void CSMWorld::BodyPartRaceColumn::set(Record<ESM::BodyPart> &record, const QVariant &data)
|
return QString::fromUtf8(record.get().mId.c_str());
|
||||||
{
|
}
|
||||||
ESM::BodyPart record2 = record.get();
|
|
||||||
|
void LandTextureNicknameColumn::set(Record<LandTexture>& record, const QVariant& data)
|
||||||
record2.mRace = data.toString().toUtf8().constData();
|
{
|
||||||
|
LandTexture copy = record.get();
|
||||||
record.setModified(record2);
|
copy.mId = data.toString().toUtf8().constData();
|
||||||
}
|
record.setModified(copy);
|
||||||
|
}
|
||||||
bool CSMWorld::BodyPartRaceColumn::isEditable() const
|
|
||||||
{
|
bool LandTextureNicknameColumn::isEditable() const
|
||||||
return true;
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LandTextureIndexColumn */
|
||||||
|
LandTextureIndexColumn::LandTextureIndexColumn()
|
||||||
|
: Column<LandTexture>(Columns::ColumnId_TextureIndex, ColumnBase::Display_Integer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant LandTextureIndexColumn::get(const Record<LandTexture>& record) const
|
||||||
|
{
|
||||||
|
return record.get().mIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LandTextureIndexColumn::isEditable() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LandPluginIndexColumn */
|
||||||
|
LandPluginIndexColumn::LandPluginIndexColumn()
|
||||||
|
: Column<Land>(Columns::ColumnId_PluginIndex, ColumnBase::Display_Integer, 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant LandPluginIndexColumn::get(const Record<Land>& record) const
|
||||||
|
{
|
||||||
|
return record.get().mPlugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LandPluginIndexColumn::isEditable() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LandTexturePluginIndexColumn */
|
||||||
|
LandTexturePluginIndexColumn::LandTexturePluginIndexColumn()
|
||||||
|
: Column<LandTexture>(Columns::ColumnId_PluginIndex, ColumnBase::Display_Integer, 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant LandTexturePluginIndexColumn::get(const Record<LandTexture>& record) const
|
||||||
|
{
|
||||||
|
return record.get().mPluginIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LandTexturePluginIndexColumn::isEditable() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LandMapLodColumn */
|
||||||
|
LandMapLodColumn::LandMapLodColumn()
|
||||||
|
: Column<Land>(Columns::ColumnId_LandMapLodIndex, ColumnBase::Display_String, 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant LandMapLodColumn::get(const Record<Land>& record) const
|
||||||
|
{
|
||||||
|
const int Size = Land::LAND_GLOBAL_MAP_LOD_SIZE;
|
||||||
|
const Land& land = record.get();
|
||||||
|
|
||||||
|
DataType values(Size, 0);
|
||||||
|
|
||||||
|
if (land.isDataLoaded(Land::DATA_WNAM))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Size; ++i)
|
||||||
|
values[i] = land.mWnam[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant variant;
|
||||||
|
variant.setValue(values);
|
||||||
|
return variant;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandMapLodColumn::set(Record<Land>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
DataType values = data.value<DataType>();
|
||||||
|
|
||||||
|
if (values.size() != Land::LAND_GLOBAL_MAP_LOD_SIZE)
|
||||||
|
throw std::runtime_error("invalid land map LOD data");
|
||||||
|
|
||||||
|
Land copy = record.get();
|
||||||
|
copy.setDataLoaded(Land::DATA_WNAM);
|
||||||
|
|
||||||
|
for (int i = 0; i < values.size(); ++i)
|
||||||
|
{
|
||||||
|
copy.mWnam[i] = values[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
record.setModified(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LandMapLodColumn::isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LandNormalsColumn */
|
||||||
|
LandNormalsColumn::LandNormalsColumn()
|
||||||
|
: Column<Land>(Columns::ColumnId_LandNormalsIndex, ColumnBase::Display_String, 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant LandNormalsColumn::get(const Record<Land>& record) const
|
||||||
|
{
|
||||||
|
const int Size = Land::LAND_NUM_VERTS * 3;
|
||||||
|
const Land& land = record.get();
|
||||||
|
|
||||||
|
DataType values(Size, 0);
|
||||||
|
|
||||||
|
if (land.isDataLoaded(Land::DATA_VNML))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Size; ++i)
|
||||||
|
values[i] = land.getLandData()->mNormals[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant variant;
|
||||||
|
variant.setValue(values);
|
||||||
|
return variant;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandNormalsColumn::set(Record<Land>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
DataType values = data.value<DataType>();
|
||||||
|
|
||||||
|
if (values.size() != Land::LAND_NUM_VERTS * 3)
|
||||||
|
throw std::runtime_error("invalid land normals data");
|
||||||
|
|
||||||
|
Land copy = record.get();
|
||||||
|
copy.setDataLoaded(Land::DATA_VNML);
|
||||||
|
|
||||||
|
for (int i = 0; i < values.size(); ++i)
|
||||||
|
{
|
||||||
|
copy.getLandData()->mNormals[i] = values[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
record.setModified(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LandNormalsColumn::isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LandHeightsColumn */
|
||||||
|
LandHeightsColumn::LandHeightsColumn()
|
||||||
|
: Column<Land>(Columns::ColumnId_LandHeightsIndex, ColumnBase::Display_String, 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant LandHeightsColumn::get(const Record<Land>& record) const
|
||||||
|
{
|
||||||
|
const int Size = Land::LAND_NUM_VERTS;
|
||||||
|
const Land& land = record.get();
|
||||||
|
|
||||||
|
DataType values(Size, 0);
|
||||||
|
|
||||||
|
if (land.isDataLoaded(Land::DATA_VHGT))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Size; ++i)
|
||||||
|
values[i] = land.getLandData()->mHeights[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant variant;
|
||||||
|
variant.setValue(values);
|
||||||
|
return variant;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandHeightsColumn::set(Record<Land>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
DataType values = data.value<DataType>();
|
||||||
|
|
||||||
|
if (values.size() != Land::LAND_NUM_VERTS)
|
||||||
|
throw std::runtime_error("invalid land heights data");
|
||||||
|
|
||||||
|
Land copy = record.get();
|
||||||
|
copy.setDataLoaded(Land::DATA_VHGT);
|
||||||
|
|
||||||
|
for (int i = 0; i < values.size(); ++i)
|
||||||
|
{
|
||||||
|
copy.getLandData()->mHeights[i] = values[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
record.setModified(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LandHeightsColumn::isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LandColoursColumn */
|
||||||
|
LandColoursColumn::LandColoursColumn()
|
||||||
|
: Column<Land>(Columns::ColumnId_LandColoursIndex, ColumnBase::Display_String, 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant LandColoursColumn::get(const Record<Land>& record) const
|
||||||
|
{
|
||||||
|
const int Size = Land::LAND_NUM_VERTS * 3;
|
||||||
|
const Land& land = record.get();
|
||||||
|
|
||||||
|
DataType values(Size, 0);
|
||||||
|
|
||||||
|
if (land.isDataLoaded(Land::DATA_VCLR))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Size; ++i)
|
||||||
|
values[i] = land.getLandData()->mColours[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant variant;
|
||||||
|
variant.setValue(values);
|
||||||
|
return variant;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandColoursColumn::set(Record<Land>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
DataType values = data.value<DataType>();
|
||||||
|
|
||||||
|
if (values.size() != Land::LAND_NUM_VERTS * 3)
|
||||||
|
throw std::runtime_error("invalid land colours data");
|
||||||
|
|
||||||
|
Land copy = record.get();
|
||||||
|
copy.setDataLoaded(Land::DATA_VCLR);
|
||||||
|
|
||||||
|
for (int i = 0; i < values.size(); ++i)
|
||||||
|
{
|
||||||
|
copy.getLandData()->mColours[i] = values[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
record.setModified(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LandColoursColumn::isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LandTexturesColumn */
|
||||||
|
LandTexturesColumn::LandTexturesColumn()
|
||||||
|
: Column<Land>(Columns::ColumnId_LandTexturesIndex, ColumnBase::Display_String, 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant LandTexturesColumn::get(const Record<Land>& record) const
|
||||||
|
{
|
||||||
|
const int Size = Land::LAND_NUM_TEXTURES;
|
||||||
|
const Land& land = record.get();
|
||||||
|
|
||||||
|
DataType values(Size, 0);
|
||||||
|
|
||||||
|
if (land.isDataLoaded(Land::DATA_VTEX))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Size; ++i)
|
||||||
|
values[i] = land.getLandData()->mTextures[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant variant;
|
||||||
|
variant.setValue(values);
|
||||||
|
return variant;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandTexturesColumn::set(Record<Land>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
DataType values = data.value<DataType>();
|
||||||
|
|
||||||
|
if (values.size() != Land::LAND_NUM_TEXTURES)
|
||||||
|
throw std::runtime_error("invalid land textures data");
|
||||||
|
|
||||||
|
Land copy = record.get();
|
||||||
|
copy.setDataLoaded(Land::DATA_VTEX);
|
||||||
|
|
||||||
|
for (int i = 0; i < values.size(); ++i)
|
||||||
|
{
|
||||||
|
copy.getLandData()->mTextures[i] = values[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
record.setModified(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LandTexturesColumn::isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BodyPartRaceColumn */
|
||||||
|
BodyPartRaceColumn::BodyPartRaceColumn(const MeshTypeColumn<ESM::BodyPart> *meshType)
|
||||||
|
: mMeshType(meshType)
|
||||||
|
{}
|
||||||
|
|
||||||
|
QVariant BodyPartRaceColumn::get(const Record<ESM::BodyPart> &record) const
|
||||||
|
{
|
||||||
|
if (mMeshType != NULL && mMeshType->get(record) == ESM::BodyPart::MT_Skin)
|
||||||
|
{
|
||||||
|
return QString::fromUtf8(record.get().mRace.c_str());
|
||||||
|
}
|
||||||
|
return QVariant(QVariant::UserType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BodyPartRaceColumn::set(Record<ESM::BodyPart> &record, const QVariant &data)
|
||||||
|
{
|
||||||
|
ESM::BodyPart record2 = record.get();
|
||||||
|
|
||||||
|
record2.mRace = data.toString().toUtf8().constData();
|
||||||
|
|
||||||
|
record.setModified(record2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BodyPartRaceColumn::isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
#define CSM_WOLRD_COLUMNIMP_H
|
#define CSM_WOLRD_COLUMNIMP_H
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
#include <components/esm/loadbody.hpp>
|
#include <components/esm/loadbody.hpp>
|
||||||
#include <components/esm/loadskil.hpp>
|
#include <components/esm/loadskil.hpp>
|
||||||
|
@ -15,6 +17,9 @@
|
||||||
#include "columns.hpp"
|
#include "columns.hpp"
|
||||||
#include "info.hpp"
|
#include "info.hpp"
|
||||||
|
|
||||||
|
#include "land.hpp"
|
||||||
|
#include "landtexture.hpp"
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
/// \note Shares ID with VarValueColumn. A table can not have both.
|
/// \note Shares ID with VarValueColumn. A table can not have both.
|
||||||
|
@ -60,6 +65,20 @@ namespace CSMWorld
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline QVariant StringIdColumn<Land>::get(const Record<Land>& record) const
|
||||||
|
{
|
||||||
|
const Land& land = record.get();
|
||||||
|
return QString::fromUtf8(Land::createUniqueRecordId(land.mX, land.mY).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline QVariant StringIdColumn<LandTexture>::get(const Record<LandTexture>& record) const
|
||||||
|
{
|
||||||
|
const LandTexture& ltex = record.get();
|
||||||
|
return QString::fromUtf8(LandTexture::createUniqueRecordId(ltex.mPluginIndex, ltex.mIndex).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ESXRecordT>
|
template<typename ESXRecordT>
|
||||||
struct RecordStateColumn : public Column<ESXRecordT>
|
struct RecordStateColumn : public Column<ESXRecordT>
|
||||||
{
|
{
|
||||||
|
@ -2418,6 +2437,94 @@ namespace CSMWorld
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LandTextureNicknameColumn : public Column<LandTexture>
|
||||||
|
{
|
||||||
|
LandTextureNicknameColumn();
|
||||||
|
|
||||||
|
QVariant get(const Record<LandTexture>& record) const override;
|
||||||
|
void set(Record<LandTexture>& record, const QVariant& data) override;
|
||||||
|
bool isEditable() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LandTextureIndexColumn : public Column<LandTexture>
|
||||||
|
{
|
||||||
|
LandTextureIndexColumn();
|
||||||
|
|
||||||
|
QVariant get(const Record<LandTexture>& record) const override;
|
||||||
|
bool isEditable() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LandPluginIndexColumn : public Column<Land>
|
||||||
|
{
|
||||||
|
LandPluginIndexColumn();
|
||||||
|
|
||||||
|
QVariant get(const Record<Land>& record) const override;
|
||||||
|
bool isEditable() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LandTexturePluginIndexColumn : public Column<LandTexture>
|
||||||
|
{
|
||||||
|
LandTexturePluginIndexColumn();
|
||||||
|
|
||||||
|
QVariant get(const Record<LandTexture>& record) const override;
|
||||||
|
bool isEditable() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LandMapLodColumn : public Column<Land>
|
||||||
|
{
|
||||||
|
using DataType = QVector<signed char>;
|
||||||
|
|
||||||
|
LandMapLodColumn();
|
||||||
|
|
||||||
|
QVariant get(const Record<Land>& record) const override;
|
||||||
|
void set(Record<Land>& record, const QVariant& data) override;
|
||||||
|
bool isEditable() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LandNormalsColumn : public Column<Land>
|
||||||
|
{
|
||||||
|
using DataType = QVector<signed char>;
|
||||||
|
|
||||||
|
LandNormalsColumn();
|
||||||
|
|
||||||
|
QVariant get(const Record<Land>& record) const override;
|
||||||
|
void set(Record<Land>& record, const QVariant& data) override;
|
||||||
|
bool isEditable() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LandHeightsColumn : public Column<Land>
|
||||||
|
{
|
||||||
|
using DataType = QVector<float>;
|
||||||
|
|
||||||
|
LandHeightsColumn();
|
||||||
|
|
||||||
|
QVariant get(const Record<Land>& record) const override;
|
||||||
|
void set(Record<Land>& record, const QVariant& data) override;
|
||||||
|
bool isEditable() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LandColoursColumn : public Column<Land>
|
||||||
|
{
|
||||||
|
using DataType = QVector<unsigned char>;
|
||||||
|
|
||||||
|
LandColoursColumn();
|
||||||
|
|
||||||
|
QVariant get(const Record<Land>& record) const override;
|
||||||
|
void set(Record<Land>& record, const QVariant& data) override;
|
||||||
|
bool isEditable() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LandTexturesColumn : public Column<Land>
|
||||||
|
{
|
||||||
|
using DataType = QVector<uint16_t>;
|
||||||
|
|
||||||
|
LandTexturesColumn();
|
||||||
|
|
||||||
|
QVariant get(const Record<Land>& record) const override;
|
||||||
|
void set(Record<Land>& record, const QVariant& data) override;
|
||||||
|
bool isEditable() const override;
|
||||||
|
};
|
||||||
|
|
||||||
struct BodyPartRaceColumn : public RaceColumn<ESM::BodyPart>
|
struct BodyPartRaceColumn : public RaceColumn<ESM::BodyPart>
|
||||||
{
|
{
|
||||||
const MeshTypeColumn<ESM::BodyPart> *mMeshType;
|
const MeshTypeColumn<ESM::BodyPart> *mMeshType;
|
||||||
|
@ -2430,4 +2537,11 @@ namespace CSMWorld
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is required to access the type as a QVariant.
|
||||||
|
Q_DECLARE_METATYPE(CSMWorld::LandMapLodColumn::DataType)
|
||||||
|
//Q_DECLARE_METATYPE(CSMWorld::LandNormalsColumn::DataType) // Same as LandMapLodColumn::DataType
|
||||||
|
Q_DECLARE_METATYPE(CSMWorld::LandHeightsColumn::DataType)
|
||||||
|
Q_DECLARE_METATYPE(CSMWorld::LandColoursColumn::DataType)
|
||||||
|
Q_DECLARE_METATYPE(CSMWorld::LandTexturesColumn::DataType)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -330,6 +330,14 @@ namespace CSMWorld
|
||||||
{ ColumnId_WeatherChance, "Percent Chance" },
|
{ ColumnId_WeatherChance, "Percent Chance" },
|
||||||
|
|
||||||
{ ColumnId_Text, "Text" },
|
{ ColumnId_Text, "Text" },
|
||||||
|
{ ColumnId_TextureNickname, "Texture Nickname" },
|
||||||
|
{ ColumnId_PluginIndex, "Plugin Index" },
|
||||||
|
{ ColumnId_TextureIndex, "Texture Index" },
|
||||||
|
{ ColumnId_LandMapLodIndex, "Land map height LOD" },
|
||||||
|
{ ColumnId_LandNormalsIndex, "Land normals" },
|
||||||
|
{ ColumnId_LandHeightsIndex, "Land heights" },
|
||||||
|
{ ColumnId_LandColoursIndex, "Land colors" },
|
||||||
|
{ ColumnId_LandTexturesIndex, "Land textures" },
|
||||||
|
|
||||||
{ ColumnId_UseValue1, "Use value 1" },
|
{ ColumnId_UseValue1, "Use value 1" },
|
||||||
{ ColumnId_UseValue2, "Use value 2" },
|
{ ColumnId_UseValue2, "Use value 2" },
|
||||||
|
|
|
@ -329,6 +329,15 @@ namespace CSMWorld
|
||||||
|
|
||||||
ColumnId_Text = 297,
|
ColumnId_Text = 297,
|
||||||
|
|
||||||
|
ColumnId_TextureNickname = 298,
|
||||||
|
ColumnId_PluginIndex = 299,
|
||||||
|
ColumnId_TextureIndex = 300,
|
||||||
|
ColumnId_LandMapLodIndex = 301,
|
||||||
|
ColumnId_LandNormalsIndex = 302,
|
||||||
|
ColumnId_LandHeightsIndex = 303,
|
||||||
|
ColumnId_LandColoursIndex = 304,
|
||||||
|
ColumnId_LandTexturesIndex = 305,
|
||||||
|
|
||||||
// Allocated to a separate value range, so we don't get a collision should we ever need
|
// Allocated to a separate value range, so we don't get a collision should we ever need
|
||||||
// to extend the number of use values.
|
// to extend the number of use values.
|
||||||
ColumnId_UseValue1 = 0x10000,
|
ColumnId_UseValue1 = 0x10000,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
|
@ -15,6 +16,175 @@
|
||||||
#include "nestedtablewrapper.hpp"
|
#include "nestedtablewrapper.hpp"
|
||||||
#include "pathgrid.hpp"
|
#include "pathgrid.hpp"
|
||||||
|
|
||||||
|
CSMWorld::TouchCommand::TouchCommand(IdTable& table, const std::string& id, QUndoCommand* parent)
|
||||||
|
: QUndoCommand(parent)
|
||||||
|
, mTable(table)
|
||||||
|
, mId(id)
|
||||||
|
, mOld(nullptr)
|
||||||
|
, mChanged(false)
|
||||||
|
{
|
||||||
|
setText(("Touch " + mId).c_str());
|
||||||
|
mOld.reset(mTable.getRecord(mId).clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::TouchCommand::redo()
|
||||||
|
{
|
||||||
|
mChanged = mTable.touchRecord(mId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::TouchCommand::undo()
|
||||||
|
{
|
||||||
|
if (mChanged)
|
||||||
|
{
|
||||||
|
mTable.setRecord(mId, *mOld);
|
||||||
|
mChanged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::ImportLandTexturesCommand::ImportLandTexturesCommand(IdTable& landTable,
|
||||||
|
IdTable& ltexTable, QUndoCommand* parent)
|
||||||
|
: QUndoCommand(parent)
|
||||||
|
, mLands(landTable)
|
||||||
|
, mLtexs(ltexTable)
|
||||||
|
, mOldState(0)
|
||||||
|
{
|
||||||
|
setText("Copy land textures to current plugin");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::ImportLandTexturesCommand::redo()
|
||||||
|
{
|
||||||
|
int pluginColumn = mLands.findColumnIndex(Columns::ColumnId_PluginIndex);
|
||||||
|
int oldPlugin = mLands.data(mLands.getModelIndex(getOriginId(), pluginColumn)).toInt();
|
||||||
|
|
||||||
|
// Original data
|
||||||
|
int textureColumn = mLands.findColumnIndex(Columns::ColumnId_LandTexturesIndex);
|
||||||
|
mOld = mLands.data(mLands.getModelIndex(getOriginId(), textureColumn)).value<DataType>();
|
||||||
|
|
||||||
|
// Need to make a copy so the old values can be looked up
|
||||||
|
DataType copy(mOld);
|
||||||
|
|
||||||
|
// Perform touch/copy/etc...
|
||||||
|
onRedo();
|
||||||
|
|
||||||
|
// Find all indices used
|
||||||
|
std::unordered_set<int> texIndices;
|
||||||
|
for (int i = 0; i < mOld.size(); ++i)
|
||||||
|
{
|
||||||
|
// All indices are offset by 1 for a default texture
|
||||||
|
if (mOld[i] > 0)
|
||||||
|
texIndices.insert(mOld[i] - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> oldTextures;
|
||||||
|
for (int index : texIndices)
|
||||||
|
{
|
||||||
|
oldTextures.push_back(LandTexture::createUniqueRecordId(oldPlugin, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import the textures, replace old values
|
||||||
|
LandTextureIdTable::ImportResults results = dynamic_cast<LandTextureIdTable&>(mLtexs).importTextures(oldTextures);
|
||||||
|
mCreatedTextures = std::move(results.createdRecords);
|
||||||
|
for (const auto& it : results.recordMapping)
|
||||||
|
{
|
||||||
|
int plugin = 0, newIndex = 0, oldIndex = 0;
|
||||||
|
LandTexture::parseUniqueRecordId(it.first, plugin, oldIndex);
|
||||||
|
LandTexture::parseUniqueRecordId(it.second, plugin, newIndex);
|
||||||
|
|
||||||
|
if (newIndex != oldIndex)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Land::LAND_NUM_TEXTURES; ++i)
|
||||||
|
{
|
||||||
|
// All indices are offset by 1 for a default texture
|
||||||
|
if (mOld[i] == oldIndex + 1)
|
||||||
|
copy[i] = newIndex + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply modification
|
||||||
|
int stateColumn = mLands.findColumnIndex(Columns::ColumnId_Modification);
|
||||||
|
mOldState = mLands.data(mLands.getModelIndex(getDestinationId(), stateColumn)).toInt();
|
||||||
|
|
||||||
|
QVariant variant;
|
||||||
|
variant.setValue(copy);
|
||||||
|
mLands.setData(mLands.getModelIndex(getDestinationId(), textureColumn), variant);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::ImportLandTexturesCommand::undo()
|
||||||
|
{
|
||||||
|
// Restore to previous
|
||||||
|
int textureColumn = mLands.findColumnIndex(Columns::ColumnId_LandTexturesIndex);
|
||||||
|
QVariant variant;
|
||||||
|
variant.setValue(mOld);
|
||||||
|
mLands.setData(mLands.getModelIndex(getDestinationId(), textureColumn), variant);
|
||||||
|
|
||||||
|
int stateColumn = mLands.findColumnIndex(Columns::ColumnId_Modification);
|
||||||
|
mLands.setData(mLands.getModelIndex(getDestinationId(), stateColumn), mOldState);
|
||||||
|
|
||||||
|
// Undo copy/touch/etc...
|
||||||
|
onUndo();
|
||||||
|
|
||||||
|
for (const std::string& id : mCreatedTextures)
|
||||||
|
{
|
||||||
|
int row = mLtexs.getModelIndex(id, 0).row();
|
||||||
|
mLtexs.removeRows(row, 1);
|
||||||
|
}
|
||||||
|
mCreatedTextures.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::CopyLandTexturesCommand::CopyLandTexturesCommand(IdTable& landTable, IdTable& ltexTable,
|
||||||
|
const std::string& origin, const std::string& dest, QUndoCommand* parent)
|
||||||
|
: ImportLandTexturesCommand(landTable, ltexTable, parent)
|
||||||
|
, mOriginId(origin)
|
||||||
|
, mDestId(dest)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& CSMWorld::CopyLandTexturesCommand::getOriginId() const
|
||||||
|
{
|
||||||
|
return mOriginId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& CSMWorld::CopyLandTexturesCommand::getDestinationId() const
|
||||||
|
{
|
||||||
|
return mDestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::TouchLandCommand::TouchLandCommand(IdTable& landTable, IdTable& ltexTable,
|
||||||
|
const std::string& id, QUndoCommand* parent)
|
||||||
|
: ImportLandTexturesCommand(landTable, ltexTable, parent)
|
||||||
|
, mId(id)
|
||||||
|
, mOld(nullptr)
|
||||||
|
, mChanged(false)
|
||||||
|
{
|
||||||
|
setText(("Touch " + mId).c_str());
|
||||||
|
mOld.reset(mLands.getRecord(mId).clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& CSMWorld::TouchLandCommand::getOriginId() const
|
||||||
|
{
|
||||||
|
return mId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& CSMWorld::TouchLandCommand::getDestinationId() const
|
||||||
|
{
|
||||||
|
return mId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::TouchLandCommand::onRedo()
|
||||||
|
{
|
||||||
|
mChanged = mLands.touchRecord(mId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::TouchLandCommand::onUndo()
|
||||||
|
{
|
||||||
|
if (mChanged)
|
||||||
|
{
|
||||||
|
mLands.setRecord(mId, *mOld);
|
||||||
|
mChanged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelIndex& index,
|
CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelIndex& index,
|
||||||
const QVariant& new_, QUndoCommand* parent)
|
const QVariant& new_, QUndoCommand* parent)
|
||||||
: QUndoCommand (parent), mModel (&model), mIndex (index), mNew (new_), mHasRecordState(false), mOldRecordState(CSMWorld::RecordBase::State_BaseOnly)
|
: QUndoCommand (parent), mModel (&model), mIndex (index), mNew (new_), mHasRecordState(false), mOldRecordState(CSMWorld::RecordBase::State_BaseOnly)
|
||||||
|
|
|
@ -5,12 +5,14 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QUndoCommand>
|
#include <QUndoCommand>
|
||||||
#include <QModelIndex>
|
#include <QModelIndex>
|
||||||
|
|
||||||
|
#include "columnimp.hpp"
|
||||||
#include "universalid.hpp"
|
#include "universalid.hpp"
|
||||||
#include "nestedtablewrapper.hpp"
|
#include "nestedtablewrapper.hpp"
|
||||||
|
|
||||||
|
@ -24,6 +26,91 @@ namespace CSMWorld
|
||||||
struct RecordBase;
|
struct RecordBase;
|
||||||
struct NestedTableWrapperBase;
|
struct NestedTableWrapperBase;
|
||||||
|
|
||||||
|
class TouchCommand : public QUndoCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
TouchCommand(IdTable& model, const std::string& id, QUndoCommand* parent=nullptr);
|
||||||
|
|
||||||
|
void redo() override;
|
||||||
|
void undo() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
IdTable& mTable;
|
||||||
|
std::string mId;
|
||||||
|
std::unique_ptr<RecordBase> mOld;
|
||||||
|
|
||||||
|
bool mChanged;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ImportLandTexturesCommand : public QUndoCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ImportLandTexturesCommand(IdTable& landTable, IdTable& ltexTable,
|
||||||
|
QUndoCommand* parent);
|
||||||
|
|
||||||
|
void redo() override;
|
||||||
|
void undo() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
using DataType = LandTexturesColumn::DataType;
|
||||||
|
|
||||||
|
virtual const std::string& getOriginId() const = 0;
|
||||||
|
virtual const std::string& getDestinationId() const = 0;
|
||||||
|
|
||||||
|
virtual void onRedo() = 0;
|
||||||
|
virtual void onUndo() = 0;
|
||||||
|
|
||||||
|
IdTable& mLands;
|
||||||
|
IdTable& mLtexs;
|
||||||
|
DataType mOld;
|
||||||
|
int mOldState;
|
||||||
|
std::vector<std::string> mCreatedTextures;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CopyLandTexturesCommand : public ImportLandTexturesCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
CopyLandTexturesCommand(IdTable& landTable, IdTable& ltexTable, const std::string& origin,
|
||||||
|
const std::string& dest, QUndoCommand* parent = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const std::string& getOriginId() const override;
|
||||||
|
const std::string& getDestinationId() const override;
|
||||||
|
|
||||||
|
void onRedo() override {}
|
||||||
|
void onUndo() override {}
|
||||||
|
|
||||||
|
std::string mOriginId;
|
||||||
|
std::string mDestId;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TouchLandCommand : public ImportLandTexturesCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
TouchLandCommand(IdTable& landTable, IdTable& ltexTable,
|
||||||
|
const std::string& id, QUndoCommand* parent = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const std::string& getOriginId() const override;
|
||||||
|
const std::string& getDestinationId() const override;
|
||||||
|
|
||||||
|
void onRedo() override;
|
||||||
|
void onUndo() override;
|
||||||
|
|
||||||
|
std::string mId;
|
||||||
|
std::unique_ptr<RecordBase> mOld;
|
||||||
|
|
||||||
|
bool mChanged;
|
||||||
|
};
|
||||||
|
|
||||||
class ModifyCommand : public QUndoCommand
|
class ModifyCommand : public QUndoCommand
|
||||||
{
|
{
|
||||||
QAbstractItemModel *mModel;
|
QAbstractItemModel *mModel;
|
||||||
|
|
|
@ -412,6 +412,24 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, bool fsStrict, const Files::Pat
|
||||||
Columns::ColumnId_NegativeLight, ESM::MagicEffect::NegativeLight));
|
Columns::ColumnId_NegativeLight, ESM::MagicEffect::NegativeLight));
|
||||||
mMagicEffects.addColumn (new DescriptionColumn<ESM::MagicEffect>);
|
mMagicEffects.addColumn (new DescriptionColumn<ESM::MagicEffect>);
|
||||||
|
|
||||||
|
mLand.addColumn (new StringIdColumn<Land>);
|
||||||
|
mLand.addColumn (new RecordStateColumn<Land>);
|
||||||
|
mLand.addColumn (new FixedRecordTypeColumn<Land>(UniversalId::Type_Land));
|
||||||
|
mLand.addColumn (new LandPluginIndexColumn);
|
||||||
|
mLand.addColumn (new LandMapLodColumn);
|
||||||
|
mLand.addColumn (new LandNormalsColumn);
|
||||||
|
mLand.addColumn (new LandHeightsColumn);
|
||||||
|
mLand.addColumn (new LandColoursColumn);
|
||||||
|
mLand.addColumn (new LandTexturesColumn);
|
||||||
|
|
||||||
|
mLandTextures.addColumn (new StringIdColumn<LandTexture>(true));
|
||||||
|
mLandTextures.addColumn (new RecordStateColumn<LandTexture>);
|
||||||
|
mLandTextures.addColumn (new FixedRecordTypeColumn<LandTexture>(UniversalId::Type_LandTexture));
|
||||||
|
mLandTextures.addColumn (new LandTextureNicknameColumn);
|
||||||
|
mLandTextures.addColumn (new LandTexturePluginIndexColumn);
|
||||||
|
mLandTextures.addColumn (new LandTextureIndexColumn);
|
||||||
|
mLandTextures.addColumn (new TextureColumn<LandTexture>);
|
||||||
|
|
||||||
mPathgrids.addColumn (new StringIdColumn<Pathgrid>);
|
mPathgrids.addColumn (new StringIdColumn<Pathgrid>);
|
||||||
mPathgrids.addColumn (new RecordStateColumn<Pathgrid>);
|
mPathgrids.addColumn (new RecordStateColumn<Pathgrid>);
|
||||||
mPathgrids.addColumn (new FixedRecordTypeColumn<Pathgrid> (UniversalId::Type_Pathgrid));
|
mPathgrids.addColumn (new FixedRecordTypeColumn<Pathgrid> (UniversalId::Type_Pathgrid));
|
||||||
|
@ -531,6 +549,8 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, bool fsStrict, const Files::Pat
|
||||||
addModel (new IdTable (&mBodyParts), UniversalId::Type_BodyPart);
|
addModel (new IdTable (&mBodyParts), UniversalId::Type_BodyPart);
|
||||||
addModel (new IdTable (&mSoundGens), UniversalId::Type_SoundGen);
|
addModel (new IdTable (&mSoundGens), UniversalId::Type_SoundGen);
|
||||||
addModel (new IdTable (&mMagicEffects), UniversalId::Type_MagicEffect);
|
addModel (new IdTable (&mMagicEffects), UniversalId::Type_MagicEffect);
|
||||||
|
addModel (new IdTable (&mLand, IdTable::Feature_AllowTouch), UniversalId::Type_Land);
|
||||||
|
addModel (new LandTextureIdTable (&mLandTextures), UniversalId::Type_LandTexture);
|
||||||
addModel (new IdTree (&mPathgrids, &mPathgrids), UniversalId::Type_Pathgrid);
|
addModel (new IdTree (&mPathgrids, &mPathgrids), UniversalId::Type_Pathgrid);
|
||||||
addModel (new IdTable (&mStartScripts), UniversalId::Type_StartScript);
|
addModel (new IdTable (&mStartScripts), UniversalId::Type_StartScript);
|
||||||
addModel (new IdTree (&mReferenceables, &mReferenceables, IdTable::Feature_Preview),
|
addModel (new IdTree (&mReferenceables, &mReferenceables, IdTable::Feature_Preview),
|
||||||
|
@ -993,19 +1013,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
|
||||||
|
|
||||||
case ESM::REC_LTEX: mLandTextures.load (*mReader, mBase); break;
|
case ESM::REC_LTEX: mLandTextures.load (*mReader, mBase); break;
|
||||||
|
|
||||||
case ESM::REC_LAND:
|
case ESM::REC_LAND: mLand.load(*mReader, mBase); break;
|
||||||
{
|
|
||||||
int index = mLand.load(*mReader, mBase);
|
|
||||||
|
|
||||||
// Load all land data for now. A future optimisation may only load non-base data
|
|
||||||
// if a suitable mechanism for avoiding race conditions can be established.
|
|
||||||
if (index!=-1/* && !mBase*/)
|
|
||||||
mLand.getRecord (index).get().loadData (
|
|
||||||
ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR |
|
|
||||||
ESM::Land::DATA_VTEX);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ESM::REC_CELL:
|
case ESM::REC_CELL:
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
|
|
||||||
#include "collection.hpp"
|
#include "collection.hpp"
|
||||||
|
#include "land.hpp"
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
|
@ -39,6 +40,22 @@ namespace CSMWorld
|
||||||
record.load (reader, isDeleted);
|
record.load (reader, isDeleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void IdCollection<Land, IdAccessor<Land> >::loadRecord (Land& record,
|
||||||
|
ESM::ESMReader& reader, bool& isDeleted)
|
||||||
|
{
|
||||||
|
record.load (reader, isDeleted);
|
||||||
|
|
||||||
|
// Load all land data for now. A future optimisation may only load non-base data
|
||||||
|
// if a suitable mechanism for avoiding race conditions can be established.
|
||||||
|
int flags = ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML |
|
||||||
|
ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX;
|
||||||
|
record.loadData (flags);
|
||||||
|
|
||||||
|
// Prevent data from being reloaded.
|
||||||
|
record.mContext.filename.clear();
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ESXRecordT, typename IdAccessorT>
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
int IdCollection<ESXRecordT, IdAccessorT>::load (ESM::ESMReader& reader, bool base)
|
int IdCollection<ESXRecordT, IdAccessorT>::load (ESM::ESMReader& reader, bool base)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
#include "idtable.hpp"
|
#include "idtable.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <limits>
|
||||||
|
#include <map>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <components/esm/cellid.hpp>
|
#include <components/esm/cellid.hpp>
|
||||||
|
|
||||||
#include "collectionbase.hpp"
|
#include "collectionbase.hpp"
|
||||||
#include "columnbase.hpp"
|
#include "columnbase.hpp"
|
||||||
|
#include "landtexture.hpp"
|
||||||
|
|
||||||
CSMWorld::IdTable::IdTable (CollectionBase *idCollection, unsigned int features)
|
CSMWorld::IdTable::IdTable (CollectionBase *idCollection, unsigned int features)
|
||||||
: IdTableBase (features), mIdCollection (idCollection)
|
: IdTableBase (features), mIdCollection (idCollection)
|
||||||
|
@ -179,6 +185,26 @@ void CSMWorld::IdTable::cloneRecord(const std::string& origin,
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CSMWorld::IdTable::touchRecord(const std::string& id)
|
||||||
|
{
|
||||||
|
bool changed = mIdCollection->touchRecord(id);
|
||||||
|
|
||||||
|
int row = mIdCollection->getIndex(id);
|
||||||
|
int column = mIdCollection->searchColumnIndex(Columns::ColumnId_RecordType);
|
||||||
|
if (changed && column != -1)
|
||||||
|
{
|
||||||
|
QModelIndex modelIndex = index(row, column);
|
||||||
|
emit dataChanged(modelIndex, modelIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CSMWorld::IdTable::getId(int row) const
|
||||||
|
{
|
||||||
|
return mIdCollection->getId(row);
|
||||||
|
}
|
||||||
|
|
||||||
///This method can return only indexes to the top level table cells
|
///This method can return only indexes to the top level table cells
|
||||||
QModelIndex CSMWorld::IdTable::getModelIndex (const std::string& id, int column) const
|
QModelIndex CSMWorld::IdTable::getModelIndex (const std::string& id, int column) const
|
||||||
{
|
{
|
||||||
|
@ -281,3 +307,72 @@ CSMWorld::CollectionBase *CSMWorld::IdTable::idCollection() const
|
||||||
{
|
{
|
||||||
return mIdCollection;
|
return mIdCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSMWorld::LandTextureIdTable::LandTextureIdTable(CollectionBase* idCollection, unsigned int features)
|
||||||
|
: IdTable(idCollection, features)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::importTextures(const std::vector<std::string>& ids)
|
||||||
|
{
|
||||||
|
ImportResults results;
|
||||||
|
|
||||||
|
// Map existing textures to ids
|
||||||
|
std::map<std::string, std::string> reverseLookupMap;
|
||||||
|
for (int i = 0; i < idCollection()->getSize(); ++i)
|
||||||
|
{
|
||||||
|
auto& record = static_cast<const Record<LandTexture>&>(idCollection()->getRecord(i));
|
||||||
|
std::string texture = record.get().mTexture;
|
||||||
|
std::transform(texture.begin(), texture.end(), texture.begin(), tolower);
|
||||||
|
if (record.isModified())
|
||||||
|
reverseLookupMap.emplace(texture, idCollection()->getId(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const std::string& id : ids)
|
||||||
|
{
|
||||||
|
int plugin, index;
|
||||||
|
|
||||||
|
LandTexture::parseUniqueRecordId(id, plugin, index);
|
||||||
|
int oldRow = idCollection()->searchId(id);
|
||||||
|
|
||||||
|
// If it does not exist or it is in the current plugin, it can be skipped.
|
||||||
|
if (oldRow <= 0 || plugin == 0)
|
||||||
|
{
|
||||||
|
results.recordMapping.push_back(std::make_pair(id, id));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for a pre-existing record
|
||||||
|
auto& record = static_cast<const Record<LandTexture>&>(idCollection()->getRecord(oldRow));
|
||||||
|
std::string texture = record.get().mTexture;
|
||||||
|
std::transform(texture.begin(), texture.end(), texture.begin(), tolower);
|
||||||
|
auto searchIt = reverseLookupMap.find(texture);
|
||||||
|
if (searchIt != reverseLookupMap.end())
|
||||||
|
{
|
||||||
|
results.recordMapping.push_back(std::make_pair(id, searchIt->second));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate until an unused index or found, or the index has completely wrapped around.
|
||||||
|
int startIndex = index;
|
||||||
|
do {
|
||||||
|
std::string newId = LandTexture::createUniqueRecordId(0, index);
|
||||||
|
int newRow = idCollection()->searchId(newId);
|
||||||
|
|
||||||
|
if (newRow < 0)
|
||||||
|
{
|
||||||
|
// Id not taken, clone it
|
||||||
|
cloneRecord(id, newId, UniversalId::Type_LandTexture);
|
||||||
|
results.createdRecords.push_back(newId);
|
||||||
|
results.recordMapping.push_back(std::make_pair(id, newId));
|
||||||
|
reverseLookupMap.emplace(texture, newId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t MaxIndex = std::numeric_limits<uint16_t>::max() - 1;
|
||||||
|
index = (index + 1) % MaxIndex;
|
||||||
|
} while (index != startIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
|
@ -61,6 +61,11 @@ namespace CSMWorld
|
||||||
const std::string& destination,
|
const std::string& destination,
|
||||||
UniversalId::Type type = UniversalId::Type_None);
|
UniversalId::Type type = UniversalId::Type_None);
|
||||||
|
|
||||||
|
bool touchRecord(const std::string& id);
|
||||||
|
///< Will change the record state to modified, if it is not already.
|
||||||
|
|
||||||
|
std::string getId(int row) const;
|
||||||
|
|
||||||
virtual QModelIndex getModelIndex (const std::string& id, int column) const;
|
virtual QModelIndex getModelIndex (const std::string& id, int column) const;
|
||||||
|
|
||||||
void setRecord (const std::string& id, const RecordBase& record,
|
void setRecord (const std::string& id, const RecordBase& record,
|
||||||
|
@ -93,6 +98,29 @@ namespace CSMWorld
|
||||||
|
|
||||||
virtual CollectionBase *idCollection() const;
|
virtual CollectionBase *idCollection() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// An IdTable customized to handle the more unique needs of LandTextureId's which behave
|
||||||
|
/// differently from other records. The major difference is that base records cannot be
|
||||||
|
/// modified.
|
||||||
|
class LandTextureIdTable : public IdTable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
struct ImportResults
|
||||||
|
{
|
||||||
|
using StringPair = std::pair<std::string,std::string>;
|
||||||
|
|
||||||
|
/// The newly added records
|
||||||
|
std::vector<std::string> createdRecords;
|
||||||
|
/// The 1st string is the original id, the 2nd is the mapped id
|
||||||
|
std::vector<StringPair> recordMapping;
|
||||||
|
};
|
||||||
|
|
||||||
|
LandTextureIdTable(CollectionBase* idCollection, unsigned int features=0);
|
||||||
|
|
||||||
|
/// Finds and maps/recreates the specified ids.
|
||||||
|
ImportResults importTextures(const std::vector<std::string>& ids);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -32,7 +32,9 @@ namespace CSMWorld
|
||||||
Feature_Preview = 8,
|
Feature_Preview = 8,
|
||||||
|
|
||||||
/// Table can not be modified through ordinary means.
|
/// Table can not be modified through ordinary means.
|
||||||
Feature_Constant = 16
|
Feature_Constant = 16,
|
||||||
|
|
||||||
|
Feature_AllowTouch = 32
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1,15 +1,30 @@
|
||||||
#include "land.hpp"
|
#include "land.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
void Land::load(ESM::ESMReader &esm, bool &isDeleted)
|
void Land::load(ESM::ESMReader &esm, bool &isDeleted)
|
||||||
{
|
{
|
||||||
ESM::Land::load(esm, isDeleted);
|
ESM::Land::load(esm, isDeleted);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Land::createUniqueRecordId(int x, int y)
|
||||||
|
{
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
stream << "#" << mX << " " << mY;
|
stream << "#" << x << " " << y;
|
||||||
mId = stream.str();
|
return stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Land::parseUniqueRecordId(const std::string& id, int& x, int& y)
|
||||||
|
{
|
||||||
|
size_t mid = id.find(' ');
|
||||||
|
|
||||||
|
if (mid == std::string::npos || id[0] != '#')
|
||||||
|
throw std::runtime_error("Invalid Land ID");
|
||||||
|
|
||||||
|
x = std::stoi(id.substr(1, mid - 1));
|
||||||
|
y = std::stoi(id.substr(mid + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,11 @@ namespace CSMWorld
|
||||||
/// \todo Add worldspace support to the Land record.
|
/// \todo Add worldspace support to the Land record.
|
||||||
struct Land : public ESM::Land
|
struct Land : public ESM::Land
|
||||||
{
|
{
|
||||||
std::string mId;
|
|
||||||
|
|
||||||
/// Loads the metadata and ID
|
/// Loads the metadata and ID
|
||||||
void load (ESM::ESMReader &esm, bool &isDeleted);
|
void load (ESM::ESMReader &esm, bool &isDeleted);
|
||||||
|
|
||||||
|
static std::string createUniqueRecordId(int x, int y);
|
||||||
|
static void parseUniqueRecordId(const std::string& id, int& x, int& y);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#include "landtexture.hpp"
|
#include "landtexture.hpp"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
|
@ -11,4 +14,21 @@ namespace CSMWorld
|
||||||
mPluginIndex = esm.getIndex();
|
mPluginIndex = esm.getIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string LandTexture::createUniqueRecordId(int plugin, int index)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << 'L' << plugin << '#' << index;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandTexture::parseUniqueRecordId(const std::string& id, int& plugin, int& index)
|
||||||
|
{
|
||||||
|
size_t middle = id.find('#');
|
||||||
|
|
||||||
|
if (middle == std::string::npos || id[0] != 'L')
|
||||||
|
throw std::runtime_error("Invalid LandTexture ID");
|
||||||
|
|
||||||
|
plugin = std::stoi(id.substr(1,middle-1));
|
||||||
|
index = std::stoi(id.substr(middle+1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,11 @@ namespace CSMWorld
|
||||||
int mPluginIndex;
|
int mPluginIndex;
|
||||||
|
|
||||||
void load (ESM::ESMReader &esm, bool &isDeleted);
|
void load (ESM::ESMReader &esm, bool &isDeleted);
|
||||||
|
|
||||||
|
/// Returns a string identifier that will be unique to any LandTexture.
|
||||||
|
static std::string createUniqueRecordId(int plugin, int index);
|
||||||
|
/// Deconstructs a unique string identifier into plugin and index.
|
||||||
|
static void parseUniqueRecordId(const std::string& id, int& plugin, int& index);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
21
apps/opencs/model/world/landtexturetableproxymodel.cpp
Normal file
21
apps/opencs/model/world/landtexturetableproxymodel.cpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#include "landtexturetableproxymodel.hpp"
|
||||||
|
|
||||||
|
#include "idtable.hpp"
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
LandTextureTableProxyModel::LandTextureTableProxyModel(QObject* parent)
|
||||||
|
: IdTableProxyModel(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LandTextureTableProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) const
|
||||||
|
{
|
||||||
|
int columnIndex = mSourceModel->findColumnIndex(Columns::ColumnId_Modification);
|
||||||
|
QModelIndex index = mSourceModel->index(sourceRow, columnIndex);
|
||||||
|
if (mSourceModel->data(index).toInt() != RecordBase::State_ModifiedOnly)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return IdTableProxyModel::filterAcceptsRow(sourceRow, sourceParent);
|
||||||
|
}
|
||||||
|
}
|
22
apps/opencs/model/world/landtexturetableproxymodel.hpp
Normal file
22
apps/opencs/model/world/landtexturetableproxymodel.hpp
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef CSM_WORLD_LANDTEXTURETABLEPROXYMODEL_H
|
||||||
|
#define CSM_WORLD_LANDTEXTURETABLEPROXYMODEL_H
|
||||||
|
|
||||||
|
#include "idtableproxymodel.hpp"
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
/// \brief Removes base records from filtered results.
|
||||||
|
class LandTextureTableProxyModel : public IdTableProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
|
||||||
|
LandTextureTableProxyModel(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
bool filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) const override;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -813,6 +813,12 @@ void CSMWorld::RefIdCollection::cloneRecord(const std::string& origin,
|
||||||
mData.insertRecord(*newRecord, type, destination);
|
mData.insertRecord(*newRecord, type, destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CSMWorld::RefIdCollection::touchRecord(const std::string& id)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("RefIdCollection::touchRecord is unimplemented");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void CSMWorld::RefIdCollection::appendRecord (const RecordBase& record,
|
void CSMWorld::RefIdCollection::appendRecord (const RecordBase& record,
|
||||||
UniversalId::Type type)
|
UniversalId::Type type)
|
||||||
{
|
{
|
||||||
|
|
|
@ -80,6 +80,8 @@ namespace CSMWorld
|
||||||
const std::string& destination,
|
const std::string& destination,
|
||||||
const UniversalId::Type type);
|
const UniversalId::Type type);
|
||||||
|
|
||||||
|
virtual bool touchRecord(const std::string& id);
|
||||||
|
|
||||||
virtual void appendBlankRecord (const std::string& id, UniversalId::Type type);
|
virtual void appendBlankRecord (const std::string& id, UniversalId::Type type);
|
||||||
///< \param type Will be ignored, unless the collection supports multiple record types
|
///< \param type Will be ignored, unless the collection supports multiple record types
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,8 @@ namespace
|
||||||
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_RunLog, "Run Log", 0 },
|
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_RunLog, "Run Log", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SoundGens, "Sound Generators", 0 },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SoundGens, "Sound Generators", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects", 0 },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Lands, "Lands", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_LandTextures, "LandTextures", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids", 0 },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_StartScripts, "Start Scripts", 0 },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_StartScripts, "Start Scripts", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MetaDatas, "Meta Data Table", 0 },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MetaDatas, "Meta Data Table", 0 },
|
||||||
|
@ -118,6 +120,8 @@ namespace
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_DebugProfile, "Debug Profile", 0 },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_DebugProfile, "Debug Profile", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_SoundGen, "Sound Generator", 0 },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_SoundGen, "Sound Generator", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MagicEffect, "Magic Effect", 0 },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MagicEffect, "Magic Effect", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Land, "Land", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_LandTexture, "LandTexture", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Pathgrid, "Pathgrid", 0 },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Pathgrid, "Pathgrid", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_StartScript, "Start Script", 0 },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_StartScript, "Start Script", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MetaData, "Meta Data", 0 },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MetaData, "Meta Data", 0 },
|
||||||
|
|
|
@ -126,6 +126,10 @@ namespace CSMWorld
|
||||||
Type_SoundGen,
|
Type_SoundGen,
|
||||||
Type_MagicEffects,
|
Type_MagicEffects,
|
||||||
Type_MagicEffect,
|
Type_MagicEffect,
|
||||||
|
Type_Lands,
|
||||||
|
Type_Land,
|
||||||
|
Type_LandTextures,
|
||||||
|
Type_LandTexture,
|
||||||
Type_Pathgrids,
|
Type_Pathgrids,
|
||||||
Type_Pathgrid,
|
Type_Pathgrid,
|
||||||
Type_StartScripts,
|
Type_StartScripts,
|
||||||
|
|
|
@ -172,6 +172,16 @@ void CSVDoc::View::setupWorldMenu()
|
||||||
setupShortcut("document-world-references", references);
|
setupShortcut("document-world-references", references);
|
||||||
world->addAction (references);
|
world->addAction (references);
|
||||||
|
|
||||||
|
QAction *lands = new QAction (tr ("Lands"), this);
|
||||||
|
connect (lands, SIGNAL (triggered()), this, SLOT (addLandsSubView()));
|
||||||
|
setupShortcut("document-world-lands", lands);
|
||||||
|
world->addAction (lands);
|
||||||
|
|
||||||
|
QAction *landTextures = new QAction (tr ("Land Textures"), this);
|
||||||
|
connect (landTextures, SIGNAL (triggered()), this, SLOT (addLandTexturesSubView()));
|
||||||
|
setupShortcut("document-world-landtextures", landTextures);
|
||||||
|
world->addAction (landTextures);
|
||||||
|
|
||||||
QAction *grid = new QAction (tr ("Pathgrid"), this);
|
QAction *grid = new QAction (tr ("Pathgrid"), this);
|
||||||
connect (grid, SIGNAL (triggered()), this, SLOT (addPathgridSubView()));
|
connect (grid, SIGNAL (triggered()), this, SLOT (addPathgridSubView()));
|
||||||
setupShortcut("document-world-pathgrid", grid);
|
setupShortcut("document-world-pathgrid", grid);
|
||||||
|
@ -876,6 +886,16 @@ void CSVDoc::View::addRunLogSubView()
|
||||||
addSubView (CSMWorld::UniversalId::Type_RunLog);
|
addSubView (CSMWorld::UniversalId::Type_RunLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVDoc::View::addLandsSubView()
|
||||||
|
{
|
||||||
|
addSubView (CSMWorld::UniversalId::Type_Lands);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::View::addLandTexturesSubView()
|
||||||
|
{
|
||||||
|
addSubView (CSMWorld::UniversalId::Type_LandTextures);
|
||||||
|
}
|
||||||
|
|
||||||
void CSVDoc::View::addPathgridSubView()
|
void CSVDoc::View::addPathgridSubView()
|
||||||
{
|
{
|
||||||
addSubView (CSMWorld::UniversalId::Type_Pathgrids);
|
addSubView (CSMWorld::UniversalId::Type_Pathgrids);
|
||||||
|
|
|
@ -224,6 +224,10 @@ namespace CSVDoc
|
||||||
|
|
||||||
void addRunLogSubView();
|
void addRunLogSubView();
|
||||||
|
|
||||||
|
void addLandsSubView();
|
||||||
|
|
||||||
|
void addLandTexturesSubView();
|
||||||
|
|
||||||
void addPathgridSubView();
|
void addPathgridSubView();
|
||||||
|
|
||||||
void addStartScriptsSubView();
|
void addStartScriptsSubView();
|
||||||
|
|
|
@ -26,6 +26,33 @@
|
||||||
#include "terrainstorage.hpp"
|
#include "terrainstorage.hpp"
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
|
|
||||||
|
namespace CSVRender
|
||||||
|
{
|
||||||
|
class CellNodeContainer : public osg::Referenced
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
CellNodeContainer(Cell* cell) : mCell(cell) {}
|
||||||
|
|
||||||
|
Cell* getCell(){ return mCell; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Cell* mCell;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CellNodeCallback : public osg::NodeCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||||
|
{
|
||||||
|
CellNodeContainer* container = static_cast<CellNodeContainer*>(node->getUserData());
|
||||||
|
container->getCell()->updateLand();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
bool CSVRender::Cell::removeObject (const std::string& id)
|
bool CSVRender::Cell::removeObject (const std::string& id)
|
||||||
{
|
{
|
||||||
std::map<std::string, Object *>::iterator iter =
|
std::map<std::string, Object *>::iterator iter =
|
||||||
|
@ -75,10 +102,69 @@ bool CSVRender::Cell::addObjects (int start, int end)
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::updateLand()
|
||||||
|
{
|
||||||
|
if (!mUpdateLand || mLandDeleted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mUpdateLand = false;
|
||||||
|
|
||||||
|
// Cell is deleted
|
||||||
|
if (mDeleted)
|
||||||
|
{
|
||||||
|
unloadLand();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup land if available
|
||||||
|
const CSMWorld::IdCollection<CSMWorld::Land>& land = mData.getLand();
|
||||||
|
int landIndex = land.searchId(mId);
|
||||||
|
if (landIndex != -1 && !land.getRecord(mId).isDeleted())
|
||||||
|
{
|
||||||
|
const ESM::Land& esmLand = land.getRecord(mId).get();
|
||||||
|
|
||||||
|
if (esmLand.getLandData (ESM::Land::DATA_VHGT))
|
||||||
|
{
|
||||||
|
if (mTerrain)
|
||||||
|
{
|
||||||
|
mTerrain->unloadCell(mCoordinates.getX(), mCoordinates.getY());
|
||||||
|
mTerrain->clearAssociatedCaches();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mTerrain.reset(new Terrain::TerrainGrid(mCellNode, mCellNode,
|
||||||
|
mData.getResourceSystem().get(), new TerrainStorage(mData), Mask_Terrain));
|
||||||
|
}
|
||||||
|
|
||||||
|
mTerrain->loadCell(esmLand.mX, esmLand.mY);
|
||||||
|
|
||||||
|
if (!mCellBorder)
|
||||||
|
mCellBorder.reset(new CellBorder(mCellNode, mCoordinates));
|
||||||
|
|
||||||
|
mCellBorder->buildShape(esmLand);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No land data
|
||||||
|
mLandDeleted = true;
|
||||||
|
unloadLand();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::unloadLand()
|
||||||
|
{
|
||||||
|
if (mTerrain)
|
||||||
|
mTerrain->unloadCell(mCoordinates.getX(), mCoordinates.getY());
|
||||||
|
|
||||||
|
if (mCellBorder)
|
||||||
|
mCellBorder.reset();
|
||||||
|
}
|
||||||
|
|
||||||
CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id,
|
CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id,
|
||||||
bool deleted)
|
bool deleted)
|
||||||
: mData (data), mId (Misc::StringUtils::lowerCase (id)), mDeleted (deleted), mSubMode (0),
|
: mData (data), mId (Misc::StringUtils::lowerCase (id)), mDeleted (deleted), mSubMode (0),
|
||||||
mSubModeElementMask (0)
|
mSubModeElementMask (0), mUpdateLand(true), mLandDeleted(false)
|
||||||
{
|
{
|
||||||
std::pair<CSMWorld::CellCoordinates, bool> result = CSMWorld::CellCoordinates::fromId (id);
|
std::pair<CSMWorld::CellCoordinates, bool> result = CSMWorld::CellCoordinates::fromId (id);
|
||||||
|
|
||||||
|
@ -86,6 +172,8 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::st
|
||||||
mCoordinates = result.first;
|
mCoordinates = result.first;
|
||||||
|
|
||||||
mCellNode = new osg::Group;
|
mCellNode = new osg::Group;
|
||||||
|
mCellNode->setUserData(new CellNodeContainer(this));
|
||||||
|
mCellNode->setUpdateCallback(new CellNodeCallback);
|
||||||
rootNode->addChild(mCellNode);
|
rootNode->addChild(mCellNode);
|
||||||
|
|
||||||
setCellMarker();
|
setCellMarker();
|
||||||
|
@ -99,22 +187,7 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::st
|
||||||
|
|
||||||
addObjects (0, rows-1);
|
addObjects (0, rows-1);
|
||||||
|
|
||||||
const CSMWorld::IdCollection<CSMWorld::Land>& land = mData.getLand();
|
updateLand();
|
||||||
int landIndex = land.searchId(mId);
|
|
||||||
if (landIndex != -1)
|
|
||||||
{
|
|
||||||
const ESM::Land& esmLand = land.getRecord(mId).get();
|
|
||||||
|
|
||||||
if (esmLand.getLandData (ESM::Land::DATA_VHGT))
|
|
||||||
{
|
|
||||||
mTerrain.reset(new Terrain::TerrainGrid(mCellNode, mCellNode, data.getResourceSystem().get(), new TerrainStorage(mData), Mask_Terrain));
|
|
||||||
mTerrain->loadCell(esmLand.mX,
|
|
||||||
esmLand.mY);
|
|
||||||
|
|
||||||
mCellBorder.reset(new CellBorder(mCellNode, mCoordinates));
|
|
||||||
mCellBorder->buildShape(esmLand);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mPathgrid.reset(new Pathgrid(mData, mCellNode, mId, mCoordinates));
|
mPathgrid.reset(new Pathgrid(mData, mCellNode, mId, mCoordinates));
|
||||||
mCellWater.reset(new CellWater(mData, mCellNode, mId, mCoordinates));
|
mCellWater.reset(new CellWater(mData, mCellNode, mId, mCoordinates));
|
||||||
|
@ -285,6 +358,38 @@ void CSVRender::Cell::pathgridRemoved()
|
||||||
mPathgrid->removeGeometry();
|
mPathgrid->removeGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::landDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
mUpdateLand = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::landAboutToBeRemoved (const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
mLandDeleted = true;
|
||||||
|
unloadLand();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::landAdded (const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
mUpdateLand = true;
|
||||||
|
mLandDeleted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::landTextureChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
mUpdateLand = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::landTextureAboutToBeRemoved (const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
mUpdateLand = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::landTextureAdded (const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
mUpdateLand = true;
|
||||||
|
}
|
||||||
|
|
||||||
void CSVRender::Cell::reloadAssets()
|
void CSVRender::Cell::reloadAssets()
|
||||||
{
|
{
|
||||||
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
||||||
|
|
|
@ -57,6 +57,7 @@ namespace CSVRender
|
||||||
bool mDeleted;
|
bool mDeleted;
|
||||||
int mSubMode;
|
int mSubMode;
|
||||||
unsigned int mSubModeElementMask;
|
unsigned int mSubModeElementMask;
|
||||||
|
bool mUpdateLand, mLandDeleted;
|
||||||
|
|
||||||
/// Ignored if cell does not have an object with the given ID.
|
/// Ignored if cell does not have an object with the given ID.
|
||||||
///
|
///
|
||||||
|
@ -72,6 +73,9 @@ namespace CSVRender
|
||||||
/// \return Have any objects been added?
|
/// \return Have any objects been added?
|
||||||
bool addObjects (int start, int end);
|
bool addObjects (int start, int end);
|
||||||
|
|
||||||
|
void updateLand();
|
||||||
|
void unloadLand();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum Selection
|
enum Selection
|
||||||
|
@ -118,6 +122,18 @@ namespace CSVRender
|
||||||
|
|
||||||
void pathgridRemoved();
|
void pathgridRemoved();
|
||||||
|
|
||||||
|
void landDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
|
||||||
|
void landAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
void landAdded (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
void landTextureChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
|
||||||
|
void landTextureAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
void landTextureAdded (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
void reloadAssets();
|
void reloadAssets();
|
||||||
|
|
||||||
void setSelection (int elementMask, Selection mode);
|
void setSelection (int elementMask, Selection mode);
|
||||||
|
@ -145,6 +161,8 @@ namespace CSVRender
|
||||||
/// Erase all overrides and restore the visual representation of the cell to its
|
/// Erase all overrides and restore the visual representation of the cell to its
|
||||||
/// true state.
|
/// true state.
|
||||||
void reset (unsigned int elementMask);
|
void reset (unsigned int elementMask);
|
||||||
|
|
||||||
|
friend class CellNodeCallback;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -351,6 +351,72 @@ void CSVRender::PagedWorldspaceWidget::pathgridAdded(const QModelIndex& parent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::landDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
for (int r = topLeft.row(); r <= bottomRight.row(); ++r)
|
||||||
|
{
|
||||||
|
std::string id = mDocument.getData().getLand().getId(r);
|
||||||
|
|
||||||
|
auto cellIt = mCells.find(CSMWorld::CellCoordinates::fromId(id).first);
|
||||||
|
if (cellIt != mCells.end())
|
||||||
|
{
|
||||||
|
cellIt->second->landDataChanged(topLeft, bottomRight);
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::landAboutToBeRemoved (const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
for (int r = start; r <= end; ++r)
|
||||||
|
{
|
||||||
|
std::string id = mDocument.getData().getLand().getId(r);
|
||||||
|
|
||||||
|
auto cellIt = mCells.find(CSMWorld::CellCoordinates::fromId(id).first);
|
||||||
|
if (cellIt != mCells.end())
|
||||||
|
{
|
||||||
|
cellIt->second->landAboutToBeRemoved(parent, start, end);
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::landAdded (const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
for (int r = start; r <= end; ++r)
|
||||||
|
{
|
||||||
|
std::string id = mDocument.getData().getLand().getId(r);
|
||||||
|
|
||||||
|
auto cellIt = mCells.find(CSMWorld::CellCoordinates::fromId(id).first);
|
||||||
|
if (cellIt != mCells.end())
|
||||||
|
{
|
||||||
|
cellIt->second->landAdded(parent, start, end);
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::landTextureDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
for (auto cellIt : mCells)
|
||||||
|
cellIt.second->landTextureChanged(topLeft, bottomRight);
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::landTextureAboutToBeRemoved (const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
for (auto cellIt : mCells)
|
||||||
|
cellIt.second->landTextureAboutToBeRemoved(parent, start, end);
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::landTextureAdded (const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
for (auto cellIt : mCells)
|
||||||
|
cellIt.second->landTextureAdded(parent, start, end);
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string CSVRender::PagedWorldspaceWidget::getStartupInstruction()
|
std::string CSVRender::PagedWorldspaceWidget::getStartupInstruction()
|
||||||
{
|
{
|
||||||
|
@ -475,6 +541,24 @@ CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc
|
||||||
connect (&document.getData(), SIGNAL (assetTablesChanged ()),
|
connect (&document.getData(), SIGNAL (assetTablesChanged ()),
|
||||||
this, SLOT (assetTablesChanged ()));
|
this, SLOT (assetTablesChanged ()));
|
||||||
|
|
||||||
|
QAbstractItemModel *lands = document.getData().getTableModel (CSMWorld::UniversalId::Type_Lands);
|
||||||
|
|
||||||
|
connect (lands, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
||||||
|
this, SLOT (landDataChanged (const QModelIndex&, const QModelIndex&)));
|
||||||
|
connect (lands, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
||||||
|
this, SLOT (landAboutToBeRemoved (const QModelIndex&, int, int)));
|
||||||
|
connect (lands, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
|
||||||
|
this, SLOT (landAdded (const QModelIndex&, int, int)));
|
||||||
|
|
||||||
|
QAbstractItemModel *ltexs = document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures);
|
||||||
|
|
||||||
|
connect (ltexs, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
||||||
|
this, SLOT (landTextureDataChanged (const QModelIndex&, const QModelIndex&)));
|
||||||
|
connect (ltexs, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
||||||
|
this, SLOT (landTextureAboutToBeRemoved (const QModelIndex&, int, int)));
|
||||||
|
connect (ltexs, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
|
||||||
|
this, SLOT (landTextureAdded (const QModelIndex&, int, int)));
|
||||||
|
|
||||||
// Shortcuts
|
// Shortcuts
|
||||||
CSMPrefs::Shortcut* loadCameraCellShortcut = new CSMPrefs::Shortcut("scene-load-cam-cell", this);
|
CSMPrefs::Shortcut* loadCameraCellShortcut = new CSMPrefs::Shortcut("scene-load-cam-cell", this);
|
||||||
connect(loadCameraCellShortcut, SIGNAL(activated()), this, SLOT(loadCameraCell()));
|
connect(loadCameraCellShortcut, SIGNAL(activated()), this, SLOT(loadCameraCell()));
|
||||||
|
|
|
@ -155,6 +155,14 @@ namespace CSVRender
|
||||||
|
|
||||||
virtual void cellAdded (const QModelIndex& index, int start, int end);
|
virtual void cellAdded (const QModelIndex& index, int start, int end);
|
||||||
|
|
||||||
|
virtual void landDataChanged (const QModelIndex& topLeft, const QModelIndex& botomRight);
|
||||||
|
virtual void landAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
virtual void landAdded (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
virtual void landTextureDataChanged (const QModelIndex& topLeft, const QModelIndex& botomRight);
|
||||||
|
virtual void landTextureAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
virtual void landTextureAdded (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
void assetTablesChanged ();
|
void assetTablesChanged ();
|
||||||
|
|
||||||
void loadCameraCell();
|
void loadCameraCell();
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#include "terrainstorage.hpp"
|
#include "terrainstorage.hpp"
|
||||||
|
|
||||||
|
#include "../../model/world/land.hpp"
|
||||||
|
#include "../../model/world/landtexture.hpp"
|
||||||
|
|
||||||
namespace CSVRender
|
namespace CSVRender
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -11,12 +14,9 @@ namespace CSVRender
|
||||||
|
|
||||||
osg::ref_ptr<const ESMTerrain::LandObject> TerrainStorage::getLand(int cellX, int cellY)
|
osg::ref_ptr<const ESMTerrain::LandObject> TerrainStorage::getLand(int cellX, int cellY)
|
||||||
{
|
{
|
||||||
std::ostringstream stream;
|
|
||||||
stream << "#" << cellX << " " << cellY;
|
|
||||||
|
|
||||||
// The cell isn't guaranteed to have Land. This is because the terrain implementation
|
// The cell isn't guaranteed to have Land. This is because the terrain implementation
|
||||||
// has to wrap the vertices of the last row and column to the next cell, which may be a nonexisting cell
|
// has to wrap the vertices of the last row and column to the next cell, which may be a nonexisting cell
|
||||||
int index = mData.getLand().searchId(stream.str());
|
int index = mData.getLand().searchId(CSMWorld::Land::createUniqueRecordId(cellX, cellY));
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -26,16 +26,11 @@ namespace CSVRender
|
||||||
|
|
||||||
const ESM::LandTexture* TerrainStorage::getLandTexture(int index, short plugin)
|
const ESM::LandTexture* TerrainStorage::getLandTexture(int index, short plugin)
|
||||||
{
|
{
|
||||||
int numRecords = mData.getLandTextures().getSize();
|
int row = mData.getLandTextures().searchId(CSMWorld::LandTexture::createUniqueRecordId(plugin, index));
|
||||||
|
if (row == -1)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
for (int i=0; i<numRecords; ++i)
|
return &mData.getLandTextures().getRecord(row).get();
|
||||||
{
|
|
||||||
const CSMWorld::LandTexture* ltex = &mData.getLandTextures().getRecord(i).get();
|
|
||||||
if (ltex->mIndex == index && ltex->mPluginIndex == plugin)
|
|
||||||
return ltex;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainStorage::getBounds(float &minX, float &maxX, float &minY, float &maxY)
|
void TerrainStorage::getBounds(float &minX, float &maxX, float &minY, float &maxY)
|
||||||
|
|
|
@ -31,6 +31,9 @@ namespace CSVWorld
|
||||||
virtual void cloneMode(const std::string& originId,
|
virtual void cloneMode(const std::string& originId,
|
||||||
const CSMWorld::UniversalId::Type type) = 0;
|
const CSMWorld::UniversalId::Type type) = 0;
|
||||||
|
|
||||||
|
/// Touches a record, if the creator supports it.
|
||||||
|
virtual void touch(const std::vector<CSMWorld::UniversalId>& ids) = 0;
|
||||||
|
|
||||||
virtual void setEditLock (bool locked) = 0;
|
virtual void setEditLock (bool locked) = 0;
|
||||||
|
|
||||||
virtual void toggleWidgets(bool active = true) = 0;
|
virtual void toggleWidgets(bool active = true) = 0;
|
||||||
|
|
|
@ -51,6 +51,11 @@ std::string CSVWorld::GenericCreator::getId() const
|
||||||
return mId->text().toUtf8().constData();
|
return mId->text().toUtf8().constData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CSVWorld::GenericCreator::getClonedId() const
|
||||||
|
{
|
||||||
|
return mClonedId;
|
||||||
|
}
|
||||||
|
|
||||||
std::string CSVWorld::GenericCreator::getIdValidatorResult() const
|
std::string CSVWorld::GenericCreator::getIdValidatorResult() const
|
||||||
{
|
{
|
||||||
std::string errors;
|
std::string errors;
|
||||||
|
@ -254,6 +259,22 @@ void CSVWorld::GenericCreator::cloneMode(const std::string& originId,
|
||||||
mClonedType = type;
|
mClonedType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVWorld::GenericCreator::touch(const std::vector<CSMWorld::UniversalId>& ids)
|
||||||
|
{
|
||||||
|
// Combine multiple touch commands into one "macro" command
|
||||||
|
mUndoStack.beginMacro("Touch Records");
|
||||||
|
|
||||||
|
CSMWorld::IdTable& table = dynamic_cast<CSMWorld::IdTable&>(*mData.getTableModel(mListId));
|
||||||
|
for (const CSMWorld::UniversalId& uid : ids)
|
||||||
|
{
|
||||||
|
CSMWorld::TouchCommand* touchCmd = new CSMWorld::TouchCommand(table, uid.getId());
|
||||||
|
mUndoStack.push(touchCmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
mUndoStack.endMacro();
|
||||||
|
}
|
||||||
|
|
||||||
void CSVWorld::GenericCreator::toggleWidgets(bool active)
|
void CSVWorld::GenericCreator::toggleWidgets(bool active)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,8 @@ namespace CSVWorld
|
||||||
|
|
||||||
virtual std::string getId() const;
|
virtual std::string getId() const;
|
||||||
|
|
||||||
|
std::string getClonedId() const;
|
||||||
|
|
||||||
virtual std::string getIdValidatorResult() const;
|
virtual std::string getIdValidatorResult() const;
|
||||||
|
|
||||||
/// Allow subclasses to add additional data to \a command.
|
/// Allow subclasses to add additional data to \a command.
|
||||||
|
@ -103,6 +105,8 @@ namespace CSVWorld
|
||||||
virtual void cloneMode(const std::string& originId,
|
virtual void cloneMode(const std::string& originId,
|
||||||
const CSMWorld::UniversalId::Type type);
|
const CSMWorld::UniversalId::Type type);
|
||||||
|
|
||||||
|
virtual void touch(const std::vector<CSMWorld::UniversalId>& ids);
|
||||||
|
|
||||||
virtual std::string getErrors() const;
|
virtual std::string getErrors() const;
|
||||||
///< Return formatted error descriptions for the current state of the creator. if an empty
|
///< Return formatted error descriptions for the current state of the creator. if an empty
|
||||||
/// string is returned, there is no error.
|
/// string is returned, there is no error.
|
||||||
|
|
120
apps/opencs/view/world/landcreator.cpp
Normal file
120
apps/opencs/view/world/landcreator.cpp
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
#include "landcreator.hpp"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QSpinBox>
|
||||||
|
|
||||||
|
#include "../../model/world/commands.hpp"
|
||||||
|
#include "../../model/world/idtable.hpp"
|
||||||
|
#include "../../model/world/land.hpp"
|
||||||
|
|
||||||
|
namespace CSVWorld
|
||||||
|
{
|
||||||
|
LandCreator::LandCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id)
|
||||||
|
: GenericCreator(data, undoStack, id)
|
||||||
|
, mXLabel(nullptr)
|
||||||
|
, mYLabel(nullptr)
|
||||||
|
, mX(nullptr)
|
||||||
|
, mY(nullptr)
|
||||||
|
{
|
||||||
|
const int MaxInt = std::numeric_limits<int>::max();
|
||||||
|
const int MinInt = std::numeric_limits<int>::min();
|
||||||
|
|
||||||
|
setManualEditing(false);
|
||||||
|
|
||||||
|
mXLabel = new QLabel("X: ");
|
||||||
|
mX = new QSpinBox();
|
||||||
|
mX->setMinimum(MinInt);
|
||||||
|
mX->setMaximum(MaxInt);
|
||||||
|
insertBeforeButtons(mXLabel, false);
|
||||||
|
insertBeforeButtons(mX, true);
|
||||||
|
|
||||||
|
mYLabel = new QLabel("Y: ");
|
||||||
|
mY = new QSpinBox();
|
||||||
|
mY->setMinimum(MinInt);
|
||||||
|
mY->setMaximum(MaxInt);
|
||||||
|
insertBeforeButtons(mYLabel, false);
|
||||||
|
insertBeforeButtons(mY, true);
|
||||||
|
|
||||||
|
connect (mX, SIGNAL(valueChanged(int)), this, SLOT(coordChanged(int)));
|
||||||
|
connect (mY, SIGNAL(valueChanged(int)), this, SLOT(coordChanged(int)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandCreator::cloneMode(const std::string& originId, const CSMWorld::UniversalId::Type type)
|
||||||
|
{
|
||||||
|
GenericCreator::cloneMode(originId, type);
|
||||||
|
|
||||||
|
int x = 0, y = 0;
|
||||||
|
CSMWorld::Land::parseUniqueRecordId(originId, x, y);
|
||||||
|
|
||||||
|
mX->setValue(x);
|
||||||
|
mY->setValue(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandCreator::touch(const std::vector<CSMWorld::UniversalId>& ids)
|
||||||
|
{
|
||||||
|
// Combine multiple touch commands into one "macro" command
|
||||||
|
getUndoStack().beginMacro("Touch records");
|
||||||
|
|
||||||
|
CSMWorld::IdTable& lands = dynamic_cast<CSMWorld::IdTable&>(*getData().getTableModel(CSMWorld::UniversalId::Type_Lands));
|
||||||
|
CSMWorld::IdTable& ltexs = dynamic_cast<CSMWorld::IdTable&>(*getData().getTableModel(CSMWorld::UniversalId::Type_LandTextures));
|
||||||
|
for (const CSMWorld::UniversalId& uid : ids)
|
||||||
|
{
|
||||||
|
CSMWorld::TouchLandCommand* touchCmd = new CSMWorld::TouchLandCommand(lands, ltexs, uid.getId());
|
||||||
|
getUndoStack().push(touchCmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
getUndoStack().endMacro();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandCreator::focus()
|
||||||
|
{
|
||||||
|
mX->setFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandCreator::reset()
|
||||||
|
{
|
||||||
|
GenericCreator::reset();
|
||||||
|
mX->setValue(0);
|
||||||
|
mY->setValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LandCreator::getErrors() const
|
||||||
|
{
|
||||||
|
if (getData().getLand().searchId(getId()) >= 0)
|
||||||
|
return "A land with that name already exists.";
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LandCreator::getId() const
|
||||||
|
{
|
||||||
|
return CSMWorld::Land::createUniqueRecordId(mX->value(), mY->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandCreator::pushCommand(std::unique_ptr<CSMWorld::CreateCommand> command, const std::string& id)
|
||||||
|
{
|
||||||
|
if (mCloneMode)
|
||||||
|
{
|
||||||
|
CSMWorld::IdTable& lands = dynamic_cast<CSMWorld::IdTable&>(*getData().getTableModel(CSMWorld::UniversalId::Type_Lands));
|
||||||
|
CSMWorld::IdTable& ltexs = dynamic_cast<CSMWorld::IdTable&>(*getData().getTableModel(CSMWorld::UniversalId::Type_LandTextures));
|
||||||
|
|
||||||
|
getUndoStack().beginMacro(("Clone " + id).c_str());
|
||||||
|
getUndoStack().push(command.release());
|
||||||
|
|
||||||
|
CSMWorld::CopyLandTexturesCommand* ltexCopy = new CSMWorld::CopyLandTexturesCommand(lands, ltexs, getClonedId(), getId());
|
||||||
|
getUndoStack().push(ltexCopy);
|
||||||
|
|
||||||
|
getUndoStack().endMacro();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
getUndoStack().push (command.release());
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandCreator::coordChanged(int value)
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
47
apps/opencs/view/world/landcreator.hpp
Normal file
47
apps/opencs/view/world/landcreator.hpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef CSV_WORLD_LANDCREATOR_H
|
||||||
|
#define CSV_WORLD_LANDCREATOR_H
|
||||||
|
|
||||||
|
#include "genericcreator.hpp"
|
||||||
|
|
||||||
|
class QLabel;
|
||||||
|
class QSpinBox;
|
||||||
|
|
||||||
|
namespace CSVWorld
|
||||||
|
{
|
||||||
|
class LandCreator : public GenericCreator
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
QLabel* mXLabel;
|
||||||
|
QLabel* mYLabel;
|
||||||
|
QSpinBox* mX;
|
||||||
|
QSpinBox* mY;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
LandCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id);
|
||||||
|
|
||||||
|
void cloneMode(const std::string& originId, const CSMWorld::UniversalId::Type type) override;
|
||||||
|
|
||||||
|
void touch(const std::vector<CSMWorld::UniversalId>& ids) override;
|
||||||
|
|
||||||
|
void focus() override;
|
||||||
|
|
||||||
|
void reset() override;
|
||||||
|
|
||||||
|
std::string getErrors() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
std::string getId() const override;
|
||||||
|
|
||||||
|
void pushCommand(std::unique_ptr<CSMWorld::CreateCommand> command,
|
||||||
|
const std::string& id) override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void coordChanged(int value);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
101
apps/opencs/view/world/landtexturecreator.cpp
Normal file
101
apps/opencs/view/world/landtexturecreator.cpp
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
#include "landtexturecreator.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QSpinBox>
|
||||||
|
|
||||||
|
#include "../../model/world/commands.hpp"
|
||||||
|
#include "../../model/world/idtable.hpp"
|
||||||
|
#include "../../model/world/landtexture.hpp"
|
||||||
|
|
||||||
|
namespace CSVWorld
|
||||||
|
{
|
||||||
|
LandTextureCreator::LandTextureCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id)
|
||||||
|
: GenericCreator(data, undoStack, id)
|
||||||
|
{
|
||||||
|
// One index is reserved for a default texture
|
||||||
|
const size_t MaxIndex = std::numeric_limits<uint16_t>::max() - 1;
|
||||||
|
|
||||||
|
setManualEditing(false);
|
||||||
|
|
||||||
|
QLabel* nameLabel = new QLabel("Name");
|
||||||
|
insertBeforeButtons(nameLabel, false);
|
||||||
|
|
||||||
|
mNameEdit = new QLineEdit(this);
|
||||||
|
insertBeforeButtons(mNameEdit, true);
|
||||||
|
|
||||||
|
QLabel* indexLabel = new QLabel("Index");
|
||||||
|
insertBeforeButtons(indexLabel, false);
|
||||||
|
|
||||||
|
mIndexBox = new QSpinBox(this);
|
||||||
|
mIndexBox->setMinimum(0);
|
||||||
|
mIndexBox->setMaximum(MaxIndex);
|
||||||
|
insertBeforeButtons(mIndexBox, true);
|
||||||
|
|
||||||
|
connect(mNameEdit, SIGNAL(textChanged(const QString&)), this, SLOT(nameChanged(const QString&)));
|
||||||
|
connect(mIndexBox, SIGNAL(valueChanged(int)), this, SLOT(indexChanged(int)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandTextureCreator::cloneMode(const std::string& originId, const CSMWorld::UniversalId::Type type)
|
||||||
|
{
|
||||||
|
GenericCreator::cloneMode(originId, type);
|
||||||
|
|
||||||
|
CSMWorld::IdTable& table = dynamic_cast<CSMWorld::IdTable&>(*getData().getTableModel(getCollectionId()));
|
||||||
|
|
||||||
|
int column = table.findColumnIndex(CSMWorld::Columns::ColumnId_TextureNickname);
|
||||||
|
mNameEdit->setText((table.data(table.getModelIndex(originId, column)).toString()));
|
||||||
|
|
||||||
|
column = table.findColumnIndex(CSMWorld::Columns::ColumnId_TextureIndex);
|
||||||
|
mIndexBox->setValue((table.data(table.getModelIndex(originId, column)).toInt()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandTextureCreator::focus()
|
||||||
|
{
|
||||||
|
mIndexBox->setFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandTextureCreator::reset()
|
||||||
|
{
|
||||||
|
GenericCreator::reset();
|
||||||
|
mNameEdit->setText("");
|
||||||
|
mIndexBox->setValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LandTextureCreator::getErrors() const
|
||||||
|
{
|
||||||
|
if (getData().getLandTextures().searchId(getId()) >= 0)
|
||||||
|
{
|
||||||
|
return "Index is already in use";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandTextureCreator::configureCreateCommand(CSMWorld::CreateCommand& command) const
|
||||||
|
{
|
||||||
|
GenericCreator::configureCreateCommand(command);
|
||||||
|
|
||||||
|
CSMWorld::IdTable& table = dynamic_cast<CSMWorld::IdTable&>(*getData().getTableModel(getCollectionId()));
|
||||||
|
int column = table.findColumnIndex(CSMWorld::Columns::ColumnId_TextureNickname);
|
||||||
|
command.addValue(column, mName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LandTextureCreator::getId() const
|
||||||
|
{
|
||||||
|
return CSMWorld::LandTexture::createUniqueRecordId(0, mIndexBox->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandTextureCreator::nameChanged(const QString& value)
|
||||||
|
{
|
||||||
|
mName = value.toUtf8().constData();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandTextureCreator::indexChanged(int value)
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
49
apps/opencs/view/world/landtexturecreator.hpp
Normal file
49
apps/opencs/view/world/landtexturecreator.hpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#ifndef CSV_WORLD_LANDTEXTURECREATOR_H
|
||||||
|
#define CSV_WORLD_LANDTEXTURECREATOR_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "genericcreator.hpp"
|
||||||
|
|
||||||
|
class QLineEdit;
|
||||||
|
class QSpinBox;
|
||||||
|
|
||||||
|
namespace CSVWorld
|
||||||
|
{
|
||||||
|
class LandTextureCreator : public GenericCreator
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
LandTextureCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id);
|
||||||
|
|
||||||
|
void cloneMode(const std::string& originId, const CSMWorld::UniversalId::Type type) override;
|
||||||
|
|
||||||
|
void focus() override;
|
||||||
|
|
||||||
|
void reset() override;
|
||||||
|
|
||||||
|
std::string getErrors() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void configureCreateCommand(CSMWorld::CreateCommand& command) const override;
|
||||||
|
|
||||||
|
std::string getId() const override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void nameChanged(const QString& val);
|
||||||
|
void indexChanged(int val);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QLineEdit* mNameEdit;
|
||||||
|
QSpinBox* mIndexBox;
|
||||||
|
|
||||||
|
std::string mName;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -18,6 +18,8 @@
|
||||||
#include "pathgridcreator.hpp"
|
#include "pathgridcreator.hpp"
|
||||||
#include "previewsubview.hpp"
|
#include "previewsubview.hpp"
|
||||||
#include "bodypartcreator.hpp"
|
#include "bodypartcreator.hpp"
|
||||||
|
#include "landcreator.hpp"
|
||||||
|
#include "landtexturecreator.hpp"
|
||||||
|
|
||||||
void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
||||||
{
|
{
|
||||||
|
@ -81,6 +83,12 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
||||||
manager.add (CSMWorld::UniversalId::Type_Pathgrids,
|
manager.add (CSMWorld::UniversalId::Type_Pathgrids,
|
||||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, PathgridCreatorFactory>);
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, PathgridCreatorFactory>);
|
||||||
|
|
||||||
|
manager.add (CSMWorld::UniversalId::Type_Lands,
|
||||||
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<LandCreator> >);
|
||||||
|
|
||||||
|
manager.add (CSMWorld::UniversalId::Type_LandTextures,
|
||||||
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<LandTextureCreator> >);
|
||||||
|
|
||||||
manager.add (CSMWorld::UniversalId::Type_Globals,
|
manager.add (CSMWorld::UniversalId::Type_Globals,
|
||||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<GlobalCreator> >);
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<GlobalCreator> >);
|
||||||
|
|
||||||
|
@ -181,6 +189,12 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
||||||
manager.add (CSMWorld::UniversalId::Type_Pathgrid,
|
manager.add (CSMWorld::UniversalId::Type_Pathgrid,
|
||||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, PathgridCreatorFactory> (false));
|
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, PathgridCreatorFactory> (false));
|
||||||
|
|
||||||
|
manager.add (CSMWorld::UniversalId::Type_Land,
|
||||||
|
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<LandCreator> >(false));
|
||||||
|
|
||||||
|
manager.add (CSMWorld::UniversalId::Type_LandTexture,
|
||||||
|
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<LandTextureCreator> >(false));
|
||||||
|
|
||||||
manager.add (CSMWorld::UniversalId::Type_DebugProfile,
|
manager.add (CSMWorld::UniversalId::Type_DebugProfile,
|
||||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator, CSMWorld::Scope_Project | CSMWorld::Scope_Session> > (false));
|
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator, CSMWorld::Scope_Project | CSMWorld::Scope_Session> > (false));
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "../../model/world/idtableproxymodel.hpp"
|
#include "../../model/world/idtableproxymodel.hpp"
|
||||||
#include "../../model/world/idtablebase.hpp"
|
#include "../../model/world/idtablebase.hpp"
|
||||||
#include "../../model/world/idtable.hpp"
|
#include "../../model/world/idtable.hpp"
|
||||||
|
#include "../../model/world/landtexturetableproxymodel.hpp"
|
||||||
#include "../../model/world/record.hpp"
|
#include "../../model/world/record.hpp"
|
||||||
#include "../../model/world/columns.hpp"
|
#include "../../model/world/columns.hpp"
|
||||||
#include "../../model/world/commanddispatcher.hpp"
|
#include "../../model/world/commanddispatcher.hpp"
|
||||||
|
@ -60,6 +61,9 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
||||||
menu.addAction(mCloneAction);
|
menu.addAction(mCloneAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mTouchAction)
|
||||||
|
menu.addAction (mTouchAction);
|
||||||
|
|
||||||
if (mCreateAction)
|
if (mCreateAction)
|
||||||
menu.addAction (mCreateAction);
|
menu.addAction (mCreateAction);
|
||||||
|
|
||||||
|
@ -226,17 +230,22 @@ void CSVWorld::Table::mouseDoubleClickEvent (QMouseEvent *event)
|
||||||
|
|
||||||
CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
||||||
bool createAndDelete, bool sorting, CSMDoc::Document& document)
|
bool createAndDelete, bool sorting, CSMDoc::Document& document)
|
||||||
: DragRecordTable(document), mCreateAction (0),
|
: DragRecordTable(document), mCreateAction (nullptr), mCloneAction(nullptr), mTouchAction(nullptr),
|
||||||
mCloneAction(0), mRecordStatusDisplay (0), mJumpToAddedRecord(false), mUnselectAfterJump(false)
|
mRecordStatusDisplay (0), mJumpToAddedRecord(false), mUnselectAfterJump(false)
|
||||||
{
|
{
|
||||||
mModel = &dynamic_cast<CSMWorld::IdTableBase&> (*mDocument.getData().getTableModel (id));
|
mModel = &dynamic_cast<CSMWorld::IdTableBase&> (*mDocument.getData().getTableModel (id));
|
||||||
|
|
||||||
bool isInfoTable = id.getType() == CSMWorld::UniversalId::Type_TopicInfos ||
|
bool isInfoTable = id.getType() == CSMWorld::UniversalId::Type_TopicInfos ||
|
||||||
id.getType() == CSMWorld::UniversalId::Type_JournalInfos;
|
id.getType() == CSMWorld::UniversalId::Type_JournalInfos;
|
||||||
|
bool isLtexTable = (id.getType() == CSMWorld::UniversalId::Type_LandTextures);
|
||||||
if (isInfoTable)
|
if (isInfoTable)
|
||||||
{
|
{
|
||||||
mProxyModel = new CSMWorld::InfoTableProxyModel(id.getType(), this);
|
mProxyModel = new CSMWorld::InfoTableProxyModel(id.getType(), this);
|
||||||
}
|
}
|
||||||
|
else if (isLtexTable)
|
||||||
|
{
|
||||||
|
mProxyModel = new CSMWorld::LandTextureTableProxyModel (this);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mProxyModel = new CSMWorld::IdTableProxyModel (this);
|
mProxyModel = new CSMWorld::IdTableProxyModel (this);
|
||||||
|
@ -302,6 +311,15 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
||||||
cloneShortcut->associateAction(mCloneAction);
|
cloneShortcut->associateAction(mCloneAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mModel->getFeatures() & CSMWorld::IdTableBase::Feature_AllowTouch)
|
||||||
|
{
|
||||||
|
mTouchAction = new QAction(tr("Touch Record"), this);
|
||||||
|
connect(mTouchAction, SIGNAL(triggered()), this, SLOT(touchRecord()));
|
||||||
|
addAction(mTouchAction);
|
||||||
|
CSMPrefs::Shortcut* touchShortcut = new CSMPrefs::Shortcut("table-touch", this);
|
||||||
|
touchShortcut->associateAction(mTouchAction);
|
||||||
|
}
|
||||||
|
|
||||||
mRevertAction = new QAction (tr ("Revert Record"), this);
|
mRevertAction = new QAction (tr ("Revert Record"), this);
|
||||||
connect (mRevertAction, SIGNAL (triggered()), mDispatcher, SLOT (executeRevert()));
|
connect (mRevertAction, SIGNAL (triggered()), mDispatcher, SLOT (executeRevert()));
|
||||||
addAction (mRevertAction);
|
addAction (mRevertAction);
|
||||||
|
@ -442,6 +460,22 @@ void CSVWorld::Table::cloneRecord()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVWorld::Table::touchRecord()
|
||||||
|
{
|
||||||
|
if (!mEditLock && mModel->getFeatures() & CSMWorld::IdTableBase::Feature_AllowTouch)
|
||||||
|
{
|
||||||
|
std::vector<CSMWorld::UniversalId> touchIds;
|
||||||
|
|
||||||
|
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||||
|
for (auto it = selectedRows.begin(); it != selectedRows.end(); ++it)
|
||||||
|
{
|
||||||
|
touchIds.push_back(getUniversalId(it->row()));
|
||||||
|
}
|
||||||
|
|
||||||
|
emit touchRequest(touchIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CSVWorld::Table::moveUpRecord()
|
void CSVWorld::Table::moveUpRecord()
|
||||||
{
|
{
|
||||||
if (mEditLock || (mModel->getFeatures() & CSMWorld::IdTableBase::Feature_Constant))
|
if (mEditLock || (mModel->getFeatures() & CSMWorld::IdTableBase::Feature_Constant))
|
||||||
|
|
|
@ -56,6 +56,7 @@ namespace CSVWorld
|
||||||
QAction *mEditAction;
|
QAction *mEditAction;
|
||||||
QAction *mCreateAction;
|
QAction *mCreateAction;
|
||||||
QAction *mCloneAction;
|
QAction *mCloneAction;
|
||||||
|
QAction *mTouchAction;
|
||||||
QAction *mRevertAction;
|
QAction *mRevertAction;
|
||||||
QAction *mDeleteAction;
|
QAction *mDeleteAction;
|
||||||
QAction *mMoveUpAction;
|
QAction *mMoveUpAction;
|
||||||
|
@ -115,6 +116,8 @@ namespace CSVWorld
|
||||||
|
|
||||||
void cloneRequest(const CSMWorld::UniversalId&);
|
void cloneRequest(const CSMWorld::UniversalId&);
|
||||||
|
|
||||||
|
void touchRequest(const std::vector<CSMWorld::UniversalId>& ids);
|
||||||
|
|
||||||
void closeRequest();
|
void closeRequest();
|
||||||
|
|
||||||
void extendedDeleteConfigRequest(const std::vector<std::string> &selectedIds);
|
void extendedDeleteConfigRequest(const std::vector<std::string> &selectedIds);
|
||||||
|
@ -129,6 +132,8 @@ namespace CSVWorld
|
||||||
|
|
||||||
void cloneRecord();
|
void cloneRecord();
|
||||||
|
|
||||||
|
void touchRecord();
|
||||||
|
|
||||||
void moveUpRecord();
|
void moveUpRecord();
|
||||||
|
|
||||||
void moveDownRecord();
|
void moveDownRecord();
|
||||||
|
|
|
@ -249,6 +249,11 @@ void CSVWorld::TableBottomBox::cloneRequest(const std::string& id,
|
||||||
mCreator->focus();
|
mCreator->focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVWorld::TableBottomBox::touchRequest(const std::vector<CSMWorld::UniversalId>& ids)
|
||||||
|
{
|
||||||
|
mCreator->touch(ids);
|
||||||
|
}
|
||||||
|
|
||||||
void CSVWorld::TableBottomBox::extendedDeleteConfigRequest(const std::vector<std::string> &selectedIds)
|
void CSVWorld::TableBottomBox::extendedDeleteConfigRequest(const std::vector<std::string> &selectedIds)
|
||||||
{
|
{
|
||||||
extendedConfigRequest(ExtendedCommandConfigurator::Mode_Delete, selectedIds);
|
extendedConfigRequest(ExtendedCommandConfigurator::Mode_Delete, selectedIds);
|
||||||
|
|
|
@ -102,6 +102,7 @@ namespace CSVWorld
|
||||||
void createRequest();
|
void createRequest();
|
||||||
void cloneRequest(const std::string& id,
|
void cloneRequest(const std::string& id,
|
||||||
const CSMWorld::UniversalId::Type type);
|
const CSMWorld::UniversalId::Type type);
|
||||||
|
void touchRequest(const std::vector<CSMWorld::UniversalId>&);
|
||||||
|
|
||||||
void extendedDeleteConfigRequest(const std::vector<std::string> &selectedIds);
|
void extendedDeleteConfigRequest(const std::vector<std::string> &selectedIds);
|
||||||
void extendedRevertConfigRequest(const std::vector<std::string> &selectedIds);
|
void extendedRevertConfigRequest(const std::vector<std::string> &selectedIds);
|
||||||
|
|
|
@ -69,6 +69,9 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D
|
||||||
connect (this, SIGNAL(cloneRequest(const std::string&, const CSMWorld::UniversalId::Type)),
|
connect (this, SIGNAL(cloneRequest(const std::string&, const CSMWorld::UniversalId::Type)),
|
||||||
mBottom, SLOT(cloneRequest(const std::string&, const CSMWorld::UniversalId::Type)));
|
mBottom, SLOT(cloneRequest(const std::string&, const CSMWorld::UniversalId::Type)));
|
||||||
|
|
||||||
|
connect (mTable, SIGNAL(touchRequest(const std::vector<CSMWorld::UniversalId>&)),
|
||||||
|
mBottom, SLOT(touchRequest(const std::vector<CSMWorld::UniversalId>&)));
|
||||||
|
|
||||||
connect (mTable, SIGNAL(extendedDeleteConfigRequest(const std::vector<std::string> &)),
|
connect (mTable, SIGNAL(extendedDeleteConfigRequest(const std::vector<std::string> &)),
|
||||||
mBottom, SLOT(extendedDeleteConfigRequest(const std::vector<std::string> &)));
|
mBottom, SLOT(extendedDeleteConfigRequest(const std::vector<std::string> &)));
|
||||||
connect (mTable, SIGNAL(extendedRevertConfigRequest(const std::vector<std::string> &)),
|
connect (mTable, SIGNAL(extendedRevertConfigRequest(const std::vector<std::string> &)),
|
||||||
|
|
|
@ -42,7 +42,7 @@ add_openmw_dir (mwgui
|
||||||
itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview
|
itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview
|
||||||
tradeitemmodel companionitemmodel pickpocketitemmodel controllers savegamedialog
|
tradeitemmodel companionitemmodel pickpocketitemmodel controllers savegamedialog
|
||||||
recharge mode videowidget backgroundimage itemwidget screenfader debugwindow spellmodel spellview
|
recharge mode videowidget backgroundimage itemwidget screenfader debugwindow spellmodel spellview
|
||||||
draganddrop timeadvancer jailscreen itemchargeview
|
draganddrop timeadvancer jailscreen itemchargeview keyboardnavigation
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwdialogue
|
add_openmw_dir (mwdialogue
|
||||||
|
|
|
@ -231,11 +231,6 @@ void OMW::Engine::frame(float frametime)
|
||||||
|
|
||||||
// update GUI
|
// update GUI
|
||||||
mEnvironment.getWindowManager()->onFrame(frametime);
|
mEnvironment.getWindowManager()->onFrame(frametime);
|
||||||
if (mEnvironment.getStateManager()->getState()!=
|
|
||||||
MWBase::StateManager::State_NoGame)
|
|
||||||
{
|
|
||||||
mEnvironment.getWindowManager()->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int frameNumber = mViewer->getFrameStamp()->getFrameNumber();
|
unsigned int frameNumber = mViewer->getFrameStamp()->getFrameNumber();
|
||||||
osg::Stats* stats = mViewer->getViewerStats();
|
osg::Stats* stats = mViewer->getViewerStats();
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#define GAME_MWBASE_DIALOGUEMANAGER_H
|
#define GAME_MWBASE_DIALOGUEMANAGER_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
@ -42,7 +44,8 @@ namespace MWBase
|
||||||
|
|
||||||
virtual bool isInChoice() const = 0;
|
virtual bool isInChoice() const = 0;
|
||||||
|
|
||||||
virtual void startDialogue (const MWWorld::Ptr& actor) = 0;
|
typedef std::pair<std::string, std::string> Response; // title, text
|
||||||
|
virtual bool startDialogue (const MWWorld::Ptr& actor, Response& response) = 0;
|
||||||
|
|
||||||
virtual void addTopic (const std::string& topic) = 0;
|
virtual void addTopic (const std::string& topic) = 0;
|
||||||
|
|
||||||
|
@ -57,20 +60,24 @@ namespace MWBase
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
virtual void askQuestion (const std::string& question,int choice) = 0;
|
virtual void addChoice (const std::string& text,int choice) = 0;
|
||||||
|
virtual const std::vector<std::pair<std::string, int> >& getChoices() = 0;
|
||||||
|
|
||||||
|
virtual bool isGoodbye() = 0;
|
||||||
|
|
||||||
virtual void goodbye() = 0;
|
virtual void goodbye() = 0;
|
||||||
|
|
||||||
virtual void say(const MWWorld::Ptr &actor, const std::string &topic) = 0;
|
virtual void say(const MWWorld::Ptr &actor, const std::string &topic) = 0;
|
||||||
|
|
||||||
//calbacks for the GUI
|
virtual Response keywordSelected (const std::string& keyword) = 0;
|
||||||
virtual void keywordSelected (const std::string& keyword) = 0;
|
|
||||||
virtual void goodbyeSelected() = 0;
|
virtual void goodbyeSelected() = 0;
|
||||||
virtual void questionAnswered (int answer) = 0;
|
virtual Response questionAnswered (int answer) = 0;
|
||||||
|
|
||||||
virtual bool checkServiceRefused () = 0;
|
virtual std::list<std::string> getAvailableTopics() = 0;
|
||||||
|
|
||||||
virtual void persuade (int type) = 0;
|
virtual bool checkServiceRefused (Response& response) = 0;
|
||||||
|
|
||||||
|
virtual Response persuade (int type) = 0;
|
||||||
virtual int getTemporaryDispositionChange () const = 0;
|
virtual int getTemporaryDispositionChange () const = 0;
|
||||||
|
|
||||||
/// @note This change is temporary and gets discarded when dialogue ends.
|
/// @note This change is temporary and gets discarded when dialogue ends.
|
||||||
|
|
|
@ -248,7 +248,7 @@ namespace MWBase
|
||||||
/// Has the player stolen this item from the given owner?
|
/// Has the player stolen this item from the given owner?
|
||||||
virtual bool isItemStolenFrom(const std::string& itemid, const std::string& ownerid) = 0;
|
virtual bool isItemStolenFrom(const std::string& itemid, const std::string& ownerid) = 0;
|
||||||
|
|
||||||
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::ConstPtr& item, MWWorld::Ptr& victim) = 0;
|
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, MWWorld::Ptr& victim) = 0;
|
||||||
|
|
||||||
/// Turn actor into werewolf or normal form.
|
/// Turn actor into werewolf or normal form.
|
||||||
virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf) = 0;
|
virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf) = 0;
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
#include <MyGUI_KeyCode.h>
|
||||||
|
|
||||||
#include "../mwgui/mode.hpp"
|
#include "../mwgui/mode.hpp"
|
||||||
|
|
||||||
namespace Loading
|
namespace Loading
|
||||||
|
@ -100,23 +102,17 @@ namespace MWBase
|
||||||
|
|
||||||
virtual ~WindowManager() {}
|
virtual ~WindowManager() {}
|
||||||
|
|
||||||
/**
|
|
||||||
* Should be called each frame to update windows/gui elements.
|
|
||||||
* This could mean updating sizes of gui elements or opening
|
|
||||||
* new dialogs.
|
|
||||||
*/
|
|
||||||
virtual void update() = 0;
|
|
||||||
|
|
||||||
/// @note This method will block until the video finishes playing
|
/// @note This method will block until the video finishes playing
|
||||||
/// (and will continually update the window while doing so)
|
/// (and will continually update the window while doing so)
|
||||||
virtual void playVideo(const std::string& name, bool allowSkipping) = 0;
|
virtual void playVideo(const std::string& name, bool allowSkipping) = 0;
|
||||||
|
|
||||||
virtual void setNewGame(bool newgame) = 0;
|
virtual void setNewGame(bool newgame) = 0;
|
||||||
|
|
||||||
|
virtual void pushGuiMode (MWGui::GuiMode mode, const MWWorld::Ptr& arg) = 0;
|
||||||
virtual void pushGuiMode (MWGui::GuiMode mode) = 0;
|
virtual void pushGuiMode (MWGui::GuiMode mode) = 0;
|
||||||
virtual void popGuiMode() = 0;
|
virtual void popGuiMode(bool noSound=false) = 0;
|
||||||
|
|
||||||
virtual void removeGuiMode (MWGui::GuiMode mode) = 0;
|
virtual void removeGuiMode (MWGui::GuiMode mode, bool noSound=false) = 0;
|
||||||
///< can be anywhere in the stack
|
///< can be anywhere in the stack
|
||||||
|
|
||||||
virtual void goToJail(int days) = 0;
|
virtual void goToJail(int days) = 0;
|
||||||
|
@ -144,7 +140,6 @@ namespace MWBase
|
||||||
virtual bool isAllowed (MWGui::GuiWindow wnd) const = 0;
|
virtual bool isAllowed (MWGui::GuiWindow wnd) const = 0;
|
||||||
|
|
||||||
/// \todo investigate, if we really need to expose every single lousy UI element to the outside world
|
/// \todo investigate, if we really need to expose every single lousy UI element to the outside world
|
||||||
virtual MWGui::DialogueWindow* getDialogueWindow() = 0;
|
|
||||||
virtual MWGui::InventoryWindow* getInventoryWindow() = 0;
|
virtual MWGui::InventoryWindow* getInventoryWindow() = 0;
|
||||||
virtual MWGui::CountDialog* getCountDialog() = 0;
|
virtual MWGui::CountDialog* getCountDialog() = 0;
|
||||||
virtual MWGui::ConfirmationDialog* getConfirmationDialog() = 0;
|
virtual MWGui::ConfirmationDialog* getConfirmationDialog() = 0;
|
||||||
|
@ -195,6 +190,7 @@ namespace MWBase
|
||||||
virtual void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y) = 0;
|
virtual void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y) = 0;
|
||||||
|
|
||||||
virtual void setCursorVisible(bool visible) = 0;
|
virtual void setCursorVisible(bool visible) = 0;
|
||||||
|
virtual void setCursorActive(bool active) = 0;
|
||||||
virtual void getMousePosition(int &x, int &y) = 0;
|
virtual void getMousePosition(int &x, int &y) = 0;
|
||||||
virtual void getMousePosition(float &x, float &y) = 0;
|
virtual void getMousePosition(float &x, float &y) = 0;
|
||||||
virtual void setDragDrop(bool dragDrop) = 0;
|
virtual void setDragDrop(bool dragDrop) = 0;
|
||||||
|
@ -238,7 +234,7 @@ namespace MWBase
|
||||||
|
|
||||||
virtual void showCrosshair(bool show) = 0;
|
virtual void showCrosshair(bool show) = 0;
|
||||||
virtual bool getSubtitlesEnabled() = 0;
|
virtual bool getSubtitlesEnabled() = 0;
|
||||||
virtual bool toggleGui() = 0;
|
virtual bool toggleHud() = 0;
|
||||||
|
|
||||||
virtual void disallowMouse() = 0;
|
virtual void disallowMouse() = 0;
|
||||||
virtual void allowMouse() = 0;
|
virtual void allowMouse() = 0;
|
||||||
|
@ -302,21 +298,6 @@ namespace MWBase
|
||||||
virtual bool getPlayerSleeping() = 0;
|
virtual bool getPlayerSleeping() = 0;
|
||||||
virtual void wakeUpPlayer() = 0;
|
virtual void wakeUpPlayer() = 0;
|
||||||
|
|
||||||
virtual void showCompanionWindow(MWWorld::Ptr actor) = 0;
|
|
||||||
virtual void startSpellMaking(MWWorld::Ptr actor) = 0;
|
|
||||||
virtual void startEnchanting(MWWorld::Ptr actor) = 0;
|
|
||||||
virtual void startRecharge(MWWorld::Ptr soulgem) = 0;
|
|
||||||
virtual void startSelfEnchanting(MWWorld::Ptr soulgem) = 0;
|
|
||||||
virtual void startTraining(MWWorld::Ptr actor) = 0;
|
|
||||||
virtual void startRepair(MWWorld::Ptr actor) = 0;
|
|
||||||
virtual void startRepairItem(MWWorld::Ptr item) = 0;
|
|
||||||
virtual void startTravel(const MWWorld::Ptr& actor) = 0;
|
|
||||||
virtual void startSpellBuying(const MWWorld::Ptr& actor) = 0;
|
|
||||||
virtual void startTrade(const MWWorld::Ptr& actor) = 0;
|
|
||||||
virtual void openContainer(const MWWorld::Ptr& container, bool loot) = 0;
|
|
||||||
virtual void showBook(const MWWorld::Ptr& item, bool showTakeButton) = 0;
|
|
||||||
virtual void showScroll(const MWWorld::Ptr& item, bool showTakeButton) = 0;
|
|
||||||
|
|
||||||
virtual void showSoulgemDialog (MWWorld::Ptr item) = 0;
|
virtual void showSoulgemDialog (MWWorld::Ptr item) = 0;
|
||||||
|
|
||||||
virtual void changePointer (const std::string& name) = 0;
|
virtual void changePointer (const std::string& name) = 0;
|
||||||
|
@ -358,11 +339,11 @@ namespace MWBase
|
||||||
virtual void pinWindow (MWGui::GuiWindow window) = 0;
|
virtual void pinWindow (MWGui::GuiWindow window) = 0;
|
||||||
|
|
||||||
/// Fade the screen in, over \a time seconds
|
/// Fade the screen in, over \a time seconds
|
||||||
virtual void fadeScreenIn(const float time, bool clearQueue=true) = 0;
|
virtual void fadeScreenIn(const float time, bool clearQueue=true, float delay=0.f) = 0;
|
||||||
/// Fade the screen out to black, over \a time seconds
|
/// Fade the screen out to black, over \a time seconds
|
||||||
virtual void fadeScreenOut(const float time, bool clearQueue=true) = 0;
|
virtual void fadeScreenOut(const float time, bool clearQueue=true, float delay=0.f) = 0;
|
||||||
/// Fade the screen to a specified percentage of black, over \a time seconds
|
/// Fade the screen to a specified percentage of black, over \a time seconds
|
||||||
virtual void fadeScreenTo(const int percent, const float time, bool clearQueue=true) = 0;
|
virtual void fadeScreenTo(const int percent, const float time, bool clearQueue=true, float delay=0.f) = 0;
|
||||||
/// Darken the screen to a specified percentage
|
/// Darken the screen to a specified percentage
|
||||||
virtual void setBlindness(const int percent) = 0;
|
virtual void setBlindness(const int percent) = 0;
|
||||||
|
|
||||||
|
@ -388,6 +369,8 @@ namespace MWBase
|
||||||
virtual void writeFog(MWWorld::CellStore* cell) = 0;
|
virtual void writeFog(MWWorld::CellStore* cell) = 0;
|
||||||
|
|
||||||
virtual const MWGui::TextColours& getTextColours() = 0;
|
virtual const MWGui::TextColours& getTextColours() = 0;
|
||||||
|
|
||||||
|
virtual bool injectKeyPress(MyGUI::KeyCode key, unsigned int text) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -567,11 +567,11 @@ namespace MWClass
|
||||||
|
|
||||||
// by default user can loot friendly actors during death animation
|
// by default user can loot friendly actors during death animation
|
||||||
if (canLoot && !stats.getAiSequence().isInCombat())
|
if (canLoot && !stats.getAiSequence().isInCombat())
|
||||||
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr, true));
|
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr));
|
||||||
|
|
||||||
// otherwise wait until death animation
|
// otherwise wait until death animation
|
||||||
if(stats.isDeathAnimationFinished())
|
if(stats.isDeathAnimationFinished())
|
||||||
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr, true));
|
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr));
|
||||||
|
|
||||||
// death animation is not finished, do nothing
|
// death animation is not finished, do nothing
|
||||||
return std::shared_ptr<MWWorld::Action> (new MWWorld::FailedAction(""));
|
return std::shared_ptr<MWWorld::Action> (new MWWorld::FailedAction(""));
|
||||||
|
@ -580,6 +580,9 @@ namespace MWClass
|
||||||
if(stats.getAiSequence().isInCombat())
|
if(stats.getAiSequence().isInCombat())
|
||||||
return std::shared_ptr<MWWorld::Action>(new MWWorld::FailedAction(""));
|
return std::shared_ptr<MWWorld::Action>(new MWWorld::FailedAction(""));
|
||||||
|
|
||||||
|
if(stats.getKnockedDown())
|
||||||
|
return std::shared_ptr<MWWorld::Action>(new MWWorld::FailedAction(""));
|
||||||
|
|
||||||
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionTalk(ptr));
|
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionTalk(ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1008,11 +1008,11 @@ namespace MWClass
|
||||||
|
|
||||||
// by default user can loot friendly actors during death animation
|
// by default user can loot friendly actors during death animation
|
||||||
if (canLoot && !stats.getAiSequence().isInCombat())
|
if (canLoot && !stats.getAiSequence().isInCombat())
|
||||||
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr, true));
|
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr));
|
||||||
|
|
||||||
// otherwise wait until death animation
|
// otherwise wait until death animation
|
||||||
if(stats.isDeathAnimationFinished())
|
if(stats.isDeathAnimationFinished())
|
||||||
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr, true));
|
return std::shared_ptr<MWWorld::Action>(new MWWorld::ActionOpen(ptr));
|
||||||
|
|
||||||
// death animation is not finished, do nothing
|
// death animation is not finished, do nothing
|
||||||
return std::shared_ptr<MWWorld::Action> (new MWWorld::FailedAction(""));
|
return std::shared_ptr<MWWorld::Action> (new MWWorld::FailedAction(""));
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <components/esm/loaddial.hpp>
|
#include <components/esm/loaddial.hpp>
|
||||||
#include <components/esm/loadinfo.hpp>
|
#include <components/esm/loadinfo.hpp>
|
||||||
|
@ -46,8 +47,6 @@
|
||||||
#include "../mwworld/containerstore.hpp"
|
#include "../mwworld/containerstore.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
#include "../mwgui/dialogue.hpp"
|
|
||||||
|
|
||||||
#include "../mwscript/compilercontext.hpp"
|
#include "../mwscript/compilercontext.hpp"
|
||||||
#include "../mwscript/interpretercontext.hpp"
|
#include "../mwscript/interpretercontext.hpp"
|
||||||
#include "../mwscript/extensions.hpp"
|
#include "../mwscript/extensions.hpp"
|
||||||
|
@ -72,16 +71,8 @@ namespace MWDialogue
|
||||||
{
|
{
|
||||||
mChoice = -1;
|
mChoice = -1;
|
||||||
mIsInChoice = false;
|
mIsInChoice = false;
|
||||||
|
mGoodbye = false;
|
||||||
mCompilerContext.setExtensions (&extensions);
|
mCompilerContext.setExtensions (&extensions);
|
||||||
|
|
||||||
const MWWorld::Store<ESM::Dialogue> &dialogs =
|
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
|
|
||||||
|
|
||||||
MWWorld::Store<ESM::Dialogue>::iterator it = dialogs.begin();
|
|
||||||
for (; it != dialogs.end(); ++it)
|
|
||||||
{
|
|
||||||
mDialogueMap[Misc::StringUtils::lowerCase(it->mId)] = *it;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueManager::clear()
|
void DialogueManager::clear()
|
||||||
|
@ -146,17 +137,15 @@ namespace MWDialogue
|
||||||
if (mActorKnownTopics.count( topicId ))
|
if (mActorKnownTopics.count( topicId ))
|
||||||
mKnownTopics.insert( topicId );
|
mKnownTopics.insert( topicId );
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTopics();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueManager::startDialogue (const MWWorld::Ptr& actor)
|
bool DialogueManager::startDialogue (const MWWorld::Ptr& actor, Response& response)
|
||||||
{
|
{
|
||||||
updateGlobals();
|
updateGlobals();
|
||||||
|
|
||||||
// Dialogue with dead actor (e.g. through script) should not be allowed.
|
// Dialogue with dead actor (e.g. through script) should not be allowed.
|
||||||
if (actor.getClass().getCreatureStats(actor).isDead())
|
if (actor.getClass().getCreatureStats(actor).isDead())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
mLastTopic = "";
|
mLastTopic = "";
|
||||||
mPermanentDispositionChange = 0;
|
mPermanentDispositionChange = 0;
|
||||||
|
@ -164,6 +153,8 @@ namespace MWDialogue
|
||||||
|
|
||||||
mChoice = -1;
|
mChoice = -1;
|
||||||
mIsInChoice = false;
|
mIsInChoice = false;
|
||||||
|
mGoodbye = false;
|
||||||
|
mChoices.clear();
|
||||||
|
|
||||||
mActor = actor;
|
mActor = actor;
|
||||||
|
|
||||||
|
@ -172,13 +163,6 @@ namespace MWDialogue
|
||||||
|
|
||||||
mActorKnownTopics.clear();
|
mActorKnownTopics.clear();
|
||||||
|
|
||||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
|
||||||
|
|
||||||
// If the dialogue window was already open, keep the existing history
|
|
||||||
bool resetHistory = (!MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_Dialogue));
|
|
||||||
|
|
||||||
win->startDialogue(actor, actor.getClass().getName (actor), resetHistory);
|
|
||||||
|
|
||||||
//greeting
|
//greeting
|
||||||
const MWWorld::Store<ESM::Dialogue> &dialogs =
|
const MWWorld::Store<ESM::Dialogue> &dialogs =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
|
||||||
|
@ -192,9 +176,6 @@ namespace MWDialogue
|
||||||
// Search a response (we do not accept a fallback to "Info refusal" here)
|
// Search a response (we do not accept a fallback to "Info refusal" here)
|
||||||
if (const ESM::DialInfo *info = filter.search (*it, false))
|
if (const ESM::DialInfo *info = filter.search (*it, false))
|
||||||
{
|
{
|
||||||
//initialise the GUI
|
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Dialogue);
|
|
||||||
|
|
||||||
creatureStats.talkedToPlayer();
|
creatureStats.talkedToPlayer();
|
||||||
|
|
||||||
if (!info->mSound.empty())
|
if (!info->mSound.empty())
|
||||||
|
@ -203,29 +184,23 @@ namespace MWDialogue
|
||||||
}
|
}
|
||||||
|
|
||||||
// first topics update so that parseText knows the keywords to highlight
|
// first topics update so that parseText knows the keywords to highlight
|
||||||
updateTopics();
|
updateActorKnownTopics();
|
||||||
|
|
||||||
parseText (info->mResponse);
|
parseText (info->mResponse);
|
||||||
|
|
||||||
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
||||||
win->addResponse (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext), "", false);
|
response = Response ("", Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
|
||||||
executeScript (info->mResultScript, mActor);
|
executeScript (info->mResultScript, mActor);
|
||||||
mLastTopic = Misc::StringUtils::lowerCase(it->mId);
|
mLastTopic = it->mId;
|
||||||
|
|
||||||
// update topics again to accommodate changes resulting from executeScript
|
// update topics again to accommodate changes resulting from executeScript
|
||||||
updateTopics();
|
updateActorKnownTopics();
|
||||||
|
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
// No greetings found. The dialogue window should not be shown.
|
|
||||||
// If this is a companion, we must show the companion window directly (used by BM_bear_be_unique).
|
|
||||||
bool isCompanion = !mActor.getClass().getScript(mActor).empty()
|
|
||||||
&& mActor.getRefData().getLocals().getIntVar(mActor.getClass().getScript(mActor), "companion");
|
|
||||||
if (isCompanion)
|
|
||||||
MWBase::Environment::get().getWindowManager()->showCompanionWindow(mActor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DialogueManager::compile (const std::string& cmd, std::vector<Interpreter::Type_Code>& code, const MWWorld::Ptr& actor)
|
bool DialogueManager::compile (const std::string& cmd, std::vector<Interpreter::Type_Code>& code, const MWWorld::Ptr& actor)
|
||||||
|
@ -303,8 +278,9 @@ namespace MWDialogue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueManager::executeTopic (const std::string& topic)
|
DialogueManager::Response DialogueManager::executeTopic (const std::string& topic)
|
||||||
{
|
{
|
||||||
|
DialogueManager::Response response;
|
||||||
Filter filter (mActor, mChoice, mTalkedTo);
|
Filter filter (mActor, mChoice, mTalkedTo);
|
||||||
|
|
||||||
const MWWorld::Store<ESM::Dialogue> &dialogues =
|
const MWWorld::Store<ESM::Dialogue> &dialogues =
|
||||||
|
@ -312,8 +288,6 @@ namespace MWDialogue
|
||||||
|
|
||||||
const ESM::Dialogue& dialogue = *dialogues.find (topic);
|
const ESM::Dialogue& dialogue = *dialogues.find (topic);
|
||||||
|
|
||||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
|
||||||
|
|
||||||
const ESM::DialInfo* info = filter.search(dialogue, true);
|
const ESM::DialInfo* info = filter.search(dialogue, true);
|
||||||
if (info)
|
if (info)
|
||||||
{
|
{
|
||||||
|
@ -338,7 +312,7 @@ namespace MWDialogue
|
||||||
title = topic;
|
title = topic;
|
||||||
|
|
||||||
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
||||||
win->addResponse (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext), title);
|
response = Response(title, Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
|
||||||
|
|
||||||
if (dialogue.mType == ESM::Dialogue::Topic)
|
if (dialogue.mType == ESM::Dialogue::Topic)
|
||||||
{
|
{
|
||||||
|
@ -349,7 +323,7 @@ namespace MWDialogue
|
||||||
{
|
{
|
||||||
if (iter->mId == info->mId)
|
if (iter->mId == info->mId)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getJournal()->addTopic (topic, info->mId, mActor);
|
MWBase::Environment::get().getJournal()->addTopic (Misc::StringUtils::lowerCase(topic), info->mId, mActor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -359,11 +333,12 @@ namespace MWDialogue
|
||||||
|
|
||||||
mLastTopic = topic;
|
mLastTopic = topic;
|
||||||
}
|
}
|
||||||
else
|
return response;
|
||||||
{
|
}
|
||||||
// no response found, print a fallback text
|
|
||||||
win->addResponse ("…", topic);
|
const ESM::Dialogue *DialogueManager::searchDialogue(const std::string& id)
|
||||||
}
|
{
|
||||||
|
return MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>().search(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueManager::updateGlobals()
|
void DialogueManager::updateGlobals()
|
||||||
|
@ -371,19 +346,16 @@ namespace MWDialogue
|
||||||
MWBase::Environment::get().getWorld()->updateDialogueGlobals();
|
MWBase::Environment::get().getWorld()->updateDialogueGlobals();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueManager::updateTopics()
|
void DialogueManager::updateActorKnownTopics()
|
||||||
{
|
{
|
||||||
updateGlobals();
|
updateGlobals();
|
||||||
|
|
||||||
std::list<std::string> keywordList;
|
|
||||||
int choice = mChoice;
|
|
||||||
mChoice = -1;
|
|
||||||
mActorKnownTopics.clear();
|
mActorKnownTopics.clear();
|
||||||
|
|
||||||
const MWWorld::Store<ESM::Dialogue> &dialogs =
|
const MWWorld::Store<ESM::Dialogue> &dialogs =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
|
||||||
|
|
||||||
Filter filter (mActor, mChoice, mTalkedTo);
|
Filter filter (mActor, -1, mTalkedTo);
|
||||||
|
|
||||||
for (MWWorld::Store<ESM::Dialogue>::iterator iter = dialogs.begin(); iter != dialogs.end(); ++iter)
|
for (MWWorld::Store<ESM::Dialogue>::iterator iter = dialogs.begin(); iter != dialogs.end(); ++iter)
|
||||||
{
|
{
|
||||||
|
@ -393,90 +365,42 @@ namespace MWDialogue
|
||||||
{
|
{
|
||||||
std::string lower = Misc::StringUtils::lowerCase(iter->mId);
|
std::string lower = Misc::StringUtils::lowerCase(iter->mId);
|
||||||
mActorKnownTopics.insert (lower);
|
mActorKnownTopics.insert (lower);
|
||||||
|
|
||||||
//does the player know the topic?
|
|
||||||
if (mKnownTopics.count(lower))
|
|
||||||
{
|
|
||||||
keywordList.push_back (iter->mId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the available services of this actor
|
}
|
||||||
int services = 0;
|
|
||||||
if (mActor.getTypeName() == typeid(ESM::NPC).name())
|
std::list<std::string> DialogueManager::getAvailableTopics()
|
||||||
|
{
|
||||||
|
updateActorKnownTopics();
|
||||||
|
|
||||||
|
std::list<std::string> keywordList;
|
||||||
|
|
||||||
|
for (const std::string& topic : mActorKnownTopics)
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::NPC>* ref = mActor.get<ESM::NPC>();
|
//does the player know the topic?
|
||||||
if (ref->mBase->mHasAI)
|
if (mKnownTopics.count(Misc::StringUtils::lowerCase(topic)))
|
||||||
services = ref->mBase->mAiData.mServices;
|
keywordList.push_back(topic);
|
||||||
}
|
}
|
||||||
else if (mActor.getTypeName() == typeid(ESM::Creature).name())
|
|
||||||
{
|
|
||||||
MWWorld::LiveCellRef<ESM::Creature>* ref = mActor.get<ESM::Creature>();
|
|
||||||
if (ref->mBase->mHasAI)
|
|
||||||
services = ref->mBase->mAiData.mServices;
|
|
||||||
}
|
|
||||||
|
|
||||||
int windowServices = 0;
|
|
||||||
|
|
||||||
if (services & ESM::NPC::Weapon
|
|
||||||
|| services & ESM::NPC::Armor
|
|
||||||
|| services & ESM::NPC::Clothing
|
|
||||||
|| services & ESM::NPC::Books
|
|
||||||
|| services & ESM::NPC::Ingredients
|
|
||||||
|| services & ESM::NPC::Picks
|
|
||||||
|| services & ESM::NPC::Probes
|
|
||||||
|| services & ESM::NPC::Lights
|
|
||||||
|| services & ESM::NPC::Apparatus
|
|
||||||
|| services & ESM::NPC::RepairItem
|
|
||||||
|| services & ESM::NPC::Misc)
|
|
||||||
windowServices |= MWGui::DialogueWindow::Service_Trade;
|
|
||||||
|
|
||||||
if((mActor.getTypeName() == typeid(ESM::NPC).name() && !mActor.get<ESM::NPC>()->mBase->getTransport().empty())
|
|
||||||
|| (mActor.getTypeName() == typeid(ESM::Creature).name() && !mActor.get<ESM::Creature>()->mBase->getTransport().empty()))
|
|
||||||
windowServices |= MWGui::DialogueWindow::Service_Travel;
|
|
||||||
|
|
||||||
if (services & ESM::NPC::Spells)
|
|
||||||
windowServices |= MWGui::DialogueWindow::Service_BuySpells;
|
|
||||||
|
|
||||||
if (services & ESM::NPC::Spellmaking)
|
|
||||||
windowServices |= MWGui::DialogueWindow::Service_CreateSpells;
|
|
||||||
|
|
||||||
if (services & ESM::NPC::Training)
|
|
||||||
windowServices |= MWGui::DialogueWindow::Service_Training;
|
|
||||||
|
|
||||||
if (services & ESM::NPC::Enchanting)
|
|
||||||
windowServices |= MWGui::DialogueWindow::Service_Enchant;
|
|
||||||
|
|
||||||
if (services & ESM::NPC::Repair)
|
|
||||||
windowServices |= MWGui::DialogueWindow::Service_Repair;
|
|
||||||
|
|
||||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
|
||||||
|
|
||||||
win->setServices (windowServices);
|
|
||||||
|
|
||||||
// sort again, because the previous sort was case-sensitive
|
// sort again, because the previous sort was case-sensitive
|
||||||
keywordList.sort(Misc::StringUtils::ciLess);
|
keywordList.sort(Misc::StringUtils::ciLess);
|
||||||
win->setKeywords(keywordList);
|
return keywordList;
|
||||||
|
|
||||||
mChoice = choice;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueManager::keywordSelected (const std::string& keyword)
|
DialogueManager::Response DialogueManager::keywordSelected (const std::string& keyword)
|
||||||
{
|
{
|
||||||
|
Response response;
|
||||||
if(!mIsInChoice)
|
if(!mIsInChoice)
|
||||||
{
|
{
|
||||||
if(mDialogueMap.find(keyword) != mDialogueMap.end())
|
const ESM::Dialogue* dialogue = searchDialogue(keyword);
|
||||||
|
if (dialogue && dialogue->mType == ESM::Dialogue::Topic)
|
||||||
{
|
{
|
||||||
if (mDialogueMap[keyword].mType == ESM::Dialogue::Topic)
|
response = executeTopic (keyword);
|
||||||
{
|
|
||||||
executeTopic (keyword);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return response;
|
||||||
updateTopics();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DialogueManager::isInChoice() const
|
bool DialogueManager::isInChoice() const
|
||||||
|
@ -486,8 +410,6 @@ namespace MWDialogue
|
||||||
|
|
||||||
void DialogueManager::goodbyeSelected()
|
void DialogueManager::goodbyeSelected()
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue);
|
|
||||||
|
|
||||||
// Apply disposition change to NPC's base disposition
|
// Apply disposition change to NPC's base disposition
|
||||||
if (mActor.getClass().isNpc())
|
if (mActor.getClass().isNpc())
|
||||||
{
|
{
|
||||||
|
@ -503,37 +425,38 @@ namespace MWDialogue
|
||||||
mTemporaryDispositionChange = 0;
|
mTemporaryDispositionChange = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueManager::questionAnswered (int answer)
|
DialogueManager::Response DialogueManager::questionAnswered (int answer)
|
||||||
{
|
{
|
||||||
mChoice = answer;
|
mChoice = answer;
|
||||||
|
DialogueManager::Response response;
|
||||||
|
|
||||||
if (mDialogueMap.find(mLastTopic) != mDialogueMap.end())
|
const ESM::Dialogue* dialogue = searchDialogue(mLastTopic);
|
||||||
|
if (dialogue)
|
||||||
{
|
{
|
||||||
Filter filter (mActor, mChoice, mTalkedTo);
|
Filter filter (mActor, mChoice, mTalkedTo);
|
||||||
|
|
||||||
if (mDialogueMap[mLastTopic].mType == ESM::Dialogue::Topic
|
if (dialogue->mType == ESM::Dialogue::Topic || dialogue->mType == ESM::Dialogue::Greeting)
|
||||||
|| mDialogueMap[mLastTopic].mType == ESM::Dialogue::Greeting)
|
|
||||||
{
|
{
|
||||||
if (const ESM::DialInfo *info = filter.search (mDialogueMap[mLastTopic], true))
|
if (const ESM::DialInfo *info = filter.search (*dialogue, true))
|
||||||
{
|
{
|
||||||
std::string text = info->mResponse;
|
std::string text = info->mResponse;
|
||||||
parseText (text);
|
parseText (text);
|
||||||
|
|
||||||
mChoice = -1;
|
mChoice = -1;
|
||||||
mIsInChoice = false;
|
mIsInChoice = false;
|
||||||
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->clearChoices();
|
mChoices.clear();
|
||||||
|
|
||||||
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
||||||
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addResponse (Interpreter::fixDefinesDialog(text, interpreterContext));
|
response = Response("", Interpreter::fixDefinesDialog(text, interpreterContext));
|
||||||
|
|
||||||
// Make sure the returned DialInfo is from the Dialogue we supplied. If could also be from the Info refusal group,
|
// Make sure the returned DialInfo is from the Dialogue we supplied. If could also be from the Info refusal group,
|
||||||
// in which case it should not be added to the journal.
|
// in which case it should not be added to the journal.
|
||||||
for (ESM::Dialogue::InfoContainer::const_iterator iter = mDialogueMap[mLastTopic].mInfo.begin();
|
for (ESM::Dialogue::InfoContainer::const_iterator iter = dialogue->mInfo.begin();
|
||||||
iter!=mDialogueMap[mLastTopic].mInfo.end(); ++iter)
|
iter!=dialogue->mInfo.end(); ++iter)
|
||||||
{
|
{
|
||||||
if (iter->mId == info->mId)
|
if (iter->mId == info->mId)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getJournal()->addTopic (mLastTopic, info->mId, mActor);
|
MWBase::Environment::get().getJournal()->addTopic (Misc::StringUtils::lowerCase(mLastTopic), info->mId, mActor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -544,32 +467,39 @@ namespace MWDialogue
|
||||||
{
|
{
|
||||||
mChoice = -1;
|
mChoice = -1;
|
||||||
mIsInChoice = false;
|
mIsInChoice = false;
|
||||||
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->clearChoices();
|
mChoices.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTopics();
|
updateActorKnownTopics();
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueManager::askQuestion (const std::string& question, int choice)
|
void DialogueManager::addChoice (const std::string& text, int choice)
|
||||||
{
|
{
|
||||||
mIsInChoice = true;
|
mIsInChoice = true;
|
||||||
|
|
||||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
mChoices.push_back(std::make_pair(text, choice));
|
||||||
win->addChoice(question, choice);
|
}
|
||||||
|
|
||||||
|
const std::vector<std::pair<std::string, int> >& DialogueManager::getChoices()
|
||||||
|
{
|
||||||
|
return mChoices;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DialogueManager::isGoodbye()
|
||||||
|
{
|
||||||
|
return mGoodbye;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueManager::goodbye()
|
void DialogueManager::goodbye()
|
||||||
{
|
{
|
||||||
mIsInChoice = true;
|
mIsInChoice = false;
|
||||||
|
mGoodbye = true;
|
||||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
|
||||||
|
|
||||||
win->goodbye();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueManager::persuade(int type)
|
DialogueManager::Response DialogueManager::persuade(int type)
|
||||||
{
|
{
|
||||||
bool success;
|
bool success;
|
||||||
float temp, perm;
|
float temp, perm;
|
||||||
|
@ -618,7 +548,7 @@ namespace MWDialogue
|
||||||
text = "Bribe";
|
text = "Bribe";
|
||||||
}
|
}
|
||||||
|
|
||||||
executeTopic (text + (success ? " Success" : " Fail"));
|
return executeTopic (text + (success ? " Success" : " Fail"));
|
||||||
}
|
}
|
||||||
|
|
||||||
int DialogueManager::getTemporaryDispositionChange() const
|
int DialogueManager::getTemporaryDispositionChange() const
|
||||||
|
@ -631,7 +561,7 @@ namespace MWDialogue
|
||||||
mTemporaryDispositionChange += delta;
|
mTemporaryDispositionChange += delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DialogueManager::checkServiceRefused()
|
bool DialogueManager::checkServiceRefused(Response& response)
|
||||||
{
|
{
|
||||||
Filter filter (mActor, mChoice, mTalkedTo);
|
Filter filter (mActor, mChoice, mTalkedTo);
|
||||||
|
|
||||||
|
@ -639,7 +569,6 @@ namespace MWDialogue
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
|
||||||
|
|
||||||
const ESM::Dialogue& dialogue = *dialogues.find ("Service Refusal");
|
const ESM::Dialogue& dialogue = *dialogues.find ("Service Refusal");
|
||||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
|
||||||
|
|
||||||
std::vector<const ESM::DialInfo *> infos = filter.list (dialogue, false, false, true);
|
std::vector<const ESM::DialInfo *> infos = filter.list (dialogue, false, false, true);
|
||||||
if (!infos.empty())
|
if (!infos.empty())
|
||||||
|
@ -653,8 +582,7 @@ namespace MWDialogue
|
||||||
|
|
||||||
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
||||||
|
|
||||||
win->addResponse (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext),
|
response = Response(gmsts.find ("sServiceRefusal")->getString(), Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
|
||||||
gmsts.find ("sServiceRefusal")->getString());
|
|
||||||
|
|
||||||
executeScript (info->mResultScript, mActor);
|
executeScript (info->mResultScript, mActor);
|
||||||
return true;
|
return true;
|
||||||
|
@ -677,6 +605,12 @@ namespace MWDialogue
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (actor.getClass().getCreatureStats(actor).getKnockedDown())
|
||||||
|
{
|
||||||
|
// Unconscious actors can not speak
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const ESM::Dialogue *dial = store.get<ESM::Dialogue>().find(topic);
|
const ESM::Dialogue *dial = store.get<ESM::Dialogue>().find(topic);
|
||||||
|
|
||||||
|
@ -813,7 +747,7 @@ namespace MWDialogue
|
||||||
if (actor == mActor && !mLastTopic.empty())
|
if (actor == mActor && !mLastTopic.empty())
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getJournal()->removeLastAddedTopicResponse(
|
MWBase::Environment::get().getJournal()->removeLastAddedTopicResponse(
|
||||||
mLastTopic, actor.getClass().getName(actor));
|
Misc::StringUtils::lowerCase(mLastTopic), actor.getClass().getName(actor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ namespace MWDialogue
|
||||||
{
|
{
|
||||||
class DialogueManager : public MWBase::DialogueManager
|
class DialogueManager : public MWBase::DialogueManager
|
||||||
{
|
{
|
||||||
std::map<std::string, ESM::Dialogue> mDialogueMap;
|
|
||||||
std::set<std::string> mKnownTopics;// Those are the topics the player knows.
|
std::set<std::string> mKnownTopics;// Those are the topics the player knows.
|
||||||
|
|
||||||
// Modified faction reactions. <Faction1, <Faction2, Difference> >
|
// Modified faction reactions. <Faction1, <Faction2, Difference> >
|
||||||
|
@ -42,19 +41,24 @@ namespace MWDialogue
|
||||||
int mChoice;
|
int mChoice;
|
||||||
std::string mLastTopic; // last topic ID, lowercase
|
std::string mLastTopic; // last topic ID, lowercase
|
||||||
bool mIsInChoice;
|
bool mIsInChoice;
|
||||||
|
bool mGoodbye;
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, int> > mChoices;
|
||||||
|
|
||||||
float mTemporaryDispositionChange;
|
float mTemporaryDispositionChange;
|
||||||
float mPermanentDispositionChange;
|
float mPermanentDispositionChange;
|
||||||
|
|
||||||
void parseText (const std::string& text);
|
void parseText (const std::string& text);
|
||||||
|
|
||||||
void updateTopics();
|
void updateActorKnownTopics();
|
||||||
void updateGlobals();
|
void updateGlobals();
|
||||||
|
|
||||||
bool compile (const std::string& cmd, std::vector<Interpreter::Type_Code>& code, const MWWorld::Ptr& actor);
|
bool compile (const std::string& cmd, std::vector<Interpreter::Type_Code>& code, const MWWorld::Ptr& actor);
|
||||||
void executeScript (const std::string& script, const MWWorld::Ptr& actor);
|
void executeScript (const std::string& script, const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
void executeTopic (const std::string& topic);
|
Response executeTopic (const std::string& topic);
|
||||||
|
|
||||||
|
const ESM::Dialogue* searchDialogue(const std::string& id);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -64,7 +68,9 @@ namespace MWDialogue
|
||||||
|
|
||||||
virtual bool isInChoice() const;
|
virtual bool isInChoice() const;
|
||||||
|
|
||||||
virtual void startDialogue (const MWWorld::Ptr& actor);
|
virtual bool startDialogue (const MWWorld::Ptr& actor, Response& response);
|
||||||
|
|
||||||
|
std::list<std::string> getAvailableTopics();
|
||||||
|
|
||||||
virtual void addTopic (const std::string& topic);
|
virtual void addTopic (const std::string& topic);
|
||||||
|
|
||||||
|
@ -79,20 +85,23 @@ namespace MWDialogue
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
virtual void askQuestion (const std::string& question,int choice);
|
virtual void addChoice (const std::string& text,int choice);
|
||||||
|
const std::vector<std::pair<std::string, int> >& getChoices();
|
||||||
|
|
||||||
|
virtual bool isGoodbye();
|
||||||
|
|
||||||
virtual void goodbye();
|
virtual void goodbye();
|
||||||
|
|
||||||
virtual bool checkServiceRefused ();
|
virtual bool checkServiceRefused (Response& response);
|
||||||
|
|
||||||
virtual void say(const MWWorld::Ptr &actor, const std::string &topic);
|
virtual void say(const MWWorld::Ptr &actor, const std::string &topic);
|
||||||
|
|
||||||
//calbacks for the GUI
|
//calbacks for the GUI
|
||||||
virtual void keywordSelected (const std::string& keyword);
|
virtual Response keywordSelected (const std::string& keyword);
|
||||||
virtual void goodbyeSelected();
|
virtual void goodbyeSelected();
|
||||||
virtual void questionAnswered (int answer);
|
virtual Response questionAnswered (int answer);
|
||||||
|
|
||||||
virtual void persuade (int type);
|
virtual Response persuade (int type);
|
||||||
virtual int getTemporaryDispositionChange () const;
|
virtual int getTemporaryDispositionChange () const;
|
||||||
|
|
||||||
/// @note This change is temporary and gets discarded when dialogue ends.
|
/// @note This change is temporary and gets discarded when dialogue ends.
|
||||||
|
|
|
@ -193,7 +193,8 @@ bool MWDialogue::Filter::testFunctionLocal(const MWDialogue::SelectWrapper& sele
|
||||||
return false; // shouldn't happen, we checked that variable has a type above, so must exist
|
return false; // shouldn't happen, we checked that variable has a type above, so must exist
|
||||||
|
|
||||||
const MWScript::Locals& locals = mActor.getRefData().getLocals();
|
const MWScript::Locals& locals = mActor.getRefData().getLocals();
|
||||||
|
if (locals.isEmpty())
|
||||||
|
return select.selectCompare(0);
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case 's': return select.selectCompare (static_cast<int> (locals.mShorts[index]));
|
case 's': return select.selectCompare (static_cast<int> (locals.mShorts[index]));
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "alchemywindow.hpp"
|
#include "alchemywindow.hpp"
|
||||||
|
|
||||||
#include <MyGUI_Gui.h>
|
#include <MyGUI_Gui.h>
|
||||||
|
#include <MyGUI_Button.h>
|
||||||
|
#include <MyGUI_EditBox.h>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
@ -19,6 +21,7 @@
|
||||||
#include "sortfilteritemmodel.hpp"
|
#include "sortfilteritemmodel.hpp"
|
||||||
#include "itemview.hpp"
|
#include "itemview.hpp"
|
||||||
#include "itemwidget.hpp"
|
#include "itemwidget.hpp"
|
||||||
|
#include "widgets.hpp"
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
@ -54,12 +57,19 @@ namespace MWGui
|
||||||
mCreateButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCreateButtonClicked);
|
mCreateButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCreateButtonClicked);
|
||||||
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCancelButtonClicked);
|
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &AlchemyWindow::onCancelButtonClicked);
|
||||||
|
|
||||||
|
mNameEdit->eventEditSelectAccept += MyGUI::newDelegate(this, &AlchemyWindow::onAccept);
|
||||||
|
|
||||||
center();
|
center();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AlchemyWindow::onAccept(MyGUI::EditBox* sender)
|
||||||
|
{
|
||||||
|
onCreateButtonClicked(sender);
|
||||||
|
}
|
||||||
|
|
||||||
void AlchemyWindow::onCancelButtonClicked(MyGUI::Widget* _sender)
|
void AlchemyWindow::onCancelButtonClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
exit();
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Alchemy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlchemyWindow::onCreateButtonClicked(MyGUI::Widget* _sender)
|
void AlchemyWindow::onCreateButtonClicked(MyGUI::Widget* _sender)
|
||||||
|
@ -112,8 +122,9 @@ namespace MWGui
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlchemyWindow::open()
|
void AlchemyWindow::onOpen()
|
||||||
{
|
{
|
||||||
|
mAlchemy->clear();
|
||||||
mAlchemy->setAlchemist (MWMechanics::getPlayer());
|
mAlchemy->setAlchemist (MWMechanics::getPlayer());
|
||||||
|
|
||||||
InventoryItemModel* model = new InventoryItemModel(MWMechanics::getPlayer());
|
InventoryItemModel* model = new InventoryItemModel(MWMechanics::getPlayer());
|
||||||
|
@ -138,12 +149,8 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
|
|
||||||
update();
|
update();
|
||||||
}
|
|
||||||
|
|
||||||
void AlchemyWindow::exit() {
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mNameEdit);
|
||||||
mAlchemy->clear();
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Alchemy);
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Inventory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlchemyWindow::onIngredientSelected(MyGUI::Widget* _sender)
|
void AlchemyWindow::onIngredientSelected(MyGUI::Widget* _sender)
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
#include "../mwmechanics/alchemy.hpp"
|
#include "../mwmechanics/alchemy.hpp"
|
||||||
|
|
||||||
#include "widgets.hpp"
|
|
||||||
#include "windowbase.hpp"
|
#include "windowbase.hpp"
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
|
@ -24,8 +23,9 @@ namespace MWGui
|
||||||
public:
|
public:
|
||||||
AlchemyWindow();
|
AlchemyWindow();
|
||||||
|
|
||||||
virtual void open();
|
virtual void onOpen();
|
||||||
virtual void exit();
|
|
||||||
|
void onResChange(int, int) { center(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string mSuggestedPotionName;
|
std::string mSuggestedPotionName;
|
||||||
|
@ -43,6 +43,7 @@ namespace MWGui
|
||||||
void onCancelButtonClicked(MyGUI::Widget* _sender);
|
void onCancelButtonClicked(MyGUI::Widget* _sender);
|
||||||
void onCreateButtonClicked(MyGUI::Widget* _sender);
|
void onCreateButtonClicked(MyGUI::Widget* _sender);
|
||||||
void onIngredientSelected(MyGUI::Widget* _sender);
|
void onIngredientSelected(MyGUI::Widget* _sender);
|
||||||
|
void onAccept(MyGUI::EditBox*);
|
||||||
|
|
||||||
void onSelectedItem(int index);
|
void onSelectedItem(int index);
|
||||||
|
|
||||||
|
|
|
@ -64,11 +64,12 @@ namespace MWGui
|
||||||
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", ""));
|
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BirthDialog::open()
|
void BirthDialog::onOpen()
|
||||||
{
|
{
|
||||||
WindowModal::open();
|
WindowModal::onOpen();
|
||||||
updateBirths();
|
updateBirths();
|
||||||
updateSpells();
|
updateSpells();
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mBirthList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,9 @@ namespace MWGui
|
||||||
void setBirthId(const std::string &raceId);
|
void setBirthId(const std::string &raceId);
|
||||||
|
|
||||||
void setNextButtonShow(bool shown);
|
void setNextButtonShow(bool shown);
|
||||||
virtual void open();
|
virtual void onOpen();
|
||||||
|
|
||||||
|
bool exit() { return false; }
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void;
|
typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "bookwindow.hpp"
|
#include "bookwindow.hpp"
|
||||||
|
|
||||||
#include <MyGUI_TextBox.h>
|
#include <MyGUI_TextBox.h>
|
||||||
|
#include <MyGUI_InputManager.h>
|
||||||
|
|
||||||
#include <components/esm/loadbook.hpp>
|
#include <components/esm/loadbook.hpp>
|
||||||
|
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
|
||||||
#include "../mwworld/actiontake.hpp"
|
#include "../mwworld/actiontake.hpp"
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
#include "formatting.hpp"
|
#include "formatting.hpp"
|
||||||
|
|
||||||
|
@ -51,6 +53,11 @@ namespace MWGui
|
||||||
mRightPage->setNeedMouseFocus(true);
|
mRightPage->setNeedMouseFocus(true);
|
||||||
mRightPage->eventMouseWheel += MyGUI::newDelegate(this, &BookWindow::onMouseWheel);
|
mRightPage->eventMouseWheel += MyGUI::newDelegate(this, &BookWindow::onMouseWheel);
|
||||||
|
|
||||||
|
mNextPageButton->eventKeyButtonPressed += MyGUI::newDelegate(this, &BookWindow::onKeyButtonPressed);
|
||||||
|
mPrevPageButton->eventKeyButtonPressed += MyGUI::newDelegate(this, &BookWindow::onKeyButtonPressed);
|
||||||
|
mTakeButton->eventKeyButtonPressed += MyGUI::newDelegate(this, &BookWindow::onKeyButtonPressed);
|
||||||
|
mCloseButton->eventKeyButtonPressed += MyGUI::newDelegate(this, &BookWindow::onKeyButtonPressed);
|
||||||
|
|
||||||
if (mNextPageButton->getSize().width == 64)
|
if (mNextPageButton->getSize().width == 64)
|
||||||
{
|
{
|
||||||
// english button has a 7 pixel wide strip of garbage on its right edge
|
// english button has a 7 pixel wide strip of garbage on its right edge
|
||||||
|
@ -74,15 +81,16 @@ namespace MWGui
|
||||||
mPages.clear();
|
mPages.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BookWindow::openBook (MWWorld::Ptr book, bool showTakeButton)
|
void BookWindow::setPtr (const MWWorld::Ptr& book)
|
||||||
{
|
{
|
||||||
mBook = book;
|
mBook = book;
|
||||||
|
|
||||||
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
|
bool showTakeButton = book.getContainerStore() != &player.getClass().getContainerStore(player);
|
||||||
|
|
||||||
clearPages();
|
clearPages();
|
||||||
mCurrentPage = 0;
|
mCurrentPage = 0;
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->playSound("book open");
|
|
||||||
|
|
||||||
MWWorld::LiveCellRef<ESM::Book> *ref = mBook.get<ESM::Book>();
|
MWWorld::LiveCellRef<ESM::Book> *ref = mBook.get<ESM::Book>();
|
||||||
|
|
||||||
Formatting::BookFormatter formatter;
|
Formatting::BookFormatter formatter;
|
||||||
|
@ -92,14 +100,8 @@ namespace MWGui
|
||||||
updatePages();
|
updatePages();
|
||||||
|
|
||||||
setTakeButtonShow(showTakeButton);
|
setTakeButtonShow(showTakeButton);
|
||||||
}
|
|
||||||
|
|
||||||
void BookWindow::exit()
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton);
|
||||||
{
|
|
||||||
// no 3d sounds because the object could be in a container.
|
|
||||||
MWBase::Environment::get().getWindowManager()->playSound("book close");
|
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Book);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BookWindow::setTakeButtonShow(bool show)
|
void BookWindow::setTakeButtonShow(bool show)
|
||||||
|
@ -108,6 +110,14 @@ namespace MWGui
|
||||||
mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed);
|
mTakeButton->setVisible(mTakeButtonShow && mTakeButtonAllowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BookWindow::onKeyButtonPressed(MyGUI::Widget *sender, MyGUI::KeyCode key, MyGUI::Char character)
|
||||||
|
{
|
||||||
|
if (key == MyGUI::KeyCode::ArrowUp)
|
||||||
|
prevPage();
|
||||||
|
else if (key == MyGUI::KeyCode::ArrowDown)
|
||||||
|
nextPage();
|
||||||
|
}
|
||||||
|
|
||||||
void BookWindow::setInventoryAllowed(bool allowed)
|
void BookWindow::setInventoryAllowed(bool allowed)
|
||||||
{
|
{
|
||||||
mTakeButtonAllowed = allowed;
|
mTakeButtonAllowed = allowed;
|
||||||
|
@ -116,7 +126,7 @@ namespace MWGui
|
||||||
|
|
||||||
void BookWindow::onCloseButtonClicked (MyGUI::Widget* sender)
|
void BookWindow::onCloseButtonClicked (MyGUI::Widget* sender)
|
||||||
{
|
{
|
||||||
exit();
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Book);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BookWindow::onTakeButtonClicked (MyGUI::Widget* sender)
|
void BookWindow::onTakeButtonClicked (MyGUI::Widget* sender)
|
||||||
|
@ -144,20 +154,16 @@ namespace MWGui
|
||||||
mLeftPageNumber->setCaption( MyGUI::utility::toString(mCurrentPage*2 + 1) );
|
mLeftPageNumber->setCaption( MyGUI::utility::toString(mCurrentPage*2 + 1) );
|
||||||
mRightPageNumber->setCaption( MyGUI::utility::toString(mCurrentPage*2 + 2) );
|
mRightPageNumber->setCaption( MyGUI::utility::toString(mCurrentPage*2 + 2) );
|
||||||
|
|
||||||
//If it is the last page, hide the button "Next Page"
|
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||||
if ( (mCurrentPage+1)*2 == mPages.size()
|
bool nextPageVisible = (mCurrentPage+1)*2 < mPages.size();
|
||||||
|| (mCurrentPage+1)*2 == mPages.size() + 1)
|
mNextPageButton->setVisible(nextPageVisible);
|
||||||
{
|
bool prevPageVisible = mCurrentPage != 0;
|
||||||
mNextPageButton->setVisible(false);
|
mPrevPageButton->setVisible(prevPageVisible);
|
||||||
} else {
|
|
||||||
mNextPageButton->setVisible(true);
|
if (focus == mNextPageButton && !nextPageVisible && prevPageVisible)
|
||||||
}
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mPrevPageButton);
|
||||||
//If it is the fist page, hide the button "Prev Page"
|
else if (focus == mPrevPageButton && !prevPageVisible && nextPageVisible)
|
||||||
if (mCurrentPage == 0) {
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mNextPageButton);
|
||||||
mPrevPageButton->setVisible(false);
|
|
||||||
} else {
|
|
||||||
mPrevPageButton->setVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mPages.empty())
|
if (mPages.empty())
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -14,11 +14,11 @@ namespace MWGui
|
||||||
public:
|
public:
|
||||||
BookWindow();
|
BookWindow();
|
||||||
|
|
||||||
virtual void exit();
|
void setPtr(const MWWorld::Ptr& book);
|
||||||
|
|
||||||
void openBook(MWWorld::Ptr book, bool showTakeButton);
|
|
||||||
void setInventoryAllowed(bool allowed);
|
void setInventoryAllowed(bool allowed);
|
||||||
|
|
||||||
|
void onResChange(int, int) { center(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onNextPageButtonClicked (MyGUI::Widget* sender);
|
void onNextPageButtonClicked (MyGUI::Widget* sender);
|
||||||
void onPrevPageButtonClicked (MyGUI::Widget* sender);
|
void onPrevPageButtonClicked (MyGUI::Widget* sender);
|
||||||
|
@ -27,6 +27,8 @@ namespace MWGui
|
||||||
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||||
void setTakeButtonShow(bool show);
|
void setTakeButtonShow(bool show);
|
||||||
|
|
||||||
|
void onKeyButtonPressed(MyGUI::Widget* sender, MyGUI::KeyCode key, MyGUI::Char character);
|
||||||
|
|
||||||
void nextPage();
|
void nextPage();
|
||||||
void prevPage();
|
void prevPage();
|
||||||
|
|
||||||
|
|
|
@ -125,11 +125,12 @@ namespace MWGui
|
||||||
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", ""));
|
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sOK", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PickClassDialog::open()
|
void PickClassDialog::onOpen()
|
||||||
{
|
{
|
||||||
WindowModal::open ();
|
WindowModal::onOpen ();
|
||||||
updateClasses();
|
updateClasses();
|
||||||
updateStats();
|
updateStats();
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mClassList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -341,9 +342,9 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfoBoxDialog::open()
|
void InfoBoxDialog::onOpen()
|
||||||
{
|
{
|
||||||
WindowModal::open();
|
WindowModal::onOpen();
|
||||||
// Fix layout
|
// Fix layout
|
||||||
layoutVertically(mTextBox, 4);
|
layoutVertically(mTextBox, 4);
|
||||||
layoutVertically(mButtonBar, 6);
|
layoutVertically(mButtonBar, 6);
|
||||||
|
@ -730,9 +731,10 @@ namespace MWGui
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SelectSpecializationDialog::exit()
|
bool SelectSpecializationDialog::exit()
|
||||||
{
|
{
|
||||||
eventCancel();
|
eventCancel();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SelectAttributeDialog */
|
/* SelectAttributeDialog */
|
||||||
|
@ -778,9 +780,10 @@ namespace MWGui
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SelectAttributeDialog::exit()
|
bool SelectAttributeDialog::exit()
|
||||||
{
|
{
|
||||||
eventCancel();
|
eventCancel();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -869,9 +872,10 @@ namespace MWGui
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SelectSkillDialog::exit()
|
bool SelectSkillDialog::exit()
|
||||||
{
|
{
|
||||||
eventCancel();
|
eventCancel();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DescriptionDialog */
|
/* DescriptionDialog */
|
||||||
|
|
|
@ -21,7 +21,9 @@ namespace MWGui
|
||||||
std::string getText() const;
|
std::string getText() const;
|
||||||
void setButtons(ButtonList &buttons);
|
void setButtons(ButtonList &buttons);
|
||||||
|
|
||||||
virtual void open();
|
virtual void onOpen();
|
||||||
|
|
||||||
|
bool exit() { return false; }
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef MyGUI::delegates::CMultiDelegate1<int> EventHandle_Int;
|
typedef MyGUI::delegates::CMultiDelegate1<int> EventHandle_Int;
|
||||||
|
@ -67,6 +69,8 @@ namespace MWGui
|
||||||
std::string getClassId() const;
|
std::string getClassId() const;
|
||||||
void setClassId(const std::string &classId);
|
void setClassId(const std::string &classId);
|
||||||
|
|
||||||
|
bool exit() { return false; }
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void;
|
typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void;
|
||||||
|
|
||||||
|
@ -100,7 +104,9 @@ namespace MWGui
|
||||||
void setClassId(const std::string &classId);
|
void setClassId(const std::string &classId);
|
||||||
|
|
||||||
void setNextButtonShow(bool shown);
|
void setNextButtonShow(bool shown);
|
||||||
virtual void open();
|
virtual void onOpen();
|
||||||
|
|
||||||
|
bool exit() { return false; }
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void;
|
typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void;
|
||||||
|
@ -142,7 +148,7 @@ namespace MWGui
|
||||||
SelectSpecializationDialog();
|
SelectSpecializationDialog();
|
||||||
~SelectSpecializationDialog();
|
~SelectSpecializationDialog();
|
||||||
|
|
||||||
virtual void exit();
|
virtual bool exit();
|
||||||
|
|
||||||
ESM::Class::Specialization getSpecializationId() const { return mSpecializationId; }
|
ESM::Class::Specialization getSpecializationId() const { return mSpecializationId; }
|
||||||
|
|
||||||
|
@ -175,7 +181,7 @@ namespace MWGui
|
||||||
SelectAttributeDialog();
|
SelectAttributeDialog();
|
||||||
~SelectAttributeDialog();
|
~SelectAttributeDialog();
|
||||||
|
|
||||||
virtual void exit();
|
virtual bool exit();
|
||||||
|
|
||||||
ESM::Attribute::AttributeID getAttributeId() const { return mAttributeId; }
|
ESM::Attribute::AttributeID getAttributeId() const { return mAttributeId; }
|
||||||
|
|
||||||
|
@ -206,7 +212,7 @@ namespace MWGui
|
||||||
SelectSkillDialog();
|
SelectSkillDialog();
|
||||||
~SelectSkillDialog();
|
~SelectSkillDialog();
|
||||||
|
|
||||||
virtual void exit();
|
virtual bool exit();
|
||||||
|
|
||||||
ESM::Skill::SkillEnum getSkillId() const { return mSkillId; }
|
ESM::Skill::SkillEnum getSkillId() const { return mSkillId; }
|
||||||
|
|
||||||
|
@ -262,6 +268,8 @@ namespace MWGui
|
||||||
CreateClassDialog();
|
CreateClassDialog();
|
||||||
virtual ~CreateClassDialog();
|
virtual ~CreateClassDialog();
|
||||||
|
|
||||||
|
bool exit() { return false; }
|
||||||
|
|
||||||
std::string getName() const;
|
std::string getName() const;
|
||||||
std::string getDescription() const;
|
std::string getDescription() const;
|
||||||
ESM::Class::Specialization getSpecializationId() const;
|
ESM::Class::Specialization getSpecializationId() const;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "companionitemmodel.hpp"
|
#include "companionitemmodel.hpp"
|
||||||
#include "draganddrop.hpp"
|
#include "draganddrop.hpp"
|
||||||
#include "countdialog.hpp"
|
#include "countdialog.hpp"
|
||||||
|
#include "widgets.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -103,7 +104,7 @@ void CompanionWindow::onBackgroundSelected()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompanionWindow::openCompanion(const MWWorld::Ptr& npc)
|
void CompanionWindow::setPtr(const MWWorld::Ptr& npc)
|
||||||
{
|
{
|
||||||
mPtr = npc;
|
mPtr = npc;
|
||||||
updateEncumbranceBar();
|
updateEncumbranceBar();
|
||||||
|
@ -116,8 +117,9 @@ void CompanionWindow::openCompanion(const MWWorld::Ptr& npc)
|
||||||
setTitle(npc.getClass().getName(npc));
|
setTitle(npc.getClass().getName(npc));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompanionWindow::onFrame()
|
void CompanionWindow::onFrame(float dt)
|
||||||
{
|
{
|
||||||
|
checkReferenceAvailable();
|
||||||
updateEncumbranceBar();
|
updateEncumbranceBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,10 +141,11 @@ void CompanionWindow::updateEncumbranceBar()
|
||||||
|
|
||||||
void CompanionWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
|
void CompanionWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
exit();
|
if (exit())
|
||||||
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Companion);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompanionWindow::exit()
|
bool CompanionWindow::exit()
|
||||||
{
|
{
|
||||||
if (mModel && mModel->hasProfit(mPtr) && getProfit(mPtr) < 0)
|
if (mModel && mModel->hasProfit(mPtr) && getProfit(mPtr) < 0)
|
||||||
{
|
{
|
||||||
|
@ -151,9 +154,9 @@ void CompanionWindow::exit()
|
||||||
buttons.push_back("#{sCompanionWarningButtonTwo}");
|
buttons.push_back("#{sCompanionWarningButtonTwo}");
|
||||||
mMessageBoxManager->createInteractiveMessageBox("#{sCompanionWarningMessage}", buttons);
|
mMessageBoxManager->createInteractiveMessageBox("#{sCompanionWarningMessage}", buttons);
|
||||||
mMessageBoxManager->eventButtonPressed += MyGUI::newDelegate(this, &CompanionWindow::onMessageBoxButtonClicked);
|
mMessageBoxManager->eventButtonPressed += MyGUI::newDelegate(this, &CompanionWindow::onMessageBoxButtonClicked);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else
|
return true;
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Companion);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompanionWindow::onMessageBoxButtonClicked(int button)
|
void CompanionWindow::onMessageBoxButtonClicked(int button)
|
||||||
|
@ -162,7 +165,7 @@ void CompanionWindow::onMessageBoxButtonClicked(int button)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Companion);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Companion);
|
||||||
// Important for Calvus' contract script to work properly
|
// Important for Calvus' contract script to work properly
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue);
|
MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
#ifndef OPENMW_MWGUI_COMPANIONWINDOW_H
|
#ifndef OPENMW_MWGUI_COMPANIONWINDOW_H
|
||||||
#define OPENMW_MWGUI_COMPANIONWINDOW_H
|
#define OPENMW_MWGUI_COMPANIONWINDOW_H
|
||||||
|
|
||||||
#include "widgets.hpp"
|
|
||||||
#include "windowbase.hpp"
|
#include "windowbase.hpp"
|
||||||
#include "referenceinterface.hpp"
|
#include "referenceinterface.hpp"
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
namespace Widgets
|
||||||
|
{
|
||||||
|
class MWDynamicStat;
|
||||||
|
}
|
||||||
|
|
||||||
class MessageBoxManager;
|
class MessageBoxManager;
|
||||||
class ItemView;
|
class ItemView;
|
||||||
class DragAndDrop;
|
class DragAndDrop;
|
||||||
|
@ -18,12 +22,13 @@ namespace MWGui
|
||||||
public:
|
public:
|
||||||
CompanionWindow(DragAndDrop* dragAndDrop, MessageBoxManager* manager);
|
CompanionWindow(DragAndDrop* dragAndDrop, MessageBoxManager* manager);
|
||||||
|
|
||||||
virtual void exit();
|
virtual bool exit();
|
||||||
|
|
||||||
virtual void resetReference();
|
virtual void resetReference();
|
||||||
|
|
||||||
void openCompanion(const MWWorld::Ptr& npc);
|
void setPtr(const MWWorld::Ptr& npc);
|
||||||
void onFrame ();
|
void onFrame (float dt);
|
||||||
|
void clear() { resetReference(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ItemView* mItemView;
|
ItemView* mItemView;
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
#include <MyGUI_Button.h>
|
#include <MyGUI_Button.h>
|
||||||
#include <MyGUI_EditBox.h>
|
#include <MyGUI_EditBox.h>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
ConfirmationDialog::ConfirmationDialog() :
|
ConfirmationDialog::ConfirmationDialog() :
|
||||||
|
@ -16,14 +19,6 @@ namespace MWGui
|
||||||
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ConfirmationDialog::onOkButtonClicked);
|
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ConfirmationDialog::onOkButtonClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfirmationDialog::askForConfirmation(const std::string& message, const std::string& confirmMessage, const std::string& cancelMessage)
|
|
||||||
{
|
|
||||||
mCancelButton->setCaptionWithReplacing(cancelMessage);
|
|
||||||
mOkButton->setCaptionWithReplacing(confirmMessage);
|
|
||||||
|
|
||||||
askForConfirmation(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfirmationDialog::askForConfirmation(const std::string& message)
|
void ConfirmationDialog::askForConfirmation(const std::string& message)
|
||||||
{
|
{
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
|
@ -38,18 +33,21 @@ namespace MWGui
|
||||||
|
|
||||||
mMessage->setSize(mMessage->getWidth(), mMessage->getTextSize().height + 24);
|
mMessage->setSize(mMessage->getWidth(), mMessage->getTextSize().height + 24);
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mOkButton);
|
||||||
|
|
||||||
center();
|
center();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfirmationDialog::exit()
|
bool ConfirmationDialog::exit()
|
||||||
{
|
{
|
||||||
setVisible(false);
|
|
||||||
|
|
||||||
eventCancelClicked();
|
eventCancelClicked();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfirmationDialog::onCancelButtonClicked(MyGUI::Widget* _sender)
|
void ConfirmationDialog::onCancelButtonClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
|
setVisible(false);
|
||||||
|
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,7 @@ namespace MWGui
|
||||||
public:
|
public:
|
||||||
ConfirmationDialog();
|
ConfirmationDialog();
|
||||||
void askForConfirmation(const std::string& message);
|
void askForConfirmation(const std::string& message);
|
||||||
void askForConfirmation(const std::string& message, const std::string& confirmMessage, const std::string& cancelMessage);
|
virtual bool exit();
|
||||||
virtual void exit();
|
|
||||||
|
|
||||||
typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void;
|
typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void;
|
||||||
|
|
||||||
|
|
|
@ -145,25 +145,13 @@ namespace MWGui
|
||||||
mCompilerContext.setExtensions (&mExtensions);
|
mCompilerContext.setExtensions (&mExtensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Console::open()
|
void Console::onOpen()
|
||||||
{
|
{
|
||||||
// Give keyboard focus to the combo box whenever the console is
|
// Give keyboard focus to the combo box whenever the console is
|
||||||
// turned on
|
// turned on
|
||||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCommandLine);
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCommandLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Console::close()
|
|
||||||
{
|
|
||||||
// Apparently, hidden widgets can retain key focus
|
|
||||||
// Remove for MyGUI 3.2.2
|
|
||||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Console::exit()
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Console);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Console::setFont(const std::string &fntName)
|
void Console::setFont(const std::string &fntName)
|
||||||
{
|
{
|
||||||
mHistory->setFontName(fntName);
|
mHistory->setFontName(fntName);
|
||||||
|
@ -227,6 +215,11 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Console::clear()
|
||||||
|
{
|
||||||
|
resetReference();
|
||||||
|
}
|
||||||
|
|
||||||
void Console::keyPress(MyGUI::Widget* _sender,
|
void Console::keyPress(MyGUI::Widget* _sender,
|
||||||
MyGUI::KeyCode key,
|
MyGUI::KeyCode key,
|
||||||
MyGUI::Char _char)
|
MyGUI::Char _char)
|
||||||
|
|
|
@ -39,10 +39,7 @@ namespace MWGui
|
||||||
|
|
||||||
Console(int w, int h, bool consoleOnlyScripts);
|
Console(int w, int h, bool consoleOnlyScripts);
|
||||||
|
|
||||||
virtual void open();
|
virtual void onOpen();
|
||||||
virtual void close();
|
|
||||||
|
|
||||||
virtual void exit();
|
|
||||||
|
|
||||||
void setFont(const std::string &fntName);
|
void setFont(const std::string &fntName);
|
||||||
|
|
||||||
|
@ -63,6 +60,8 @@ namespace MWGui
|
||||||
|
|
||||||
void executeFile (const std::string& path);
|
void executeFile (const std::string& path);
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
virtual void resetReference ();
|
virtual void resetReference ();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "itemview.hpp"
|
#include "itemview.hpp"
|
||||||
#include "itemwidget.hpp"
|
#include "itemwidget.hpp"
|
||||||
#include "inventoryitemmodel.hpp"
|
#include "inventoryitemmodel.hpp"
|
||||||
|
#include "containeritemmodel.hpp"
|
||||||
#include "sortfilteritemmodel.hpp"
|
#include "sortfilteritemmodel.hpp"
|
||||||
#include "pickpocketitemmodel.hpp"
|
#include "pickpocketitemmodel.hpp"
|
||||||
#include "draganddrop.hpp"
|
#include "draganddrop.hpp"
|
||||||
|
@ -61,7 +62,6 @@ namespace MWGui
|
||||||
|
|
||||||
mDisposeCorpseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onDisposeCorpseButtonClicked);
|
mDisposeCorpseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onDisposeCorpseButtonClicked);
|
||||||
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onCloseButtonClicked);
|
mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onCloseButtonClicked);
|
||||||
mCloseButton->eventKeyButtonPressed += MyGUI::newDelegate(this, &ContainerWindow::onKeyPressed);
|
|
||||||
mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked);
|
mTakeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerWindow::onTakeAllButtonClicked);
|
||||||
|
|
||||||
setCoord(200,0,600,300);
|
setCoord(200,0,600,300);
|
||||||
|
@ -219,22 +219,39 @@ namespace MWGui
|
||||||
dropItem();
|
dropItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContainerWindow::openContainer(const MWWorld::Ptr& container, bool loot)
|
void ContainerWindow::setPtr(const MWWorld::Ptr& container)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Mark this container as open for multiplayer logic purposes
|
||||||
|
*/
|
||||||
mwmp::Main::get().getCellController()->openContainer(container, loot);
|
mwmp::Main::get().getCellController()->openContainer(container, loot);
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
mPickpocketDetected = false;
|
mPickpocketDetected = false;
|
||||||
mPtr = container;
|
mPtr = container;
|
||||||
|
|
||||||
if (mPtr.getTypeName() == typeid(ESM::NPC).name() && !loot)
|
bool loot = mPtr.getClass().isActor() && mPtr.getClass().getCreatureStats(mPtr).isDead();
|
||||||
|
|
||||||
|
if (mPtr.getClass().hasInventoryStore(mPtr))
|
||||||
{
|
{
|
||||||
// we are stealing stuff
|
if (mPtr.getClass().isNpc() && !loot)
|
||||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
{
|
||||||
mModel = new PickpocketItemModel(player, new InventoryItemModel(container),
|
// we are stealing stuff
|
||||||
!mPtr.getClass().getCreatureStats(mPtr).getKnockedDown());
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
|
mModel = new PickpocketItemModel(player, new InventoryItemModel(container),
|
||||||
|
!mPtr.getClass().getCreatureStats(mPtr).getKnockedDown());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mModel = new InventoryItemModel(container);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mModel = new InventoryItemModel(container);
|
{
|
||||||
|
mModel = new ContainerItemModel(container);
|
||||||
|
}
|
||||||
|
|
||||||
mDisposeCorpseButton->setVisible(loot);
|
mDisposeCorpseButton->setVisible(loot);
|
||||||
|
|
||||||
|
@ -248,14 +265,6 @@ namespace MWGui
|
||||||
setTitle(container.getClass().getName(container));
|
setTitle(container.getClass().getName(container));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContainerWindow::onKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char)
|
|
||||||
{
|
|
||||||
if (_key == MyGUI::KeyCode::Space)
|
|
||||||
onCloseButtonClicked(mCloseButton);
|
|
||||||
if (_key == MyGUI::KeyCode::Return || _key == MyGUI::KeyCode::NumpadEnter)
|
|
||||||
onTakeAllButtonClicked(mTakeButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ContainerWindow::resetReference()
|
void ContainerWindow::resetReference()
|
||||||
{
|
{
|
||||||
ReferenceInterface::resetReference();
|
ReferenceInterface::resetReference();
|
||||||
|
@ -264,10 +273,19 @@ namespace MWGui
|
||||||
mSortModel = NULL;
|
mSortModel = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContainerWindow::close()
|
void ContainerWindow::onClose()
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Mark this container as closed for multiplayer logic purposes
|
||||||
|
*/
|
||||||
mwmp::Main::get().getCellController()->closeContainer(mPtr);
|
mwmp::Main::get().getCellController()->closeContainer(mPtr);
|
||||||
WindowBase::close();
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
|
WindowBase::onClose();
|
||||||
|
|
||||||
if (dynamic_cast<PickpocketItemModel*>(mModel)
|
if (dynamic_cast<PickpocketItemModel*>(mModel)
|
||||||
// Make sure we were actually closed, rather than just temporarily hidden (e.g. console or main menu opened)
|
// Make sure we were actually closed, rather than just temporarily hidden (e.g. console or main menu opened)
|
||||||
|
@ -289,17 +307,9 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContainerWindow::exit()
|
|
||||||
{
|
|
||||||
if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop)
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
|
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
exit();
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender)
|
void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender)
|
||||||
|
@ -420,9 +430,8 @@ namespace MWGui
|
||||||
MWMechanics::Pickpocket pickpocket(player, mPtr);
|
MWMechanics::Pickpocket pickpocket(player, mPtr);
|
||||||
if (pickpocket.pick(item.mBase, count))
|
if (pickpocket.pick(item.mBase, count))
|
||||||
{
|
{
|
||||||
int value = item.mBase.getClass().getValue(item.mBase) * count;
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->commitCrime(
|
MWBase::Environment::get().getMechanicsManager()->commitCrime(
|
||||||
player, mPtr, MWBase::MechanicsManager::OT_Theft, value, true);
|
player, mPtr, MWBase::MechanicsManager::OT_Pickpocket, 0, true);
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container);
|
||||||
mPickpocketDetected = true;
|
mPickpocketDetected = true;
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -33,13 +33,14 @@ namespace MWGui
|
||||||
public:
|
public:
|
||||||
ContainerWindow(DragAndDrop* dragAndDrop);
|
ContainerWindow(DragAndDrop* dragAndDrop);
|
||||||
|
|
||||||
void openContainer(const MWWorld::Ptr& container, bool loot=false);
|
void setPtr(const MWWorld::Ptr& container);
|
||||||
virtual void close();
|
virtual void onClose();
|
||||||
|
void clear() { resetReference(); }
|
||||||
|
|
||||||
|
void onFrame(float dt) { checkReferenceAvailable(); }
|
||||||
|
|
||||||
virtual void resetReference();
|
virtual void resetReference();
|
||||||
|
|
||||||
virtual void exit();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DragAndDrop* mDragAndDrop;
|
DragAndDrop* mDragAndDrop;
|
||||||
|
|
||||||
|
@ -61,7 +62,6 @@ namespace MWGui
|
||||||
void onCloseButtonClicked(MyGUI::Widget* _sender);
|
void onCloseButtonClicked(MyGUI::Widget* _sender);
|
||||||
void onTakeAllButtonClicked(MyGUI::Widget* _sender);
|
void onTakeAllButtonClicked(MyGUI::Widget* _sender);
|
||||||
void onDisposeCorpseButtonClicked(MyGUI::Widget* sender);
|
void onDisposeCorpseButtonClicked(MyGUI::Widget* sender);
|
||||||
void onKeyPressed(MyGUI::Widget* _sender, MyGUI::KeyCode _key, MyGUI::Char _char);
|
|
||||||
|
|
||||||
/// @return is taking the item allowed?
|
/// @return is taking the item allowed?
|
||||||
bool onTakeItem(const ItemStack& item, int count);
|
bool onTakeItem(const ItemStack& item, int count);
|
||||||
|
|
|
@ -6,8 +6,11 @@
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
|
||||||
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -47,6 +50,19 @@ ContainerItemModel::ContainerItemModel (const MWWorld::Ptr& source)
|
||||||
mItemSources.push_back(source);
|
mItemSources.push_back(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ContainerItemModel::allowedToUseItems() const
|
||||||
|
{
|
||||||
|
if (mItemSources.size() == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
MWWorld::Ptr ptr = MWMechanics::getPlayer();
|
||||||
|
MWWorld::Ptr victim;
|
||||||
|
|
||||||
|
// Check if the player is allowed to use items from opened container
|
||||||
|
MWBase::MechanicsManager* mm = MWBase::Environment::get().getMechanicsManager();
|
||||||
|
return mm->isAllowedToUse(ptr, mItemSources[0], victim);
|
||||||
|
}
|
||||||
|
|
||||||
ItemStack ContainerItemModel::getItem (ModelIndex index)
|
ItemStack ContainerItemModel::getItem (ModelIndex index)
|
||||||
{
|
{
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace MWGui
|
||||||
|
|
||||||
ContainerItemModel (const MWWorld::Ptr& source);
|
ContainerItemModel (const MWWorld::Ptr& source);
|
||||||
|
|
||||||
|
virtual bool allowedToUseItems() const;
|
||||||
virtual ItemStack getItem (ModelIndex index);
|
virtual ItemStack getItem (ModelIndex index);
|
||||||
virtual ModelIndex getIndex (ItemStack item);
|
virtual ModelIndex getIndex (ItemStack item);
|
||||||
virtual size_t getItemCount();
|
virtual size_t getItemCount();
|
||||||
|
|
|
@ -56,19 +56,9 @@ namespace MWGui
|
||||||
mItemEdit->setValue(maxCount);
|
mItemEdit->setValue(maxCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CountDialog::cancel() //Keeping this here as I don't know if anything else relies on it.
|
|
||||||
{
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CountDialog::exit()
|
|
||||||
{
|
|
||||||
setVisible(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CountDialog::onCancelButtonClicked(MyGUI::Widget* _sender)
|
void CountDialog::onCancelButtonClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
cancel();
|
setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CountDialog::onOkButtonClicked(MyGUI::Widget* _sender)
|
void CountDialog::onOkButtonClicked(MyGUI::Widget* _sender)
|
||||||
|
|
|
@ -15,8 +15,6 @@ namespace MWGui
|
||||||
public:
|
public:
|
||||||
CountDialog();
|
CountDialog();
|
||||||
void openCountDialog(const std::string& item, const std::string& message, const int maxCount);
|
void openCountDialog(const std::string& item, const std::string& message, const int maxCount);
|
||||||
void cancel();
|
|
||||||
virtual void exit();
|
|
||||||
|
|
||||||
typedef MyGUI::delegates::CMultiDelegate2<MyGUI::Widget*, int> EventHandle_WidgetInt;
|
typedef MyGUI::delegates::CMultiDelegate2<MyGUI::Widget*, int> EventHandle_WidgetInt;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include <MyGUI_LanguageManager.h>
|
#include <MyGUI_LanguageManager.h>
|
||||||
#include <MyGUI_Window.h>
|
#include <MyGUI_Window.h>
|
||||||
#include <MyGUI_ProgressBar.h>
|
#include <MyGUI_ProgressBar.h>
|
||||||
|
#include <MyGUI_ScrollBar.h>
|
||||||
|
#include <MyGUI_Button.h>
|
||||||
|
|
||||||
#include <components/widgets/list.hpp>
|
#include <components/widgets/list.hpp>
|
||||||
#include <components/translation/translation.hpp>
|
#include <components/translation/translation.hpp>
|
||||||
|
@ -20,7 +22,6 @@
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
|
||||||
#include "widgets.hpp"
|
|
||||||
#include "bookpage.hpp"
|
#include "bookpage.hpp"
|
||||||
#include "textcolours.hpp"
|
#include "textcolours.hpp"
|
||||||
|
|
||||||
|
@ -52,7 +53,7 @@ namespace MWGui
|
||||||
|
|
||||||
void PersuasionDialog::onCancel(MyGUI::Widget *sender)
|
void PersuasionDialog::onCancel(MyGUI::Widget *sender)
|
||||||
{
|
{
|
||||||
exit();
|
setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PersuasionDialog::onPersuade(MyGUI::Widget *sender)
|
void PersuasionDialog::onPersuade(MyGUI::Widget *sender)
|
||||||
|
@ -68,14 +69,15 @@ namespace MWGui
|
||||||
else /*if (sender == mBribe1000Button)*/
|
else /*if (sender == mBribe1000Button)*/
|
||||||
type = MWBase::MechanicsManager::PT_Bribe1000;
|
type = MWBase::MechanicsManager::PT_Bribe1000;
|
||||||
|
|
||||||
MWBase::Environment::get().getDialogueManager()->persuade(type);
|
MWBase::DialogueManager::Response response = MWBase::Environment::get().getDialogueManager()->persuade(type);
|
||||||
|
|
||||||
|
eventPersuadeMsg(response.first, response.second);
|
||||||
|
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PersuasionDialog::open()
|
void PersuasionDialog::onOpen()
|
||||||
{
|
{
|
||||||
WindowModal::open();
|
|
||||||
center();
|
center();
|
||||||
|
|
||||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
|
@ -86,11 +88,12 @@ namespace MWGui
|
||||||
mBribe1000Button->setEnabled (playerGold >= 1000);
|
mBribe1000Button->setEnabled (playerGold >= 1000);
|
||||||
|
|
||||||
mGoldLabel->setCaptionWithReplacing("#{sGold}: " + MyGUI::utility::toString(playerGold));
|
mGoldLabel->setCaptionWithReplacing("#{sGold}: " + MyGUI::utility::toString(playerGold));
|
||||||
|
WindowModal::onOpen();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PersuasionDialog::exit()
|
MyGUI::Widget* PersuasionDialog::getDefaultKeyFocus()
|
||||||
{
|
{
|
||||||
setVisible(false);
|
return mAdmireButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------------
|
||||||
|
@ -219,31 +222,27 @@ namespace MWGui
|
||||||
|
|
||||||
void Choice::activated()
|
void Choice::activated()
|
||||||
{
|
{
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->playSound("Menu Click");
|
MWBase::Environment::get().getWindowManager()->playSound("Menu Click");
|
||||||
MWBase::Environment::get().getDialogueManager()->questionAnswered(mChoiceId);
|
eventChoiceActivated(mChoiceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Topic::activated()
|
void Topic::activated()
|
||||||
{
|
{
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->playSound("Menu Click");
|
MWBase::Environment::get().getWindowManager()->playSound("Menu Click");
|
||||||
MWBase::Environment::get().getDialogueManager()->keywordSelected(Misc::StringUtils::lowerCase(mTopicId));
|
eventTopicActivated(mTopicId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Goodbye::activated()
|
void Goodbye::activated()
|
||||||
{
|
{
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->playSound("Menu Click");
|
MWBase::Environment::get().getWindowManager()->playSound("Menu Click");
|
||||||
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
eventActivated();
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
DialogueWindow::DialogueWindow()
|
DialogueWindow::DialogueWindow()
|
||||||
: WindowBase("openmw_dialogue_window.layout")
|
: WindowBase("openmw_dialogue_window.layout")
|
||||||
, mServices(0)
|
, mIsCompanion(false)
|
||||||
, mEnabled(false)
|
|
||||||
, mGoodbye(false)
|
, mGoodbye(false)
|
||||||
, mPersuasionDialog()
|
, mPersuasionDialog()
|
||||||
{
|
{
|
||||||
|
@ -251,17 +250,17 @@ namespace MWGui
|
||||||
center();
|
center();
|
||||||
|
|
||||||
mPersuasionDialog.setVisible(false);
|
mPersuasionDialog.setVisible(false);
|
||||||
|
mPersuasionDialog.eventPersuadeMsg += MyGUI::newDelegate(this, &DialogueWindow::onPersuadeResult);
|
||||||
|
|
||||||
//History view
|
//History view
|
||||||
getWidget(mHistory, "History");
|
getWidget(mHistory, "History");
|
||||||
|
|
||||||
//Topics list
|
//Topics list
|
||||||
getWidget(mTopicsList, "TopicsList");
|
getWidget(mTopicsList, "TopicsList");
|
||||||
mTopicsList->eventItemSelected += MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
|
mTopicsList->eventItemSelected += MyGUI::newDelegate(this, &DialogueWindow::onSelectListItem);
|
||||||
|
|
||||||
MyGUI::Button* byeButton;
|
getWidget(mGoodbyeButton, "ByeButton");
|
||||||
getWidget(byeButton, "ByeButton");
|
mGoodbyeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DialogueWindow::onByeClicked);
|
||||||
byeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DialogueWindow::onByeClicked);
|
|
||||||
|
|
||||||
getWidget(mDispositionBar, "Disposition");
|
getWidget(mDispositionBar, "Disposition");
|
||||||
getWidget(mDispositionText,"DispositionText");
|
getWidget(mDispositionText,"DispositionText");
|
||||||
|
@ -276,18 +275,36 @@ namespace MWGui
|
||||||
mMainWidget->castType<MyGUI::Window>()->eventWindowChangeCoord += MyGUI::newDelegate(this, &DialogueWindow::onWindowResize);
|
mMainWidget->castType<MyGUI::Window>()->eventWindowChangeCoord += MyGUI::newDelegate(this, &DialogueWindow::onWindowResize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::exit()
|
DialogueWindow::~DialogueWindow()
|
||||||
{
|
{
|
||||||
if ((!mEnabled || MWBase::Environment::get().getDialogueManager()->isInChoice())
|
mPersuasionDialog.eventPersuadeMsg.clear();
|
||||||
&& !mGoodbye)
|
|
||||||
|
deleteLater();
|
||||||
|
for (Link* link : mLinks)
|
||||||
|
delete link;
|
||||||
|
for (auto link : mTopicLinks)
|
||||||
|
delete link.second;
|
||||||
|
for (auto history : mHistoryContents)
|
||||||
|
delete history;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::onTradeComplete()
|
||||||
|
{
|
||||||
|
addResponse("", MyGUI::LanguageManager::getInstance().replaceTags("#{sBarterDialog5}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DialogueWindow::exit()
|
||||||
|
{
|
||||||
|
if ((MWBase::Environment::get().getDialogueManager()->isInChoice()))
|
||||||
{
|
{
|
||||||
// in choice, not allowed to escape, but give access to main menu to allow loading other saves
|
return false;
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
resetReference();
|
||||||
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
||||||
mTopicsList->scrollToTop();
|
mTopicsList->scrollToTop();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,12 +329,13 @@ namespace MWGui
|
||||||
|
|
||||||
void DialogueWindow::onByeClicked(MyGUI::Widget* _sender)
|
void DialogueWindow::onByeClicked(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
exit();
|
if (exit())
|
||||||
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::onSelectTopic(const std::string& topic, int id)
|
void DialogueWindow::onSelectListItem(const std::string& topic, int id)
|
||||||
{
|
{
|
||||||
if (!mEnabled || MWBase::Environment::get().getDialogueManager()->isInChoice())
|
if (mGoodbye || MWBase::Environment::get().getDialogueManager()->isInChoice())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int separatorPos = 0;
|
int separatorPos = 0;
|
||||||
|
@ -328,63 +346,84 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id >= separatorPos)
|
if (id >= separatorPos)
|
||||||
MWBase::Environment::get().getDialogueManager()->keywordSelected(Misc::StringUtils::lowerCase(topic));
|
{
|
||||||
|
onTopicActivated(topic);
|
||||||
|
if (mGoodbyeButton->getEnabled())
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mGoodbyeButton);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
const MWWorld::Store<ESM::GameSetting> &gmst =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
|
|
||||||
|
MWBase::DialogueManager::Response response;
|
||||||
if (topic == gmst.find("sPersuasion")->getString())
|
if (topic == gmst.find("sPersuasion")->getString())
|
||||||
mPersuasionDialog.setVisible(true);
|
mPersuasionDialog.setVisible(true);
|
||||||
else if (topic == gmst.find("sCompanionShare")->getString())
|
else if (topic == gmst.find("sCompanionShare")->getString())
|
||||||
MWBase::Environment::get().getWindowManager()->showCompanionWindow(mPtr);
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Companion, mPtr);
|
||||||
else if (!MWBase::Environment::get().getDialogueManager()->checkServiceRefused())
|
else if (!MWBase::Environment::get().getDialogueManager()->checkServiceRefused(response))
|
||||||
{
|
{
|
||||||
if (topic == gmst.find("sBarter")->getString())
|
if (topic == gmst.find("sBarter")->getString())
|
||||||
MWBase::Environment::get().getWindowManager()->startTrade(mPtr);
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Barter, mPtr);
|
||||||
else if (topic == gmst.find("sSpells")->getString())
|
else if (topic == gmst.find("sSpells")->getString())
|
||||||
MWBase::Environment::get().getWindowManager()->startSpellBuying(mPtr);
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_SpellBuying, mPtr);
|
||||||
else if (topic == gmst.find("sTravel")->getString())
|
else if (topic == gmst.find("sTravel")->getString())
|
||||||
MWBase::Environment::get().getWindowManager()->startTravel(mPtr);
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Travel, mPtr);
|
||||||
else if (topic == gmst.find("sSpellMakingMenuTitle")->getString())
|
else if (topic == gmst.find("sSpellMakingMenuTitle")->getString())
|
||||||
MWBase::Environment::get().getWindowManager()->startSpellMaking (mPtr);
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_SpellCreation, mPtr);
|
||||||
else if (topic == gmst.find("sEnchanting")->getString())
|
else if (topic == gmst.find("sEnchanting")->getString())
|
||||||
MWBase::Environment::get().getWindowManager()->startEnchanting (mPtr);
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Enchanting, mPtr);
|
||||||
else if (topic == gmst.find("sServiceTrainingTitle")->getString())
|
else if (topic == gmst.find("sServiceTrainingTitle")->getString())
|
||||||
MWBase::Environment::get().getWindowManager()->startTraining (mPtr);
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Training, mPtr);
|
||||||
else if (topic == gmst.find("sRepair")->getString())
|
else if (topic == gmst.find("sRepair")->getString())
|
||||||
MWBase::Environment::get().getWindowManager()->startRepair (mPtr);
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_MerchantRepair, mPtr);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
addResponse(response.first, response.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName, bool resetHistory)
|
void DialogueWindow::setPtr(const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
|
MWBase::DialogueManager::Response response;
|
||||||
|
if (!MWBase::Environment::get().getDialogueManager()->startDialogue(actor, response))
|
||||||
|
{
|
||||||
|
// No greetings found. The dialogue window should not be shown.
|
||||||
|
// If this is a companion, we must show the companion window directly (used by BM_bear_be_unique).
|
||||||
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue);
|
||||||
|
if (isCompanion())
|
||||||
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Companion, mPtr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mGoodbyeButton);
|
||||||
|
|
||||||
mGoodbye = false;
|
mGoodbye = false;
|
||||||
mEnabled = true;
|
|
||||||
bool sameActor = (mPtr == actor);
|
bool sameActor = (mPtr == actor);
|
||||||
mPtr = actor;
|
mPtr = actor;
|
||||||
mTopicsList->setEnabled(true);
|
mTopicsList->setEnabled(true);
|
||||||
setTitle(npcName);
|
setTitle(mPtr.getClass().getName(mPtr));
|
||||||
|
|
||||||
clearChoices();
|
|
||||||
|
|
||||||
mTopicsList->clear();
|
mTopicsList->clear();
|
||||||
|
|
||||||
if (resetHistory || !sameActor)
|
if (!sameActor)
|
||||||
{
|
{
|
||||||
for (std::vector<DialogueText*>::iterator it = mHistoryContents.begin(); it != mHistoryContents.end(); ++it)
|
for (std::vector<DialogueText*>::iterator it = mHistoryContents.begin(); it != mHistoryContents.end(); ++it)
|
||||||
delete (*it);
|
delete (*it);
|
||||||
mHistoryContents.clear();
|
mHistoryContents.clear();
|
||||||
|
|
||||||
|
mKeywords.clear();
|
||||||
|
updateTopicsPane();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::vector<Link*>::iterator it = mLinks.begin(); it != mLinks.end(); ++it)
|
for (std::vector<Link*>::iterator it = mLinks.begin(); it != mLinks.end(); ++it)
|
||||||
delete (*it);
|
mDeleteLater.push_back(*it); // Links are not deleted right away to prevent issues with event handlers
|
||||||
mLinks.clear();
|
mLinks.clear();
|
||||||
|
|
||||||
updateOptions();
|
updateDisposition();
|
||||||
|
|
||||||
restock();
|
restock();
|
||||||
|
|
||||||
|
addResponse(response.first, response.second, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::restock()
|
void DialogueWindow::restock()
|
||||||
|
@ -401,16 +440,35 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::deleteLater()
|
||||||
|
{
|
||||||
|
for (Link* link : mDeleteLater)
|
||||||
|
delete link;
|
||||||
|
mDeleteLater.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void DialogueWindow::setKeywords(std::list<std::string> keyWords)
|
void DialogueWindow::setKeywords(std::list<std::string> keyWords)
|
||||||
|
{
|
||||||
|
if (mKeywords == keyWords && isCompanion() == mIsCompanion)
|
||||||
|
return;
|
||||||
|
mIsCompanion = isCompanion();
|
||||||
|
mKeywords = keyWords;
|
||||||
|
|
||||||
|
updateTopicsPane();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::updateTopicsPane()
|
||||||
{
|
{
|
||||||
mTopicsList->clear();
|
mTopicsList->clear();
|
||||||
for (std::map<std::string, Link*>::iterator it = mTopicLinks.begin(); it != mTopicLinks.end(); ++it)
|
for (std::map<std::string, Link*>::iterator it = mTopicLinks.begin(); it != mTopicLinks.end(); ++it)
|
||||||
delete it->second;
|
mDeleteLater.push_back(it->second);
|
||||||
mTopicLinks.clear();
|
mTopicLinks.clear();
|
||||||
mKeywordSearch.clear();
|
mKeywordSearch.clear();
|
||||||
|
|
||||||
bool isCompanion = !mPtr.getClass().getScript(mPtr).empty()
|
int services = mPtr.getClass().getServices(mPtr);
|
||||||
&& mPtr.getRefData().getLocals().getIntVar(mPtr.getClass().getScript(mPtr), "companion");
|
|
||||||
|
bool travel = (mPtr.getTypeName() == typeid(ESM::NPC).name() && !mPtr.get<ESM::NPC>()->mBase->getTransport().empty())
|
||||||
|
|| (mPtr.getTypeName() == typeid(ESM::Creature).name() && !mPtr.get<ESM::Creature>()->mBase->getTransport().empty());
|
||||||
|
|
||||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
const MWWorld::Store<ESM::GameSetting> &gmst =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
|
@ -418,39 +476,40 @@ namespace MWGui
|
||||||
if (mPtr.getTypeName() == typeid(ESM::NPC).name())
|
if (mPtr.getTypeName() == typeid(ESM::NPC).name())
|
||||||
mTopicsList->addItem(gmst.find("sPersuasion")->getString());
|
mTopicsList->addItem(gmst.find("sPersuasion")->getString());
|
||||||
|
|
||||||
if (mServices & Service_Trade)
|
if (services & ESM::NPC::AllItems)
|
||||||
mTopicsList->addItem(gmst.find("sBarter")->getString());
|
mTopicsList->addItem(gmst.find("sBarter")->getString());
|
||||||
|
|
||||||
if (mServices & Service_BuySpells)
|
if (services & ESM::NPC::Spells)
|
||||||
mTopicsList->addItem(gmst.find("sSpells")->getString());
|
mTopicsList->addItem(gmst.find("sSpells")->getString());
|
||||||
|
|
||||||
if (mServices & Service_Travel)
|
if (travel)
|
||||||
mTopicsList->addItem(gmst.find("sTravel")->getString());
|
mTopicsList->addItem(gmst.find("sTravel")->getString());
|
||||||
|
|
||||||
if (mServices & Service_CreateSpells)
|
if (services & ESM::NPC::Spellmaking)
|
||||||
mTopicsList->addItem(gmst.find("sSpellmakingMenuTitle")->getString());
|
mTopicsList->addItem(gmst.find("sSpellmakingMenuTitle")->getString());
|
||||||
|
|
||||||
if (mServices & Service_Enchant)
|
if (services & ESM::NPC::Enchanting)
|
||||||
mTopicsList->addItem(gmst.find("sEnchanting")->getString());
|
mTopicsList->addItem(gmst.find("sEnchanting")->getString());
|
||||||
|
|
||||||
if (mServices & Service_Training)
|
if (services & ESM::NPC::Training)
|
||||||
mTopicsList->addItem(gmst.find("sServiceTrainingTitle")->getString());
|
mTopicsList->addItem(gmst.find("sServiceTrainingTitle")->getString());
|
||||||
|
|
||||||
if (mServices & Service_Repair)
|
if (services & ESM::NPC::Repair)
|
||||||
mTopicsList->addItem(gmst.find("sRepair")->getString());
|
mTopicsList->addItem(gmst.find("sRepair")->getString());
|
||||||
|
|
||||||
if (isCompanion)
|
if (isCompanion())
|
||||||
mTopicsList->addItem(gmst.find("sCompanionShare")->getString());
|
mTopicsList->addItem(gmst.find("sCompanionShare")->getString());
|
||||||
|
|
||||||
if (mTopicsList->getItemCount() > 0)
|
if (mTopicsList->getItemCount() > 0)
|
||||||
mTopicsList->addSeparator();
|
mTopicsList->addSeparator();
|
||||||
|
|
||||||
|
|
||||||
for(std::list<std::string>::iterator it = keyWords.begin(); it != keyWords.end(); ++it)
|
for(std::list<std::string>::iterator it = mKeywords.begin(); it != mKeywords.end(); ++it)
|
||||||
{
|
{
|
||||||
mTopicsList->addItem(*it);
|
mTopicsList->addItem(*it);
|
||||||
|
|
||||||
Topic* t = new Topic(*it);
|
Topic* t = new Topic(*it);
|
||||||
|
t->eventTopicActivated += MyGUI::newDelegate(this, &DialogueWindow::onTopicActivated);
|
||||||
mTopicLinks[Misc::StringUtils::lowerCase(*it)] = t;
|
mTopicLinks[Misc::StringUtils::lowerCase(*it)] = t;
|
||||||
|
|
||||||
mKeywordSearch.seed(Misc::StringUtils::lowerCase(*it), intptr_t(t));
|
mKeywordSearch.seed(Misc::StringUtils::lowerCase(*it), intptr_t(t));
|
||||||
|
@ -484,9 +543,11 @@ namespace MWGui
|
||||||
typesetter->sectionBreak(9);
|
typesetter->sectionBreak(9);
|
||||||
// choices
|
// choices
|
||||||
const TextColours& textColours = MWBase::Environment::get().getWindowManager()->getTextColours();
|
const TextColours& textColours = MWBase::Environment::get().getWindowManager()->getTextColours();
|
||||||
for (std::vector<std::pair<std::string, int> >::iterator it = mChoices.begin(); it != mChoices.end(); ++it)
|
mChoices = MWBase::Environment::get().getDialogueManager()->getChoices();
|
||||||
|
for (std::vector<std::pair<std::string, int> >::const_iterator it = mChoices.begin(); it != mChoices.end(); ++it)
|
||||||
{
|
{
|
||||||
Choice* link = new Choice(it->second);
|
Choice* link = new Choice(it->second);
|
||||||
|
link->eventChoiceActivated += MyGUI::newDelegate(this, &DialogueWindow::onChoiceActivated);
|
||||||
mLinks.push_back(link);
|
mLinks.push_back(link);
|
||||||
|
|
||||||
typesetter->lineBreak();
|
typesetter->lineBreak();
|
||||||
|
@ -496,9 +557,11 @@ namespace MWGui
|
||||||
typesetter->write(questionStyle, to_utf8_span(it->first.c_str()));
|
typesetter->write(questionStyle, to_utf8_span(it->first.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mGoodbye = MWBase::Environment::get().getDialogueManager()->isGoodbye();
|
||||||
if (mGoodbye)
|
if (mGoodbye)
|
||||||
{
|
{
|
||||||
Goodbye* link = new Goodbye();
|
Goodbye* link = new Goodbye();
|
||||||
|
link->eventActivated += MyGUI::newDelegate(this, &DialogueWindow::onGoodbyeActivated);
|
||||||
mLinks.push_back(link);
|
mLinks.push_back(link);
|
||||||
std::string goodbye = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sGoodbye")->getString();
|
std::string goodbye = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sGoodbye")->getString();
|
||||||
BookTypesetter::Style* questionStyle = typesetter->createHotStyle(body, textColours.answer, textColours.answerOver,
|
BookTypesetter::Style* questionStyle = typesetter->createHotStyle(body, textColours.answer, textColours.answerOver,
|
||||||
|
@ -528,10 +591,11 @@ namespace MWGui
|
||||||
onScrollbarMoved(mScrollBar, 0);
|
onScrollbarMoved(mScrollBar, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
MyGUI::Button* byeButton;
|
|
||||||
getWidget(byeButton, "ByeButton");
|
|
||||||
bool goodbyeEnabled = !MWBase::Environment::get().getDialogueManager()->isInChoice() || mGoodbye;
|
bool goodbyeEnabled = !MWBase::Environment::get().getDialogueManager()->isInChoice() || mGoodbye;
|
||||||
byeButton->setEnabled(goodbyeEnabled);
|
bool goodbyeWasEnabled = mGoodbyeButton->getEnabled();
|
||||||
|
mGoodbyeButton->setEnabled(goodbyeEnabled);
|
||||||
|
if (goodbyeEnabled && !goodbyeWasEnabled)
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mGoodbyeButton);
|
||||||
|
|
||||||
bool topicsEnabled = !MWBase::Environment::get().getDialogueManager()->isInChoice() && !mGoodbye;
|
bool topicsEnabled = !MWBase::Environment::get().getDialogueManager()->isInChoice() && !mGoodbye;
|
||||||
mTopicsList->setEnabled(topicsEnabled);
|
mTopicsList->setEnabled(topicsEnabled);
|
||||||
|
@ -542,32 +606,35 @@ namespace MWGui
|
||||||
reinterpret_cast<Link*>(link)->activated();
|
reinterpret_cast<Link*>(link)->activated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::onTopicActivated(const std::string &topicId)
|
||||||
|
{
|
||||||
|
MWBase::DialogueManager::Response response = MWBase::Environment::get().getDialogueManager()->keywordSelected(topicId);
|
||||||
|
addResponse(response.first, response.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::onChoiceActivated(int id)
|
||||||
|
{
|
||||||
|
MWBase::DialogueManager::Response response = MWBase::Environment::get().getDialogueManager()->questionAnswered(id);
|
||||||
|
addResponse(response.first, response.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::onGoodbyeActivated()
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
||||||
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue);
|
||||||
|
resetReference();
|
||||||
|
}
|
||||||
|
|
||||||
void DialogueWindow::onScrollbarMoved(MyGUI::ScrollBar *sender, size_t pos)
|
void DialogueWindow::onScrollbarMoved(MyGUI::ScrollBar *sender, size_t pos)
|
||||||
{
|
{
|
||||||
mHistory->setPosition(0, static_cast<int>(pos) * -1);
|
mHistory->setPosition(0, static_cast<int>(pos) * -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::addResponse(const std::string &text, const std::string &title, bool needMargin)
|
void DialogueWindow::addResponse(const std::string &title, const std::string &text, bool needMargin)
|
||||||
{
|
{
|
||||||
// This is called from the dialogue manager, so text is
|
mHistoryContents.push_back(new Response(text, title, needMargin));
|
||||||
// case-smashed - thus we have to retrieve the correct case
|
|
||||||
// of the title through the topic list.
|
|
||||||
std::string realTitle = title;
|
|
||||||
if (realTitle != "")
|
|
||||||
{
|
|
||||||
for (size_t i=0; i<mTopicsList->getItemCount(); ++i)
|
|
||||||
{
|
|
||||||
std::string item = mTopicsList->getItemNameAt(i);
|
|
||||||
if (Misc::StringUtils::ciEqual(item, title))
|
|
||||||
{
|
|
||||||
realTitle = item;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mHistoryContents.push_back(new Response(text, realTitle, needMargin));
|
|
||||||
updateHistory();
|
updateHistory();
|
||||||
|
updateTopics();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::addMessageBox(const std::string& text)
|
void DialogueWindow::addMessageBox(const std::string& text)
|
||||||
|
@ -576,25 +643,10 @@ namespace MWGui
|
||||||
updateHistory();
|
updateHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::addChoice(const std::string& choice, int id)
|
void DialogueWindow::updateDisposition()
|
||||||
{
|
{
|
||||||
mChoices.push_back(std::make_pair(choice, id));
|
|
||||||
updateHistory();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DialogueWindow::clearChoices()
|
|
||||||
{
|
|
||||||
mChoices.clear();
|
|
||||||
updateHistory();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DialogueWindow::updateOptions()
|
|
||||||
{
|
|
||||||
//Clear the list of topics
|
|
||||||
mTopicsList->clear();
|
|
||||||
|
|
||||||
bool dispositionVisible = false;
|
bool dispositionVisible = false;
|
||||||
if (mPtr.getClass().isNpc())
|
if (!mPtr.isEmpty() && mPtr.getClass().isNpc())
|
||||||
{
|
{
|
||||||
dispositionVisible = true;
|
dispositionVisible = true;
|
||||||
mDispositionBar->setProgressRange(100);
|
mDispositionBar->setProgressRange(100);
|
||||||
|
@ -620,26 +672,38 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::goodbye()
|
|
||||||
{
|
|
||||||
mGoodbye = true;
|
|
||||||
mEnabled = false;
|
|
||||||
updateHistory();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DialogueWindow::onReferenceUnavailable()
|
void DialogueWindow::onReferenceUnavailable()
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueWindow::onFrame()
|
void DialogueWindow::onFrame(float dt)
|
||||||
{
|
{
|
||||||
if(mMainWidget->getVisible() && mPtr.getTypeName() == typeid(ESM::NPC).name())
|
checkReferenceAvailable();
|
||||||
{
|
if (mPtr.isEmpty())
|
||||||
int disp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr);
|
return;
|
||||||
mDispositionBar->setProgressRange(100);
|
|
||||||
mDispositionBar->setProgressPosition(disp);
|
updateDisposition();
|
||||||
mDispositionText->setCaption(MyGUI::utility::toString(disp)+std::string("/100"));
|
deleteLater();
|
||||||
}
|
|
||||||
|
if (mChoices != MWBase::Environment::get().getDialogueManager()->getChoices()
|
||||||
|
|| mGoodbye != MWBase::Environment::get().getDialogueManager()->isGoodbye())
|
||||||
|
updateHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::updateTopics()
|
||||||
|
{
|
||||||
|
setKeywords(MWBase::Environment::get().getDialogueManager()->getAvailableTopics());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DialogueWindow::isCompanion()
|
||||||
|
{
|
||||||
|
return !mPtr.getClass().getScript(mPtr).empty()
|
||||||
|
&& mPtr.getRefData().getLocals().getIntVar(mPtr.getClass().getScript(mPtr), "companion");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueWindow::onPersuadeResult(const std::string &title, const std::string &text)
|
||||||
|
{
|
||||||
|
addResponse(title, text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#include "../mwdialogue/keywordsearch.hpp"
|
#include "../mwdialogue/keywordsearch.hpp"
|
||||||
|
|
||||||
|
#include <MyGUI_Delegate.h>
|
||||||
|
|
||||||
namespace Gui
|
namespace Gui
|
||||||
{
|
{
|
||||||
class MWList;
|
class MWList;
|
||||||
|
@ -20,16 +22,17 @@ namespace MWGui
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
class DialogueHistoryViewModel;
|
|
||||||
class BookPage;
|
|
||||||
|
|
||||||
class PersuasionDialog : public WindowModal
|
class PersuasionDialog : public WindowModal
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PersuasionDialog();
|
PersuasionDialog();
|
||||||
|
|
||||||
virtual void open();
|
typedef MyGUI::delegates::CMultiDelegate2<const std::string&, const std::string&> EventHandle_Result;
|
||||||
virtual void exit();
|
EventHandle_Result eventPersuadeMsg;
|
||||||
|
|
||||||
|
virtual void onOpen();
|
||||||
|
|
||||||
|
virtual MyGUI::Widget* getDefaultKeyFocus();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MyGUI::Button* mCancelButton;
|
MyGUI::Button* mCancelButton;
|
||||||
|
@ -54,6 +57,8 @@ namespace MWGui
|
||||||
|
|
||||||
struct Topic : Link
|
struct Topic : Link
|
||||||
{
|
{
|
||||||
|
typedef MyGUI::delegates::CMultiDelegate1<const std::string&> EventHandle_TopicId;
|
||||||
|
EventHandle_TopicId eventTopicActivated;
|
||||||
Topic(const std::string& id) : mTopicId(id) {}
|
Topic(const std::string& id) : mTopicId(id) {}
|
||||||
std::string mTopicId;
|
std::string mTopicId;
|
||||||
virtual void activated ();
|
virtual void activated ();
|
||||||
|
@ -61,6 +66,8 @@ namespace MWGui
|
||||||
|
|
||||||
struct Choice : Link
|
struct Choice : Link
|
||||||
{
|
{
|
||||||
|
typedef MyGUI::delegates::CMultiDelegate1<int> EventHandle_ChoiceId;
|
||||||
|
EventHandle_ChoiceId eventChoiceActivated;
|
||||||
Choice(int id) : mChoiceId(id) {}
|
Choice(int id) : mChoiceId(id) {}
|
||||||
int mChoiceId;
|
int mChoiceId;
|
||||||
virtual void activated ();
|
virtual void activated ();
|
||||||
|
@ -68,6 +75,8 @@ namespace MWGui
|
||||||
|
|
||||||
struct Goodbye : Link
|
struct Goodbye : Link
|
||||||
{
|
{
|
||||||
|
typedef MyGUI::delegates::CMultiDelegate0 Event_Activated;
|
||||||
|
Event_Activated eventActivated;
|
||||||
virtual void activated ();
|
virtual void activated ();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -99,46 +108,41 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DialogueWindow();
|
DialogueWindow();
|
||||||
|
~DialogueWindow();
|
||||||
|
|
||||||
virtual void exit();
|
void onTradeComplete();
|
||||||
|
|
||||||
|
virtual bool exit();
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void;
|
typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void;
|
||||||
|
|
||||||
void notifyLinkClicked (TypesetBook::InteractiveId link);
|
void notifyLinkClicked (TypesetBook::InteractiveId link);
|
||||||
|
|
||||||
void startDialogue(MWWorld::Ptr actor, std::string npcName, bool resetHistory);
|
void setPtr(const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
void setKeywords(std::list<std::string> keyWord);
|
void setKeywords(std::list<std::string> keyWord);
|
||||||
|
|
||||||
void addResponse (const std::string& text, const std::string& title="", bool needMargin = true);
|
void addResponse (const std::string& title, const std::string& text, bool needMargin = true);
|
||||||
|
|
||||||
void addMessageBox(const std::string& text);
|
void addMessageBox(const std::string& text);
|
||||||
|
|
||||||
void addChoice(const std::string& choice, int id);
|
void onFrame(float dt);
|
||||||
void clearChoices();
|
void clear() { resetReference(); }
|
||||||
|
|
||||||
void goodbye();
|
|
||||||
void onFrame();
|
|
||||||
|
|
||||||
// make sure to call these before setKeywords()
|
|
||||||
void setServices(int services) { mServices = services; }
|
|
||||||
|
|
||||||
enum Services
|
|
||||||
{
|
|
||||||
Service_Trade = 0x01,
|
|
||||||
Service_BuySpells = 0x02,
|
|
||||||
Service_CreateSpells = 0x04,
|
|
||||||
Service_Enchant = 0x08,
|
|
||||||
Service_Training = 0x10,
|
|
||||||
Service_Travel = 0x20,
|
|
||||||
Service_Repair = 0x40
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onSelectTopic(const std::string& topic, int id);
|
void updateTopics();
|
||||||
|
void updateTopicsPane();
|
||||||
|
bool isCompanion();
|
||||||
|
|
||||||
|
void onPersuadeResult(const std::string& title, const std::string& text);
|
||||||
|
void onSelectListItem(const std::string& topic, int id);
|
||||||
void onByeClicked(MyGUI::Widget* _sender);
|
void onByeClicked(MyGUI::Widget* _sender);
|
||||||
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||||
void onWindowResize(MyGUI::Window* _sender);
|
void onWindowResize(MyGUI::Window* _sender);
|
||||||
|
void onTopicActivated(const std::string& topicId);
|
||||||
|
void onChoiceActivated(int id);
|
||||||
|
void onGoodbyeActivated();
|
||||||
|
|
||||||
void onScrollbarMoved (MyGUI::ScrollBar* sender, size_t pos);
|
void onScrollbarMoved (MyGUI::ScrollBar* sender, size_t pos);
|
||||||
|
|
||||||
|
@ -147,21 +151,24 @@ namespace MWGui
|
||||||
virtual void onReferenceUnavailable();
|
virtual void onReferenceUnavailable();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateOptions();
|
void updateDisposition();
|
||||||
void restock();
|
void restock();
|
||||||
|
void deleteLater();
|
||||||
int mServices;
|
|
||||||
|
|
||||||
bool mEnabled;
|
bool mEnabled;
|
||||||
|
|
||||||
bool mGoodbye;
|
bool mIsCompanion;
|
||||||
|
std::list<std::string> mKeywords;
|
||||||
|
|
||||||
std::vector<DialogueText*> mHistoryContents;
|
std::vector<DialogueText*> mHistoryContents;
|
||||||
std::vector<std::pair<std::string, int> > mChoices;
|
std::vector<std::pair<std::string, int> > mChoices;
|
||||||
|
bool mGoodbye;
|
||||||
|
|
||||||
std::vector<Link*> mLinks;
|
std::vector<Link*> mLinks;
|
||||||
std::map<std::string, Link*> mTopicLinks;
|
std::map<std::string, Link*> mTopicLinks;
|
||||||
|
|
||||||
|
std::vector<Link*> mDeleteLater;
|
||||||
|
|
||||||
KeywordSearchT mKeywordSearch;
|
KeywordSearchT mKeywordSearch;
|
||||||
|
|
||||||
BookPage* mHistory;
|
BookPage* mHistory;
|
||||||
|
@ -169,6 +176,7 @@ namespace MWGui
|
||||||
MyGUI::ScrollBar* mScrollBar;
|
MyGUI::ScrollBar* mScrollBar;
|
||||||
MyGUI::ProgressBar* mDispositionBar;
|
MyGUI::ProgressBar* mDispositionBar;
|
||||||
MyGUI::TextBox* mDispositionText;
|
MyGUI::TextBox* mDispositionText;
|
||||||
|
MyGUI::Button* mGoodbyeButton;
|
||||||
|
|
||||||
PersuasionDialog mPersuasionDialog;
|
PersuasionDialog mPersuasionDialog;
|
||||||
|
|
||||||
|
|
|
@ -121,10 +121,18 @@ void DragAndDrop::drop(ItemModel *targetModel, ItemView *targetView)
|
||||||
mSourceView->update();
|
mSourceView->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DragAndDrop::onFrame()
|
||||||
|
{
|
||||||
|
if (mIsOnDragAndDrop && mItem.mBase.getRefData().getCount() == 0)
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
void DragAndDrop::finish()
|
void DragAndDrop::finish()
|
||||||
{
|
{
|
||||||
mIsOnDragAndDrop = false;
|
mIsOnDragAndDrop = false;
|
||||||
mSourceSortModel->clearDragItems();
|
mSourceSortModel->clearDragItems();
|
||||||
|
// since mSourceView doesn't get updated in drag()
|
||||||
|
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView();
|
||||||
|
|
||||||
MyGUI::Gui::getInstance().destroyWidget(mDraggedWidget);
|
MyGUI::Gui::getInstance().destroyWidget(mDraggedWidget);
|
||||||
mDraggedWidget = 0;
|
mDraggedWidget = 0;
|
||||||
|
|
|
@ -29,6 +29,7 @@ namespace MWGui
|
||||||
|
|
||||||
void startDrag (int index, SortFilterItemModel* sortModel, ItemModel* sourceModel, ItemView* sourceView, int count);
|
void startDrag (int index, SortFilterItemModel* sortModel, ItemModel* sourceModel, ItemView* sourceView, int count);
|
||||||
void drop (ItemModel* targetModel, ItemView* targetView);
|
void drop (ItemModel* targetModel, ItemView* targetView);
|
||||||
|
void onFrame();
|
||||||
|
|
||||||
void finish();
|
void finish();
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,11 +4,11 @@
|
||||||
|
|
||||||
#include <MyGUI_Button.h>
|
#include <MyGUI_Button.h>
|
||||||
#include <MyGUI_ScrollView.h>
|
#include <MyGUI_ScrollView.h>
|
||||||
|
#include <MyGUI_EditBox.h>
|
||||||
|
|
||||||
#include <components/widgets/list.hpp>
|
#include <components/widgets/list.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
#include "../mwbase/dialoguemanager.hpp"
|
|
||||||
#include "../mwbase/mechanicsmanager.hpp"
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/containerstore.hpp"
|
#include "../mwworld/containerstore.hpp"
|
||||||
|
@ -53,6 +53,7 @@ namespace MWGui
|
||||||
mSoulBox->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onSelectSoul);
|
mSoulBox->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onSelectSoul);
|
||||||
mBuyButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onBuyButtonClicked);
|
mBuyButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onBuyButtonClicked);
|
||||||
mTypeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onTypeButtonClicked);
|
mTypeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onTypeButtonClicked);
|
||||||
|
mName->eventEditSelectAccept += MyGUI::newDelegate(this, &EnchantingDialog::onAccept);
|
||||||
}
|
}
|
||||||
|
|
||||||
EnchantingDialog::~EnchantingDialog()
|
EnchantingDialog::~EnchantingDialog()
|
||||||
|
@ -60,9 +61,10 @@ namespace MWGui
|
||||||
delete mItemSelectionDialog;
|
delete mItemSelectionDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnchantingDialog::open()
|
void EnchantingDialog::onOpen()
|
||||||
{
|
{
|
||||||
center();
|
center();
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnchantingDialog::setSoulGem(const MWWorld::Ptr &gem)
|
void EnchantingDialog::setSoulGem(const MWWorld::Ptr &gem)
|
||||||
|
@ -100,11 +102,6 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnchantingDialog::exit()
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnchantingDialog::updateLabels()
|
void EnchantingDialog::updateLabels()
|
||||||
{
|
{
|
||||||
std::stringstream enchantCost;
|
std::stringstream enchantCost;
|
||||||
|
@ -143,57 +140,41 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnchantingDialog::startEnchanting (MWWorld::Ptr actor)
|
void EnchantingDialog::setPtr (const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
mName->setCaption("");
|
mName->setCaption("");
|
||||||
|
|
||||||
mEnchanting.setSelfEnchanting(false);
|
if (ptr.getClass().isActor())
|
||||||
mEnchanting.setEnchanter(actor);
|
{
|
||||||
|
mEnchanting.setSelfEnchanting(false);
|
||||||
|
mEnchanting.setEnchanter(ptr);
|
||||||
|
mBuyButton->setCaptionWithReplacing("#{sBuy}");
|
||||||
|
mChanceLayout->setVisible(false);
|
||||||
|
mPtr = ptr;
|
||||||
|
setSoulGem(MWWorld::Ptr());
|
||||||
|
mPrice->setVisible(true);
|
||||||
|
mPriceText->setVisible(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mEnchanting.setSelfEnchanting(true);
|
||||||
|
mEnchanting.setEnchanter(MWMechanics::getPlayer());
|
||||||
|
mBuyButton->setCaptionWithReplacing("#{sCreate}");
|
||||||
|
bool enabled = Settings::Manager::getBool("show enchant chance","Game");
|
||||||
|
mChanceLayout->setVisible(enabled);
|
||||||
|
mPtr = MWMechanics::getPlayer();
|
||||||
|
setSoulGem(ptr);
|
||||||
|
mPrice->setVisible(false);
|
||||||
|
mPriceText->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
mBuyButton->setCaptionWithReplacing("#{sBuy}");
|
|
||||||
|
|
||||||
mChanceLayout->setVisible(false);
|
|
||||||
|
|
||||||
mPtr = actor;
|
|
||||||
|
|
||||||
setSoulGem(MWWorld::Ptr());
|
|
||||||
setItem(MWWorld::Ptr());
|
setItem(MWWorld::Ptr());
|
||||||
|
|
||||||
startEditing ();
|
startEditing ();
|
||||||
mPrice->setVisible(true);
|
|
||||||
mPriceText->setVisible(true);
|
|
||||||
updateLabels();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnchantingDialog::startSelfEnchanting(MWWorld::Ptr soulgem)
|
|
||||||
{
|
|
||||||
mName->setCaption("");
|
|
||||||
|
|
||||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
|
||||||
|
|
||||||
mEnchanting.setSelfEnchanting(true);
|
|
||||||
mEnchanting.setEnchanter(player);
|
|
||||||
|
|
||||||
mBuyButton->setCaptionWithReplacing("#{sCreate}");
|
|
||||||
|
|
||||||
bool enabled = Settings::Manager::getBool("show enchant chance","Game");
|
|
||||||
|
|
||||||
mChanceLayout->setVisible(enabled);
|
|
||||||
|
|
||||||
mPtr = player;
|
|
||||||
startEditing();
|
|
||||||
|
|
||||||
setSoulGem(soulgem);
|
|
||||||
setItem(MWWorld::Ptr());
|
|
||||||
|
|
||||||
mPrice->setVisible(false);
|
|
||||||
mPriceText->setVisible(false);
|
|
||||||
updateLabels();
|
updateLabels();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnchantingDialog::onReferenceUnavailable ()
|
void EnchantingDialog::onReferenceUnavailable ()
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Dialogue);
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting);
|
||||||
resetReference();
|
resetReference();
|
||||||
}
|
}
|
||||||
|
@ -209,7 +190,7 @@ namespace MWGui
|
||||||
|
|
||||||
void EnchantingDialog::onCancelButtonClicked(MyGUI::Widget* sender)
|
void EnchantingDialog::onCancelButtonClicked(MyGUI::Widget* sender)
|
||||||
{
|
{
|
||||||
exit();
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Enchanting);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnchantingDialog::onSelectItem(MyGUI::Widget *sender)
|
void EnchantingDialog::onSelectItem(MyGUI::Widget *sender)
|
||||||
|
@ -304,6 +285,11 @@ namespace MWGui
|
||||||
updateEffectsView();
|
updateEffectsView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EnchantingDialog::onAccept(MyGUI::EditBox *sender)
|
||||||
|
{
|
||||||
|
onBuyButtonClicked(sender);
|
||||||
|
}
|
||||||
|
|
||||||
void EnchantingDialog::onBuyButtonClicked(MyGUI::Widget* sender)
|
void EnchantingDialog::onBuyButtonClicked(MyGUI::Widget* sender)
|
||||||
{
|
{
|
||||||
if (mEffects.size() <= 0)
|
if (mEffects.size() <= 0)
|
||||||
|
@ -364,7 +350,7 @@ namespace MWGui
|
||||||
MWBase::Environment::get().getMechanicsManager()->confiscateStolenItemToOwner(player, item, mPtr, 1);
|
MWBase::Environment::get().getMechanicsManager()->confiscateStolenItemToOwner(player, item, mPtr, 1);
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting);
|
||||||
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,15 +19,17 @@ namespace MWGui
|
||||||
EnchantingDialog();
|
EnchantingDialog();
|
||||||
virtual ~EnchantingDialog();
|
virtual ~EnchantingDialog();
|
||||||
|
|
||||||
virtual void open();
|
virtual void onOpen();
|
||||||
|
|
||||||
virtual void exit();
|
void onFrame(float dt) { checkReferenceAvailable(); }
|
||||||
|
void clear() { resetReference(); }
|
||||||
|
|
||||||
void setSoulGem (const MWWorld::Ptr& gem);
|
void setSoulGem (const MWWorld::Ptr& gem);
|
||||||
void setItem (const MWWorld::Ptr& item);
|
void setItem (const MWWorld::Ptr& item);
|
||||||
|
|
||||||
void startEnchanting(MWWorld::Ptr actor);
|
/// Actor Ptr: buy enchantment from this actor
|
||||||
void startSelfEnchanting(MWWorld::Ptr soulgem);
|
/// Soulgem Ptr: player self-enchant
|
||||||
|
void setPtr(const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
virtual void resetReference();
|
virtual void resetReference();
|
||||||
|
|
||||||
|
@ -46,6 +48,7 @@ namespace MWGui
|
||||||
void onBuyButtonClicked(MyGUI::Widget* sender);
|
void onBuyButtonClicked(MyGUI::Widget* sender);
|
||||||
void updateLabels();
|
void updateLabels();
|
||||||
void onTypeButtonClicked(MyGUI::Widget* sender);
|
void onTypeButtonClicked(MyGUI::Widget* sender);
|
||||||
|
void onAccept(MyGUI::EditBox* sender);
|
||||||
|
|
||||||
ItemSelectionDialog* mItemSelectionDialog;
|
ItemSelectionDialog* mItemSelectionDialog;
|
||||||
|
|
||||||
|
@ -58,7 +61,7 @@ namespace MWGui
|
||||||
MyGUI::Button* mTypeButton;
|
MyGUI::Button* mTypeButton;
|
||||||
MyGUI::Button* mBuyButton;
|
MyGUI::Button* mBuyButton;
|
||||||
|
|
||||||
MyGUI::TextBox* mName;
|
MyGUI::EditBox* mName;
|
||||||
MyGUI::TextBox* mEnchantmentPoints;
|
MyGUI::TextBox* mEnchantmentPoints;
|
||||||
MyGUI::TextBox* mCastCost;
|
MyGUI::TextBox* mCastCost;
|
||||||
MyGUI::TextBox* mCharge;
|
MyGUI::TextBox* mCharge;
|
||||||
|
|
|
@ -406,10 +406,11 @@ namespace MWGui
|
||||||
MyGUI::EditBox* box = parent->createWidget<MyGUI::EditBox>("NormalText",
|
MyGUI::EditBox* box = parent->createWidget<MyGUI::EditBox>("NormalText",
|
||||||
MyGUI::IntCoord(0, pag.getCurrentTop(), pag.getPageWidth(), 0), MyGUI::Align::Left | MyGUI::Align::Top,
|
MyGUI::IntCoord(0, pag.getCurrentTop(), pag.getPageWidth(), 0), MyGUI::Align::Left | MyGUI::Align::Top,
|
||||||
parent->getName() + MyGUI::utility::toString(parent->getChildCount()));
|
parent->getName() + MyGUI::utility::toString(parent->getChildCount()));
|
||||||
box->setProperty("Static", "true");
|
box->setEditStatic(true);
|
||||||
box->setProperty("MultiLine", "true");
|
box->setEditMultiLine(true);
|
||||||
box->setProperty("WordWrap", "true");
|
box->setEditWordWrap(true);
|
||||||
box->setProperty("NeedMouse", "false");
|
box->setNeedMouseFocus(false);
|
||||||
|
box->setNeedKeyFocus(false);
|
||||||
box->setMaxTextLength(text.size());
|
box->setMaxTextLength(text.size());
|
||||||
box->setTextAlign(mBlockStyle.mAlign);
|
box->setTextAlign(mBlockStyle.mAlign);
|
||||||
box->setTextColour(mTextStyle.mColour);
|
box->setTextColour(mTextStyle.mColour);
|
||||||
|
|
|
@ -108,7 +108,7 @@ namespace MWGui
|
||||||
|
|
||||||
|
|
||||||
HUD::HUD(CustomMarkerCollection &customMarkers, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender)
|
HUD::HUD(CustomMarkerCollection &customMarkers, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender)
|
||||||
: Layout("openmw_hud.layout")
|
: WindowBase("openmw_hud.layout")
|
||||||
, LocalMapBase(customMarkers, localMapRender, Settings::Manager::getBool("local map hud fog of war", "Map"))
|
, LocalMapBase(customMarkers, localMapRender, Settings::Manager::getBool("local map hud fog of war", "Map"))
|
||||||
, mHealth(NULL)
|
, mHealth(NULL)
|
||||||
, mMagicka(NULL)
|
, mMagicka(NULL)
|
||||||
|
@ -422,6 +422,20 @@ namespace MWGui
|
||||||
|
|
||||||
if (mIsDrowning)
|
if (mIsDrowning)
|
||||||
mDrowningFlashTheta += dt * osg::PI*2;
|
mDrowningFlashTheta += dt * osg::PI*2;
|
||||||
|
|
||||||
|
mSpellIcons->updateWidgets(mEffectBox, true);
|
||||||
|
|
||||||
|
if (mEnemyActorId != -1 && mEnemyHealth->getVisible())
|
||||||
|
{
|
||||||
|
updateEnemyHealthBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mIsDrowning)
|
||||||
|
{
|
||||||
|
float intensity = (cos(mDrowningFlashTheta) + 2.0f) / 3.0f;
|
||||||
|
|
||||||
|
mDrowningFlash->setAlpha(intensity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent)
|
void HUD::setSelectedSpell(const std::string& spellId, int successChancePercent)
|
||||||
|
@ -653,23 +667,6 @@ namespace MWGui
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HUD::update()
|
|
||||||
{
|
|
||||||
mSpellIcons->updateWidgets(mEffectBox, true);
|
|
||||||
|
|
||||||
if (mEnemyActorId != -1 && mEnemyHealth->getVisible())
|
|
||||||
{
|
|
||||||
updateEnemyHealthBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mIsDrowning)
|
|
||||||
{
|
|
||||||
float intensity = (cos(mDrowningFlashTheta) + 2.0f) / 3.0f;
|
|
||||||
|
|
||||||
mDrowningFlash->setAlpha(intensity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HUD::setEnemy(const MWWorld::Ptr &enemy)
|
void HUD::setEnemy(const MWWorld::Ptr &enemy)
|
||||||
{
|
{
|
||||||
mEnemyActorId = enemy.getClass().getCreatureStats(enemy).getActorId();
|
mEnemyActorId = enemy.getClass().getCreatureStats(enemy).getActorId();
|
||||||
|
@ -686,6 +683,13 @@ namespace MWGui
|
||||||
mEnemyHealthTimer = -1;
|
mEnemyHealthTimer = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HUD::clear()
|
||||||
|
{
|
||||||
|
unsetSelectedSpell();
|
||||||
|
unsetSelectedWeapon();
|
||||||
|
resetEnemy();
|
||||||
|
}
|
||||||
|
|
||||||
void HUD::customMarkerCreated(MyGUI::Widget *marker)
|
void HUD::customMarkerCreated(MyGUI::Widget *marker)
|
||||||
{
|
{
|
||||||
marker->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked);
|
marker->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked);
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace MWGui
|
||||||
class SpellIcons;
|
class SpellIcons;
|
||||||
class ItemWidget;
|
class ItemWidget;
|
||||||
|
|
||||||
class HUD : public Layout, public LocalMapBase
|
class HUD : public WindowBase, public LocalMapBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HUD(CustomMarkerCollection& customMarkers, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender);
|
HUD(CustomMarkerCollection& customMarkers, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender);
|
||||||
|
@ -55,11 +55,11 @@ namespace MWGui
|
||||||
|
|
||||||
MyGUI::Widget* getEffectBox() { return mEffectBox; }
|
MyGUI::Widget* getEffectBox() { return mEffectBox; }
|
||||||
|
|
||||||
void update();
|
|
||||||
|
|
||||||
void setEnemy(const MWWorld::Ptr& enemy);
|
void setEnemy(const MWWorld::Ptr& enemy);
|
||||||
void resetEnemy();
|
void resetEnemy();
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MyGUI::ProgressBar *mHealth, *mMagicka, *mStamina, *mEnemyHealth, *mDrowning;
|
MyGUI::ProgressBar *mHealth, *mMagicka, *mStamina, *mEnemyHealth, *mDrowning;
|
||||||
MyGUI::Widget* mHealthFrame;
|
MyGUI::Widget* mHealthFrame;
|
||||||
|
|
|
@ -377,7 +377,7 @@ namespace MWGui
|
||||||
dirtyPreview();
|
dirtyPreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryWindow::open()
|
void InventoryWindow::onOpen()
|
||||||
{
|
{
|
||||||
if (!mPtr.isEmpty())
|
if (!mPtr.isEmpty())
|
||||||
{
|
{
|
||||||
|
@ -603,11 +603,8 @@ namespace MWGui
|
||||||
mEncumbranceBar->setValue(static_cast<int>(encumbrance), static_cast<int>(capacity));
|
mEncumbranceBar->setValue(static_cast<int>(encumbrance), static_cast<int>(capacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryWindow::onFrame()
|
void InventoryWindow::onFrame(float dt)
|
||||||
{
|
{
|
||||||
if (!mMainWidget->getVisible())
|
|
||||||
return;
|
|
||||||
|
|
||||||
updateEncumbranceBar();
|
updateEncumbranceBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,12 +35,12 @@ namespace MWGui
|
||||||
public:
|
public:
|
||||||
InventoryWindow(DragAndDrop* dragAndDrop, osg::Group* parent, Resource::ResourceSystem* resourceSystem);
|
InventoryWindow(DragAndDrop* dragAndDrop, osg::Group* parent, Resource::ResourceSystem* resourceSystem);
|
||||||
|
|
||||||
virtual void open();
|
virtual void onOpen();
|
||||||
|
|
||||||
/// start trading, disables item drag&drop
|
/// start trading, disables item drag&drop
|
||||||
void setTrading(bool trading);
|
void setTrading(bool trading);
|
||||||
|
|
||||||
void onFrame();
|
void onFrame(float dt);
|
||||||
|
|
||||||
void pickUpObject (MWWorld::Ptr object);
|
void pickUpObject (MWWorld::Ptr object);
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,11 @@ namespace MWGui
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ItemModel::allowedToUseItems() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ItemModel::allowedToInsertItems() const
|
bool ItemModel::allowedToInsertItems() const
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -135,6 +140,11 @@ namespace MWGui
|
||||||
delete mSourceModel;
|
delete mSourceModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ProxyItemModel::allowedToUseItems() const
|
||||||
|
{
|
||||||
|
return mSourceModel->allowedToUseItems();
|
||||||
|
}
|
||||||
|
|
||||||
MWWorld::Ptr ProxyItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner)
|
MWWorld::Ptr ProxyItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner)
|
||||||
{
|
{
|
||||||
return mSourceModel->copyItem (item, count, setNewOwner);
|
return mSourceModel->copyItem (item, count, setNewOwner);
|
||||||
|
|
|
@ -70,6 +70,9 @@ namespace MWGui
|
||||||
virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false) = 0;
|
virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false) = 0;
|
||||||
virtual void removeItem (const ItemStack& item, size_t count) = 0;
|
virtual void removeItem (const ItemStack& item, size_t count) = 0;
|
||||||
|
|
||||||
|
/// Is the player allowed to use items from this item model? (default true)
|
||||||
|
virtual bool allowedToUseItems() const;
|
||||||
|
|
||||||
/// Is the player allowed to insert items into this model? (default true)
|
/// Is the player allowed to insert items into this model? (default true)
|
||||||
virtual bool allowedToInsertItems() const;
|
virtual bool allowedToInsertItems() const;
|
||||||
|
|
||||||
|
@ -85,6 +88,9 @@ namespace MWGui
|
||||||
public:
|
public:
|
||||||
ProxyItemModel();
|
ProxyItemModel();
|
||||||
virtual ~ProxyItemModel();
|
virtual ~ProxyItemModel();
|
||||||
|
|
||||||
|
bool allowedToUseItems() const;
|
||||||
|
|
||||||
virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false);
|
virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false);
|
||||||
virtual void removeItem (const ItemStack& item, size_t count);
|
virtual void removeItem (const ItemStack& item, size_t count);
|
||||||
virtual ModelIndex getIndex (ItemStack item);
|
virtual ModelIndex getIndex (ItemStack item);
|
||||||
|
|
|
@ -29,9 +29,10 @@ namespace MWGui
|
||||||
center();
|
center();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemSelectionDialog::exit()
|
bool ItemSelectionDialog::exit()
|
||||||
{
|
{
|
||||||
eventDialogCanceled();
|
eventDialogCanceled();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemSelectionDialog::openContainer(const MWWorld::Ptr& container)
|
void ItemSelectionDialog::openContainer(const MWWorld::Ptr& container)
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace MWGui
|
||||||
public:
|
public:
|
||||||
ItemSelectionDialog(const std::string& label);
|
ItemSelectionDialog(const std::string& label);
|
||||||
|
|
||||||
virtual void exit();
|
virtual bool exit();
|
||||||
|
|
||||||
typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void;
|
typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void;
|
||||||
typedef MyGUI::delegates::CMultiDelegate1<MWWorld::Ptr> EventHandle_Item;
|
typedef MyGUI::delegates::CMultiDelegate1<MWWorld::Ptr> EventHandle_Item;
|
||||||
|
|
|
@ -37,8 +37,6 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
getWidget(mProgressBar, "ProgressBar");
|
getWidget(mProgressBar, "ProgressBar");
|
||||||
|
|
||||||
setVisible(false);
|
|
||||||
|
|
||||||
mTimeAdvancer.eventProgressChanged += MyGUI::newDelegate(this, &JailScreen::onJailProgressChanged);
|
mTimeAdvancer.eventProgressChanged += MyGUI::newDelegate(this, &JailScreen::onJailProgressChanged);
|
||||||
mTimeAdvancer.eventFinished += MyGUI::newDelegate(this, &JailScreen::onJailFinished);
|
mTimeAdvancer.eventFinished += MyGUI::newDelegate(this, &JailScreen::onJailFinished);
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ namespace MWGui
|
||||||
|
|
||||||
void onFrame(float dt);
|
void onFrame(float dt);
|
||||||
|
|
||||||
|
bool exit() { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int mDays;
|
int mDays;
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <MyGUI_TextBox.h>
|
#include <MyGUI_TextBox.h>
|
||||||
#include <MyGUI_Button.h>
|
#include <MyGUI_Button.h>
|
||||||
|
#include <MyGUI_InputManager.h>
|
||||||
|
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
#include <components/widgets/imagebutton.hpp>
|
#include <components/widgets/imagebutton.hpp>
|
||||||
|
@ -44,7 +45,7 @@ namespace
|
||||||
static char const LeftTopicIndex [] = "LeftTopicIndex";
|
static char const LeftTopicIndex [] = "LeftTopicIndex";
|
||||||
static char const RightTopicIndex [] = "RightTopicIndex";
|
static char const RightTopicIndex [] = "RightTopicIndex";
|
||||||
|
|
||||||
struct JournalWindowImpl : MWGui::WindowBase, MWGui::JournalBooks, MWGui::JournalWindow
|
struct JournalWindowImpl : MWGui::JournalBooks, MWGui::JournalWindow
|
||||||
{
|
{
|
||||||
struct DisplayState
|
struct DisplayState
|
||||||
{
|
{
|
||||||
|
@ -84,19 +85,24 @@ namespace
|
||||||
|
|
||||||
void adviseButtonClick (char const * name, void (JournalWindowImpl::*Handler) (MyGUI::Widget* _sender))
|
void adviseButtonClick (char const * name, void (JournalWindowImpl::*Handler) (MyGUI::Widget* _sender))
|
||||||
{
|
{
|
||||||
getWidget <Gui::ImageButton> (name) ->
|
getWidget <MyGUI::Widget> (name) ->
|
||||||
eventMouseButtonClick += newDelegate(this, Handler);
|
eventMouseButtonClick += newDelegate(this, Handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void adviseKeyPress (char const * name, void (JournalWindowImpl::*Handler) (MyGUI::Widget* _sender, MyGUI::KeyCode key, MyGUI::Char character))
|
||||||
|
{
|
||||||
|
getWidget <MyGUI::Widget> (name) ->
|
||||||
|
eventKeyButtonPressed += newDelegate(this, Handler);
|
||||||
|
}
|
||||||
|
|
||||||
MWGui::BookPage* getPage (char const * name)
|
MWGui::BookPage* getPage (char const * name)
|
||||||
{
|
{
|
||||||
return getWidget <MWGui::BookPage> (name);
|
return getWidget <MWGui::BookPage> (name);
|
||||||
}
|
}
|
||||||
|
|
||||||
JournalWindowImpl (MWGui::JournalViewModel::Ptr Model, bool questList)
|
JournalWindowImpl (MWGui::JournalViewModel::Ptr Model, bool questList)
|
||||||
: WindowBase("openmw_journal.layout"), JournalBooks (Model)
|
: JournalBooks (Model), JournalWindow()
|
||||||
{
|
{
|
||||||
mMainWidget->setVisible(false);
|
|
||||||
center();
|
center();
|
||||||
|
|
||||||
adviseButtonClick (OptionsBTN, &JournalWindowImpl::notifyOptions );
|
adviseButtonClick (OptionsBTN, &JournalWindowImpl::notifyOptions );
|
||||||
|
@ -112,6 +118,12 @@ namespace
|
||||||
adviseButtonClick (ShowAllBTN, &JournalWindowImpl::notifyShowAll );
|
adviseButtonClick (ShowAllBTN, &JournalWindowImpl::notifyShowAll );
|
||||||
adviseButtonClick (ShowActiveBTN, &JournalWindowImpl::notifyShowActive);
|
adviseButtonClick (ShowActiveBTN, &JournalWindowImpl::notifyShowActive);
|
||||||
|
|
||||||
|
adviseKeyPress (OptionsBTN, &JournalWindowImpl::notifyKeyPress);
|
||||||
|
adviseKeyPress (PrevPageBTN, &JournalWindowImpl::notifyKeyPress);
|
||||||
|
adviseKeyPress (NextPageBTN, &JournalWindowImpl::notifyKeyPress);
|
||||||
|
adviseKeyPress (CloseBTN, &JournalWindowImpl::notifyKeyPress);
|
||||||
|
adviseKeyPress (JournalBTN, &JournalWindowImpl::notifyKeyPress);
|
||||||
|
|
||||||
Gui::MWList* list = getWidget<Gui::MWList>(QuestsList);
|
Gui::MWList* list = getWidget<Gui::MWList>(QuestsList);
|
||||||
list->eventItemSelected += MyGUI::newDelegate(this, &JournalWindowImpl::notifyQuestClicked);
|
list->eventItemSelected += MyGUI::newDelegate(this, &JournalWindowImpl::notifyQuestClicked);
|
||||||
|
|
||||||
|
@ -211,7 +223,7 @@ namespace
|
||||||
button->setPosition(button->getPosition() + MyGUI::IntPoint(diff.width,0));
|
button->setPosition(button->getPosition() + MyGUI::IntPoint(diff.width,0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void open()
|
void onOpen()
|
||||||
{
|
{
|
||||||
if (!MWBase::Environment::get().getWindowManager ()->getJournalAllowed ())
|
if (!MWBase::Environment::get().getWindowManager ()->getJournalAllowed ())
|
||||||
{
|
{
|
||||||
|
@ -238,9 +250,11 @@ namespace
|
||||||
--page;
|
--page;
|
||||||
}
|
}
|
||||||
updateShowingPages();
|
updateShowingPages();
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(getWidget<MyGUI::Widget>(CloseBTN));
|
||||||
}
|
}
|
||||||
|
|
||||||
void close()
|
void onClose()
|
||||||
{
|
{
|
||||||
mModel->unload ();
|
mModel->unload ();
|
||||||
|
|
||||||
|
@ -349,8 +363,19 @@ namespace
|
||||||
relPages = 0;
|
relPages = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
setVisible (PrevPageBTN, page > 0);
|
MyGUI::Widget* nextPageBtn = getWidget<MyGUI::Widget>(NextPageBTN);
|
||||||
setVisible (NextPageBTN, relPages > 2);
|
MyGUI::Widget* prevPageBtn = getWidget<MyGUI::Widget>(PrevPageBTN);
|
||||||
|
|
||||||
|
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||||
|
bool nextPageVisible = relPages > 2;
|
||||||
|
nextPageBtn->setVisible(nextPageVisible);
|
||||||
|
bool prevPageVisible = page > 0;
|
||||||
|
prevPageBtn->setVisible(prevPageVisible);
|
||||||
|
|
||||||
|
if (focus == nextPageBtn && !nextPageVisible && prevPageVisible)
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(prevPageBtn);
|
||||||
|
else if (focus == prevPageBtn && !prevPageVisible && nextPageVisible)
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(nextPageBtn);
|
||||||
|
|
||||||
setVisible (PageOneNum, relPages > 0);
|
setVisible (PageOneNum, relPages > 0);
|
||||||
setVisible (PageTwoNum, relPages > 1);
|
setVisible (PageTwoNum, relPages > 1);
|
||||||
|
@ -362,6 +387,14 @@ namespace
|
||||||
setText (PageTwoNum, page + 2);
|
setText (PageTwoNum, page + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void notifyKeyPress(MyGUI::Widget* sender, MyGUI::KeyCode key, MyGUI::Char character)
|
||||||
|
{
|
||||||
|
if (key == MyGUI::KeyCode::ArrowUp)
|
||||||
|
notifyPrevPage(sender);
|
||||||
|
else if (key == MyGUI::KeyCode::ArrowDown)
|
||||||
|
notifyNextPage(sender);
|
||||||
|
}
|
||||||
|
|
||||||
void notifyTopicClicked (intptr_t linkId)
|
void notifyTopicClicked (intptr_t linkId)
|
||||||
{
|
{
|
||||||
Book topicBook = createTopicBook (linkId);
|
Book topicBook = createTopicBook (linkId);
|
||||||
|
@ -603,3 +636,9 @@ MWGui::JournalWindow * MWGui::JournalWindow::create (JournalViewModel::Ptr Model
|
||||||
{
|
{
|
||||||
return new JournalWindowImpl (Model, questList);
|
return new JournalWindowImpl (Model, questList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MWGui::JournalWindow::JournalWindow()
|
||||||
|
:WindowBase("openmw_journal.layout")
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef MWGUI_JOURNAL_H
|
#ifndef MWGUI_JOURNAL_H
|
||||||
#define MWGUI_JOURNAL_H
|
#define MWGUI_JOURNAL_H
|
||||||
|
|
||||||
|
#include "windowbase.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace MWBase { class WindowManager; }
|
namespace MWBase { class WindowManager; }
|
||||||
|
@ -9,8 +11,10 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
struct JournalViewModel;
|
struct JournalViewModel;
|
||||||
|
|
||||||
struct JournalWindow
|
struct JournalWindow : public WindowBase
|
||||||
{
|
{
|
||||||
|
JournalWindow();
|
||||||
|
|
||||||
/// construct a new instance of the one JournalWindow implementation
|
/// construct a new instance of the one JournalWindow implementation
|
||||||
static JournalWindow * create (std::shared_ptr <JournalViewModel> Model, bool questList);
|
static JournalWindow * create (std::shared_ptr <JournalViewModel> Model, bool questList);
|
||||||
|
|
||||||
|
|
283
apps/openmw/mwgui/keyboardnavigation.cpp
Normal file
283
apps/openmw/mwgui/keyboardnavigation.cpp
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
#include "keyboardnavigation.hpp"
|
||||||
|
|
||||||
|
#include <MyGUI_InputManager.h>
|
||||||
|
#include <MyGUI_WidgetManager.h>
|
||||||
|
#include <MyGUI_Button.h>
|
||||||
|
#include <MyGUI_Gui.h>
|
||||||
|
#include <MyGUI_Window.h>
|
||||||
|
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
|
||||||
|
namespace MWGui
|
||||||
|
{
|
||||||
|
|
||||||
|
bool shouldAcceptKeyFocus(MyGUI::Widget* w)
|
||||||
|
{
|
||||||
|
return w && !w->castType<MyGUI::Window>(false) && w->getInheritedEnabled() && w->getInheritedVisible() && w->getVisible() && w->getEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Recursively get all child widgets that accept keyboard input
|
||||||
|
void getKeyFocusWidgets(MyGUI::Widget* parent, std::vector<MyGUI::Widget*>& results)
|
||||||
|
{
|
||||||
|
if (!parent->getVisible() || !parent->getEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
MyGUI::EnumeratorWidgetPtr enumerator = parent->getEnumerator();
|
||||||
|
while (enumerator.next())
|
||||||
|
{
|
||||||
|
MyGUI::Widget* w = enumerator.current();
|
||||||
|
if (!w->getVisible() || !w->getEnabled())
|
||||||
|
continue;
|
||||||
|
if (w->getNeedKeyFocus() && shouldAcceptKeyFocus(w))
|
||||||
|
results.push_back(w);
|
||||||
|
else
|
||||||
|
getKeyFocusWidgets(w, results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyboardNavigation::KeyboardNavigation()
|
||||||
|
: mCurrentFocus(nullptr)
|
||||||
|
, mModalWindow(nullptr)
|
||||||
|
{
|
||||||
|
MyGUI::WidgetManager::getInstance().registerUnlinker(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyboardNavigation::~KeyboardNavigation()
|
||||||
|
{
|
||||||
|
MyGUI::WidgetManager::getInstance().unregisterUnlinker(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardNavigation::saveFocus(int mode)
|
||||||
|
{
|
||||||
|
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||||
|
if (shouldAcceptKeyFocus(focus))
|
||||||
|
{
|
||||||
|
mKeyFocus[mode] = focus;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mKeyFocus[mode] = mCurrentFocus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardNavigation::restoreFocus(int mode)
|
||||||
|
{
|
||||||
|
std::map<int, MyGUI::Widget*>::const_iterator found = mKeyFocus.find(mode);
|
||||||
|
if (found != mKeyFocus.end())
|
||||||
|
{
|
||||||
|
MyGUI::Widget* w = found->second;
|
||||||
|
if (w && w->getVisible() && w->getEnabled())
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(found->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardNavigation::_unlinkWidget(MyGUI::Widget *widget)
|
||||||
|
{
|
||||||
|
for (std::pair<const int, MyGUI::Widget*>& w : mKeyFocus)
|
||||||
|
if (w.second == widget)
|
||||||
|
w.second = nullptr;
|
||||||
|
if (widget == mCurrentFocus)
|
||||||
|
mCurrentFocus = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void styleFocusedButton(MyGUI::Widget* w)
|
||||||
|
{
|
||||||
|
if (w)
|
||||||
|
{
|
||||||
|
if (MyGUI::Button* b = w->castType<MyGUI::Button>(false))
|
||||||
|
{
|
||||||
|
b->_setWidgetState("highlighted");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isRootParent(MyGUI::Widget* widget, MyGUI::Widget* root)
|
||||||
|
{
|
||||||
|
while (widget && widget->getParent())
|
||||||
|
widget = widget->getParent();
|
||||||
|
return widget == root;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardNavigation::onFrame()
|
||||||
|
{
|
||||||
|
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||||
|
|
||||||
|
if (focus == mCurrentFocus)
|
||||||
|
{
|
||||||
|
styleFocusedButton(mCurrentFocus);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// workaround incorrect key focus resets (fix in MyGUI TBD)
|
||||||
|
if (!shouldAcceptKeyFocus(focus) && shouldAcceptKeyFocus(mCurrentFocus) && (!mModalWindow || isRootParent(mCurrentFocus, mModalWindow)))
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCurrentFocus);
|
||||||
|
focus = mCurrentFocus;
|
||||||
|
}
|
||||||
|
|
||||||
|
// style highlighted button (won't be needed for MyGUI 3.2.3)
|
||||||
|
if (focus != mCurrentFocus)
|
||||||
|
{
|
||||||
|
if (mCurrentFocus)
|
||||||
|
{
|
||||||
|
if (MyGUI::Button* b = mCurrentFocus->castType<MyGUI::Button>(false))
|
||||||
|
b->_setWidgetState("normal");
|
||||||
|
}
|
||||||
|
|
||||||
|
mCurrentFocus = focus;
|
||||||
|
}
|
||||||
|
|
||||||
|
styleFocusedButton(mCurrentFocus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardNavigation::setDefaultFocus(MyGUI::Widget *window, MyGUI::Widget *defaultFocus)
|
||||||
|
{
|
||||||
|
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||||
|
if (!focus || !shouldAcceptKeyFocus(focus))
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(defaultFocus);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!isRootParent(focus, window))
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(defaultFocus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardNavigation::setModalWindow(MyGUI::Widget *window)
|
||||||
|
{
|
||||||
|
mModalWindow = window;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Direction
|
||||||
|
{
|
||||||
|
D_Left,
|
||||||
|
D_Up,
|
||||||
|
D_Right,
|
||||||
|
D_Down,
|
||||||
|
D_Next,
|
||||||
|
D_Prev
|
||||||
|
};
|
||||||
|
|
||||||
|
bool KeyboardNavigation::injectKeyPress(MyGUI::KeyCode key, unsigned int text)
|
||||||
|
{
|
||||||
|
switch (key.getValue())
|
||||||
|
{
|
||||||
|
case MyGUI::KeyCode::ArrowLeft:
|
||||||
|
return switchFocus(D_Left, false);
|
||||||
|
case MyGUI::KeyCode::ArrowRight:
|
||||||
|
return switchFocus(D_Right, false);
|
||||||
|
case MyGUI::KeyCode::ArrowUp:
|
||||||
|
return switchFocus(D_Up, false);
|
||||||
|
case MyGUI::KeyCode::ArrowDown:
|
||||||
|
return switchFocus(D_Down, false);
|
||||||
|
case MyGUI::KeyCode::Tab:
|
||||||
|
return switchFocus(MyGUI::InputManager::getInstance().isShiftPressed() ? D_Prev : D_Next, true);
|
||||||
|
case MyGUI::KeyCode::Return:
|
||||||
|
case MyGUI::KeyCode::NumpadEnter:
|
||||||
|
case MyGUI::KeyCode::Space:
|
||||||
|
return accept();
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KeyboardNavigation::switchFocus(int direction, bool wrap)
|
||||||
|
{
|
||||||
|
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||||
|
|
||||||
|
bool isCycle = (direction == D_Prev || direction == D_Next);
|
||||||
|
|
||||||
|
if ((focus && focus->getTypeName().find("Button") == std::string::npos) && !isCycle)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (focus && isCycle && focus->getUserString("AcceptTab") == "true")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((!focus || !focus->getNeedKeyFocus()) && isCycle)
|
||||||
|
{
|
||||||
|
// if nothing is selected, select the first widget
|
||||||
|
return selectFirstWidget();
|
||||||
|
}
|
||||||
|
if (!focus)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MyGUI::Widget* window = focus;
|
||||||
|
while (window && window->getParent())
|
||||||
|
window = window->getParent();
|
||||||
|
MyGUI::VectorWidgetPtr keyFocusList;
|
||||||
|
getKeyFocusWidgets(window, keyFocusList);
|
||||||
|
|
||||||
|
if (keyFocusList.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MyGUI::VectorWidgetPtr::iterator found = std::find(keyFocusList.begin(), keyFocusList.end(), focus);
|
||||||
|
if (found == keyFocusList.end())
|
||||||
|
{
|
||||||
|
if (isCycle)
|
||||||
|
return selectFirstWidget();
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool forward = (direction == D_Next || direction == D_Right || direction == D_Down);
|
||||||
|
|
||||||
|
int index = found - keyFocusList.begin();
|
||||||
|
index = forward ? (index+1) : (index-1);
|
||||||
|
if (wrap)
|
||||||
|
index = (index + keyFocusList.size())%keyFocusList.size();
|
||||||
|
else
|
||||||
|
index = std::min(std::max(0, index), static_cast<int>(keyFocusList.size())-1);
|
||||||
|
|
||||||
|
MyGUI::Widget* next = keyFocusList[index];
|
||||||
|
int vertdiff = next->getTop() - focus->getTop();
|
||||||
|
int horizdiff = next->getLeft() - focus->getLeft();
|
||||||
|
bool isVertical = std::abs(vertdiff) > std::abs(horizdiff);
|
||||||
|
if (direction == D_Right && (horizdiff <= 0 || isVertical))
|
||||||
|
return false;
|
||||||
|
else if (direction == D_Left && (horizdiff >= 0 || isVertical))
|
||||||
|
return false;
|
||||||
|
else if (direction == D_Down && (vertdiff <= 0 || !isVertical))
|
||||||
|
return false;
|
||||||
|
else if (direction == D_Up && (vertdiff >= 0 || !isVertical))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(keyFocusList[index]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KeyboardNavigation::selectFirstWidget()
|
||||||
|
{
|
||||||
|
MyGUI::VectorWidgetPtr keyFocusList;
|
||||||
|
MyGUI::EnumeratorWidgetPtr enumerator = MyGUI::Gui::getInstance().getEnumerator();
|
||||||
|
if (mModalWindow)
|
||||||
|
enumerator = mModalWindow->getEnumerator();
|
||||||
|
while (enumerator.next())
|
||||||
|
getKeyFocusWidgets(enumerator.current(), keyFocusList);
|
||||||
|
|
||||||
|
if (!keyFocusList.empty())
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(keyFocusList[0]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KeyboardNavigation::accept()
|
||||||
|
{
|
||||||
|
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||||
|
if (!focus)
|
||||||
|
return false;
|
||||||
|
//MyGUI::Button* button = focus->castType<MyGUI::Button>(false);
|
||||||
|
//if (button && button->getEnabled())
|
||||||
|
if (focus->getTypeName().find("Button") != std::string::npos && focus->getEnabled())
|
||||||
|
{
|
||||||
|
focus->eventMouseButtonClick(focus);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
47
apps/openmw/mwgui/keyboardnavigation.hpp
Normal file
47
apps/openmw/mwgui/keyboardnavigation.hpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef OPENMW_MWGUI_KEYBOARDNAVIGATION_H
|
||||||
|
#define OPENMW_MWGUI_KEYBOARDNAVIGATION_H
|
||||||
|
|
||||||
|
#include <MyGUI_KeyCode.h>
|
||||||
|
#include <MyGUI_IUnlinkWidget.h>
|
||||||
|
|
||||||
|
namespace MWGui
|
||||||
|
{
|
||||||
|
|
||||||
|
class KeyboardNavigation : public MyGUI::IUnlinkWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KeyboardNavigation();
|
||||||
|
~KeyboardNavigation();
|
||||||
|
|
||||||
|
/// @return Was the key handled by this class?
|
||||||
|
bool injectKeyPress(MyGUI::KeyCode key, unsigned int text);
|
||||||
|
|
||||||
|
void saveFocus(int mode);
|
||||||
|
void restoreFocus(int mode);
|
||||||
|
|
||||||
|
void _unlinkWidget(MyGUI::Widget* widget);
|
||||||
|
|
||||||
|
void onFrame();
|
||||||
|
|
||||||
|
/// Set a key focus widget for this window, if one isn't already set.
|
||||||
|
void setDefaultFocus(MyGUI::Widget* window, MyGUI::Widget* defaultFocus);
|
||||||
|
|
||||||
|
void setModalWindow(MyGUI::Widget* window);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool switchFocus(int direction, bool wrap);
|
||||||
|
|
||||||
|
bool selectFirstWidget();
|
||||||
|
|
||||||
|
/// Send button press event to focused button
|
||||||
|
bool accept();
|
||||||
|
|
||||||
|
std::map<int, MyGUI::Widget*> mKeyFocus;
|
||||||
|
|
||||||
|
MyGUI::Widget* mCurrentFocus;
|
||||||
|
MyGUI::Widget* mModalWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -41,6 +41,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
MyGUI::TextBox* t;
|
MyGUI::TextBox* t;
|
||||||
getWidget(t, "AttribVal" + MyGUI::utility::toString(i));
|
getWidget(t, "AttribVal" + MyGUI::utility::toString(i));
|
||||||
|
mAttributeValues.push_back(t);
|
||||||
|
|
||||||
MyGUI::Button* b;
|
MyGUI::Button* b;
|
||||||
getWidget(b, "Attrib" + MyGUI::utility::toString(i));
|
getWidget(b, "Attrib" + MyGUI::utility::toString(i));
|
||||||
|
@ -48,10 +49,7 @@ namespace MWGui
|
||||||
b->eventMouseButtonClick += MyGUI::newDelegate(this, &LevelupDialog::onAttributeClicked);
|
b->eventMouseButtonClick += MyGUI::newDelegate(this, &LevelupDialog::onAttributeClicked);
|
||||||
mAttributes.push_back(b);
|
mAttributes.push_back(b);
|
||||||
|
|
||||||
mAttributeValues.push_back(t);
|
|
||||||
|
|
||||||
getWidget(t, "AttribMultiplier" + MyGUI::utility::toString(i));
|
getWidget(t, "AttribMultiplier" + MyGUI::utility::toString(i));
|
||||||
|
|
||||||
mAttributeMultipliers.push_back(t);
|
mAttributeMultipliers.push_back(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +126,7 @@ namespace MWGui
|
||||||
setAttributeValues();
|
setAttributeValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelupDialog::open()
|
void LevelupDialog::onOpen()
|
||||||
{
|
{
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
MWWorld::Ptr player = world->getPlayerPtr();
|
MWWorld::Ptr player = world->getPlayerPtr();
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace MWGui
|
||||||
public:
|
public:
|
||||||
LevelupDialog();
|
LevelupDialog();
|
||||||
|
|
||||||
virtual void open();
|
virtual void onOpen();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MyGUI::Button* mOkButton;
|
MyGUI::Button* mOkButton;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue