mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-27 03:35:27 +00:00
Merge branch 'master' of https://github.com/OpenMW/openmw.git into QtOGre
This commit is contained in:
commit
875daed4ec
@ -12,7 +12,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
|
|||||||
message(STATUS "Configuring OpenMW...")
|
message(STATUS "Configuring OpenMW...")
|
||||||
|
|
||||||
set(OPENMW_VERSION_MAJOR 0)
|
set(OPENMW_VERSION_MAJOR 0)
|
||||||
set(OPENMW_VERSION_MINOR 30)
|
set(OPENMW_VERSION_MINOR 31)
|
||||||
set(OPENMW_VERSION_RELEASE 0)
|
set(OPENMW_VERSION_RELEASE 0)
|
||||||
|
|
||||||
set(OPENMW_VERSION_COMMITHASH "")
|
set(OPENMW_VERSION_COMMITHASH "")
|
||||||
|
@ -18,13 +18,13 @@ opencs_hdrs_noqt (model/doc
|
|||||||
|
|
||||||
|
|
||||||
opencs_units (model/world
|
opencs_units (model/world
|
||||||
idtable idtableproxymodel regionmap data commanddispatcher
|
idtable idtableproxymodel regionmap data commanddispatcher idtablebase resourcetable
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
opencs_units_noqt (model/world
|
opencs_units_noqt (model/world
|
||||||
universalid record commands columnbase scriptcontext cell refidcollection
|
universalid record commands columnbase scriptcontext cell refidcollection
|
||||||
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection
|
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_hdrs_noqt (model/world
|
opencs_hdrs_noqt (model/world
|
||||||
@ -59,8 +59,17 @@ opencs_hdrs_noqt (view/doc
|
|||||||
|
|
||||||
opencs_units (view/world
|
opencs_units (view/world
|
||||||
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
|
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
|
||||||
cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool
|
cellcreator referenceablecreator referencecreator scenesubview
|
||||||
scenetoolmode infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable
|
infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable
|
||||||
|
)
|
||||||
|
|
||||||
|
opencs_units_noqt (view/world
|
||||||
|
subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
|
||||||
|
scripthighlighter idvalidator dialoguecreator
|
||||||
|
)
|
||||||
|
|
||||||
|
opencs_units (view/widget
|
||||||
|
scenetoolbar scenetool scenetoolmode pushbutton
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units (view/render
|
opencs_units (view/render
|
||||||
@ -73,11 +82,6 @@ opencs_units_noqt (view/render
|
|||||||
lightingbright object cell
|
lightingbright object cell
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units_noqt (view/world
|
|
||||||
subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
|
|
||||||
scripthighlighter idvalidator dialoguecreator
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
opencs_units (view/tools
|
opencs_units (view/tools
|
||||||
reportsubview
|
reportsubview
|
||||||
|
@ -35,6 +35,8 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
|
|||||||
Bsa::registerResources (Files::Collections (config.first, !mFsStrict), config.second, true,
|
Bsa::registerResources (Files::Collections (config.first, !mFsStrict), config.second, true,
|
||||||
mFsStrict);
|
mFsStrict);
|
||||||
|
|
||||||
|
mDocumentManager.listResources();
|
||||||
|
|
||||||
mNewGame.setLocalData (mLocal);
|
mNewGame.setLocalData (mLocal);
|
||||||
mFileDialog.setLocalData (mLocal);
|
mFileDialog.setLocalData (mLocal);
|
||||||
|
|
||||||
|
@ -2205,9 +2205,9 @@ void CSMDoc::Document::createBase()
|
|||||||
CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
||||||
const std::vector< boost::filesystem::path >& files, bool new_,
|
const std::vector< boost::filesystem::path >& files, bool new_,
|
||||||
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
|
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
|
||||||
ToUTF8::FromType encoding)
|
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager)
|
||||||
: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding), mTools (mData),
|
: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, resourcesManager),
|
||||||
mResDir(resDir),
|
mTools (mData), mResDir(resDir),
|
||||||
mProjectPath ((configuration.getUserDataPath() / "projects") /
|
mProjectPath ((configuration.getUserDataPath() / "projects") /
|
||||||
(savePath.filename().string() + ".project")),
|
(savePath.filename().string() + ".project")),
|
||||||
mSaving (*this, mProjectPath, encoding)
|
mSaving (*this, mProjectPath, encoding)
|
||||||
|
@ -31,6 +31,11 @@ namespace Files
|
|||||||
class ConfigurationManager;
|
class ConfigurationManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class ResourcesManager;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CSMDoc
|
namespace CSMDoc
|
||||||
{
|
{
|
||||||
class Document : public QObject
|
class Document : public QObject
|
||||||
@ -73,7 +78,7 @@ namespace CSMDoc
|
|||||||
Document (const Files::ConfigurationManager& configuration,
|
Document (const Files::ConfigurationManager& configuration,
|
||||||
const std::vector< boost::filesystem::path >& files, bool new_,
|
const std::vector< boost::filesystem::path >& files, bool new_,
|
||||||
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
|
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
|
||||||
ToUTF8::FromType encoding);
|
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager);
|
||||||
|
|
||||||
~Document();
|
~Document();
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ CSMDoc::DocumentManager::~DocumentManager()
|
|||||||
void CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files, const boost::filesystem::path& savePath,
|
void CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files, const boost::filesystem::path& savePath,
|
||||||
bool new_)
|
bool new_)
|
||||||
{
|
{
|
||||||
Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding);
|
Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager);
|
||||||
|
|
||||||
mDocuments.push_back (document);
|
mDocuments.push_back (document);
|
||||||
|
|
||||||
@ -85,6 +85,11 @@ void CSMDoc::DocumentManager::setEncoding (ToUTF8::FromType encoding)
|
|||||||
mEncoding = encoding;
|
mEncoding = encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMDoc::DocumentManager::listResources()
|
||||||
|
{
|
||||||
|
mResourcesManager.listResources();
|
||||||
|
}
|
||||||
|
|
||||||
void CSMDoc::DocumentManager::documentLoaded (Document *document)
|
void CSMDoc::DocumentManager::documentLoaded (Document *document)
|
||||||
{
|
{
|
||||||
emit documentAdded (document);
|
emit documentAdded (document);
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include <components/to_utf8/to_utf8.hpp>
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
|
#include "../world/resourcesmanager.hpp"
|
||||||
|
|
||||||
#include "loader.hpp"
|
#include "loader.hpp"
|
||||||
|
|
||||||
namespace Files
|
namespace Files
|
||||||
@ -31,6 +33,7 @@ namespace CSMDoc
|
|||||||
QThread mLoaderThread;
|
QThread mLoaderThread;
|
||||||
Loader mLoader;
|
Loader mLoader;
|
||||||
ToUTF8::FromType mEncoding;
|
ToUTF8::FromType mEncoding;
|
||||||
|
CSMWorld::ResourcesManager mResourcesManager;
|
||||||
|
|
||||||
DocumentManager (const DocumentManager&);
|
DocumentManager (const DocumentManager&);
|
||||||
DocumentManager& operator= (const DocumentManager&);
|
DocumentManager& operator= (const DocumentManager&);
|
||||||
@ -50,6 +53,9 @@ namespace CSMDoc
|
|||||||
|
|
||||||
void setEncoding (ToUTF8::FromType encoding);
|
void setEncoding (ToUTF8::FromType encoding);
|
||||||
|
|
||||||
|
/// Ask OGRE for a list of available resources.
|
||||||
|
void listResources();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
boost::filesystem::path mResDir;
|
boost::filesystem::path mResDir;
|
||||||
|
@ -7,7 +7,7 @@ CSMFilter::AndNode::AndNode (const std::vector<boost::shared_ptr<Node> >& nodes)
|
|||||||
: NAryNode (nodes, "and")
|
: NAryNode (nodes, "and")
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool CSMFilter::AndNode::test (const CSMWorld::IdTable& table, int row,
|
bool CSMFilter::AndNode::test (const CSMWorld::IdTableBase& table, int row,
|
||||||
const std::map<int, int>& columns) const
|
const std::map<int, int>& columns) const
|
||||||
{
|
{
|
||||||
int size = getSize();
|
int size = getSize();
|
||||||
|
@ -11,7 +11,7 @@ namespace CSMFilter
|
|||||||
|
|
||||||
AndNode (const std::vector<boost::shared_ptr<Node> >& nodes);
|
AndNode (const std::vector<boost::shared_ptr<Node> >& nodes);
|
||||||
|
|
||||||
virtual bool test (const CSMWorld::IdTable& table, int row,
|
virtual bool test (const CSMWorld::IdTableBase& table, int row,
|
||||||
const std::map<int, int>& columns) const;
|
const std::map<int, int>& columns) const;
|
||||||
///< \return Can the specified table row pass through to filter?
|
///< \return Can the specified table row pass through to filter?
|
||||||
/// \param columns column ID to column index mapping
|
/// \param columns column ID to column index mapping
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
CSMFilter::BooleanNode::BooleanNode (bool true_) : mTrue (true_) {}
|
CSMFilter::BooleanNode::BooleanNode (bool true_) : mTrue (true_) {}
|
||||||
|
|
||||||
bool CSMFilter::BooleanNode::test (const CSMWorld::IdTable& table, int row,
|
bool CSMFilter::BooleanNode::test (const CSMWorld::IdTableBase& table, int row,
|
||||||
const std::map<int, int>& columns) const
|
const std::map<int, int>& columns) const
|
||||||
{
|
{
|
||||||
return mTrue;
|
return mTrue;
|
||||||
|
@ -13,7 +13,7 @@ namespace CSMFilter
|
|||||||
|
|
||||||
BooleanNode (bool true_);
|
BooleanNode (bool true_);
|
||||||
|
|
||||||
virtual bool test (const CSMWorld::IdTable& table, int row,
|
virtual bool test (const CSMWorld::IdTableBase& table, int row,
|
||||||
const std::map<int, int>& columns) const;
|
const std::map<int, int>& columns) const;
|
||||||
///< \return Can the specified table row pass through to filter?
|
///< \return Can the specified table row pass through to filter?
|
||||||
/// \param columns column ID to column index mapping
|
/// \param columns column ID to column index mapping
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
class IdTable;
|
class IdTableBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace CSMFilter
|
namespace CSMFilter
|
||||||
@ -32,7 +32,7 @@ namespace CSMFilter
|
|||||||
|
|
||||||
virtual ~Node();
|
virtual ~Node();
|
||||||
|
|
||||||
virtual bool test (const CSMWorld::IdTable& table, int row,
|
virtual bool test (const CSMWorld::IdTableBase& table, int row,
|
||||||
const std::map<int, int>& columns) const = 0;
|
const std::map<int, int>& columns) const = 0;
|
||||||
///< \return Can the specified table row pass through to filter?
|
///< \return Can the specified table row pass through to filter?
|
||||||
/// \param columns column ID to column index mapping
|
/// \param columns column ID to column index mapping
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
CSMFilter::NotNode::NotNode (boost::shared_ptr<Node> child) : UnaryNode (child, "not") {}
|
CSMFilter::NotNode::NotNode (boost::shared_ptr<Node> child) : UnaryNode (child, "not") {}
|
||||||
|
|
||||||
bool CSMFilter::NotNode::test (const CSMWorld::IdTable& table, int row,
|
bool CSMFilter::NotNode::test (const CSMWorld::IdTableBase& table, int row,
|
||||||
const std::map<int, int>& columns) const
|
const std::map<int, int>& columns) const
|
||||||
{
|
{
|
||||||
return !getChild().test (table, row, columns);
|
return !getChild().test (table, row, columns);
|
||||||
|
@ -11,7 +11,7 @@ namespace CSMFilter
|
|||||||
|
|
||||||
NotNode (boost::shared_ptr<Node> child);
|
NotNode (boost::shared_ptr<Node> child);
|
||||||
|
|
||||||
virtual bool test (const CSMWorld::IdTable& table, int row,
|
virtual bool test (const CSMWorld::IdTableBase& table, int row,
|
||||||
const std::map<int, int>& columns) const;
|
const std::map<int, int>& columns) const;
|
||||||
///< \return Can the specified table row pass through to filter?
|
///< \return Can the specified table row pass through to filter?
|
||||||
/// \param columns column ID to column index mapping
|
/// \param columns column ID to column index mapping
|
||||||
|
@ -7,7 +7,7 @@ CSMFilter::OrNode::OrNode (const std::vector<boost::shared_ptr<Node> >& nodes)
|
|||||||
: NAryNode (nodes, "or")
|
: NAryNode (nodes, "or")
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool CSMFilter::OrNode::test (const CSMWorld::IdTable& table, int row,
|
bool CSMFilter::OrNode::test (const CSMWorld::IdTableBase& table, int row,
|
||||||
const std::map<int, int>& columns) const
|
const std::map<int, int>& columns) const
|
||||||
{
|
{
|
||||||
int size = getSize();
|
int size = getSize();
|
||||||
|
@ -11,7 +11,7 @@ namespace CSMFilter
|
|||||||
|
|
||||||
OrNode (const std::vector<boost::shared_ptr<Node> >& nodes);
|
OrNode (const std::vector<boost::shared_ptr<Node> >& nodes);
|
||||||
|
|
||||||
virtual bool test (const CSMWorld::IdTable& table, int row,
|
virtual bool test (const CSMWorld::IdTableBase& table, int row,
|
||||||
const std::map<int, int>& columns) const;
|
const std::map<int, int>& columns) const;
|
||||||
///< \return Can the specified table row pass through to filter?
|
///< \return Can the specified table row pass through to filter?
|
||||||
/// \param columns column ID to column index mapping
|
/// \param columns column ID to column index mapping
|
||||||
|
@ -7,13 +7,13 @@
|
|||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
|
|
||||||
#include "../world/columns.hpp"
|
#include "../world/columns.hpp"
|
||||||
#include "../world/idtable.hpp"
|
#include "../world/idtablebase.hpp"
|
||||||
|
|
||||||
CSMFilter::TextNode::TextNode (int columnId, const std::string& text)
|
CSMFilter::TextNode::TextNode (int columnId, const std::string& text)
|
||||||
: mColumnId (columnId), mText (text)
|
: mColumnId (columnId), mText (text)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool CSMFilter::TextNode::test (const CSMWorld::IdTable& table, int row,
|
bool CSMFilter::TextNode::test (const CSMWorld::IdTableBase& table, int row,
|
||||||
const std::map<int, int>& columns) const
|
const std::map<int, int>& columns) const
|
||||||
{
|
{
|
||||||
const std::map<int, int>::const_iterator iter = columns.find (mColumnId);
|
const std::map<int, int>::const_iterator iter = columns.find (mColumnId);
|
||||||
|
@ -14,7 +14,7 @@ namespace CSMFilter
|
|||||||
|
|
||||||
TextNode (int columnId, const std::string& text);
|
TextNode (int columnId, const std::string& text);
|
||||||
|
|
||||||
virtual bool test (const CSMWorld::IdTable& table, int row,
|
virtual bool test (const CSMWorld::IdTableBase& table, int row,
|
||||||
const std::map<int, int>& columns) const;
|
const std::map<int, int>& columns) const;
|
||||||
///< \return Can the specified table row pass through to filter?
|
///< \return Can the specified table row pass through to filter?
|
||||||
/// \param columns column ID to column index mapping
|
/// \param columns column ID to column index mapping
|
||||||
|
@ -5,13 +5,13 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "../world/columns.hpp"
|
#include "../world/columns.hpp"
|
||||||
#include "../world/idtable.hpp"
|
#include "../world/idtablebase.hpp"
|
||||||
|
|
||||||
CSMFilter::ValueNode::ValueNode (int columnId, Type lowerType, Type upperType,
|
CSMFilter::ValueNode::ValueNode (int columnId, Type lowerType, Type upperType,
|
||||||
double lower, double upper)
|
double lower, double upper)
|
||||||
: mColumnId (columnId), mLowerType (lowerType), mUpperType (upperType), mLower (lower), mUpper (upper){}
|
: mColumnId (columnId), mLowerType (lowerType), mUpperType (upperType), mLower (lower), mUpper (upper){}
|
||||||
|
|
||||||
bool CSMFilter::ValueNode::test (const CSMWorld::IdTable& table, int row,
|
bool CSMFilter::ValueNode::test (const CSMWorld::IdTableBase& table, int row,
|
||||||
const std::map<int, int>& columns) const
|
const std::map<int, int>& columns) const
|
||||||
{
|
{
|
||||||
const std::map<int, int>::const_iterator iter = columns.find (mColumnId);
|
const std::map<int, int>::const_iterator iter = columns.find (mColumnId);
|
||||||
|
@ -27,7 +27,7 @@ namespace CSMFilter
|
|||||||
|
|
||||||
ValueNode (int columnId, Type lowerType, Type upperType, double lower, double upper);
|
ValueNode (int columnId, Type lowerType, Type upperType, double lower, double upper);
|
||||||
|
|
||||||
virtual bool test (const CSMWorld::IdTable& table, int row,
|
virtual bool test (const CSMWorld::IdTableBase& table, int row,
|
||||||
const std::map<int, int>& columns) const;
|
const std::map<int, int>& columns) const;
|
||||||
///< \return Can the specified table row pass through to filter?
|
///< \return Can the specified table row pass through to filter?
|
||||||
/// \param columns column ID to column index mapping
|
/// \param columns column ID to column index mapping
|
||||||
|
@ -92,7 +92,14 @@ namespace CSMWorld
|
|||||||
Display_EnchantmentType,
|
Display_EnchantmentType,
|
||||||
Display_BodyPartType,
|
Display_BodyPartType,
|
||||||
Display_MeshType,
|
Display_MeshType,
|
||||||
Display_Gender
|
Display_Gender,
|
||||||
|
Display_Mesh,
|
||||||
|
Display_Icon,
|
||||||
|
Display_Music,
|
||||||
|
Display_SoundRes,
|
||||||
|
Display_Texture,
|
||||||
|
Display_Video,
|
||||||
|
Display_Colour
|
||||||
};
|
};
|
||||||
|
|
||||||
int mColumnId;
|
int mColumnId;
|
||||||
|
@ -604,7 +604,7 @@ namespace CSMWorld
|
|||||||
struct SoundFileColumn : public Column<ESXRecordT>
|
struct SoundFileColumn : public Column<ESXRecordT>
|
||||||
{
|
{
|
||||||
SoundFileColumn()
|
SoundFileColumn()
|
||||||
: Column<ESXRecordT> (Columns::ColumnId_SoundFile, ColumnBase::Display_Sound)
|
: Column<ESXRecordT> (Columns::ColumnId_SoundFile, ColumnBase::Display_SoundRes)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
@ -634,7 +634,7 @@ namespace CSMWorld
|
|||||||
{
|
{
|
||||||
/// \todo Replace Display_Integer with something that displays the colour value more directly.
|
/// \todo Replace Display_Integer with something that displays the colour value more directly.
|
||||||
MapColourColumn()
|
MapColourColumn()
|
||||||
: Column<ESXRecordT> (Columns::ColumnId_MapColour, ColumnBase::Display_Integer)
|
: Column<ESXRecordT> (Columns::ColumnId_MapColour, ColumnBase::Display_Colour)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
|
@ -49,7 +49,7 @@ namespace CSMWorld
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
CloneCommand (IdTable& model, const std::string& idOrigin,
|
CloneCommand (IdTable& model, const std::string& idOrigin,
|
||||||
const std::string& IdDestination,
|
const std::string& IdDestination,
|
||||||
const UniversalId::Type type,
|
const UniversalId::Type type,
|
||||||
QUndoCommand* parent = 0);
|
QUndoCommand* parent = 0);
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#include "columnimp.hpp"
|
#include "columnimp.hpp"
|
||||||
#include "regionmap.hpp"
|
#include "regionmap.hpp"
|
||||||
#include "columns.hpp"
|
#include "columns.hpp"
|
||||||
|
#include "resourcesmanager.hpp"
|
||||||
|
#include "resourcetable.hpp"
|
||||||
|
|
||||||
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type, bool update)
|
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type, bool update)
|
||||||
{
|
{
|
||||||
@ -56,8 +58,9 @@ int CSMWorld::Data::count (RecordBase::State state, const CollectionBase& collec
|
|||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::Data::Data (ToUTF8::FromType encoding)
|
CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager)
|
||||||
: mEncoder (encoding), mRefs (mCells), mReader (0), mDialogue (0)
|
: mEncoder (encoding), mRefs (mCells), mResourcesManager (resourcesManager), mReader (0),
|
||||||
|
mDialogue (0)
|
||||||
{
|
{
|
||||||
mGlobals.addColumn (new StringIdColumn<ESM::Global>);
|
mGlobals.addColumn (new StringIdColumn<ESM::Global>);
|
||||||
mGlobals.addColumn (new RecordStateColumn<ESM::Global>);
|
mGlobals.addColumn (new RecordStateColumn<ESM::Global>);
|
||||||
@ -277,6 +280,18 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding)
|
|||||||
UniversalId::Type_Referenceable);
|
UniversalId::Type_Referenceable);
|
||||||
addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference);
|
addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference);
|
||||||
addModel (new IdTable (&mFilters), UniversalId::Type_Filter);
|
addModel (new IdTable (&mFilters), UniversalId::Type_Filter);
|
||||||
|
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Mesh)),
|
||||||
|
UniversalId::Type_Mesh);
|
||||||
|
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Icon)),
|
||||||
|
UniversalId::Type_Icon);
|
||||||
|
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Music)),
|
||||||
|
UniversalId::Type_Music);
|
||||||
|
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_SoundRes)),
|
||||||
|
UniversalId::Type_SoundRes);
|
||||||
|
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Texture)),
|
||||||
|
UniversalId::Type_Texture);
|
||||||
|
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Video)),
|
||||||
|
UniversalId::Type_Video);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::Data::~Data()
|
CSMWorld::Data::~Data()
|
||||||
@ -498,6 +513,11 @@ CSMWorld::IdCollection<ESM::BodyPart>& CSMWorld::Data::getBodyParts()
|
|||||||
return mBodyParts;
|
return mBodyParts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) const
|
||||||
|
{
|
||||||
|
return mResourcesManager.get (UniversalId::getParentType (id.getType()));
|
||||||
|
}
|
||||||
|
|
||||||
QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id)
|
QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id)
|
||||||
{
|
{
|
||||||
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
|
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
|
||||||
|
@ -47,6 +47,9 @@ namespace ESM
|
|||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
|
class ResourcesManager;
|
||||||
|
class Resources;
|
||||||
|
|
||||||
class Data : public QObject
|
class Data : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -73,6 +76,7 @@ namespace CSMWorld
|
|||||||
RefIdCollection mReferenceables;
|
RefIdCollection mReferenceables;
|
||||||
RefCollection mRefs;
|
RefCollection mRefs;
|
||||||
IdCollection<CSMFilter::Filter> mFilters;
|
IdCollection<CSMFilter::Filter> mFilters;
|
||||||
|
const ResourcesManager& mResourcesManager;
|
||||||
std::vector<QAbstractItemModel *> mModels;
|
std::vector<QAbstractItemModel *> mModels;
|
||||||
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
||||||
std::string mAuthor;
|
std::string mAuthor;
|
||||||
@ -98,7 +102,7 @@ namespace CSMWorld
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Data (ToUTF8::FromType encoding);
|
Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager);
|
||||||
|
|
||||||
virtual ~Data();
|
virtual ~Data();
|
||||||
|
|
||||||
@ -186,6 +190,9 @@ namespace CSMWorld
|
|||||||
|
|
||||||
IdCollection<ESM::BodyPart>& getBodyParts();
|
IdCollection<ESM::BodyPart>& getBodyParts();
|
||||||
|
|
||||||
|
/// Throws an exception, if \a id does not match a resources list.
|
||||||
|
const Resources& getResources (const UniversalId& id) const;
|
||||||
|
|
||||||
QAbstractItemModel *getTableModel (const UniversalId& id);
|
QAbstractItemModel *getTableModel (const UniversalId& id);
|
||||||
///< If no table model is available for \a id, an exception is thrown.
|
///< If no table model is available for \a id, an exception is thrown.
|
||||||
///
|
///
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include "columnbase.hpp"
|
#include "columnbase.hpp"
|
||||||
|
|
||||||
CSMWorld::IdTable::IdTable (CollectionBase *idCollection, unsigned int features)
|
CSMWorld::IdTable::IdTable (CollectionBase *idCollection, unsigned int features)
|
||||||
: mIdCollection (idCollection), mFeatures (features)
|
: IdTableBase (features), mIdCollection (idCollection)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
CSMWorld::IdTable::~IdTable()
|
CSMWorld::IdTable::~IdTable()
|
||||||
@ -185,17 +185,12 @@ void CSMWorld::IdTable::reorderRows (int baseIndex, const std::vector<int>& newO
|
|||||||
index (baseIndex+newOrder.size()-1, mIdCollection->getColumns()-1));
|
index (baseIndex+newOrder.size()-1, mIdCollection->getColumns()-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int CSMWorld::IdTable::getFeatures() const
|
|
||||||
{
|
|
||||||
return mFeatures;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row) const
|
std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row) const
|
||||||
{
|
{
|
||||||
std::string id;
|
std::string id;
|
||||||
std::string hint;
|
std::string hint;
|
||||||
|
|
||||||
if (mFeatures & Feature_ViewCell)
|
if (getFeatures() & Feature_ViewCell)
|
||||||
{
|
{
|
||||||
int cellColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Cell);
|
int cellColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Cell);
|
||||||
int idColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Id);
|
int idColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Id);
|
||||||
@ -206,7 +201,7 @@ std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row)
|
|||||||
hint = "r:" + std::string (mIdCollection->getData (row, idColumn).toString().toUtf8().constData());
|
hint = "r:" + std::string (mIdCollection->getData (row, idColumn).toString().toUtf8().constData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mFeatures & Feature_ViewId)
|
else if (getFeatures() & Feature_ViewId)
|
||||||
{
|
{
|
||||||
int column = mIdCollection->searchColumnIndex (Columns::ColumnId_Id);
|
int column = mIdCollection->searchColumnIndex (Columns::ColumnId_Id);
|
||||||
|
|
||||||
@ -226,6 +221,11 @@ std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row)
|
|||||||
return std::make_pair (UniversalId (UniversalId::Type_Scene, id), hint);
|
return std::make_pair (UniversalId (UniversalId::Type_Scene, id), hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CSMWorld::IdTable::isDeleted (const std::string& id) const
|
||||||
|
{
|
||||||
|
return getRecord (id).isDeleted();
|
||||||
|
}
|
||||||
|
|
||||||
int CSMWorld::IdTable::getColumnId(int column) const
|
int CSMWorld::IdTable::getColumnId(int column) const
|
||||||
{
|
{
|
||||||
return mIdCollection->getColumn(column).getId();
|
return mIdCollection->getColumn(column).getId();
|
||||||
|
@ -3,8 +3,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <QAbstractItemModel>
|
#include "idtablebase.hpp"
|
||||||
|
|
||||||
#include "universalid.hpp"
|
#include "universalid.hpp"
|
||||||
#include "columns.hpp"
|
#include "columns.hpp"
|
||||||
|
|
||||||
@ -13,34 +12,13 @@ namespace CSMWorld
|
|||||||
class CollectionBase;
|
class CollectionBase;
|
||||||
class RecordBase;
|
class RecordBase;
|
||||||
|
|
||||||
class IdTable : public QAbstractItemModel
|
class IdTable : public IdTableBase
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum Features
|
|
||||||
{
|
|
||||||
Feature_ReorderWithinTopic = 1,
|
|
||||||
|
|
||||||
/// Use ID column to generate view request (ID is transformed into
|
|
||||||
/// worldspace and original ID is passed as hint with c: prefix).
|
|
||||||
Feature_ViewId = 2,
|
|
||||||
|
|
||||||
/// Use cell column to generate view request (cell ID is transformed
|
|
||||||
/// into worldspace and record ID is passed as hint with r: prefix).
|
|
||||||
Feature_ViewCell = 4,
|
|
||||||
|
|
||||||
Feature_View = Feature_ViewId | Feature_ViewCell,
|
|
||||||
|
|
||||||
Feature_Preview = 8
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
CollectionBase *mIdCollection;
|
CollectionBase *mIdCollection;
|
||||||
unsigned int mFeatures;
|
|
||||||
bool mPreview;
|
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
IdTable (const IdTable&);
|
IdTable (const IdTable&);
|
||||||
@ -79,17 +57,17 @@ namespace CSMWorld
|
|||||||
const std::string& destination,
|
const std::string& destination,
|
||||||
UniversalId::Type type = UniversalId::Type_None);
|
UniversalId::Type type = UniversalId::Type_None);
|
||||||
|
|
||||||
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);
|
||||||
///< Add record or overwrite existing recrod.
|
///< Add record or overwrite existing recrod.
|
||||||
|
|
||||||
const RecordBase& getRecord (const std::string& id) const;
|
const RecordBase& getRecord (const std::string& id) const;
|
||||||
|
|
||||||
int searchColumnIndex (Columns::ColumnId id) const;
|
virtual int searchColumnIndex (Columns::ColumnId id) const;
|
||||||
///< Return index of column with the given \a id. If no such column exists, -1 is returned.
|
///< Return index of column with the given \a id. If no such column exists, -1 is returned.
|
||||||
|
|
||||||
int findColumnIndex (Columns::ColumnId id) const;
|
virtual int findColumnIndex (Columns::ColumnId id) const;
|
||||||
///< Return index of column with the given \a id. If no such column exists, an exception is
|
///< Return index of column with the given \a id. If no such column exists, an exception is
|
||||||
/// thrown.
|
/// thrown.
|
||||||
|
|
||||||
@ -97,12 +75,13 @@ namespace CSMWorld
|
|||||||
///< Reorder the rows [baseIndex, baseIndex+newOrder.size()) according to the indices
|
///< Reorder the rows [baseIndex, baseIndex+newOrder.size()) according to the indices
|
||||||
/// given in \a newOrder (baseIndex+newOrder[0] specifies the new index of row baseIndex).
|
/// given in \a newOrder (baseIndex+newOrder[0] specifies the new index of row baseIndex).
|
||||||
|
|
||||||
unsigned int getFeatures() const;
|
virtual std::pair<UniversalId, std::string> view (int row) const;
|
||||||
|
|
||||||
std::pair<UniversalId, std::string> view (int row) const;
|
|
||||||
///< Return the UniversalId and the hint for viewing \a row. If viewing is not
|
///< Return the UniversalId and the hint for viewing \a row. If viewing is not
|
||||||
/// supported by this table, return (UniversalId::Type_None, "").
|
/// supported by this table, return (UniversalId::Type_None, "").
|
||||||
|
|
||||||
|
/// Is \a id flagged as deleted?
|
||||||
|
virtual bool isDeleted (const std::string& id) const;
|
||||||
|
|
||||||
int getColumnId(int column) const;
|
int getColumnId(int column) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
9
apps/opencs/model/world/idtablebase.cpp
Normal file
9
apps/opencs/model/world/idtablebase.cpp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
#include "idtablebase.hpp"
|
||||||
|
|
||||||
|
CSMWorld::IdTableBase::IdTableBase (unsigned int features) : mFeatures (features) {}
|
||||||
|
|
||||||
|
unsigned int CSMWorld::IdTableBase::getFeatures() const
|
||||||
|
{
|
||||||
|
return mFeatures;
|
||||||
|
}
|
67
apps/opencs/model/world/idtablebase.hpp
Normal file
67
apps/opencs/model/world/idtablebase.hpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#ifndef CSM_WOLRD_IDTABLEBASE_H
|
||||||
|
#define CSM_WOLRD_IDTABLEBASE_H
|
||||||
|
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
|
||||||
|
#include "columns.hpp"
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class UniversalId;
|
||||||
|
|
||||||
|
class IdTableBase : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum Features
|
||||||
|
{
|
||||||
|
Feature_ReorderWithinTopic = 1,
|
||||||
|
|
||||||
|
/// Use ID column to generate view request (ID is transformed into
|
||||||
|
/// worldspace and original ID is passed as hint with c: prefix).
|
||||||
|
Feature_ViewId = 2,
|
||||||
|
|
||||||
|
/// Use cell column to generate view request (cell ID is transformed
|
||||||
|
/// into worldspace and record ID is passed as hint with r: prefix).
|
||||||
|
Feature_ViewCell = 4,
|
||||||
|
|
||||||
|
Feature_View = Feature_ViewId | Feature_ViewCell,
|
||||||
|
|
||||||
|
Feature_Preview = 8,
|
||||||
|
|
||||||
|
/// Table can not be modified through ordinary means.
|
||||||
|
Feature_Constant = 16
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
unsigned int mFeatures;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
IdTableBase (unsigned int features);
|
||||||
|
|
||||||
|
virtual QModelIndex getModelIndex (const std::string& id, int column) const = 0;
|
||||||
|
|
||||||
|
/// Return index of column with the given \a id. If no such column exists, -1 is
|
||||||
|
/// returned.
|
||||||
|
virtual int searchColumnIndex (Columns::ColumnId id) const = 0;
|
||||||
|
|
||||||
|
/// Return index of column with the given \a id. If no such column exists, an
|
||||||
|
/// exception is thrown.
|
||||||
|
virtual int findColumnIndex (Columns::ColumnId id) const = 0;
|
||||||
|
|
||||||
|
/// Return the UniversalId and the hint for viewing \a row. If viewing is not
|
||||||
|
/// supported by this table, return (UniversalId::Type_None, "").
|
||||||
|
virtual std::pair<UniversalId, std::string> view (int row) const = 0;
|
||||||
|
|
||||||
|
/// Is \a id flagged as deleted?
|
||||||
|
virtual bool isDeleted (const std::string& id) const = 0;
|
||||||
|
|
||||||
|
unsigned int getFeatures() const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "idtable.hpp"
|
#include "idtablebase.hpp"
|
||||||
|
|
||||||
void CSMWorld::IdTableProxyModel::updateColumnMap()
|
void CSMWorld::IdTableProxyModel::updateColumnMap()
|
||||||
{
|
{
|
||||||
@ -13,7 +13,7 @@ void CSMWorld::IdTableProxyModel::updateColumnMap()
|
|||||||
{
|
{
|
||||||
std::vector<int> columns = mFilter->getReferencedColumns();
|
std::vector<int> columns = mFilter->getReferencedColumns();
|
||||||
|
|
||||||
const IdTable& table = dynamic_cast<const IdTable&> (*sourceModel());
|
const IdTableBase& table = dynamic_cast<const IdTableBase&> (*sourceModel());
|
||||||
|
|
||||||
for (std::vector<int>::const_iterator iter (columns.begin()); iter!=columns.end(); ++iter)
|
for (std::vector<int>::const_iterator iter (columns.begin()); iter!=columns.end(); ++iter)
|
||||||
mColumnMap.insert (std::make_pair (*iter,
|
mColumnMap.insert (std::make_pair (*iter,
|
||||||
@ -28,7 +28,7 @@ bool CSMWorld::IdTableProxyModel::filterAcceptsRow (int sourceRow, const QModelI
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
return mFilter->test (
|
return mFilter->test (
|
||||||
dynamic_cast<IdTable&> (*sourceModel()), sourceRow, mColumnMap);
|
dynamic_cast<IdTableBase&> (*sourceModel()), sourceRow, mColumnMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::IdTableProxyModel::IdTableProxyModel (QObject *parent)
|
CSMWorld::IdTableProxyModel::IdTableProxyModel (QObject *parent)
|
||||||
@ -39,7 +39,7 @@ CSMWorld::IdTableProxyModel::IdTableProxyModel (QObject *parent)
|
|||||||
|
|
||||||
QModelIndex CSMWorld::IdTableProxyModel::getModelIndex (const std::string& id, int column) const
|
QModelIndex CSMWorld::IdTableProxyModel::getModelIndex (const std::string& id, int column) const
|
||||||
{
|
{
|
||||||
return mapFromSource (dynamic_cast<IdTable&> (*sourceModel()).getModelIndex (id, column));
|
return mapFromSource (dynamic_cast<IdTableBase&> (*sourceModel()).getModelIndex (id, column));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::IdTableProxyModel::setFilter (const boost::shared_ptr<CSMFilter::Node>& filter)
|
void CSMWorld::IdTableProxyModel::setFilter (const boost::shared_ptr<CSMFilter::Node>& filter)
|
||||||
|
@ -52,7 +52,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||||||
|
|
||||||
ModelColumns modelColumns (baseColumns);
|
ModelColumns modelColumns (baseColumns);
|
||||||
|
|
||||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Model, ColumnBase::Display_String));
|
mColumns.push_back (RefIdColumn (Columns::ColumnId_Model, ColumnBase::Display_Mesh));
|
||||||
modelColumns.mModel = &mColumns.back();
|
modelColumns.mModel = &mColumns.back();
|
||||||
|
|
||||||
NameColumns nameColumns (modelColumns);
|
NameColumns nameColumns (modelColumns);
|
||||||
@ -64,7 +64,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||||||
|
|
||||||
InventoryColumns inventoryColumns (nameColumns);
|
InventoryColumns inventoryColumns (nameColumns);
|
||||||
|
|
||||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Icon, ColumnBase::Display_String));
|
mColumns.push_back (RefIdColumn (Columns::ColumnId_Icon, ColumnBase::Display_Icon));
|
||||||
inventoryColumns.mIcon = &mColumns.back();
|
inventoryColumns.mIcon = &mColumns.back();
|
||||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Weight, ColumnBase::Display_Float));
|
mColumns.push_back (RefIdColumn (Columns::ColumnId_Weight, ColumnBase::Display_Float));
|
||||||
inventoryColumns.mWeight = &mColumns.back();
|
inventoryColumns.mWeight = &mColumns.back();
|
||||||
|
103
apps/opencs/model/world/resources.cpp
Normal file
103
apps/opencs/model/world/resources.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
|
||||||
|
#include "resources.hpp"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <OgreResourceGroupManager.h>
|
||||||
|
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
|
CSMWorld::Resources::Resources (const std::string& baseDirectory, UniversalId::Type type,
|
||||||
|
const char * const *extensions)
|
||||||
|
: mBaseDirectory (baseDirectory), mType (type)
|
||||||
|
{
|
||||||
|
int baseSize = mBaseDirectory.size();
|
||||||
|
|
||||||
|
Ogre::StringVector resourcesGroups =
|
||||||
|
Ogre::ResourceGroupManager::getSingleton().getResourceGroups();
|
||||||
|
|
||||||
|
for (Ogre::StringVector::iterator iter (resourcesGroups.begin());
|
||||||
|
iter!=resourcesGroups.end(); ++iter)
|
||||||
|
{
|
||||||
|
if (*iter=="General" || *iter=="Internal" || *iter=="Autodetect")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Ogre::StringVectorPtr resources =
|
||||||
|
Ogre::ResourceGroupManager::getSingleton().listResourceNames (*iter);
|
||||||
|
|
||||||
|
for (Ogre::StringVector::const_iterator iter (resources->begin());
|
||||||
|
iter!=resources->end(); ++iter)
|
||||||
|
{
|
||||||
|
if (static_cast<int> (iter->size())<baseSize+1 ||
|
||||||
|
iter->substr (0, baseSize)!=mBaseDirectory ||
|
||||||
|
((*iter)[baseSize]!='/' && (*iter)[baseSize]!='\\'))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (extensions)
|
||||||
|
{
|
||||||
|
std::string::size_type index = iter->find_last_of ('.');
|
||||||
|
|
||||||
|
if (index==std::string::npos)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::string extension = iter->substr (index+1);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (; extensions[i]; ++i)
|
||||||
|
if (extensions[i]==extension)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!extensions[i])
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string file = iter->substr (baseSize+1);
|
||||||
|
mFiles.push_back (file);
|
||||||
|
mIndex.insert (std::make_pair (file, static_cast<int> (mFiles.size())-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMWorld::Resources::getSize() const
|
||||||
|
{
|
||||||
|
return mFiles.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CSMWorld::Resources::getId (int index) const
|
||||||
|
{
|
||||||
|
return mFiles.at (index);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMWorld::Resources::getIndex (const std::string& id) const
|
||||||
|
{
|
||||||
|
int index = searchId (id);
|
||||||
|
|
||||||
|
if (index==-1)
|
||||||
|
{
|
||||||
|
std::ostringstream stream;
|
||||||
|
stream << "Invalid resource: " << mBaseDirectory << '/' << id;
|
||||||
|
|
||||||
|
throw std::runtime_error (stream.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMWorld::Resources::searchId (const std::string& id) const
|
||||||
|
{
|
||||||
|
std::string id2 = Misc::StringUtils::lowerCase (id);
|
||||||
|
|
||||||
|
std::map<std::string, int>::const_iterator iter = mIndex.find (id2);
|
||||||
|
|
||||||
|
if (iter==mIndex.end())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::UniversalId::Type CSMWorld::Resources::getType() const
|
||||||
|
{
|
||||||
|
return mType;
|
||||||
|
}
|
37
apps/opencs/model/world/resources.hpp
Normal file
37
apps/opencs/model/world/resources.hpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef CSM_WOLRD_RESOURCES_H
|
||||||
|
#define CSM_WOLRD_RESOURCES_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "universalid.hpp"
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class Resources
|
||||||
|
{
|
||||||
|
std::map<std::string, int> mIndex;
|
||||||
|
std::vector<std::string> mFiles;
|
||||||
|
std::string mBaseDirectory;
|
||||||
|
UniversalId::Type mType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \param type Type of resources in this table.
|
||||||
|
Resources (const std::string& baseDirectory, UniversalId::Type type,
|
||||||
|
const char * const *extensions = 0);
|
||||||
|
|
||||||
|
int getSize() const;
|
||||||
|
|
||||||
|
std::string getId (int index) const;
|
||||||
|
|
||||||
|
int getIndex (const std::string& id) const;
|
||||||
|
|
||||||
|
int searchId (const std::string& id) const;
|
||||||
|
|
||||||
|
UniversalId::Type getType() const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
31
apps/opencs/model/world/resourcesmanager.cpp
Normal file
31
apps/opencs/model/world/resourcesmanager.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
#include "resourcesmanager.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
void CSMWorld::ResourcesManager::addResources (const Resources& resources)
|
||||||
|
{
|
||||||
|
mResources.insert (std::make_pair (resources.getType(), resources));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::ResourcesManager::listResources()
|
||||||
|
{
|
||||||
|
static const char * const sMeshTypes[] = { "nif", 0 };
|
||||||
|
|
||||||
|
addResources (Resources ("meshes", UniversalId::Type_Mesh, sMeshTypes));
|
||||||
|
addResources (Resources ("icons", UniversalId::Type_Icon));
|
||||||
|
addResources (Resources ("music", UniversalId::Type_Music));
|
||||||
|
addResources (Resources ("sound", UniversalId::Type_SoundRes));
|
||||||
|
addResources (Resources ("textures", UniversalId::Type_Texture));
|
||||||
|
addResources (Resources ("videos", UniversalId::Type_Video));
|
||||||
|
}
|
||||||
|
|
||||||
|
const CSMWorld::Resources& CSMWorld::ResourcesManager::get (UniversalId::Type type) const
|
||||||
|
{
|
||||||
|
std::map<UniversalId::Type, Resources>::const_iterator iter = mResources.find (type);
|
||||||
|
|
||||||
|
if (iter==mResources.end())
|
||||||
|
throw std::logic_error ("Unknown resource type");
|
||||||
|
|
||||||
|
return iter->second;
|
||||||
|
}
|
28
apps/opencs/model/world/resourcesmanager.hpp
Normal file
28
apps/opencs/model/world/resourcesmanager.hpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef CSM_WOLRD_RESOURCESMANAGER_H
|
||||||
|
#define CSM_WOLRD_RESOURCESMANAGER_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "universalid.hpp"
|
||||||
|
#include "resources.hpp"
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class ResourcesManager
|
||||||
|
{
|
||||||
|
std::map<UniversalId::Type, Resources> mResources;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void addResources (const Resources& resources);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// Ask OGRE for a list of available resources.
|
||||||
|
void listResources();
|
||||||
|
|
||||||
|
const Resources& get (UniversalId::Type type) const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
146
apps/opencs/model/world/resourcetable.cpp
Normal file
146
apps/opencs/model/world/resourcetable.cpp
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
|
||||||
|
#include "resourcetable.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "resources.hpp"
|
||||||
|
#include "columnbase.hpp"
|
||||||
|
#include "universalid.hpp"
|
||||||
|
|
||||||
|
CSMWorld::ResourceTable::ResourceTable (const Resources *resources, unsigned int features)
|
||||||
|
: IdTableBase (features | Feature_Constant), mResources (resources)
|
||||||
|
{}
|
||||||
|
|
||||||
|
CSMWorld::ResourceTable::~ResourceTable() {}
|
||||||
|
|
||||||
|
int CSMWorld::ResourceTable::rowCount (const QModelIndex & parent) const
|
||||||
|
{
|
||||||
|
if (parent.isValid())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return mResources->getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMWorld::ResourceTable::columnCount (const QModelIndex & parent) const
|
||||||
|
{
|
||||||
|
if (parent.isValid())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 2; // ID, type
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant CSMWorld::ResourceTable::data (const QModelIndex & index, int role) const
|
||||||
|
{
|
||||||
|
if (role!=Qt::DisplayRole)
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
if (index.column()==0)
|
||||||
|
return QString::fromUtf8 (mResources->getId (index.row()).c_str());
|
||||||
|
|
||||||
|
if (index.column()==1)
|
||||||
|
return static_cast<int> (mResources->getType());
|
||||||
|
|
||||||
|
throw std::logic_error ("Invalid column in resource table");
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant CSMWorld::ResourceTable::headerData (int section, Qt::Orientation orientation,
|
||||||
|
int role ) const
|
||||||
|
{
|
||||||
|
if (orientation==Qt::Vertical)
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
if (role==ColumnBase::Role_Flags)
|
||||||
|
return ColumnBase::Flag_Table;
|
||||||
|
|
||||||
|
switch (section)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
|
||||||
|
if (role==Qt::DisplayRole)
|
||||||
|
return Columns::getName (Columns::ColumnId_Id).c_str();
|
||||||
|
|
||||||
|
if (role==ColumnBase::Role_Display)
|
||||||
|
return ColumnBase::Display_String;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
|
||||||
|
if (role==Qt::DisplayRole)
|
||||||
|
return Columns::getName (Columns::ColumnId_RecordType).c_str();
|
||||||
|
|
||||||
|
if (role==ColumnBase::Role_Display)
|
||||||
|
return ColumnBase::Display_Integer;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMWorld::ResourceTable::setData ( const QModelIndex &index, const QVariant &value,
|
||||||
|
int role)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags CSMWorld::ResourceTable::flags (const QModelIndex & index) const
|
||||||
|
{
|
||||||
|
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex CSMWorld::ResourceTable::index (int row, int column, const QModelIndex& parent)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
if (parent.isValid())
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
if (row<0 || row>=mResources->getSize())
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
if (column<0 || column>1)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
return createIndex (row, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex CSMWorld::ResourceTable::parent (const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex CSMWorld::ResourceTable::getModelIndex (const std::string& id, int column) const
|
||||||
|
{
|
||||||
|
return index (mResources->getIndex (id), column);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMWorld::ResourceTable::searchColumnIndex (Columns::ColumnId id) const
|
||||||
|
{
|
||||||
|
if (id==Columns::ColumnId_Id)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (id==Columns::ColumnId_RecordType)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMWorld::ResourceTable::findColumnIndex (Columns::ColumnId id) const
|
||||||
|
{
|
||||||
|
int index = searchColumnIndex (id);
|
||||||
|
|
||||||
|
if (index==-1)
|
||||||
|
throw std::logic_error ("invalid column index");
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<CSMWorld::UniversalId, std::string> CSMWorld::ResourceTable::view (int row) const
|
||||||
|
{
|
||||||
|
return std::make_pair (UniversalId::Type_None, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMWorld::ResourceTable::isDeleted (const std::string& id) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
57
apps/opencs/model/world/resourcetable.hpp
Normal file
57
apps/opencs/model/world/resourcetable.hpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#ifndef CSM_WOLRD_RESOURCETABLE_H
|
||||||
|
#define CSM_WOLRD_RESOURCETABLE_H
|
||||||
|
|
||||||
|
#include "idtablebase.hpp"
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class Resources;
|
||||||
|
|
||||||
|
class ResourceTable : public IdTableBase
|
||||||
|
{
|
||||||
|
const Resources *mResources;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \note The feature Feature_Constant will be added implicitly.
|
||||||
|
ResourceTable (const Resources *resources, unsigned int features = 0);
|
||||||
|
|
||||||
|
virtual ~ResourceTable();
|
||||||
|
|
||||||
|
virtual int rowCount (const QModelIndex & parent = QModelIndex()) const;
|
||||||
|
|
||||||
|
virtual int columnCount (const QModelIndex & parent = QModelIndex()) const;
|
||||||
|
|
||||||
|
virtual QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const;
|
||||||
|
|
||||||
|
virtual QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||||
|
|
||||||
|
virtual bool setData ( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
|
||||||
|
|
||||||
|
virtual Qt::ItemFlags flags (const QModelIndex & index) const;
|
||||||
|
|
||||||
|
virtual QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex())
|
||||||
|
const;
|
||||||
|
|
||||||
|
virtual QModelIndex parent (const QModelIndex& index) const;
|
||||||
|
|
||||||
|
virtual QModelIndex getModelIndex (const std::string& id, int column) const;
|
||||||
|
|
||||||
|
/// Return index of column with the given \a id. If no such column exists, -1 is
|
||||||
|
/// returned.
|
||||||
|
virtual int searchColumnIndex (Columns::ColumnId id) const;
|
||||||
|
|
||||||
|
/// Return index of column with the given \a id. If no such column exists, an
|
||||||
|
/// exception is thrown.
|
||||||
|
virtual int findColumnIndex (Columns::ColumnId id) const;
|
||||||
|
|
||||||
|
/// Return the UniversalId and the hint for viewing \a row. If viewing is not
|
||||||
|
/// supported by this table, return (UniversalId::Type_None, "").
|
||||||
|
virtual std::pair<UniversalId, std::string> view (int row) const;
|
||||||
|
|
||||||
|
/// Is \a id flagged as deleted?
|
||||||
|
virtual bool isDeleted (const std::string& id) const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -37,7 +37,7 @@ std::string CSMWorld::TableMimeData::getIcon() const
|
|||||||
if (mUniversalId.empty())
|
if (mUniversalId.empty())
|
||||||
{
|
{
|
||||||
qDebug()<<"TableMimeData object does not hold any records!"; //because throwing in the event loop tends to be problematic
|
qDebug()<<"TableMimeData object does not hold any records!"; //because throwing in the event loop tends to be problematic
|
||||||
throw("TableMimeData object does not hold any records!");
|
throw std::runtime_error ("TableMimeData object does not hold any records!");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string tmpIcon;
|
std::string tmpIcon;
|
||||||
@ -179,7 +179,7 @@ CSMWorld::UniversalId CSMWorld::TableMimeData::returnMatching (CSMWorld::Univers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw ("TableMimeData object does not hold object of the seeked type");
|
throw std::runtime_error ("TableMimeData object does not hold object of the seeked type");
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::UniversalId CSMWorld::TableMimeData::returnMatching (CSMWorld::ColumnBase::Display type) const
|
CSMWorld::UniversalId CSMWorld::TableMimeData::returnMatching (CSMWorld::ColumnBase::Display type) const
|
||||||
@ -201,7 +201,7 @@ CSMWorld::UniversalId CSMWorld::TableMimeData::returnMatching (CSMWorld::ColumnB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw ("TableMimeData object does not hold object of the seeked type");
|
throw std::runtime_error ("TableMimeData object does not hold object of the seeked type");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSMWorld::TableMimeData::fromDocument (const CSMDoc::Document& document) const
|
bool CSMWorld::TableMimeData::fromDocument (const CSMDoc::Document& document) const
|
||||||
@ -209,327 +209,82 @@ bool CSMWorld::TableMimeData::fromDocument (const CSMDoc::Document& document) co
|
|||||||
return &document == &mDocument;
|
return &document == &mDocument;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::UniversalId::Type CSMWorld::TableMimeData::convertEnums (CSMWorld::ColumnBase::Display type)
|
namespace
|
||||||
{
|
{
|
||||||
switch (type)
|
struct Mapping
|
||||||
{
|
{
|
||||||
case CSMWorld::ColumnBase::Display_Race:
|
CSMWorld::UniversalId::Type mUniversalIdType;
|
||||||
return CSMWorld::UniversalId::Type_Race;
|
CSMWorld::ColumnBase::Display mDisplayType;
|
||||||
|
};
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Skill:
|
const Mapping mapping[] =
|
||||||
return CSMWorld::UniversalId::Type_Skill;
|
{
|
||||||
|
{ CSMWorld::UniversalId::Type_Race, CSMWorld::ColumnBase::Display_Race },
|
||||||
|
{ CSMWorld::UniversalId::Type_Skill, CSMWorld::ColumnBase::Display_Skill },
|
||||||
case CSMWorld::ColumnBase::Display_Class:
|
{ CSMWorld::UniversalId::Type_Class, CSMWorld::ColumnBase::Display_Class },
|
||||||
return CSMWorld::UniversalId::Type_Class;
|
{ CSMWorld::UniversalId::Type_Class, CSMWorld::ColumnBase::Display_Class },
|
||||||
|
{ CSMWorld::UniversalId::Type_Faction, CSMWorld::ColumnBase::Display_Faction },
|
||||||
|
{ CSMWorld::UniversalId::Type_Sound, CSMWorld::ColumnBase::Display_Sound },
|
||||||
case CSMWorld::ColumnBase::Display_Faction:
|
{ CSMWorld::UniversalId::Type_Region, CSMWorld::ColumnBase::Display_Region },
|
||||||
return CSMWorld::UniversalId::Type_Faction;
|
{ CSMWorld::UniversalId::Type_Birthsign, CSMWorld::ColumnBase::Display_Birthsign },
|
||||||
|
{ CSMWorld::UniversalId::Type_Spell, CSMWorld::ColumnBase::Display_Spell },
|
||||||
|
{ CSMWorld::UniversalId::Type_Cell, CSMWorld::ColumnBase::Display_Cell },
|
||||||
case CSMWorld::ColumnBase::Display_Sound:
|
{ CSMWorld::UniversalId::Type_Referenceable, CSMWorld::ColumnBase::Display_Referenceable },
|
||||||
return CSMWorld::UniversalId::Type_Sound;
|
{ CSMWorld::UniversalId::Type_Activator, CSMWorld::ColumnBase::Display_Activator },
|
||||||
|
{ CSMWorld::UniversalId::Type_Potion, CSMWorld::ColumnBase::Display_Potion },
|
||||||
|
{ CSMWorld::UniversalId::Type_Apparatus, CSMWorld::ColumnBase::Display_Apparatus },
|
||||||
case CSMWorld::ColumnBase::Display_Region:
|
{ CSMWorld::UniversalId::Type_Armor, CSMWorld::ColumnBase::Display_Armor },
|
||||||
return CSMWorld::UniversalId::Type_Region;
|
{ CSMWorld::UniversalId::Type_Book, CSMWorld::ColumnBase::Display_Book },
|
||||||
|
{ CSMWorld::UniversalId::Type_Clothing, CSMWorld::ColumnBase::Display_Clothing },
|
||||||
|
{ CSMWorld::UniversalId::Type_Container, CSMWorld::ColumnBase::Display_Container },
|
||||||
case CSMWorld::ColumnBase::Display_Birthsign:
|
{ CSMWorld::UniversalId::Type_Creature, CSMWorld::ColumnBase::Display_Creature },
|
||||||
return CSMWorld::UniversalId::Type_Birthsign;
|
{ CSMWorld::UniversalId::Type_Door, CSMWorld::ColumnBase::Display_Door },
|
||||||
|
{ CSMWorld::UniversalId::Type_Ingredient, CSMWorld::ColumnBase::Display_Ingredient },
|
||||||
|
{ CSMWorld::UniversalId::Type_CreatureLevelledList, CSMWorld::ColumnBase::Display_CreatureLevelledList },
|
||||||
case CSMWorld::ColumnBase::Display_Spell:
|
{ CSMWorld::UniversalId::Type_ItemLevelledList, CSMWorld::ColumnBase::Display_ItemLevelledList },
|
||||||
return CSMWorld::UniversalId::Type_Spell;
|
{ CSMWorld::UniversalId::Type_Light, CSMWorld::ColumnBase::Display_Light },
|
||||||
|
{ CSMWorld::UniversalId::Type_Lockpick, CSMWorld::ColumnBase::Display_Lockpick },
|
||||||
|
{ CSMWorld::UniversalId::Type_Miscellaneous, CSMWorld::ColumnBase::Display_Miscellaneous },
|
||||||
case CSMWorld::ColumnBase::Display_Cell:
|
{ CSMWorld::UniversalId::Type_Npc, CSMWorld::ColumnBase::Display_Npc },
|
||||||
return CSMWorld::UniversalId::Type_Cell;
|
{ CSMWorld::UniversalId::Type_Probe, CSMWorld::ColumnBase::Display_Probe },
|
||||||
|
{ CSMWorld::UniversalId::Type_Repair, CSMWorld::ColumnBase::Display_Repair },
|
||||||
|
{ CSMWorld::UniversalId::Type_Static, CSMWorld::ColumnBase::Display_Static },
|
||||||
case CSMWorld::ColumnBase::Display_Referenceable:
|
{ CSMWorld::UniversalId::Type_Weapon, CSMWorld::ColumnBase::Display_Weapon },
|
||||||
return CSMWorld::UniversalId::Type_Referenceable;
|
{ CSMWorld::UniversalId::Type_Reference, CSMWorld::ColumnBase::Display_Reference },
|
||||||
|
{ CSMWorld::UniversalId::Type_Filter, CSMWorld::ColumnBase::Display_Filter },
|
||||||
|
{ CSMWorld::UniversalId::Type_Topic, CSMWorld::ColumnBase::Display_Topic },
|
||||||
case CSMWorld::ColumnBase::Display_Activator:
|
{ CSMWorld::UniversalId::Type_Journal, CSMWorld::ColumnBase::Display_Journal },
|
||||||
return CSMWorld::UniversalId::Type_Activator;
|
{ CSMWorld::UniversalId::Type_TopicInfo, CSMWorld::ColumnBase::Display_TopicInfo },
|
||||||
|
{ CSMWorld::UniversalId::Type_JournalInfo, CSMWorld::ColumnBase::Display_JournalInfo },
|
||||||
|
{ CSMWorld::UniversalId::Type_Scene, CSMWorld::ColumnBase::Display_Scene },
|
||||||
case CSMWorld::ColumnBase::Display_Potion:
|
{ CSMWorld::UniversalId::Type_Script, CSMWorld::ColumnBase::Display_Script },
|
||||||
return CSMWorld::UniversalId::Type_Potion;
|
{ CSMWorld::UniversalId::Type_Mesh, CSMWorld::ColumnBase::Display_Mesh },
|
||||||
|
{ CSMWorld::UniversalId::Type_Icon, CSMWorld::ColumnBase::Display_Icon },
|
||||||
|
{ CSMWorld::UniversalId::Type_Music, CSMWorld::ColumnBase::Display_Music },
|
||||||
case CSMWorld::ColumnBase::Display_Apparatus:
|
{ CSMWorld::UniversalId::Type_SoundRes, CSMWorld::ColumnBase::Display_SoundRes },
|
||||||
return CSMWorld::UniversalId::Type_Apparatus;
|
{ CSMWorld::UniversalId::Type_Texture, CSMWorld::ColumnBase::Display_Texture },
|
||||||
|
{ CSMWorld::UniversalId::Type_Video, CSMWorld::ColumnBase::Display_Video },
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Armor:
|
{ CSMWorld::UniversalId::Type_None, CSMWorld::ColumnBase::Display_None } // end marker
|
||||||
return CSMWorld::UniversalId::Type_Armor;
|
};
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Book:
|
|
||||||
return CSMWorld::UniversalId::Type_Book;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Clothing:
|
|
||||||
return CSMWorld::UniversalId::Type_Clothing;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Container:
|
|
||||||
return CSMWorld::UniversalId::Type_Container;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Creature:
|
|
||||||
return CSMWorld::UniversalId::Type_Creature;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Door:
|
|
||||||
return CSMWorld::UniversalId::Type_Door;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Ingredient:
|
|
||||||
return CSMWorld::UniversalId::Type_Ingredient;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_CreatureLevelledList:
|
|
||||||
return CSMWorld::UniversalId::Type_CreatureLevelledList;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_ItemLevelledList:
|
|
||||||
return CSMWorld::UniversalId::Type_ItemLevelledList;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Light:
|
|
||||||
return CSMWorld::UniversalId::Type_Light;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Lockpick:
|
|
||||||
return CSMWorld::UniversalId::Type_Lockpick;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Miscellaneous:
|
|
||||||
return CSMWorld::UniversalId::Type_Miscellaneous;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Npc:
|
|
||||||
return CSMWorld::UniversalId::Type_Npc;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Probe:
|
|
||||||
return CSMWorld::UniversalId::Type_Probe;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Repair:
|
|
||||||
return CSMWorld::UniversalId::Type_Repair;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Static:
|
|
||||||
return CSMWorld::UniversalId::Type_Static;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Weapon:
|
|
||||||
return CSMWorld::UniversalId::Type_Weapon;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Reference:
|
|
||||||
return CSMWorld::UniversalId::Type_Reference;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Filter:
|
|
||||||
return CSMWorld::UniversalId::Type_Filter;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Topic:
|
|
||||||
return CSMWorld::UniversalId::Type_Topic;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Journal:
|
|
||||||
return CSMWorld::UniversalId::Type_Journal;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_TopicInfo:
|
|
||||||
return CSMWorld::UniversalId::Type_TopicInfo;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_JournalInfo:
|
|
||||||
return CSMWorld::UniversalId::Type_JournalInfo;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Scene:
|
|
||||||
return CSMWorld::UniversalId::Type_Scene;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::ColumnBase::Display_Script:
|
|
||||||
return CSMWorld::UniversalId::Type_Script;
|
|
||||||
|
|
||||||
|
|
||||||
default:
|
|
||||||
return CSMWorld::UniversalId::Type_None;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::ColumnBase::Display CSMWorld::TableMimeData::convertEnums (CSMWorld::UniversalId::Type type)
|
CSMWorld::UniversalId::Type CSMWorld::TableMimeData::convertEnums (ColumnBase::Display type)
|
||||||
{
|
{
|
||||||
switch (type)
|
for (int i=0; mapping[i].mUniversalIdType!=CSMWorld::UniversalId::Type_None; ++i)
|
||||||
{
|
if (mapping[i].mDisplayType==type)
|
||||||
case CSMWorld::UniversalId::Type_Race:
|
return mapping[i].mUniversalIdType;
|
||||||
return CSMWorld::ColumnBase::Display_Race;
|
|
||||||
|
|
||||||
|
return CSMWorld::UniversalId::Type_None;
|
||||||
|
}
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Skill:
|
CSMWorld::ColumnBase::Display CSMWorld::TableMimeData::convertEnums (UniversalId::Type type)
|
||||||
return CSMWorld::ColumnBase::Display_Skill;
|
{
|
||||||
|
for (int i=0; mapping[i].mUniversalIdType!=CSMWorld::UniversalId::Type_None; ++i)
|
||||||
|
if (mapping[i].mUniversalIdType==type)
|
||||||
|
return mapping[i].mDisplayType;
|
||||||
|
|
||||||
|
return CSMWorld::ColumnBase::Display_None;
|
||||||
case CSMWorld::UniversalId::Type_Class:
|
|
||||||
return CSMWorld::ColumnBase::Display_Class;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Faction:
|
|
||||||
return CSMWorld::ColumnBase::Display_Faction;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Sound:
|
|
||||||
return CSMWorld::ColumnBase::Display_Sound;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Region:
|
|
||||||
return CSMWorld::ColumnBase::Display_Region;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Birthsign:
|
|
||||||
return CSMWorld::ColumnBase::Display_Birthsign;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Spell:
|
|
||||||
return CSMWorld::ColumnBase::Display_Spell;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Cell:
|
|
||||||
return CSMWorld::ColumnBase::Display_Cell;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Referenceable:
|
|
||||||
return CSMWorld::ColumnBase::Display_Referenceable;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Activator:
|
|
||||||
return CSMWorld::ColumnBase::Display_Activator;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Potion:
|
|
||||||
return CSMWorld::ColumnBase::Display_Potion;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Apparatus:
|
|
||||||
return CSMWorld::ColumnBase::Display_Apparatus;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Armor:
|
|
||||||
return CSMWorld::ColumnBase::Display_Armor;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Book:
|
|
||||||
return CSMWorld::ColumnBase::Display_Book;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Clothing:
|
|
||||||
return CSMWorld::ColumnBase::Display_Clothing;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Container:
|
|
||||||
return CSMWorld::ColumnBase::Display_Container;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Creature:
|
|
||||||
return CSMWorld::ColumnBase::Display_Creature;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Door:
|
|
||||||
return CSMWorld::ColumnBase::Display_Door;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Ingredient:
|
|
||||||
return CSMWorld::ColumnBase::Display_Ingredient;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_CreatureLevelledList:
|
|
||||||
return CSMWorld::ColumnBase::Display_CreatureLevelledList;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_ItemLevelledList:
|
|
||||||
return CSMWorld::ColumnBase::Display_ItemLevelledList;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Light:
|
|
||||||
return CSMWorld::ColumnBase::Display_Light;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Lockpick:
|
|
||||||
return CSMWorld::ColumnBase::Display_Lockpick;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Miscellaneous:
|
|
||||||
return CSMWorld::ColumnBase::Display_Miscellaneous;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Npc:
|
|
||||||
return CSMWorld::ColumnBase::Display_Npc;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Probe:
|
|
||||||
return CSMWorld::ColumnBase::Display_Probe;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Repair:
|
|
||||||
return CSMWorld::ColumnBase::Display_Repair;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Static:
|
|
||||||
return CSMWorld::ColumnBase::Display_Static;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Weapon:
|
|
||||||
return CSMWorld::ColumnBase::Display_Weapon;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Reference:
|
|
||||||
return CSMWorld::ColumnBase::Display_Reference;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Filter:
|
|
||||||
return CSMWorld::ColumnBase::Display_Filter;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Topic:
|
|
||||||
return CSMWorld::ColumnBase::Display_Topic;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Journal:
|
|
||||||
return CSMWorld::ColumnBase::Display_Journal;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_TopicInfo:
|
|
||||||
return CSMWorld::ColumnBase::Display_TopicInfo;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_JournalInfo:
|
|
||||||
return CSMWorld::ColumnBase::Display_JournalInfo;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Scene:
|
|
||||||
return CSMWorld::ColumnBase::Display_Scene;
|
|
||||||
|
|
||||||
|
|
||||||
case CSMWorld::UniversalId::Type_Script:
|
|
||||||
return CSMWorld::ColumnBase::Display_Script;
|
|
||||||
|
|
||||||
|
|
||||||
default:
|
|
||||||
return CSMWorld::ColumnBase::Display_None;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const CSMDoc::Document* CSMWorld::TableMimeData::getDocumentPtr() const
|
const CSMDoc::Document* CSMWorld::TableMimeData::getDocumentPtr() const
|
||||||
|
@ -44,6 +44,12 @@ namespace
|
|||||||
{ CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap,
|
{ CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap,
|
||||||
"Region Map", 0 },
|
"Region Map", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Filters, "Filters", 0 },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Filters, "Filters", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Meshes, "Meshes", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Icons, "Icons", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Musics, "Musics", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_SoundsRes, "Sound Files", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Textures, "Textures", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Videos, "Videos", 0 },
|
||||||
|
|
||||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
|
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
|
||||||
};
|
};
|
||||||
@ -97,6 +103,12 @@ namespace
|
|||||||
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", 0 },
|
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Enchantment, "Enchantment", 0 },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Enchantment, "Enchantment", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_BodyPart, "Body Part", 0 },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_BodyPart, "Body Part", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Mesh, "Mesh", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Icon, "Icon", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Music, "Music", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_SoundRes, "Sound File", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Texture, "Texture", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Video, "Video", 0 },
|
||||||
|
|
||||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
|
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
|
||||||
};
|
};
|
||||||
@ -331,7 +343,8 @@ CSMWorld::UniversalId::Type CSMWorld::UniversalId::getParentType (Type type)
|
|||||||
if (sIdArg[i].mClass==Class_RefRecord)
|
if (sIdArg[i].mClass==Class_RefRecord)
|
||||||
return Type_Referenceables;
|
return Type_Referenceables;
|
||||||
|
|
||||||
if (sIdArg[i].mClass==Class_SubRecord || sIdArg[i].mClass==Class_Record)
|
if (sIdArg[i].mClass==Class_SubRecord || sIdArg[i].mClass==Class_Record ||
|
||||||
|
sIdArg[i].mClass==Class_Resource)
|
||||||
{
|
{
|
||||||
if (type==Type_Cell_Missing)
|
if (type==Type_Cell_Missing)
|
||||||
return Type_Cells;
|
return Type_Cells;
|
||||||
|
@ -22,7 +22,10 @@ namespace CSMWorld
|
|||||||
Class_RecordList,
|
Class_RecordList,
|
||||||
Class_Collection, // multiple types of records combined
|
Class_Collection, // multiple types of records combined
|
||||||
Class_Transient, // not part of the world data or the project data
|
Class_Transient, // not part of the world data or the project data
|
||||||
Class_NonRecord // record like data that is not part of the world
|
Class_NonRecord, // record like data that is not part of the world
|
||||||
|
Class_Resource, ///< \attention Resource IDs are unique only within the
|
||||||
|
/// respective collection
|
||||||
|
Class_ResourceList
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ArgumentType
|
enum ArgumentType
|
||||||
@ -104,7 +107,19 @@ namespace CSMWorld
|
|||||||
Type_Enchantments,
|
Type_Enchantments,
|
||||||
Type_Enchantment,
|
Type_Enchantment,
|
||||||
Type_BodyParts,
|
Type_BodyParts,
|
||||||
Type_BodyPart
|
Type_BodyPart,
|
||||||
|
Type_Meshes,
|
||||||
|
Type_Mesh,
|
||||||
|
Type_Icons,
|
||||||
|
Type_Icon,
|
||||||
|
Type_Musics,
|
||||||
|
Type_Music,
|
||||||
|
Type_SoundsRes,
|
||||||
|
Type_SoundRes,
|
||||||
|
Type_Textures,
|
||||||
|
Type_Texture,
|
||||||
|
Type_Videos,
|
||||||
|
Type_Video
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { NumberOfTypes = Type_BodyPart+1 };
|
enum { NumberOfTypes = Type_BodyPart+1 };
|
||||||
|
@ -81,6 +81,7 @@ QWidget *CSVDoc::StartupDialogue::createTools()
|
|||||||
|
|
||||||
config->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
|
config->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||||
config->setIcon (QIcon (":startup/configure"));
|
config->setIcon (QIcon (":startup/configure"));
|
||||||
|
config->setToolTip ("Open user settings");
|
||||||
|
|
||||||
layout->addWidget (config);
|
layout->addWidget (config);
|
||||||
|
|
||||||
|
@ -204,6 +204,32 @@ void CSVDoc::View::setupAssetsMenu()
|
|||||||
QAction *sounds = new QAction (tr ("Sounds"), this);
|
QAction *sounds = new QAction (tr ("Sounds"), this);
|
||||||
connect (sounds, SIGNAL (triggered()), this, SLOT (addSoundsSubView()));
|
connect (sounds, SIGNAL (triggered()), this, SLOT (addSoundsSubView()));
|
||||||
assets->addAction (sounds);
|
assets->addAction (sounds);
|
||||||
|
|
||||||
|
assets->addSeparator(); // resources follow here
|
||||||
|
|
||||||
|
QAction *meshes = new QAction (tr ("Meshes"), this);
|
||||||
|
connect (meshes, SIGNAL (triggered()), this, SLOT (addMeshesSubView()));
|
||||||
|
assets->addAction (meshes);
|
||||||
|
|
||||||
|
QAction *icons = new QAction (tr ("Icons"), this);
|
||||||
|
connect (icons, SIGNAL (triggered()), this, SLOT (addIconsSubView()));
|
||||||
|
assets->addAction (icons);
|
||||||
|
|
||||||
|
QAction *musics = new QAction (tr ("Music"), this);
|
||||||
|
connect (musics, SIGNAL (triggered()), this, SLOT (addMusicsSubView()));
|
||||||
|
assets->addAction (musics);
|
||||||
|
|
||||||
|
QAction *soundsRes = new QAction (tr ("Sound Files"), this);
|
||||||
|
connect (soundsRes, SIGNAL (triggered()), this, SLOT (addSoundsResSubView()));
|
||||||
|
assets->addAction (soundsRes);
|
||||||
|
|
||||||
|
QAction *textures = new QAction (tr ("Textures"), this);
|
||||||
|
connect (textures, SIGNAL (triggered()), this, SLOT (addTexturesSubView()));
|
||||||
|
assets->addAction (textures);
|
||||||
|
|
||||||
|
QAction *videos = new QAction (tr ("Videos"), this);
|
||||||
|
connect (videos, SIGNAL (triggered()), this, SLOT (addVideosSubView()));
|
||||||
|
assets->addAction (videos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::View::setupUi()
|
void CSVDoc::View::setupUi()
|
||||||
@ -487,6 +513,36 @@ void CSVDoc::View::addBodyPartsSubView()
|
|||||||
addSubView (CSMWorld::UniversalId::Type_BodyParts);
|
addSubView (CSMWorld::UniversalId::Type_BodyParts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVDoc::View::addMeshesSubView()
|
||||||
|
{
|
||||||
|
addSubView (CSMWorld::UniversalId::Type_Meshes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::View::addIconsSubView()
|
||||||
|
{
|
||||||
|
addSubView (CSMWorld::UniversalId::Type_Icons);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::View::addMusicsSubView()
|
||||||
|
{
|
||||||
|
addSubView (CSMWorld::UniversalId::Type_Musics);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::View::addSoundsResSubView()
|
||||||
|
{
|
||||||
|
addSubView (CSMWorld::UniversalId::Type_SoundsRes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::View::addTexturesSubView()
|
||||||
|
{
|
||||||
|
addSubView (CSMWorld::UniversalId::Type_Textures);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::View::addVideosSubView()
|
||||||
|
{
|
||||||
|
addSubView (CSMWorld::UniversalId::Type_Videos);
|
||||||
|
}
|
||||||
|
|
||||||
void CSVDoc::View::abortOperation (int type)
|
void CSVDoc::View::abortOperation (int type)
|
||||||
{
|
{
|
||||||
mDocument->abortOperation (type);
|
mDocument->abortOperation (type);
|
||||||
|
@ -182,6 +182,18 @@ namespace CSVDoc
|
|||||||
|
|
||||||
void addBodyPartsSubView();
|
void addBodyPartsSubView();
|
||||||
|
|
||||||
|
void addMeshesSubView();
|
||||||
|
|
||||||
|
void addIconsSubView();
|
||||||
|
|
||||||
|
void addMusicsSubView();
|
||||||
|
|
||||||
|
void addSoundsResSubView();
|
||||||
|
|
||||||
|
void addTexturesSubView();
|
||||||
|
|
||||||
|
void addVideosSubView();
|
||||||
|
|
||||||
void toggleShowStatusBar (bool show);
|
void toggleShowStatusBar (bool show);
|
||||||
|
|
||||||
void loadErrorLog();
|
void loadErrorLog();
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
#include <QResizeEvent>
|
#include <QResizeEvent>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QShortcut>
|
||||||
|
|
||||||
#include <OgreRoot.h>
|
#include <OgreRoot.h>
|
||||||
#include <OgreRenderWindow.h>
|
#include <OgreRenderWindow.h>
|
||||||
@ -11,7 +12,7 @@
|
|||||||
#include <OgreSceneNode.h>
|
#include <OgreSceneNode.h>
|
||||||
#include <OgreViewport.h>
|
#include <OgreViewport.h>
|
||||||
|
|
||||||
#include "../world/scenetoolmode.hpp"
|
#include "../widget/scenetoolmode.hpp"
|
||||||
|
|
||||||
#include "navigation.hpp"
|
#include "navigation.hpp"
|
||||||
#include "lighting.hpp"
|
#include "lighting.hpp"
|
||||||
@ -51,16 +52,34 @@ namespace CSVRender
|
|||||||
QTimer *timer = new QTimer (this);
|
QTimer *timer = new QTimer (this);
|
||||||
|
|
||||||
connect (timer, SIGNAL (timeout()), this, SLOT (update()));
|
connect (timer, SIGNAL (timeout()), this, SLOT (update()));
|
||||||
timer->start (20); /// \todo make this configurable
|
timer->start (20); ///< \todo make this configurable
|
||||||
|
|
||||||
|
/// \todo make shortcut configurable
|
||||||
|
QShortcut *focusToolbar = new QShortcut (Qt::Key_T, this, 0, 0, Qt::WidgetWithChildrenShortcut);
|
||||||
|
connect (focusToolbar, SIGNAL (activated()), this, SIGNAL (focusToolbarRequest()));
|
||||||
}
|
}
|
||||||
|
|
||||||
CSVWorld::SceneToolMode *SceneWidget::makeLightingSelector (CSVWorld::SceneToolbar *parent)
|
CSVWidget::SceneToolMode *SceneWidget::makeLightingSelector (CSVWidget::SceneToolbar *parent)
|
||||||
{
|
{
|
||||||
CSVWorld::SceneToolMode *tool = new CSVWorld::SceneToolMode (parent);
|
CSVWidget::SceneToolMode *tool = new CSVWidget::SceneToolMode (parent, "Lighting Mode");
|
||||||
|
|
||||||
tool->addButton (":door.png", "day"); /// \todo replace icons
|
/// \todo replace icons
|
||||||
tool->addButton (":GMST.png", "night");
|
tool->addButton (":door.png", "day",
|
||||||
tool->addButton (":Info.png", "bright");
|
"Day"
|
||||||
|
"<ul><li>Cell specific ambient in interiors</li>"
|
||||||
|
"<li>Low ambient in exteriors</li>"
|
||||||
|
"<li>Strong directional light source/lir>"
|
||||||
|
"<li>This mode closely resembles day time in-game</li></ul>");
|
||||||
|
tool->addButton (":GMST.png", "night",
|
||||||
|
"Night"
|
||||||
|
"<ul><li>Cell specific ambient in interiors</li>"
|
||||||
|
"<li>Low ambient in exteriors</li>"
|
||||||
|
"<li>Weak directional light source</li>"
|
||||||
|
"<li>This mode closely resembles night time in-game</li></ul>");
|
||||||
|
tool->addButton (":Info.png", "bright",
|
||||||
|
"Bright"
|
||||||
|
"<ul><li>Maximum ambient</li>"
|
||||||
|
"<li>Strong directional light source</li></ul>");
|
||||||
|
|
||||||
connect (tool, SIGNAL (modeChanged (const std::string&)),
|
connect (tool, SIGNAL (modeChanged (const std::string&)),
|
||||||
this, SLOT (selectLightingMode (const std::string&)));
|
this, SLOT (selectLightingMode (const std::string&)));
|
||||||
@ -347,6 +366,9 @@ namespace CSVRender
|
|||||||
|
|
||||||
mLighting = lighting;
|
mLighting = lighting;
|
||||||
mLighting->activate (mSceneMgr, mHasDefaultAmbient ? &mDefaultAmbient : 0);
|
mLighting->activate (mSceneMgr, mHasDefaultAmbient ? &mDefaultAmbient : 0);
|
||||||
|
|
||||||
|
if (mWindow)
|
||||||
|
mWindow->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneWidget::selectLightingMode (const std::string& mode)
|
void SceneWidget::selectLightingMode (const std::string& mode)
|
||||||
|
@ -16,7 +16,7 @@ namespace Ogre
|
|||||||
class RenderWindow;
|
class RenderWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace CSVWorld
|
namespace CSVWidget
|
||||||
{
|
{
|
||||||
class SceneToolMode;
|
class SceneToolMode;
|
||||||
class SceneToolbar;
|
class SceneToolbar;
|
||||||
@ -38,7 +38,7 @@ namespace CSVRender
|
|||||||
|
|
||||||
QPaintEngine* paintEngine() const;
|
QPaintEngine* paintEngine() const;
|
||||||
|
|
||||||
CSVWorld::SceneToolMode *makeLightingSelector (CSVWorld::SceneToolbar *parent);
|
CSVWidget::SceneToolMode *makeLightingSelector (CSVWidget::SceneToolbar *parent);
|
||||||
///< \attention The created tool is not added to the toolbar (via addTool). Doing that
|
///< \attention The created tool is not added to the toolbar (via addTool). Doing that
|
||||||
/// is the responsibility of the calling function.
|
/// is the responsibility of the calling function.
|
||||||
|
|
||||||
@ -111,6 +111,10 @@ namespace CSVRender
|
|||||||
void update();
|
void update();
|
||||||
|
|
||||||
void selectLightingMode (const std::string& mode);
|
void selectLightingMode (const std::string& mode);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void focusToolbarRequest();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,8 +7,9 @@
|
|||||||
|
|
||||||
#include <QtGui/qevent.h>
|
#include <QtGui/qevent.h>
|
||||||
|
|
||||||
#include "../world/scenetoolmode.hpp"
|
#include "../../model/world/universalid.hpp"
|
||||||
#include <apps/opencs/model/world/universalid.hpp>
|
|
||||||
|
#include "../widget/scenetoolmode.hpp"
|
||||||
|
|
||||||
CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent)
|
CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent)
|
||||||
: SceneWidget (parent), mDocument(document)
|
: SceneWidget (parent), mDocument(document)
|
||||||
@ -53,14 +54,39 @@ void CSVRender::WorldspaceWidget::selectDefaultNavigationMode()
|
|||||||
setNavigation (&m1st);
|
setNavigation (&m1st);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSVWorld::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector (
|
CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector (
|
||||||
CSVWorld::SceneToolbar *parent)
|
CSVWidget::SceneToolbar *parent)
|
||||||
{
|
{
|
||||||
CSVWorld::SceneToolMode *tool = new CSVWorld::SceneToolMode (parent);
|
CSVWidget::SceneToolMode *tool = new CSVWidget::SceneToolMode (parent, "Camera Mode");
|
||||||
|
|
||||||
tool->addButton (":door.png", "1st"); /// \todo replace icons
|
/// \todo replace icons
|
||||||
tool->addButton (":GMST.png", "free");
|
/// \todo consider user-defined button-mapping
|
||||||
tool->addButton (":Info.png", "orbit");
|
tool->addButton (":door.png", "1st",
|
||||||
|
"First Person"
|
||||||
|
"<ul><li>Mouse-Look while holding the left button</li>"
|
||||||
|
"<li>WASD movement keys</li>"
|
||||||
|
"<li>Mouse wheel moves the camera forawrd/backward</li>"
|
||||||
|
"<li>Stafing (also vertically) by holding the left mouse button and control</li>"
|
||||||
|
"<li>Camera is held upright</li>"
|
||||||
|
"<li>Hold shift to speed up movement</li>"
|
||||||
|
"</ul>");
|
||||||
|
tool->addButton (":GMST.png", "free",
|
||||||
|
"Free Camera"
|
||||||
|
"<ul><li>Mouse-Look while holding the left button</li>"
|
||||||
|
"<li>Stafing (also vertically) via WASD or by holding the left mouse button and control</li>"
|
||||||
|
"<li>Mouse wheel moves the camera forawrd/backward</li>"
|
||||||
|
"<li>Roll camera with Q and E keys</li>"
|
||||||
|
"<li>Hold shift to speed up movement</li>"
|
||||||
|
"</ul>");
|
||||||
|
tool->addButton (":Info.png", "orbit",
|
||||||
|
"Orbiting Camera"
|
||||||
|
"<ul><li>Always facing the centre point</li>"
|
||||||
|
"<li>Rotate around the centre point via WASD or by moving the mouse while holding the left button</li>"
|
||||||
|
"<li>Mouse wheel moves camera away or towards centre point but can not pass through it</li>"
|
||||||
|
"<li>Roll camera with Q and E keys</li>"
|
||||||
|
"<li>Stafing (also vertically) by holding the left mouse button and control (includes relocation of the centre point)</li>"
|
||||||
|
"<li>Hold shift to speed up movement</li>"
|
||||||
|
"</ul>");
|
||||||
|
|
||||||
connect (tool, SIGNAL (modeChanged (const std::string&)),
|
connect (tool, SIGNAL (modeChanged (const std::string&)),
|
||||||
this, SLOT (selectNavigationMode (const std::string&)));
|
this, SLOT (selectNavigationMode (const std::string&)));
|
||||||
|
@ -13,7 +13,7 @@ namespace CSMWorld
|
|||||||
{
|
{
|
||||||
class UniversalId;
|
class UniversalId;
|
||||||
}
|
}
|
||||||
namespace CSVWorld
|
namespace CSVWidget
|
||||||
{
|
{
|
||||||
class SceneToolMode;
|
class SceneToolMode;
|
||||||
class SceneToolbar;
|
class SceneToolbar;
|
||||||
@ -49,7 +49,7 @@ namespace CSVRender
|
|||||||
|
|
||||||
WorldspaceWidget (CSMDoc::Document& document, QWidget *parent = 0);
|
WorldspaceWidget (CSMDoc::Document& document, QWidget *parent = 0);
|
||||||
|
|
||||||
CSVWorld::SceneToolMode *makeNavigationSelector (CSVWorld::SceneToolbar *parent);
|
CSVWidget::SceneToolMode *makeNavigationSelector (CSVWidget::SceneToolbar *parent);
|
||||||
///< \attention The created tool is not added to the toolbar (via addTool). Doing that
|
///< \attention The created tool is not added to the toolbar (via addTool). Doing that
|
||||||
/// is the responsibility of the calling function.
|
/// is the responsibility of the calling function.
|
||||||
|
|
||||||
|
83
apps/opencs/view/widget/pushbutton.cpp
Normal file
83
apps/opencs/view/widget/pushbutton.cpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
|
||||||
|
#include "pushbutton.hpp"
|
||||||
|
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QKeyEvent>
|
||||||
|
|
||||||
|
void CSVWidget::PushButton::setExtendedToolTip (const QString& text)
|
||||||
|
{
|
||||||
|
QString tooltip = text;
|
||||||
|
|
||||||
|
if (tooltip.isEmpty())
|
||||||
|
tooltip = "(Tool tip not implemented yet)";
|
||||||
|
|
||||||
|
switch (mType)
|
||||||
|
{
|
||||||
|
case Type_TopMode:
|
||||||
|
|
||||||
|
tooltip +=
|
||||||
|
"<p>(left click to change mode)";
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Type_Mode:
|
||||||
|
|
||||||
|
tooltip +=
|
||||||
|
"<p>(left click to activate,"
|
||||||
|
"<br>shift-left click to activate and keep panel open)";
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
setToolTip (tooltip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::PushButton::keyPressEvent (QKeyEvent *event)
|
||||||
|
{
|
||||||
|
if (event->key()!=Qt::Key_Shift)
|
||||||
|
mKeepOpen = false;
|
||||||
|
|
||||||
|
QPushButton::keyPressEvent (event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::PushButton::keyReleaseEvent (QKeyEvent *event)
|
||||||
|
{
|
||||||
|
if (event->key()==Qt::Key_Return || event->key()==Qt::Key_Enter)
|
||||||
|
{
|
||||||
|
mKeepOpen = event->modifiers() & Qt::ShiftModifier;
|
||||||
|
emit clicked();
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton::keyReleaseEvent (event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::PushButton::mouseReleaseEvent (QMouseEvent *event)
|
||||||
|
{
|
||||||
|
mKeepOpen = event->button()==Qt::LeftButton && (event->modifiers() & Qt::ShiftModifier);
|
||||||
|
QPushButton::mouseReleaseEvent (event);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVWidget::PushButton::PushButton (const QIcon& icon, Type type, const QString& tooltip,
|
||||||
|
QWidget *parent)
|
||||||
|
: QPushButton (icon, "", parent), mKeepOpen (false), mType (type), mToolTip (tooltip)
|
||||||
|
{
|
||||||
|
setCheckable (type==Type_Mode);
|
||||||
|
setExtendedToolTip (tooltip);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVWidget::PushButton::PushButton (Type type, const QString& tooltip, QWidget *parent)
|
||||||
|
: QPushButton (parent), mKeepOpen (false), mType (type), mToolTip (tooltip)
|
||||||
|
{
|
||||||
|
setCheckable (type==Type_Mode);
|
||||||
|
setExtendedToolTip (tooltip);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSVWidget::PushButton::hasKeepOpen() const
|
||||||
|
{
|
||||||
|
return mKeepOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CSVWidget::PushButton::getBaseToolTip() const
|
||||||
|
{
|
||||||
|
return mToolTip;
|
||||||
|
}
|
55
apps/opencs/view/widget/pushbutton.hpp
Normal file
55
apps/opencs/view/widget/pushbutton.hpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#ifndef CSV_WIDGET_PUSHBUTTON_H
|
||||||
|
#define CSV_WIDGET_PUSHBUTTON_H
|
||||||
|
|
||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
|
namespace CSVWidget
|
||||||
|
{
|
||||||
|
class PushButton : public QPushButton
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
Type_TopMode, // top level button for mode selector panel
|
||||||
|
Type_Mode // mode button
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool mKeepOpen;
|
||||||
|
Type mType;
|
||||||
|
QString mToolTip;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void setExtendedToolTip (const QString& text);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void keyPressEvent (QKeyEvent *event);
|
||||||
|
|
||||||
|
virtual void keyReleaseEvent (QKeyEvent *event);
|
||||||
|
|
||||||
|
virtual void mouseReleaseEvent (QMouseEvent *event);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \param push Do not maintain a toggle state
|
||||||
|
PushButton (const QIcon& icon, Type type, const QString& tooltip = "",
|
||||||
|
QWidget *parent = 0);
|
||||||
|
|
||||||
|
/// \param push Do not maintain a toggle state
|
||||||
|
PushButton (Type type, const QString& tooltip = "",
|
||||||
|
QWidget *parent = 0);
|
||||||
|
|
||||||
|
bool hasKeepOpen() const;
|
||||||
|
|
||||||
|
/// Return tooltip used at construction (without any button-specific modifications)
|
||||||
|
QString getBaseToolTip() const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
#include "scenetoolbar.hpp"
|
#include "scenetoolbar.hpp"
|
||||||
|
|
||||||
CSVWorld::SceneTool::SceneTool (SceneToolbar *parent) : QPushButton (parent)
|
CSVWidget::SceneTool::SceneTool (SceneToolbar *parent)
|
||||||
|
: PushButton (PushButton::Type_TopMode, "", parent)
|
||||||
{
|
{
|
||||||
setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
|
setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||||
setIconSize (QSize (parent->getIconSize(), parent->getIconSize()));
|
setIconSize (QSize (parent->getIconSize(), parent->getIconSize()));
|
||||||
@ -12,7 +13,7 @@ CSVWorld::SceneTool::SceneTool (SceneToolbar *parent) : QPushButton (parent)
|
|||||||
connect (this, SIGNAL (clicked()), this, SLOT (openRequest()));
|
connect (this, SIGNAL (clicked()), this, SLOT (openRequest()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::SceneTool::openRequest()
|
void CSVWidget::SceneTool::openRequest()
|
||||||
{
|
{
|
||||||
showPanel (parentWidget()->mapToGlobal (pos()));
|
showPanel (parentWidget()->mapToGlobal (pos()));
|
||||||
}
|
}
|
@ -1,14 +1,14 @@
|
|||||||
#ifndef CSV_WORLD_SCENETOOL_H
|
#ifndef CSV_WIDGET_SCENETOOL_H
|
||||||
#define CSV_WORLD_SCENETOOL_H
|
#define CSV_WIDGET_SCENETOOL_H
|
||||||
|
|
||||||
#include <QPushButton>
|
#include "pushbutton.hpp"
|
||||||
|
|
||||||
namespace CSVWorld
|
namespace CSVWidget
|
||||||
{
|
{
|
||||||
class SceneToolbar;
|
class SceneToolbar;
|
||||||
|
|
||||||
///< \brief Tool base class
|
///< \brief Tool base class
|
||||||
class SceneTool : public QPushButton
|
class SceneTool : public PushButton
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
47
apps/opencs/view/widget/scenetoolbar.cpp
Normal file
47
apps/opencs/view/widget/scenetoolbar.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
#include "scenetoolbar.hpp"
|
||||||
|
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QShortcut>
|
||||||
|
|
||||||
|
#include "scenetool.hpp"
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolbar::focusInEvent (QFocusEvent *event)
|
||||||
|
{
|
||||||
|
QWidget::focusInEvent (event);
|
||||||
|
|
||||||
|
if (mLayout->count())
|
||||||
|
dynamic_cast<QWidgetItem&> (*mLayout->itemAt (0)).widget()->setFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVWidget::SceneToolbar::SceneToolbar (int buttonSize, QWidget *parent)
|
||||||
|
: QWidget (parent), mButtonSize (buttonSize), mIconSize (buttonSize-6)
|
||||||
|
{
|
||||||
|
setFixedWidth (mButtonSize);
|
||||||
|
|
||||||
|
mLayout = new QVBoxLayout (this);
|
||||||
|
mLayout->setAlignment (Qt::AlignTop);
|
||||||
|
|
||||||
|
mLayout->setContentsMargins (QMargins (0, 0, 0, 0));
|
||||||
|
|
||||||
|
setLayout (mLayout);
|
||||||
|
|
||||||
|
/// \todo make shortcut configurable
|
||||||
|
QShortcut *focusScene = new QShortcut (Qt::Key_T, this, 0, 0, Qt::WidgetWithChildrenShortcut);
|
||||||
|
connect (focusScene, SIGNAL (activated()), this, SIGNAL (focusSceneRequest()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolbar::addTool (SceneTool *tool)
|
||||||
|
{
|
||||||
|
mLayout->addWidget (tool, 0, Qt::AlignTop);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSVWidget::SceneToolbar::getButtonSize() const
|
||||||
|
{
|
||||||
|
return mButtonSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSVWidget::SceneToolbar::getIconSize() const
|
||||||
|
{
|
||||||
|
return mIconSize;
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
#ifndef CSV_WORLD_SCENETOOLBAR_H
|
#ifndef CSV_WIDGET_SCENETOOLBAR_H
|
||||||
#define CSV_WORLD_SCENETOOLBAR_H
|
#define CSV_WIDGET_SCENETOOLBAR_H
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
class QVBoxLayout;
|
class QVBoxLayout;
|
||||||
|
|
||||||
namespace CSVWorld
|
namespace CSVWidget
|
||||||
{
|
{
|
||||||
class SceneTool;
|
class SceneTool;
|
||||||
|
|
||||||
@ -17,6 +17,10 @@ namespace CSVWorld
|
|||||||
int mButtonSize;
|
int mButtonSize;
|
||||||
int mIconSize;
|
int mIconSize;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void focusInEvent (QFocusEvent *event);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SceneToolbar (int buttonSize, QWidget *parent = 0);
|
SceneToolbar (int buttonSize, QWidget *parent = 0);
|
||||||
@ -26,6 +30,10 @@ namespace CSVWorld
|
|||||||
int getButtonSize() const;
|
int getButtonSize() const;
|
||||||
|
|
||||||
int getIconSize() const;
|
int getIconSize() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void focusSceneRequest();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
86
apps/opencs/view/widget/scenetoolmode.cpp
Normal file
86
apps/opencs/view/widget/scenetoolmode.cpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
|
||||||
|
#include "scenetoolmode.hpp"
|
||||||
|
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QFrame>
|
||||||
|
#include <QSignalMapper>
|
||||||
|
|
||||||
|
#include "scenetoolbar.hpp"
|
||||||
|
#include "pushbutton.hpp"
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolMode::adjustToolTip (const PushButton *activeMode)
|
||||||
|
{
|
||||||
|
QString toolTip = mToolTip;
|
||||||
|
|
||||||
|
toolTip += "<p>Currently selected: " + activeMode->getBaseToolTip();
|
||||||
|
|
||||||
|
toolTip += "<p>(left click to change mode)";
|
||||||
|
|
||||||
|
setToolTip (toolTip);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVWidget::SceneToolMode::SceneToolMode (SceneToolbar *parent, const QString& toolTip)
|
||||||
|
: SceneTool (parent), mButtonSize (parent->getButtonSize()), mIconSize (parent->getIconSize()),
|
||||||
|
mToolTip (toolTip), mFirst (0)
|
||||||
|
{
|
||||||
|
mPanel = new QFrame (this, Qt::Popup);
|
||||||
|
|
||||||
|
mLayout = new QHBoxLayout (mPanel);
|
||||||
|
|
||||||
|
mLayout->setContentsMargins (QMargins (0, 0, 0, 0));
|
||||||
|
|
||||||
|
mPanel->setLayout (mLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolMode::showPanel (const QPoint& position)
|
||||||
|
{
|
||||||
|
mPanel->move (position);
|
||||||
|
mPanel->show();
|
||||||
|
|
||||||
|
if (mFirst)
|
||||||
|
mFirst->setFocus (Qt::OtherFocusReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolMode::addButton (const std::string& icon, const std::string& id,
|
||||||
|
const QString& tooltip)
|
||||||
|
{
|
||||||
|
PushButton *button = new PushButton (QIcon (QPixmap (icon.c_str())), PushButton::Type_Mode,
|
||||||
|
tooltip, mPanel);
|
||||||
|
button->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||||
|
button->setIconSize (QSize (mIconSize, mIconSize));
|
||||||
|
button->setFixedSize (mButtonSize, mButtonSize);
|
||||||
|
|
||||||
|
mLayout->addWidget (button);
|
||||||
|
|
||||||
|
mButtons.insert (std::make_pair (button, id));
|
||||||
|
|
||||||
|
connect (button, SIGNAL (clicked()), this, SLOT (selected()));
|
||||||
|
|
||||||
|
if (mButtons.size()==1)
|
||||||
|
{
|
||||||
|
mFirst = button;
|
||||||
|
setIcon (button->icon());
|
||||||
|
button->setChecked (true);
|
||||||
|
adjustToolTip (button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWidget::SceneToolMode::selected()
|
||||||
|
{
|
||||||
|
std::map<PushButton *, std::string>::const_iterator iter =
|
||||||
|
mButtons.find (dynamic_cast<PushButton *> (sender()));
|
||||||
|
|
||||||
|
if (iter!=mButtons.end())
|
||||||
|
{
|
||||||
|
if (!iter->first->hasKeepOpen())
|
||||||
|
mPanel->hide();
|
||||||
|
|
||||||
|
for (std::map<PushButton *, std::string>::const_iterator iter2 = mButtons.begin();
|
||||||
|
iter2!=mButtons.end(); ++iter2)
|
||||||
|
iter2->first->setChecked (iter2==iter);
|
||||||
|
|
||||||
|
setIcon (iter->first->icon());
|
||||||
|
adjustToolTip (iter->first);
|
||||||
|
emit modeChanged (iter->second);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef CSV_WORLD_SCENETOOL_MODE_H
|
#ifndef CSV_WIDGET_SCENETOOL_MODE_H
|
||||||
#define CSV_WORLD_SCENETOOL_MODE_H
|
#define CSV_WIDGET_SCENETOOL_MODE_H
|
||||||
|
|
||||||
#include "scenetool.hpp"
|
#include "scenetool.hpp"
|
||||||
|
|
||||||
@ -7,9 +7,10 @@
|
|||||||
|
|
||||||
class QHBoxLayout;
|
class QHBoxLayout;
|
||||||
|
|
||||||
namespace CSVWorld
|
namespace CSVWidget
|
||||||
{
|
{
|
||||||
class SceneToolbar;
|
class SceneToolbar;
|
||||||
|
class PushButton;
|
||||||
|
|
||||||
///< \brief Mode selector tool
|
///< \brief Mode selector tool
|
||||||
class SceneToolMode : public SceneTool
|
class SceneToolMode : public SceneTool
|
||||||
@ -18,17 +19,22 @@ namespace CSVWorld
|
|||||||
|
|
||||||
QWidget *mPanel;
|
QWidget *mPanel;
|
||||||
QHBoxLayout *mLayout;
|
QHBoxLayout *mLayout;
|
||||||
std::map<QPushButton *, std::string> mButtons; // widget, id
|
std::map<PushButton *, std::string> mButtons; // widget, id
|
||||||
int mButtonSize;
|
int mButtonSize;
|
||||||
int mIconSize;
|
int mIconSize;
|
||||||
|
QString mToolTip;
|
||||||
|
PushButton *mFirst;
|
||||||
|
|
||||||
|
void adjustToolTip (const PushButton *activeMode);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SceneToolMode (SceneToolbar *parent);
|
SceneToolMode (SceneToolbar *parent, const QString& toolTip);
|
||||||
|
|
||||||
virtual void showPanel (const QPoint& position);
|
virtual void showPanel (const QPoint& position);
|
||||||
|
|
||||||
void addButton (const std::string& icon, const std::string& id);
|
void addButton (const std::string& icon, const std::string& id,
|
||||||
|
const QString& tooltip = "");
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
@ -426,25 +426,32 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM
|
|||||||
QHBoxLayout *buttonsLayout = new QHBoxLayout;
|
QHBoxLayout *buttonsLayout = new QHBoxLayout;
|
||||||
QToolButton* prevButton = new QToolButton(mainWidget);
|
QToolButton* prevButton = new QToolButton(mainWidget);
|
||||||
prevButton->setIcon(QIcon(":/go-previous.png"));
|
prevButton->setIcon(QIcon(":/go-previous.png"));
|
||||||
|
prevButton->setToolTip ("Switch to previous record");
|
||||||
QToolButton* nextButton = new QToolButton(mainWidget);
|
QToolButton* nextButton = new QToolButton(mainWidget);
|
||||||
nextButton->setIcon(QIcon(":/go-next.png"));
|
nextButton->setIcon(QIcon(":/go-next.png"));
|
||||||
|
nextButton->setToolTip ("Switch to next record");
|
||||||
buttonsLayout->addWidget(prevButton, 0);
|
buttonsLayout->addWidget(prevButton, 0);
|
||||||
buttonsLayout->addWidget(nextButton, 1);
|
buttonsLayout->addWidget(nextButton, 1);
|
||||||
buttonsLayout->addStretch(2);
|
buttonsLayout->addStretch(2);
|
||||||
|
|
||||||
QToolButton* cloneButton = new QToolButton(mainWidget);
|
QToolButton* cloneButton = new QToolButton(mainWidget);
|
||||||
cloneButton->setIcon(QIcon(":/edit-clone.png"));
|
cloneButton->setIcon(QIcon(":/edit-clone.png"));
|
||||||
|
cloneButton->setToolTip ("Clone record");
|
||||||
QToolButton* addButton = new QToolButton(mainWidget);
|
QToolButton* addButton = new QToolButton(mainWidget);
|
||||||
addButton->setIcon(QIcon(":/add.png"));
|
addButton->setIcon(QIcon(":/add.png"));
|
||||||
|
addButton->setToolTip ("Add new record");
|
||||||
QToolButton* deleteButton = new QToolButton(mainWidget);
|
QToolButton* deleteButton = new QToolButton(mainWidget);
|
||||||
deleteButton->setIcon(QIcon(":/edit-delete.png"));
|
deleteButton->setIcon(QIcon(":/edit-delete.png"));
|
||||||
|
deleteButton->setToolTip ("Delete record");
|
||||||
QToolButton* revertButton = new QToolButton(mainWidget);
|
QToolButton* revertButton = new QToolButton(mainWidget);
|
||||||
revertButton->setIcon(QIcon(":/edit-undo.png"));
|
revertButton->setIcon(QIcon(":/edit-undo.png"));
|
||||||
|
revertButton->setToolTip ("Revert record");
|
||||||
|
|
||||||
if (mTable->getFeatures() & CSMWorld::IdTable::Feature_Preview)
|
if (mTable->getFeatures() & CSMWorld::IdTable::Feature_Preview)
|
||||||
{
|
{
|
||||||
QToolButton* previewButton = new QToolButton(mainWidget);
|
QToolButton* previewButton = new QToolButton(mainWidget);
|
||||||
previewButton->setIcon(QIcon(":/edit-preview.png"));
|
previewButton->setIcon(QIcon(":/edit-preview.png"));
|
||||||
|
previewButton->setToolTip ("Open a preview of this record");
|
||||||
buttonsLayout->addWidget(previewButton);
|
buttonsLayout->addWidget(previewButton);
|
||||||
connect(previewButton, SIGNAL(clicked()), this, SLOT(showPreview()));
|
connect(previewButton, SIGNAL(clicked()), this, SLOT(showPreview()));
|
||||||
}
|
}
|
||||||
@ -453,6 +460,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM
|
|||||||
{
|
{
|
||||||
QToolButton* viewButton = new QToolButton(mainWidget);
|
QToolButton* viewButton = new QToolButton(mainWidget);
|
||||||
viewButton->setIcon(QIcon(":/cell.png"));
|
viewButton->setIcon(QIcon(":/cell.png"));
|
||||||
|
viewButton->setToolTip ("Open a scene view of the cell this record is located in");
|
||||||
buttonsLayout->addWidget(viewButton);
|
buttonsLayout->addWidget(viewButton);
|
||||||
connect(viewButton, SIGNAL(clicked()), this, SLOT(viewRecord()));
|
connect(viewButton, SIGNAL(clicked()), this, SLOT(viewRecord()));
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
#include "../render/previewwidget.hpp"
|
#include "../render/previewwidget.hpp"
|
||||||
|
|
||||||
#include "scenetoolbar.hpp"
|
#include "../widget/scenetoolbar.hpp"
|
||||||
#include "scenetoolmode.hpp"
|
#include "../widget/scenetoolmode.hpp"
|
||||||
|
|
||||||
CSVWorld::PreviewSubView::PreviewSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
|
CSVWorld::PreviewSubView::PreviewSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
|
||||||
: SubView (id)
|
: SubView (id)
|
||||||
@ -28,9 +28,9 @@ CSVWorld::PreviewSubView::PreviewSubView (const CSMWorld::UniversalId& id, CSMDo
|
|||||||
else
|
else
|
||||||
mScene = new CSVRender::PreviewWidget (document.getData(), id.getId(), true, this);
|
mScene = new CSVRender::PreviewWidget (document.getData(), id.getId(), true, this);
|
||||||
|
|
||||||
SceneToolbar *toolbar = new SceneToolbar (48+6, this);
|
CSVWidget::SceneToolbar *toolbar = new CSVWidget::SceneToolbar (48+6, this);
|
||||||
|
|
||||||
SceneToolMode *lightingTool = mScene->makeLightingSelector (toolbar);
|
CSVWidget::SceneToolMode *lightingTool = mScene->makeLightingSelector (toolbar);
|
||||||
toolbar->addTool (lightingTool);
|
toolbar->addTool (lightingTool);
|
||||||
|
|
||||||
layout->addWidget (toolbar, 0);
|
layout->addWidget (toolbar, 0);
|
||||||
@ -46,6 +46,8 @@ CSVWorld::PreviewSubView::PreviewSubView (const CSMWorld::UniversalId& id, CSMDo
|
|||||||
connect (mScene, SIGNAL (closeRequest()), this, SLOT (closeRequest()));
|
connect (mScene, SIGNAL (closeRequest()), this, SLOT (closeRequest()));
|
||||||
connect (mScene, SIGNAL (referenceableIdChanged (const std::string&)),
|
connect (mScene, SIGNAL (referenceableIdChanged (const std::string&)),
|
||||||
this, SLOT (referenceableIdChanged (const std::string&)));
|
this, SLOT (referenceableIdChanged (const std::string&)));
|
||||||
|
connect (mScene, SIGNAL (focusToolbarRequest()), toolbar, SLOT (setFocus()));
|
||||||
|
connect (toolbar, SIGNAL (focusSceneRequest()), mScene, SLOT (setFocus()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::PreviewSubView::setEditLock (bool locked) {}
|
void CSVWorld::PreviewSubView::setEditLock (bool locked) {}
|
||||||
|
@ -17,9 +17,11 @@
|
|||||||
#include "../render/pagedworldspacewidget.hpp"
|
#include "../render/pagedworldspacewidget.hpp"
|
||||||
#include "../render/unpagedworldspacewidget.hpp"
|
#include "../render/unpagedworldspacewidget.hpp"
|
||||||
|
|
||||||
|
#include "../widget/scenetoolbar.hpp"
|
||||||
|
#include "../widget/scenetoolmode.hpp"
|
||||||
|
|
||||||
#include "tablebottombox.hpp"
|
#include "tablebottombox.hpp"
|
||||||
#include "creator.hpp"
|
#include "creator.hpp"
|
||||||
#include "scenetoolmode.hpp"
|
|
||||||
|
|
||||||
CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
|
CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
|
||||||
: SubView (id), mLayout(new QHBoxLayout), mDocument(document), mScene(NULL), mToolbar(NULL)
|
: SubView (id), mLayout(new QHBoxLayout), mDocument(document), mScene(NULL), mToolbar(NULL)
|
||||||
@ -95,18 +97,18 @@ void CSVWorld::SceneSubView::makeConnections (CSVRender::PagedWorldspaceWidget*
|
|||||||
this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&)));
|
this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&)));
|
||||||
}
|
}
|
||||||
|
|
||||||
CSVWorld::SceneToolbar* CSVWorld::SceneSubView::makeToolbar (CSVRender::WorldspaceWidget* widget, widgetType type)
|
CSVWidget::SceneToolbar* CSVWorld::SceneSubView::makeToolbar (CSVRender::WorldspaceWidget* widget, widgetType type)
|
||||||
{
|
{
|
||||||
CSVWorld::SceneToolbar* toolbar = new SceneToolbar (48+6, this);
|
CSVWidget::SceneToolbar* toolbar = new CSVWidget::SceneToolbar (48+6, this);
|
||||||
|
|
||||||
SceneToolMode *navigationTool = widget->makeNavigationSelector (toolbar);
|
CSVWidget::SceneToolMode *navigationTool = widget->makeNavigationSelector (toolbar);
|
||||||
toolbar->addTool (navigationTool);
|
toolbar->addTool (navigationTool);
|
||||||
|
|
||||||
SceneToolMode *lightingTool = widget->makeLightingSelector (toolbar);
|
CSVWidget::SceneToolMode *lightingTool = widget->makeLightingSelector (toolbar);
|
||||||
toolbar->addTool (lightingTool);
|
toolbar->addTool (lightingTool);
|
||||||
|
|
||||||
/* Add buttons specific to the type. For now no need for it.
|
/* Add buttons specific to the type. For now no need for it.
|
||||||
*
|
*
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case widget_Paged:
|
case widget_Paged:
|
||||||
@ -188,7 +190,7 @@ void CSVWorld::SceneSubView::handleDrop (const std::vector< CSMWorld::UniversalI
|
|||||||
{
|
{
|
||||||
CSVRender::PagedWorldspaceWidget* pagedNewWidget = NULL;
|
CSVRender::PagedWorldspaceWidget* pagedNewWidget = NULL;
|
||||||
CSVRender::UnpagedWorldspaceWidget* unPagedNewWidget = NULL;
|
CSVRender::UnpagedWorldspaceWidget* unPagedNewWidget = NULL;
|
||||||
SceneToolbar* toolbar = NULL;
|
CSVWidget::SceneToolbar* toolbar = NULL;
|
||||||
|
|
||||||
switch (mScene->getDropRequirements(CSVRender::WorldspaceWidget::getDropType(data)))
|
switch (mScene->getDropRequirements(CSVRender::WorldspaceWidget::getDropType(data)))
|
||||||
{
|
{
|
||||||
@ -217,7 +219,7 @@ void CSVWorld::SceneSubView::handleDrop (const std::vector< CSMWorld::UniversalI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceWidget* widget, CSVWorld::SceneToolbar* toolbar)
|
void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceWidget* widget, CSVWidget::SceneToolbar* toolbar)
|
||||||
{
|
{
|
||||||
assert(mLayout);
|
assert(mLayout);
|
||||||
|
|
||||||
@ -236,8 +238,12 @@ void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceW
|
|||||||
mScene = widget;
|
mScene = widget;
|
||||||
mToolbar = toolbar;
|
mToolbar = toolbar;
|
||||||
|
|
||||||
|
connect (mScene, SIGNAL (focusToolbarRequest()), mToolbar, SLOT (setFocus()));
|
||||||
|
connect (mToolbar, SIGNAL (focusSceneRequest()), mScene, SLOT (setFocus()));
|
||||||
|
|
||||||
mLayout->addWidget (mToolbar, 0);
|
mLayout->addWidget (mToolbar, 0);
|
||||||
mLayout->addWidget (mScene, 1);
|
mLayout->addWidget (mScene, 1);
|
||||||
|
|
||||||
mScene->selectDefaultNavigationMode();
|
mScene->selectDefaultNavigationMode();
|
||||||
|
setFocusProxy (mScene);
|
||||||
}
|
}
|
@ -4,7 +4,6 @@
|
|||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
#include "../doc/subview.hpp"
|
#include "../doc/subview.hpp"
|
||||||
#include "scenetoolbar.hpp"
|
|
||||||
|
|
||||||
class QModelIndex;
|
class QModelIndex;
|
||||||
|
|
||||||
@ -25,6 +24,11 @@ namespace CSVRender
|
|||||||
class UnpagedWorldspaceWidget;
|
class UnpagedWorldspaceWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace CSVWidget
|
||||||
|
{
|
||||||
|
class SceneToolbar;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CSVWorld
|
namespace CSVWorld
|
||||||
{
|
{
|
||||||
class Table;
|
class Table;
|
||||||
@ -39,7 +43,7 @@ namespace CSVWorld
|
|||||||
CSVRender::WorldspaceWidget *mScene;
|
CSVRender::WorldspaceWidget *mScene;
|
||||||
QHBoxLayout* mLayout;
|
QHBoxLayout* mLayout;
|
||||||
CSMDoc::Document& mDocument;
|
CSMDoc::Document& mDocument;
|
||||||
SceneToolbar* mToolbar;
|
CSVWidget::SceneToolbar* mToolbar;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -59,14 +63,15 @@ namespace CSVWorld
|
|||||||
|
|
||||||
void makeConnections(CSVRender::UnpagedWorldspaceWidget* widget);
|
void makeConnections(CSVRender::UnpagedWorldspaceWidget* widget);
|
||||||
|
|
||||||
void replaceToolbarAndWorldspace(CSVRender::WorldspaceWidget* widget, SceneToolbar* toolbar);
|
void replaceToolbarAndWorldspace(CSVRender::WorldspaceWidget* widget, CSVWidget::SceneToolbar* toolbar);
|
||||||
|
|
||||||
enum widgetType
|
enum widgetType
|
||||||
{
|
{
|
||||||
widget_Paged,
|
widget_Paged,
|
||||||
widget_Unpaged
|
widget_Unpaged
|
||||||
};
|
};
|
||||||
SceneToolbar* makeToolbar(CSVRender::WorldspaceWidget* widget, widgetType type);
|
|
||||||
|
CSVWidget::SceneToolbar* makeToolbar(CSVRender::WorldspaceWidget* widget, widgetType type);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
|
|
||||||
#include "scenetoolbar.hpp"
|
|
||||||
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
#include "scenetool.hpp"
|
|
||||||
|
|
||||||
CSVWorld::SceneToolbar::SceneToolbar (int buttonSize, QWidget *parent)
|
|
||||||
: QWidget (parent), mButtonSize (buttonSize), mIconSize (buttonSize-6)
|
|
||||||
{
|
|
||||||
setFixedWidth (mButtonSize);
|
|
||||||
|
|
||||||
mLayout = new QVBoxLayout (this);
|
|
||||||
mLayout->setAlignment (Qt::AlignTop);
|
|
||||||
|
|
||||||
mLayout->setContentsMargins (QMargins (0, 0, 0, 0));
|
|
||||||
|
|
||||||
setLayout (mLayout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSVWorld::SceneToolbar::addTool (SceneTool *tool)
|
|
||||||
{
|
|
||||||
mLayout->addWidget (tool, 0, Qt::AlignTop);
|
|
||||||
}
|
|
||||||
|
|
||||||
int CSVWorld::SceneToolbar::getButtonSize() const
|
|
||||||
{
|
|
||||||
return mButtonSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CSVWorld::SceneToolbar::getIconSize() const
|
|
||||||
{
|
|
||||||
return mIconSize;
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
|
|
||||||
#include "scenetoolmode.hpp"
|
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QFrame>
|
|
||||||
#include <QSignalMapper>
|
|
||||||
|
|
||||||
#include "scenetoolbar.hpp"
|
|
||||||
|
|
||||||
CSVWorld::SceneToolMode::SceneToolMode (SceneToolbar *parent)
|
|
||||||
: SceneTool (parent), mButtonSize (parent->getButtonSize()), mIconSize (parent->getIconSize())
|
|
||||||
{
|
|
||||||
mPanel = new QFrame (this, Qt::Popup);
|
|
||||||
|
|
||||||
mLayout = new QHBoxLayout (mPanel);
|
|
||||||
|
|
||||||
mLayout->setContentsMargins (QMargins (0, 0, 0, 0));
|
|
||||||
|
|
||||||
mPanel->setLayout (mLayout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSVWorld::SceneToolMode::showPanel (const QPoint& position)
|
|
||||||
{
|
|
||||||
mPanel->move (position);
|
|
||||||
mPanel->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSVWorld::SceneToolMode::addButton (const std::string& icon, const std::string& id)
|
|
||||||
{
|
|
||||||
QPushButton *button = new QPushButton (QIcon (QPixmap (icon.c_str())), "", mPanel);
|
|
||||||
button->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
|
|
||||||
button->setIconSize (QSize (mIconSize, mIconSize));
|
|
||||||
button->setFixedSize (mButtonSize, mButtonSize);
|
|
||||||
|
|
||||||
mLayout->addWidget (button);
|
|
||||||
|
|
||||||
mButtons.insert (std::make_pair (button, id));
|
|
||||||
|
|
||||||
connect (button, SIGNAL (clicked()), this, SLOT (selected()));
|
|
||||||
|
|
||||||
if (mButtons.size()==1)
|
|
||||||
setIcon (button->icon());
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSVWorld::SceneToolMode::selected()
|
|
||||||
{
|
|
||||||
std::map<QPushButton *, std::string>::const_iterator iter =
|
|
||||||
mButtons.find (dynamic_cast<QPushButton *> (sender()));
|
|
||||||
|
|
||||||
if (iter!=mButtons.end())
|
|
||||||
{
|
|
||||||
mPanel->hide();
|
|
||||||
|
|
||||||
setIcon (iter->first->icon());
|
|
||||||
emit modeChanged (iter->second);
|
|
||||||
}
|
|
||||||
}
|
|
@ -70,6 +70,21 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
|||||||
manager.add (CSMWorld::UniversalId::Type_JournalInfos,
|
manager.add (CSMWorld::UniversalId::Type_JournalInfos,
|
||||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<InfoCreator> > (false));
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<InfoCreator> > (false));
|
||||||
|
|
||||||
|
// Subviews for resources tables
|
||||||
|
manager.add (CSMWorld::UniversalId::Type_Meshes,
|
||||||
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, NullCreatorFactory>);
|
||||||
|
manager.add (CSMWorld::UniversalId::Type_Icons,
|
||||||
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, NullCreatorFactory>);
|
||||||
|
manager.add (CSMWorld::UniversalId::Type_Musics,
|
||||||
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, NullCreatorFactory>);
|
||||||
|
manager.add (CSMWorld::UniversalId::Type_SoundsRes,
|
||||||
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, NullCreatorFactory>);
|
||||||
|
manager.add (CSMWorld::UniversalId::Type_Textures,
|
||||||
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, NullCreatorFactory>);
|
||||||
|
manager.add (CSMWorld::UniversalId::Type_Videos,
|
||||||
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, NullCreatorFactory>);
|
||||||
|
|
||||||
|
|
||||||
// Subviews for editing/viewing individual records
|
// Subviews for editing/viewing individual records
|
||||||
manager.add (CSMWorld::UniversalId::Type_Script, new CSVDoc::SubViewFactory<ScriptSubView>);
|
manager.add (CSMWorld::UniversalId::Type_Script, new CSVDoc::SubViewFactory<ScriptSubView>);
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "../../model/world/data.hpp"
|
#include "../../model/world/data.hpp"
|
||||||
#include "../../model/world/commands.hpp"
|
#include "../../model/world/commands.hpp"
|
||||||
#include "../../model/world/idtableproxymodel.hpp"
|
#include "../../model/world/idtableproxymodel.hpp"
|
||||||
|
#include "../../model/world/idtablebase.hpp"
|
||||||
#include "../../model/world/idtable.hpp"
|
#include "../../model/world/idtable.hpp"
|
||||||
#include "../../model/world/record.hpp"
|
#include "../../model/world/record.hpp"
|
||||||
#include "../../model/world/columns.hpp"
|
#include "../../model/world/columns.hpp"
|
||||||
@ -53,7 +54,7 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
|||||||
|
|
||||||
/// \todo add menu items for select all and clear selection
|
/// \todo add menu items for select all and clear selection
|
||||||
|
|
||||||
if (!mEditLock)
|
if (!mEditLock && !(mModel->getFeatures() & CSMWorld::IdTableBase::Feature_Constant))
|
||||||
{
|
{
|
||||||
if (selectedRows.size()==1)
|
if (selectedRows.size()==1)
|
||||||
{
|
{
|
||||||
@ -82,7 +83,7 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
|||||||
menu.addAction (mExtendedDeleteAction);
|
menu.addAction (mExtendedDeleteAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mModel->getFeatures() & CSMWorld::IdTable::Feature_ReorderWithinTopic)
|
if (mModel->getFeatures() & CSMWorld::IdTableBase::Feature_ReorderWithinTopic)
|
||||||
{
|
{
|
||||||
/// \todo allow reordering of multiple rows
|
/// \todo allow reordering of multiple rows
|
||||||
if (selectedRows.size()==1)
|
if (selectedRows.size()==1)
|
||||||
@ -119,7 +120,7 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
|||||||
|
|
||||||
row = mProxyModel->mapToSource (mProxyModel->index (row, 0)).row();
|
row = mProxyModel->mapToSource (mProxyModel->index (row, 0)).row();
|
||||||
|
|
||||||
if (mModel->getFeatures() & CSMWorld::IdTable::Feature_View)
|
if (mModel->getFeatures() & CSMWorld::IdTableBase::Feature_View)
|
||||||
{
|
{
|
||||||
CSMWorld::UniversalId id = mModel->view (row).first;
|
CSMWorld::UniversalId id = mModel->view (row).first;
|
||||||
|
|
||||||
@ -131,7 +132,7 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
|||||||
menu.addAction (mViewAction);
|
menu.addAction (mViewAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mModel->getFeatures() & CSMWorld::IdTable::Feature_Preview)
|
if (mModel->getFeatures() & CSMWorld::IdTableBase::Feature_Preview)
|
||||||
{
|
{
|
||||||
QModelIndex index = mModel->index (row,
|
QModelIndex index = mModel->index (row,
|
||||||
mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Modification));
|
mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Modification));
|
||||||
@ -152,7 +153,7 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
|||||||
: mCreateAction (0), mCloneAction(0), mRecordStatusDisplay (0),
|
: mCreateAction (0), mCloneAction(0), mRecordStatusDisplay (0),
|
||||||
DragRecordTable(document)
|
DragRecordTable(document)
|
||||||
{
|
{
|
||||||
mModel = &dynamic_cast<CSMWorld::IdTable&> (*mDocument.getData().getTableModel (id));
|
mModel = &dynamic_cast<CSMWorld::IdTableBase&> (*mDocument.getData().getTableModel (id));
|
||||||
|
|
||||||
mProxyModel = new CSMWorld::IdTableProxyModel (this);
|
mProxyModel = new CSMWorld::IdTableProxyModel (this);
|
||||||
mProxyModel->setSourceModel (mModel);
|
mProxyModel->setSourceModel (mModel);
|
||||||
@ -275,7 +276,7 @@ CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const
|
|||||||
|
|
||||||
void CSVWorld::Table::editRecord()
|
void CSVWorld::Table::editRecord()
|
||||||
{
|
{
|
||||||
if (!mEditLock)
|
if (!mEditLock || (mModel->getFeatures() & CSMWorld::IdTableBase::Feature_Constant))
|
||||||
{
|
{
|
||||||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||||
|
|
||||||
@ -286,11 +287,11 @@ void CSVWorld::Table::editRecord()
|
|||||||
|
|
||||||
void CSVWorld::Table::cloneRecord()
|
void CSVWorld::Table::cloneRecord()
|
||||||
{
|
{
|
||||||
if (!mEditLock)
|
if (!mEditLock || (mModel->getFeatures() & CSMWorld::IdTableBase::Feature_Constant))
|
||||||
{
|
{
|
||||||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||||
const CSMWorld::UniversalId& toClone = getUniversalId(selectedRows.begin()->row());
|
const CSMWorld::UniversalId& toClone = getUniversalId(selectedRows.begin()->row());
|
||||||
if (selectedRows.size()==1 && !mModel->getRecord(toClone.getId()).isDeleted())
|
if (selectedRows.size()==1 && !mModel->isDeleted (toClone.getId()))
|
||||||
{
|
{
|
||||||
emit cloneRequest (toClone);
|
emit cloneRequest (toClone);
|
||||||
}
|
}
|
||||||
@ -299,7 +300,7 @@ void CSVWorld::Table::cloneRecord()
|
|||||||
|
|
||||||
void CSVWorld::Table::moveUpRecord()
|
void CSVWorld::Table::moveUpRecord()
|
||||||
{
|
{
|
||||||
if (mEditLock)
|
if (mEditLock || (mModel->getFeatures() & CSMWorld::IdTableBase::Feature_Constant))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||||
@ -324,14 +325,15 @@ void CSVWorld::Table::moveUpRecord()
|
|||||||
for (int i=1; i<row2-row; ++i)
|
for (int i=1; i<row2-row; ++i)
|
||||||
newOrder[i] = i;
|
newOrder[i] = i;
|
||||||
|
|
||||||
mDocument.getUndoStack().push (new CSMWorld::ReorderRowsCommand (*mModel, row, newOrder));
|
mDocument.getUndoStack().push (new CSMWorld::ReorderRowsCommand (
|
||||||
|
dynamic_cast<CSMWorld::IdTable&> (*mModel), row, newOrder));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::Table::moveDownRecord()
|
void CSVWorld::Table::moveDownRecord()
|
||||||
{
|
{
|
||||||
if (mEditLock)
|
if (mEditLock || (mModel->getFeatures() & CSMWorld::IdTableBase::Feature_Constant))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||||
@ -356,7 +358,8 @@ void CSVWorld::Table::moveDownRecord()
|
|||||||
for (int i=1; i<row2-row; ++i)
|
for (int i=1; i<row2-row; ++i)
|
||||||
newOrder[i] = i;
|
newOrder[i] = i;
|
||||||
|
|
||||||
mDocument.getUndoStack().push (new CSMWorld::ReorderRowsCommand (*mModel, row, newOrder));
|
mDocument.getUndoStack().push (new CSMWorld::ReorderRowsCommand (
|
||||||
|
dynamic_cast<CSMWorld::IdTable&> (*mModel), row, newOrder));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -422,21 +425,27 @@ void CSVWorld::Table::tableSizeUpdate()
|
|||||||
{
|
{
|
||||||
int rows = mProxyModel->rowCount();
|
int rows = mProxyModel->rowCount();
|
||||||
|
|
||||||
for (int i=0; i<rows; ++i)
|
int columnIndex = mModel->searchColumnIndex (CSMWorld::Columns::ColumnId_Modification);
|
||||||
|
|
||||||
|
if (columnIndex!=-1)
|
||||||
{
|
{
|
||||||
QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (i, 0));
|
for (int i=0; i<rows; ++i)
|
||||||
|
|
||||||
int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Modification);
|
|
||||||
int state = mModel->data (mModel->index (index.row(), columnIndex)).toInt();
|
|
||||||
|
|
||||||
switch (state)
|
|
||||||
{
|
{
|
||||||
case CSMWorld::RecordBase::State_BaseOnly: ++size; break;
|
QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (i, 0));
|
||||||
case CSMWorld::RecordBase::State_Modified: ++size; ++modified; break;
|
|
||||||
case CSMWorld::RecordBase::State_ModifiedOnly: ++size; ++modified; break;
|
int state = mModel->data (mModel->index (index.row(), columnIndex)).toInt();
|
||||||
case CSMWorld::RecordBase:: State_Deleted: ++deleted; ++modified; break;
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case CSMWorld::RecordBase::State_BaseOnly: ++size; break;
|
||||||
|
case CSMWorld::RecordBase::State_Modified: ++size; ++modified; break;
|
||||||
|
case CSMWorld::RecordBase::State_ModifiedOnly: ++size; ++modified; break;
|
||||||
|
case CSMWorld::RecordBase:: State_Deleted: ++deleted; ++modified; break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
size = rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
tableSizeChanged (size, deleted, modified);
|
tableSizeChanged (size, deleted, modified);
|
||||||
|
@ -23,7 +23,7 @@ namespace CSMWorld
|
|||||||
class Data;
|
class Data;
|
||||||
class UniversalId;
|
class UniversalId;
|
||||||
class IdTableProxyModel;
|
class IdTableProxyModel;
|
||||||
class IdTable;
|
class IdTableBase;
|
||||||
class CommandDispatcher;
|
class CommandDispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ namespace CSVWorld
|
|||||||
QAction *mExtendedDeleteAction;
|
QAction *mExtendedDeleteAction;
|
||||||
QAction *mExtendedRevertAction;
|
QAction *mExtendedRevertAction;
|
||||||
CSMWorld::IdTableProxyModel *mProxyModel;
|
CSMWorld::IdTableProxyModel *mProxyModel;
|
||||||
CSMWorld::IdTable *mModel;
|
CSMWorld::IdTableBase *mModel;
|
||||||
int mRecordStatusDisplay;
|
int mRecordStatusDisplay;
|
||||||
CSMWorld::CommandDispatcher *mDispatcher;
|
CSMWorld::CommandDispatcher *mDispatcher;
|
||||||
|
|
||||||
|
@ -143,49 +143,55 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (display != CSMWorld::ColumnBase::Display_None)
|
switch (display)
|
||||||
{
|
{
|
||||||
if (variant.type() == QVariant::Color)
|
case CSMWorld::ColumnBase::Display_Colour:
|
||||||
{
|
|
||||||
return new QLineEdit(parent);
|
return new QLineEdit(parent);
|
||||||
}
|
|
||||||
if (display == CSMWorld::ColumnBase::Display_Integer)
|
case CSMWorld::ColumnBase::Display_Integer:
|
||||||
{
|
|
||||||
return new QSpinBox(parent);
|
return new QSpinBox(parent);
|
||||||
}
|
|
||||||
if (display == CSMWorld::ColumnBase::Display_Var)
|
case CSMWorld::ColumnBase::Display_Var:
|
||||||
{
|
|
||||||
return new QLineEdit(parent);
|
return new QLineEdit(parent);
|
||||||
}
|
|
||||||
if (display == CSMWorld::ColumnBase::Display_Float)
|
case CSMWorld::ColumnBase::Display_Float:
|
||||||
{
|
|
||||||
return new QDoubleSpinBox(parent);
|
return new QDoubleSpinBox(parent);
|
||||||
}
|
|
||||||
if (display == CSMWorld::ColumnBase::Display_LongString)
|
case CSMWorld::ColumnBase::Display_LongString:
|
||||||
{
|
|
||||||
return new QTextEdit(parent);
|
return new QTextEdit(parent);
|
||||||
}
|
|
||||||
if (display == CSMWorld::ColumnBase::Display_String ||
|
case CSMWorld::ColumnBase::Display_Boolean:
|
||||||
display == CSMWorld::ColumnBase::Display_Skill ||
|
|
||||||
display == CSMWorld::ColumnBase::Display_Script ||
|
|
||||||
display == CSMWorld::ColumnBase::Display_Race ||
|
|
||||||
display == CSMWorld::ColumnBase::Display_Class ||
|
|
||||||
display == CSMWorld::ColumnBase::Display_Faction ||
|
|
||||||
display == CSMWorld::ColumnBase::Display_Miscellaneous ||
|
|
||||||
display == CSMWorld::ColumnBase::Display_Sound)
|
|
||||||
{
|
|
||||||
return new DropLineEdit(parent);
|
|
||||||
}
|
|
||||||
if (display == CSMWorld::ColumnBase::Display_Boolean)
|
|
||||||
{
|
|
||||||
return new QCheckBox(parent);
|
return new QCheckBox(parent);
|
||||||
}
|
|
||||||
|
case CSMWorld::ColumnBase::Display_String:
|
||||||
|
case CSMWorld::ColumnBase::Display_Skill:
|
||||||
|
case CSMWorld::ColumnBase::Display_Script:
|
||||||
|
case CSMWorld::ColumnBase::Display_Race:
|
||||||
|
case CSMWorld::ColumnBase::Display_Class:
|
||||||
|
case CSMWorld::ColumnBase::Display_Faction:
|
||||||
|
case CSMWorld::ColumnBase::Display_Miscellaneous:
|
||||||
|
case CSMWorld::ColumnBase::Display_Sound:
|
||||||
|
case CSMWorld::ColumnBase::Display_Mesh:
|
||||||
|
case CSMWorld::ColumnBase::Display_Icon:
|
||||||
|
case CSMWorld::ColumnBase::Display_Music:
|
||||||
|
case CSMWorld::ColumnBase::Display_SoundRes:
|
||||||
|
case CSMWorld::ColumnBase::Display_Texture:
|
||||||
|
case CSMWorld::ColumnBase::Display_Video:
|
||||||
|
|
||||||
|
return new DropLineEdit(parent);
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
return QStyledItemDelegate::createEditor (parent, option, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
return QStyledItemDelegate::createEditor (parent, option, index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CSVWorld::CommandDelegate::setEditLock (bool locked)
|
void CSVWorld::CommandDelegate::setEditLock (bool locked)
|
||||||
{
|
{
|
||||||
mEditLock = locked;
|
mEditLock = locked;
|
||||||
|
@ -69,7 +69,7 @@ add_openmw_dir (mwmechanics
|
|||||||
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
|
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
|
||||||
drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor
|
drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor
|
||||||
aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting
|
aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting
|
||||||
disease pickpocket levelledlist combat steering obstacle
|
disease pickpocket levelledlist combat steering obstacle autocalcspell
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwstate
|
add_openmw_dir (mwstate
|
||||||
|
@ -250,8 +250,11 @@ namespace MWClass
|
|||||||
text += "\n#{sTrapped}";
|
text += "\n#{sTrapped}";
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWindowManager()->getFullHelp())
|
if (MWBase::Environment::get().getWindowManager()->getFullHelp())
|
||||||
|
{
|
||||||
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
|
text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script");
|
||||||
|
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getOwner(), "Owner");
|
||||||
|
text += MWGui::ToolTips::getMiscString(ptr.getCellRef().getFaction(), "Faction");
|
||||||
|
}
|
||||||
info.text = text;
|
info.text = text;
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "../mwmechanics/spellcasting.hpp"
|
#include "../mwmechanics/spellcasting.hpp"
|
||||||
#include "../mwmechanics/disease.hpp"
|
#include "../mwmechanics/disease.hpp"
|
||||||
#include "../mwmechanics/combat.hpp"
|
#include "../mwmechanics/combat.hpp"
|
||||||
|
#include "../mwmechanics/autocalcspell.hpp"
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/actiontalk.hpp"
|
#include "../mwworld/actiontalk.hpp"
|
||||||
@ -53,6 +54,24 @@ namespace
|
|||||||
return new NpcCustomData (*this);
|
return new NpcCustomData (*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int is_even(double d) {
|
||||||
|
double int_part;
|
||||||
|
modf(d / 2.0, &int_part);
|
||||||
|
return 2.0 * int_part == d;
|
||||||
|
}
|
||||||
|
|
||||||
|
int round_ieee_754(double d) {
|
||||||
|
double i = floor(d);
|
||||||
|
d -= i;
|
||||||
|
if(d < 0.5)
|
||||||
|
return i;
|
||||||
|
if(d > 0.5)
|
||||||
|
return i + 1.0;
|
||||||
|
if(is_even(i))
|
||||||
|
return i;
|
||||||
|
return i + 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
void autoCalculateAttributes (const ESM::NPC* npc, MWMechanics::CreatureStats& creatureStats)
|
void autoCalculateAttributes (const ESM::NPC* npc, MWMechanics::CreatureStats& creatureStats)
|
||||||
{
|
{
|
||||||
// race bonus
|
// race bonus
|
||||||
@ -108,8 +127,9 @@ namespace
|
|||||||
}
|
}
|
||||||
modifierSum += add;
|
modifierSum += add;
|
||||||
}
|
}
|
||||||
creatureStats.setAttribute(attribute, std::min(creatureStats.getAttribute(attribute).getBase()
|
creatureStats.setAttribute(attribute, std::min(
|
||||||
+ static_cast<int>((level-1) * modifierSum+0.5), 100) );
|
round_ieee_754(creatureStats.getAttribute(attribute).getBase()
|
||||||
|
+ (level-1) * modifierSum), 100) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// initial health
|
// initial health
|
||||||
@ -193,18 +213,6 @@ namespace
|
|||||||
majorMultiplier = 1.0f;
|
majorMultiplier = 1.0f;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (class_->mData.mSkills[k][1] == skillIndex)
|
|
||||||
{
|
|
||||||
// Major skill -> add starting spells for this skill if existing
|
|
||||||
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
|
||||||
MWWorld::Store<ESM::Spell>::iterator it = store.get<ESM::Spell>().begin();
|
|
||||||
for (; it != store.get<ESM::Spell>().end(); ++it)
|
|
||||||
{
|
|
||||||
if (it->mData.mFlags & ESM::Spell::F_Autocalc
|
|
||||||
&& MWMechanics::spellSchoolToSkill(MWMechanics::getSpellSchool(&*it, ptr)) == skillIndex)
|
|
||||||
npcStats.getSpells().add(it->mId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// is this skill in the same Specialization as the class?
|
// is this skill in the same Specialization as the class?
|
||||||
@ -217,12 +225,25 @@ namespace
|
|||||||
|
|
||||||
npcStats.getSkill(skillIndex).setBase(
|
npcStats.getSkill(skillIndex).setBase(
|
||||||
std::min(
|
std::min(
|
||||||
npcStats.getSkill(skillIndex).getBase()
|
round_ieee_754(
|
||||||
|
npcStats.getSkill(skillIndex).getBase()
|
||||||
+ 5
|
+ 5
|
||||||
+ raceBonus
|
+ raceBonus
|
||||||
+ specBonus
|
+ specBonus
|
||||||
+ static_cast<int>((level-1) * (majorMultiplier + specMultiplier)), 100));
|
+(int(level)-1) * (majorMultiplier + specMultiplier)), 100)); // Must gracefully handle level 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int skills[ESM::Skill::Length];
|
||||||
|
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||||
|
skills[i] = npcStats.getSkill(i).getBase();
|
||||||
|
|
||||||
|
int attributes[ESM::Attribute::Length];
|
||||||
|
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||||
|
attributes[i] = npcStats.getAttribute(i).getBase();
|
||||||
|
|
||||||
|
std::vector<std::string> spells = MWMechanics::autoCalcNpcSpells(skills, attributes, race);
|
||||||
|
for (std::vector<std::string>::iterator it = spells.begin(); it != spells.end(); ++it)
|
||||||
|
npcStats.getSpells().add(*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,6 +153,11 @@ void CompanionWindow::onReferenceUnavailable()
|
|||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Companion);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Companion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CompanionWindow::resetReference()
|
||||||
|
{
|
||||||
|
ReferenceInterface::resetReference();
|
||||||
|
mItemView->setModel(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@ namespace MWGui
|
|||||||
|
|
||||||
virtual void exit();
|
virtual void exit();
|
||||||
|
|
||||||
|
virtual void resetReference();
|
||||||
|
|
||||||
void open(const MWWorld::Ptr& npc);
|
void open(const MWWorld::Ptr& npc);
|
||||||
void onFrame ();
|
void onFrame ();
|
||||||
|
|
||||||
|
@ -258,6 +258,12 @@ namespace MWGui
|
|||||||
onTakeAllButtonClicked(mTakeButton);
|
onTakeAllButtonClicked(mTakeButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ContainerWindow::resetReference()
|
||||||
|
{
|
||||||
|
ReferenceInterface::resetReference();
|
||||||
|
mItemView->setModel(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void ContainerWindow::close()
|
void ContainerWindow::close()
|
||||||
{
|
{
|
||||||
WindowBase::close();
|
WindowBase::close();
|
||||||
|
@ -54,6 +54,8 @@ namespace MWGui
|
|||||||
void open(const MWWorld::Ptr& container, bool loot=false);
|
void open(const MWWorld::Ptr& container, bool loot=false);
|
||||||
virtual void close();
|
virtual void close();
|
||||||
|
|
||||||
|
virtual void resetReference();
|
||||||
|
|
||||||
virtual void exit();
|
virtual void exit();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -260,21 +260,28 @@ namespace MWGui
|
|||||||
|
|
||||||
// More hacks! The french game uses several win1252 characters that are not included
|
// More hacks! The french game uses several win1252 characters that are not included
|
||||||
// in the cp437 encoding of the font. Fall back to similar available characters.
|
// in the cp437 encoding of the font. Fall back to similar available characters.
|
||||||
// Same for U+2013
|
if (mEncoding == ToUTF8::CP437)
|
||||||
std::map<int, int> additional;
|
|
||||||
additional[39] = 0x2019; // apostrophe
|
|
||||||
additional[45] = 0x2013; // dash
|
|
||||||
if (additional.find(i) != additional.end() && mEncoding == ToUTF8::CP437)
|
|
||||||
{
|
{
|
||||||
MyGUI::xml::ElementPtr code = codes->createChild("Code");
|
std::multimap<int, int> additional;
|
||||||
code->addAttribute("index", additional[i]);
|
additional.insert(std::make_pair(39, 0x2019)); // apostrophe
|
||||||
code->addAttribute("coord", MyGUI::utility::toString(x1) + " "
|
additional.insert(std::make_pair(45, 0x2013)); // dash
|
||||||
+ MyGUI::utility::toString(y1) + " "
|
additional.insert(std::make_pair(34, 0x201D)); // right double quotation mark
|
||||||
+ MyGUI::utility::toString(w) + " "
|
additional.insert(std::make_pair(34, 0x201C)); // left double quotation mark
|
||||||
+ MyGUI::utility::toString(h));
|
for (std::multimap<int, int>::iterator it = additional.begin(); it != additional.end(); ++it)
|
||||||
code->addAttribute("advance", data[i].width);
|
{
|
||||||
code->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " "
|
if (it->first != i)
|
||||||
+ MyGUI::utility::toString((fontSize-data[i].ascent)));
|
continue;
|
||||||
|
|
||||||
|
MyGUI::xml::ElementPtr code = codes->createChild("Code");
|
||||||
|
code->addAttribute("index", it->second);
|
||||||
|
code->addAttribute("coord", MyGUI::utility::toString(x1) + " "
|
||||||
|
+ MyGUI::utility::toString(y1) + " "
|
||||||
|
+ MyGUI::utility::toString(w) + " "
|
||||||
|
+ MyGUI::utility::toString(h));
|
||||||
|
code->addAttribute("advance", data[i].width);
|
||||||
|
code->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " "
|
||||||
|
+ MyGUI::utility::toString((fontSize-data[i].ascent)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ASCII vertical bar, use this as text input cursor
|
// ASCII vertical bar, use this as text input cursor
|
||||||
|
@ -140,26 +140,28 @@ void ItemView::onMouseWheel(MyGUI::Widget *_sender, int _rel)
|
|||||||
|
|
||||||
void ItemView::setSize(const MyGUI::IntSize &_value)
|
void ItemView::setSize(const MyGUI::IntSize &_value)
|
||||||
{
|
{
|
||||||
|
bool changed = (_value.width != getWidth() || _value.height != getHeight());
|
||||||
Base::setSize(_value);
|
Base::setSize(_value);
|
||||||
update();
|
if (changed)
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemView::setSize(int _width, int _height)
|
void ItemView::setSize(int _width, int _height)
|
||||||
{
|
{
|
||||||
Base::setSize(_width, _height);
|
setSize(MyGUI::IntSize(_width, _height));
|
||||||
update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemView::setCoord(const MyGUI::IntCoord &_value)
|
void ItemView::setCoord(const MyGUI::IntCoord &_value)
|
||||||
{
|
{
|
||||||
|
bool changed = (_value.width != getWidth() || _value.height != getHeight());
|
||||||
Base::setCoord(_value);
|
Base::setCoord(_value);
|
||||||
update();
|
if (changed)
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemView::setCoord(int _left, int _top, int _width, int _height)
|
void ItemView::setCoord(int _left, int _top, int _width, int _height)
|
||||||
{
|
{
|
||||||
Base::setCoord(_left, _top, _width, _height);
|
setCoord(MyGUI::IntCoord(_left, _top, _width, _height));
|
||||||
update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemView::registerComponents()
|
void ItemView::registerComponents()
|
||||||
|
@ -16,9 +16,10 @@
|
|||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
const unsigned int LevelupDialog::sMaxCoins = 3;
|
||||||
LevelupDialog::LevelupDialog()
|
LevelupDialog::LevelupDialog()
|
||||||
: WindowBase("openmw_levelup_dialog.layout")
|
: WindowBase("openmw_levelup_dialog.layout"),
|
||||||
|
mCoinCount(sMaxCoins)
|
||||||
{
|
{
|
||||||
getWidget(mOkButton, "OkButton");
|
getWidget(mOkButton, "OkButton");
|
||||||
getWidget(mClassImage, "ClassImage");
|
getWidget(mClassImage, "ClassImage");
|
||||||
@ -46,12 +47,10 @@ namespace MWGui
|
|||||||
mAttributeMultipliers.push_back(t);
|
mAttributeMultipliers.push_back(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
int curX = mMainWidget->getWidth()/2 - (16 + 2) * 1.5;
|
for (unsigned int i = 0; i < mCoinCount; ++i)
|
||||||
for (int i=0; i<3; ++i)
|
|
||||||
{
|
{
|
||||||
MyGUI::ImageBox* image = mMainWidget->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(curX,250,16,16), MyGUI::Align::Default);
|
MyGUI::ImageBox* image = mCoinBox->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(0,0,16,16), MyGUI::Align::Default);
|
||||||
image->setImageTexture ("icons\\tx_goldicon.dds");
|
image->setImageTexture ("icons\\tx_goldicon.dds");
|
||||||
curX += 24+2;
|
|
||||||
mCoins.push_back(image);
|
mCoins.push_back(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,15 +60,15 @@ namespace MWGui
|
|||||||
void LevelupDialog::setAttributeValues()
|
void LevelupDialog::setAttributeValues()
|
||||||
{
|
{
|
||||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
||||||
MWMechanics::CreatureStats& creatureStats = player.getClass().getCreatureStats (player);
|
MWMechanics::CreatureStats& creatureStats = player.getClass().getCreatureStats(player);
|
||||||
MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats (player);
|
MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats (player);
|
||||||
|
|
||||||
for (int i=0; i<8; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
int val = creatureStats.getAttribute (i).getBase ();
|
int val = creatureStats.getAttribute(i).getBase();
|
||||||
if (std::find(mSpentAttributes.begin(), mSpentAttributes.end(), i) != mSpentAttributes.end())
|
if (std::find(mSpentAttributes.begin(), mSpentAttributes.end(), i) != mSpentAttributes.end())
|
||||||
{
|
{
|
||||||
val += pcStats.getLevelupAttributeMultiplier (i);
|
val += pcStats.getLevelupAttributeMultiplier(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val >= 100)
|
if (val >= 100)
|
||||||
@ -80,20 +79,21 @@ namespace MWGui
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LevelupDialog::resetCoins ()
|
void LevelupDialog::resetCoins()
|
||||||
{
|
{
|
||||||
int curX = 0;
|
const int coinSpacing = 10;
|
||||||
for (int i=0; i<3; ++i)
|
int curX = mCoinBox->getWidth()/2 - (coinSpacing*(mCoinCount - 1) + 16*mCoinCount)/2;
|
||||||
|
for (unsigned int i=0; i<mCoinCount; ++i)
|
||||||
{
|
{
|
||||||
MyGUI::ImageBox* image = mCoins[i];
|
MyGUI::ImageBox* image = mCoins[i];
|
||||||
image->detachFromWidget();
|
image->detachFromWidget();
|
||||||
image->attachToWidget(mCoinBox);
|
image->attachToWidget(mCoinBox);
|
||||||
image->setCoord(MyGUI::IntCoord(curX,0,16,16));
|
image->setCoord(MyGUI::IntCoord(curX,0,16,16));
|
||||||
curX += 24+2;
|
curX += 16+coinSpacing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelupDialog::assignCoins ()
|
void LevelupDialog::assignCoins()
|
||||||
{
|
{
|
||||||
resetCoins();
|
resetCoins();
|
||||||
for (unsigned int i=0; i<mSpentAttributes.size(); ++i)
|
for (unsigned int i=0; i<mSpentAttributes.size(); ++i)
|
||||||
@ -118,13 +118,8 @@ namespace MWGui
|
|||||||
{
|
{
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
MWWorld::Ptr player = world->getPlayerPtr();
|
MWWorld::Ptr player = world->getPlayerPtr();
|
||||||
MWMechanics::CreatureStats& creatureStats = player.getClass().getCreatureStats (player);
|
MWMechanics::CreatureStats& creatureStats = player.getClass().getCreatureStats(player);
|
||||||
MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats (player);
|
MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats(player);
|
||||||
|
|
||||||
mSpentAttributes.clear();
|
|
||||||
resetCoins();
|
|
||||||
|
|
||||||
setAttributeValues();
|
|
||||||
|
|
||||||
const ESM::NPC *playerData = player.get<ESM::NPC>()->mBase;
|
const ESM::NPC *playerData = player.get<ESM::NPC>()->mBase;
|
||||||
|
|
||||||
@ -144,70 +139,98 @@ namespace MWGui
|
|||||||
if(it->mData.mIsPlayable && it->mData.mSpecialization == 2 && it->mData.mAttribute[0] == 4 && it->mData.mAttribute[1] == 3)
|
if(it->mData.mIsPlayable && it->mData.mSpecialization == 2 && it->mData.mAttribute[0] == 4 && it->mData.mAttribute[1] == 3)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mClassImage->setImageTexture ("textures\\levelup\\" + it->mId + ".dds");
|
mClassImage->setImageTexture("textures\\levelup\\" + it->mId + ".dds");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mClassImage->setImageTexture ("textures\\levelup\\" + cls->mId + ".dds");
|
mClassImage->setImageTexture("textures\\levelup\\" + cls->mId + ".dds");
|
||||||
|
|
||||||
int level = creatureStats.getLevel ()+1;
|
int level = creatureStats.getLevel ()+1;
|
||||||
mLevelText->setCaptionWithReplacing("#{sLevelUpMenu1} " + boost::lexical_cast<std::string>(level));
|
mLevelText->setCaptionWithReplacing("#{sLevelUpMenu1} " + boost::lexical_cast<std::string>(level));
|
||||||
|
|
||||||
std::string levelupdescription;
|
std::string levelupdescription;
|
||||||
if(level>20)
|
if(level > 20)
|
||||||
levelupdescription=world->getFallback()->getFallbackString("Level_Up_Default");
|
levelupdescription=world->getFallback()->getFallbackString("Level_Up_Default");
|
||||||
else
|
else
|
||||||
levelupdescription=world->getFallback()->getFallbackString("Level_Up_Level"+boost::lexical_cast<std::string>(level));
|
levelupdescription=world->getFallback()->getFallbackString("Level_Up_Level"+boost::lexical_cast<std::string>(level));
|
||||||
|
|
||||||
mLevelDescription->setCaption (levelupdescription);
|
mLevelDescription->setCaption (levelupdescription);
|
||||||
|
|
||||||
for (int i=0; i<8; ++i)
|
unsigned int availableAttributes = 0;
|
||||||
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
MyGUI::TextBox* text = mAttributeMultipliers[i];
|
MyGUI::TextBox* text = mAttributeMultipliers[i];
|
||||||
int mult = pcStats.getLevelupAttributeMultiplier (i);
|
if (pcStats.getAttribute(i).getBase() < 100)
|
||||||
text->setCaption(mult <= 1 ? "" : "x" + boost::lexical_cast<std::string>(mult));
|
{
|
||||||
|
mAttributes[i]->setEnabled(true);
|
||||||
|
availableAttributes++;
|
||||||
|
|
||||||
|
int mult = pcStats.getLevelupAttributeMultiplier (i);
|
||||||
|
text->setCaption(mult <= 1 ? "" : "x" + boost::lexical_cast<std::string>(mult));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mAttributes[i]->setEnabled(false);
|
||||||
|
|
||||||
|
text->setCaption("");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mCoinCount = std::min(sMaxCoins, availableAttributes);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < sMaxCoins; i++)
|
||||||
|
{
|
||||||
|
if (i < mCoinCount)
|
||||||
|
mCoins[i]->attachToWidget(mCoinBox);
|
||||||
|
else
|
||||||
|
mCoins[i]->detachFromWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
mSpentAttributes.clear();
|
||||||
|
resetCoins();
|
||||||
|
|
||||||
|
setAttributeValues();
|
||||||
|
|
||||||
center();
|
center();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelupDialog::onOkButtonClicked (MyGUI::Widget* sender)
|
void LevelupDialog::onOkButtonClicked(MyGUI::Widget* sender)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||||
MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats (player);
|
MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats (player);
|
||||||
|
|
||||||
if (mSpentAttributes.size() < 3)
|
if (mSpentAttributes.size() < mCoinCount)
|
||||||
MWBase::Environment::get().getWindowManager ()->messageBox("#{sNotifyMessage36}");
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage36}");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// increase attributes
|
// increase attributes
|
||||||
for (int i=0; i<3; ++i)
|
for (unsigned int i = 0; i < mCoinCount; ++i)
|
||||||
{
|
{
|
||||||
MWMechanics::AttributeValue attribute = pcStats.getAttribute(mSpentAttributes[i]);
|
MWMechanics::AttributeValue attribute = pcStats.getAttribute(mSpentAttributes[i]);
|
||||||
attribute.setBase (attribute.getBase () + pcStats.getLevelupAttributeMultiplier (mSpentAttributes[i]));
|
attribute.setBase(attribute.getBase() + pcStats.getLevelupAttributeMultiplier(mSpentAttributes[i]));
|
||||||
|
|
||||||
if (attribute.getBase() >= 100)
|
if (attribute.getBase() >= 100)
|
||||||
attribute.setBase(100);
|
attribute.setBase(100);
|
||||||
pcStats.setAttribute(mSpentAttributes[i], attribute);
|
pcStats.setAttribute(mSpentAttributes[i], attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
pcStats.levelUp ();
|
pcStats.levelUp();
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Levelup);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Levelup);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelupDialog::onAttributeClicked (MyGUI::Widget *sender)
|
void LevelupDialog::onAttributeClicked(MyGUI::Widget *sender)
|
||||||
{
|
{
|
||||||
int attribute = *sender->getUserData<int>();
|
int attribute = *sender->getUserData<int>();
|
||||||
|
|
||||||
std::vector<int>::iterator found = std::find(mSpentAttributes.begin(), mSpentAttributes.end(), attribute);
|
std::vector<int>::iterator found = std::find(mSpentAttributes.begin(), mSpentAttributes.end(), attribute);
|
||||||
if (found != mSpentAttributes.end())
|
if (found != mSpentAttributes.end())
|
||||||
mSpentAttributes.erase (found);
|
mSpentAttributes.erase(found);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (mSpentAttributes.size() == 3)
|
if (mSpentAttributes.size() == mCoinCount)
|
||||||
mSpentAttributes[2] = attribute;
|
mSpentAttributes[mCoinCount - 1] = attribute;
|
||||||
else
|
else
|
||||||
mSpentAttributes.push_back(attribute);
|
mSpentAttributes.push_back(attribute);
|
||||||
}
|
}
|
||||||
|
@ -28,8 +28,11 @@ namespace MWGui
|
|||||||
|
|
||||||
std::vector<int> mSpentAttributes;
|
std::vector<int> mSpentAttributes;
|
||||||
|
|
||||||
void onOkButtonClicked (MyGUI::Widget* sender);
|
unsigned int mCoinCount;
|
||||||
void onAttributeClicked (MyGUI::Widget* sender);
|
static const unsigned int sMaxCoins;
|
||||||
|
|
||||||
|
void onOkButtonClicked(MyGUI::Widget* sender);
|
||||||
|
void onAttributeClicked(MyGUI::Widget* sender);
|
||||||
|
|
||||||
void assignCoins();
|
void assignCoins();
|
||||||
void resetCoins();
|
void resetCoins();
|
||||||
|
@ -321,6 +321,11 @@ namespace MWGui
|
|||||||
skillValueWidget->_setWidgetState(state);
|
skillValueWidget->_setWidgetState(state);
|
||||||
skillValueWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel);
|
skillValueWidget->eventMouseWheel += MyGUI::newDelegate(this, &StatsWindow::onMouseWheel);
|
||||||
|
|
||||||
|
// resize dynamically according to text size
|
||||||
|
int textWidthPlusMargin = skillValueWidget->getTextSize().width + 12;
|
||||||
|
skillValueWidget->setCoord(coord2.left + coord2.width - textWidthPlusMargin, coord2.top, textWidthPlusMargin, coord2.height);
|
||||||
|
skillNameWidget->setSize(skillNameWidget->getSize() + MyGUI::IntSize(coord2.width - textWidthPlusMargin, 0));
|
||||||
|
|
||||||
mSkillWidgets.push_back(skillNameWidget);
|
mSkillWidgets.push_back(skillNameWidget);
|
||||||
mSkillWidgets.push_back(skillValueWidget);
|
mSkillWidgets.push_back(skillValueWidget);
|
||||||
|
|
||||||
|
@ -531,4 +531,10 @@ namespace MWGui
|
|||||||
sellerStats.setLastRestockTime(MWBase::Environment::get().getWorld()->getTimeStamp());
|
sellerStats.setLastRestockTime(MWBase::Environment::get().getWorld()->getTimeStamp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TradeWindow::resetReference()
|
||||||
|
{
|
||||||
|
ReferenceInterface::resetReference();
|
||||||
|
mItemView->setModel(NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ namespace MWGui
|
|||||||
|
|
||||||
virtual void exit();
|
virtual void exit();
|
||||||
|
|
||||||
|
virtual void resetReference();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ItemView* mItemView;
|
ItemView* mItemView;
|
||||||
|
@ -1529,6 +1529,8 @@ namespace MWGui
|
|||||||
mCompanionWindow->resetReference();
|
mCompanionWindow->resetReference();
|
||||||
mConsole->resetReference();
|
mConsole->resetReference();
|
||||||
|
|
||||||
|
mSelectedSpell.clear();
|
||||||
|
|
||||||
mGuiModes.clear();
|
mGuiModes.clear();
|
||||||
MWBase::Environment::get().getInputManager()->changeInputMode(false);
|
MWBase::Environment::get().getInputManager()->changeInputMode(false);
|
||||||
updateVisible();
|
updateVisible();
|
||||||
|
@ -707,11 +707,13 @@ namespace MWInput
|
|||||||
}
|
}
|
||||||
|
|
||||||
void InputManager::quickLoad() {
|
void InputManager::quickLoad() {
|
||||||
MWBase::Environment::get().getStateManager()->quickLoad();
|
if (!MyGUI::InputManager::getInstance().isModalAny())
|
||||||
|
MWBase::Environment::get().getStateManager()->quickLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputManager::quickSave() {
|
void InputManager::quickSave() {
|
||||||
MWBase::Environment::get().getStateManager()->quickSave();
|
if (!MyGUI::InputManager::getInstance().isModalAny())
|
||||||
|
MWBase::Environment::get().getStateManager()->quickSave();
|
||||||
}
|
}
|
||||||
void InputManager::toggleSpell()
|
void InputManager::toggleSpell()
|
||||||
{
|
{
|
||||||
|
@ -265,7 +265,7 @@ namespace MWMechanics
|
|||||||
|
|
||||||
const ESM::Weapon *weapon = NULL;
|
const ESM::Weapon *weapon = NULL;
|
||||||
MWMechanics::WeaponType weaptype;
|
MWMechanics::WeaponType weaptype;
|
||||||
float weapRange;
|
float weapRange = 1.0f;
|
||||||
|
|
||||||
actorClass.getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true);
|
actorClass.getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true);
|
||||||
|
|
||||||
@ -300,7 +300,7 @@ namespace MWMechanics
|
|||||||
else //is creature
|
else //is creature
|
||||||
{
|
{
|
||||||
weaptype = WeapType_HandToHand; //doesn't matter, should only reflect if it is melee or distant weapon
|
weaptype = WeapType_HandToHand; //doesn't matter, should only reflect if it is melee or distant weapon
|
||||||
weapRange = 150; //TODO: use true attack range (the same problem in Creature::hit)
|
weapRange = 150.0f; //TODO: use true attack range (the same problem in Creature::hit)
|
||||||
}
|
}
|
||||||
|
|
||||||
float rangeAttack;
|
float rangeAttack;
|
||||||
|
232
apps/openmw/mwmechanics/autocalcspell.cpp
Normal file
232
apps/openmw/mwmechanics/autocalcspell.cpp
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
#include "autocalcspell.hpp"
|
||||||
|
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace MWMechanics
|
||||||
|
{
|
||||||
|
|
||||||
|
struct SchoolCaps
|
||||||
|
{
|
||||||
|
int mCount;
|
||||||
|
int mLimit;
|
||||||
|
bool mReachedLimit;
|
||||||
|
int mMinCost;
|
||||||
|
std::string mWeakestSpell;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<std::string> autoCalcNpcSpells(const int *actorSkills, const int *actorAttributes, const ESM::Race* race)
|
||||||
|
{
|
||||||
|
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
|
static const float fNPCbaseMagickaMult = gmst.find("fNPCbaseMagickaMult")->getFloat();
|
||||||
|
float baseMagicka = fNPCbaseMagickaMult * actorAttributes[ESM::Attribute::Intelligence];
|
||||||
|
|
||||||
|
static const std::string schools[] = {
|
||||||
|
"alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration"
|
||||||
|
};
|
||||||
|
static int iAutoSpellSchoolMax[6];
|
||||||
|
static bool init = false;
|
||||||
|
if (!init)
|
||||||
|
{
|
||||||
|
for (int i=0; i<6; ++i)
|
||||||
|
{
|
||||||
|
const std::string& gmstName = "iAutoSpell" + schools[i] + "Max";
|
||||||
|
iAutoSpellSchoolMax[i] = gmst.find(gmstName)->getInt();
|
||||||
|
}
|
||||||
|
init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<int, SchoolCaps> schoolCaps;
|
||||||
|
for (int i=0; i<6; ++i)
|
||||||
|
{
|
||||||
|
SchoolCaps caps;
|
||||||
|
caps.mCount = 0;
|
||||||
|
caps.mLimit = iAutoSpellSchoolMax[i];
|
||||||
|
caps.mReachedLimit = iAutoSpellSchoolMax[i] <= 0;
|
||||||
|
caps.mMinCost = INT_MAX;
|
||||||
|
caps.mWeakestSpell.clear();
|
||||||
|
schoolCaps[i] = caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> selectedSpells;
|
||||||
|
|
||||||
|
const MWWorld::Store<ESM::Spell> &spells =
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>();
|
||||||
|
|
||||||
|
// Note: the algorithm heavily depends on the traversal order of the spells. For vanilla-compatible results the
|
||||||
|
// Store must preserve the record ordering as it was in the content files.
|
||||||
|
for (MWWorld::Store<ESM::Spell>::iterator iter = spells.begin(); iter != spells.end(); ++iter)
|
||||||
|
{
|
||||||
|
const ESM::Spell* spell = &*iter;
|
||||||
|
|
||||||
|
if (spell->mData.mType != ESM::Spell::ST_Spell)
|
||||||
|
continue;
|
||||||
|
if (!(spell->mData.mFlags & ESM::Spell::F_Autocalc))
|
||||||
|
continue;
|
||||||
|
static const int iAutoSpellTimesCanCast = gmst.find("iAutoSpellTimesCanCast")->getInt();
|
||||||
|
if (baseMagicka < iAutoSpellTimesCanCast * spell->mData.mCost)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (race && std::find(race->mPowers.mList.begin(), race->mPowers.mList.end(), spell->mId) != race->mPowers.mList.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!attrSkillCheck(spell, actorSkills, actorAttributes))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int school;
|
||||||
|
float skillTerm;
|
||||||
|
calcWeakestSchool(spell, actorSkills, school, skillTerm);
|
||||||
|
assert(school >= 0 && school < 6);
|
||||||
|
SchoolCaps& cap = schoolCaps[school];
|
||||||
|
|
||||||
|
if (cap.mReachedLimit && spell->mData.mCost <= cap.mMinCost)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
static const float fAutoSpellChance = gmst.find("fAutoSpellChance")->getFloat();
|
||||||
|
if (calcAutoCastChance(spell, actorSkills, actorAttributes, school) < fAutoSpellChance)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
selectedSpells.push_back(spell->mId);
|
||||||
|
|
||||||
|
if (cap.mReachedLimit)
|
||||||
|
{
|
||||||
|
std::vector<std::string>::iterator found = std::find(selectedSpells.begin(), selectedSpells.end(), cap.mWeakestSpell);
|
||||||
|
if (found != selectedSpells.end())
|
||||||
|
selectedSpells.erase(found);
|
||||||
|
|
||||||
|
cap.mMinCost = INT_MAX;
|
||||||
|
for (std::vector<std::string>::iterator weakIt = selectedSpells.begin(); weakIt != selectedSpells.end(); ++weakIt)
|
||||||
|
{
|
||||||
|
const ESM::Spell* testSpell = spells.find(*weakIt);
|
||||||
|
|
||||||
|
//int testSchool;
|
||||||
|
//float dummySkillTerm;
|
||||||
|
//calcWeakestSchool(testSpell, actorSkills, testSchool, dummySkillTerm);
|
||||||
|
|
||||||
|
// Note: if there are multiple spells with the same cost, we pick the first one we found.
|
||||||
|
// So the algorithm depends on the iteration order of the outer loop.
|
||||||
|
if (
|
||||||
|
// There is a huge bug here. It is not checked that weakestSpell is of the correct school.
|
||||||
|
// As result multiple SchoolCaps could have the same mWeakestSpell. Erasing the weakest spell would then fail if another school
|
||||||
|
// already erased it, and so the number of spells would often exceed the sum of limits.
|
||||||
|
// This bug cannot be fixed without significantly changing the results of the spell autocalc, which will not have been playtested.
|
||||||
|
//testSchool == school &&
|
||||||
|
testSpell->mData.mCost < cap.mMinCost)
|
||||||
|
{
|
||||||
|
cap.mMinCost = testSpell->mData.mCost;
|
||||||
|
cap.mWeakestSpell = testSpell->mId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cap.mCount += 1;
|
||||||
|
if (cap.mCount == cap.mLimit)
|
||||||
|
cap.mReachedLimit = true;
|
||||||
|
|
||||||
|
if (spell->mData.mCost < cap.mMinCost)
|
||||||
|
{
|
||||||
|
cap.mWeakestSpell = spell->mId;
|
||||||
|
cap.mMinCost = spell->mData.mCost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return selectedSpells;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool attrSkillCheck (const ESM::Spell* spell, const int* actorSkills, const int* actorAttributes)
|
||||||
|
{
|
||||||
|
const std::vector<ESM::ENAMstruct>& effects = spell->mEffects.mList;
|
||||||
|
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = effects.begin(); effectIt != effects.end(); ++effectIt)
|
||||||
|
{
|
||||||
|
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effectIt->mEffectID);
|
||||||
|
static const int iAutoSpellAttSkillMin = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("iAutoSpellAttSkillMin")->getInt();
|
||||||
|
|
||||||
|
if ((magicEffect->mData.mFlags & ESM::MagicEffect::TargetSkill))
|
||||||
|
{
|
||||||
|
assert (effectIt->mSkill >= 0 && effectIt->mSkill < ESM::Skill::Length);
|
||||||
|
if (actorSkills[effectIt->mSkill] < iAutoSpellAttSkillMin)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((magicEffect->mData.mFlags & ESM::MagicEffect::TargetAttribute))
|
||||||
|
{
|
||||||
|
assert (effectIt->mAttribute >= 0 && effectIt->mAttribute < ESM::Attribute::Length);
|
||||||
|
if (actorAttributes[effectIt->mAttribute] < iAutoSpellAttSkillMin)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESM::Skill::SkillEnum mapSchoolToSkill(int school)
|
||||||
|
{
|
||||||
|
std::map<int, ESM::Skill::SkillEnum> schoolSkillMap; // maps spell school to skill id
|
||||||
|
schoolSkillMap[0] = ESM::Skill::Alteration;
|
||||||
|
schoolSkillMap[1] = ESM::Skill::Conjuration;
|
||||||
|
schoolSkillMap[3] = ESM::Skill::Illusion;
|
||||||
|
schoolSkillMap[2] = ESM::Skill::Destruction;
|
||||||
|
schoolSkillMap[4] = ESM::Skill::Mysticism;
|
||||||
|
schoolSkillMap[5] = ESM::Skill::Restoration;
|
||||||
|
assert(schoolSkillMap.find(school) != schoolSkillMap.end());
|
||||||
|
return schoolSkillMap[school];
|
||||||
|
}
|
||||||
|
|
||||||
|
void calcWeakestSchool (const ESM::Spell* spell, const int* actorSkills, int& effectiveSchool, float& skillTerm)
|
||||||
|
{
|
||||||
|
float minChance = FLT_MAX;
|
||||||
|
|
||||||
|
const ESM::EffectList& effects = spell->mEffects;
|
||||||
|
for (std::vector<ESM::ENAMstruct>::const_iterator it = effects.mList.begin(); it != effects.mList.end(); ++it)
|
||||||
|
{
|
||||||
|
const ESM::ENAMstruct& effect = *it;
|
||||||
|
float x = effect.mDuration;
|
||||||
|
|
||||||
|
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effect.mEffectID);
|
||||||
|
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::UncappedDamage))
|
||||||
|
x = std::max(1.f, x);
|
||||||
|
|
||||||
|
x *= 0.1f * magicEffect->mData.mBaseCost;
|
||||||
|
x *= 0.5f * (effect.mMagnMin + effect.mMagnMax);
|
||||||
|
x += effect.mArea * 0.05f * magicEffect->mData.mBaseCost;
|
||||||
|
if (effect.mRange == ESM::RT_Target)
|
||||||
|
x *= 1.5f;
|
||||||
|
|
||||||
|
static const float fEffectCostMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fEffectCostMult")->getFloat();
|
||||||
|
x *= fEffectCostMult;
|
||||||
|
|
||||||
|
float s = 2.f * actorSkills[mapSchoolToSkill(magicEffect->mData.mSchool)];
|
||||||
|
if (s - x < minChance)
|
||||||
|
{
|
||||||
|
minChance = s - x;
|
||||||
|
effectiveSchool = magicEffect->mData.mSchool;
|
||||||
|
skillTerm = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float calcAutoCastChance(const ESM::Spell *spell, const int *actorSkills, const int *actorAttributes, int effectiveSchool)
|
||||||
|
{
|
||||||
|
if (spell->mData.mType != ESM::Spell::ST_Spell)
|
||||||
|
return 100.f;
|
||||||
|
|
||||||
|
if (spell->mData.mFlags & ESM::Spell::F_Always)
|
||||||
|
return 100.f;
|
||||||
|
|
||||||
|
float skillTerm;
|
||||||
|
if (effectiveSchool != -1)
|
||||||
|
skillTerm = 2.f * actorSkills[mapSchoolToSkill(effectiveSchool)];
|
||||||
|
else
|
||||||
|
calcWeakestSchool(spell, actorSkills, effectiveSchool, skillTerm); // Note effectiveSchool is unused after this
|
||||||
|
|
||||||
|
float castChance = skillTerm - spell->mData.mCost + 0.2f * actorAttributes[ESM::Attribute::Willpower] + 0.1f * actorAttributes[ESM::Attribute::Luck];
|
||||||
|
return castChance;
|
||||||
|
}
|
||||||
|
}
|
31
apps/openmw/mwmechanics/autocalcspell.hpp
Normal file
31
apps/openmw/mwmechanics/autocalcspell.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef OPENMW_AUTOCALCSPELL_H
|
||||||
|
#define OPENMW_AUTOCALCSPELL_H
|
||||||
|
|
||||||
|
#include <cfloat>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include <components/esm/loadspel.hpp>
|
||||||
|
#include <components/esm/loadskil.hpp>
|
||||||
|
#include <components/esm/loadrace.hpp>
|
||||||
|
|
||||||
|
namespace MWMechanics
|
||||||
|
{
|
||||||
|
|
||||||
|
/// Contains algorithm for calculating an NPC's spells based on stats
|
||||||
|
/// @note We might want to move this code to a component later, so the editor can use it for preview purposes
|
||||||
|
|
||||||
|
std::vector<std::string> autoCalcNpcSpells(const int* actorSkills, const int* actorAttributes, const ESM::Race* race);
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
|
||||||
|
bool attrSkillCheck (const ESM::Spell* spell, const int* actorSkills, const int* actorAttributes);
|
||||||
|
|
||||||
|
ESM::Skill::SkillEnum mapSchoolToSkill(int school);
|
||||||
|
|
||||||
|
void calcWeakestSchool(const ESM::Spell* spell, const int* actorSkills, int& effectiveSchool, float& skillTerm);
|
||||||
|
|
||||||
|
float calcAutoCastChance(const ESM::Spell* spell, const int* actorSkills, const int* actorAttributes, int effectiveSchool);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -361,9 +361,10 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
|
|||||||
* beginning. */
|
* beginning. */
|
||||||
int mode = ((movement == mCurrentMovement) ? 2 : 1);
|
int mode = ((movement == mCurrentMovement) ? 2 : 1);
|
||||||
|
|
||||||
|
mMovementAnimationControlled = true;
|
||||||
|
|
||||||
mAnimation->disable(mCurrentMovement);
|
mAnimation->disable(mCurrentMovement);
|
||||||
mCurrentMovement = movement;
|
mCurrentMovement = movement;
|
||||||
mMovementAnimVelocity = 0.0f;
|
|
||||||
if(!mCurrentMovement.empty())
|
if(!mCurrentMovement.empty())
|
||||||
{
|
{
|
||||||
float vel, speedmult = 1.0f;
|
float vel, speedmult = 1.0f;
|
||||||
@ -383,16 +384,18 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
|
|||||||
|
|
||||||
if(mMovementSpeed > 0.0f && (vel=mAnimation->getVelocity(anim)) > 1.0f)
|
if(mMovementSpeed > 0.0f && (vel=mAnimation->getVelocity(anim)) > 1.0f)
|
||||||
{
|
{
|
||||||
mMovementAnimVelocity = vel;
|
|
||||||
speedmult = mMovementSpeed / vel;
|
speedmult = mMovementSpeed / vel;
|
||||||
}
|
}
|
||||||
else if (mMovementState == CharState_TurnLeft || mMovementState == CharState_TurnRight)
|
else if (mMovementState == CharState_TurnLeft || mMovementState == CharState_TurnRight)
|
||||||
speedmult = 1.f; // TODO: should get a speed mult depending on the current turning speed
|
speedmult = 1.f; // TODO: should get a speed mult depending on the current turning speed
|
||||||
else if (mMovementSpeed > 0.0f)
|
else if (mMovementSpeed > 0.0f)
|
||||||
|
{
|
||||||
// The first person anims don't have any velocity to calculate a speed multiplier from.
|
// The first person anims don't have any velocity to calculate a speed multiplier from.
|
||||||
// We use the third person velocities instead.
|
// We use the third person velocities instead.
|
||||||
// FIXME: should be pulled from the actual animation, but it is not presently loaded.
|
// FIXME: should be pulled from the actual animation, but it is not presently loaded.
|
||||||
speedmult = mMovementSpeed / (isrunning ? 222.857f : 154.064f);
|
speedmult = mMovementSpeed / (isrunning ? 222.857f : 154.064f);
|
||||||
|
mMovementAnimationControlled = false;
|
||||||
|
}
|
||||||
mAnimation->play(mCurrentMovement, Priority_Movement, movegroup, false,
|
mAnimation->play(mCurrentMovement, Priority_Movement, movegroup, false,
|
||||||
speedmult, ((mode!=2)?"start":"loop start"), "stop", 0.0f, ~0ul);
|
speedmult, ((mode!=2)?"start":"loop start"), "stop", 0.0f, ~0ul);
|
||||||
}
|
}
|
||||||
@ -506,6 +509,7 @@ void CharacterController::playDeath(float startpoint, CharacterState death)
|
|||||||
mJumpState = JumpState_None;
|
mJumpState = JumpState_None;
|
||||||
mAnimation->disable(mCurrentJump);
|
mAnimation->disable(mCurrentJump);
|
||||||
mCurrentJump = "";
|
mCurrentJump = "";
|
||||||
|
mMovementAnimationControlled = true;
|
||||||
|
|
||||||
mAnimation->play(mCurrentDeath, Priority_Death, MWRender::Animation::Group_All,
|
mAnimation->play(mCurrentDeath, Priority_Death, MWRender::Animation::Group_All,
|
||||||
false, 1.0f, "start", "stop", startpoint, 0);
|
false, 1.0f, "start", "stop", startpoint, 0);
|
||||||
@ -547,7 +551,7 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim
|
|||||||
, mIdleState(CharState_None)
|
, mIdleState(CharState_None)
|
||||||
, mMovementState(CharState_None)
|
, mMovementState(CharState_None)
|
||||||
, mMovementSpeed(0.0f)
|
, mMovementSpeed(0.0f)
|
||||||
, mMovementAnimVelocity(0.0f)
|
, mMovementAnimationControlled(true)
|
||||||
, mDeathState(CharState_None)
|
, mDeathState(CharState_None)
|
||||||
, mHitState(CharState_None)
|
, mHitState(CharState_None)
|
||||||
, mUpperBodyState(UpperCharState_Nothing)
|
, mUpperBodyState(UpperCharState_Nothing)
|
||||||
@ -570,10 +574,14 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim
|
|||||||
if (cls.hasInventoryStore(mPtr))
|
if (cls.hasInventoryStore(mPtr))
|
||||||
{
|
{
|
||||||
getActiveWeapon(cls.getCreatureStats(mPtr), cls.getInventoryStore(mPtr), &mWeaponType);
|
getActiveWeapon(cls.getCreatureStats(mPtr), cls.getInventoryStore(mPtr), &mWeaponType);
|
||||||
|
if (mWeaponType != WeapType_None)
|
||||||
|
{
|
||||||
|
mUpperBodyState = UpperCharState_WeapEquiped;
|
||||||
|
getWeaponGroup(mWeaponType, mCurrentWeapon);
|
||||||
|
}
|
||||||
|
|
||||||
if(mWeaponType != WeapType_None && mWeaponType != WeapType_Spell && mWeaponType != WeapType_HandToHand)
|
if(mWeaponType != WeapType_None && mWeaponType != WeapType_Spell && mWeaponType != WeapType_HandToHand)
|
||||||
{
|
{
|
||||||
getWeaponGroup(mWeaponType, mCurrentWeapon);
|
|
||||||
mUpperBodyState = UpperCharState_WeapEquiped;
|
|
||||||
mAnimation->showWeapons(true);
|
mAnimation->showWeapons(true);
|
||||||
mAnimation->setWeaponGroup(mCurrentWeapon);
|
mAnimation->setWeaponGroup(mCurrentWeapon);
|
||||||
}
|
}
|
||||||
@ -1241,6 +1249,7 @@ void CharacterController::update(float duration)
|
|||||||
if (inwater || flying)
|
if (inwater || flying)
|
||||||
cls.getCreatureStats(mPtr).land();
|
cls.getCreatureStats(mPtr).land();
|
||||||
|
|
||||||
|
bool inJump = true;
|
||||||
if(!onground && !flying && !inwater)
|
if(!onground && !flying && !inwater)
|
||||||
{
|
{
|
||||||
// In the air (either getting up —ascending part of jump— or falling).
|
// In the air (either getting up —ascending part of jump— or falling).
|
||||||
@ -1330,6 +1339,8 @@ void CharacterController::update(float duration)
|
|||||||
mJumpState = JumpState_None;
|
mJumpState = JumpState_None;
|
||||||
vec.z = 0.0f;
|
vec.z = 0.0f;
|
||||||
|
|
||||||
|
inJump = false;
|
||||||
|
|
||||||
if(std::abs(vec.x/2.0f) > std::abs(vec.y))
|
if(std::abs(vec.x/2.0f) > std::abs(vec.y))
|
||||||
{
|
{
|
||||||
if(vec.x > 0.0f)
|
if(vec.x > 0.0f)
|
||||||
@ -1391,6 +1402,8 @@ void CharacterController::update(float duration)
|
|||||||
forcestateupdate = updateCreatureState() || forcestateupdate;
|
forcestateupdate = updateCreatureState() || forcestateupdate;
|
||||||
|
|
||||||
refreshCurrentAnims(idlestate, movestate, forcestateupdate);
|
refreshCurrentAnims(idlestate, movestate, forcestateupdate);
|
||||||
|
if (inJump)
|
||||||
|
mMovementAnimationControlled = false;
|
||||||
|
|
||||||
if (!mSkipAnim)
|
if (!mSkipAnim)
|
||||||
{
|
{
|
||||||
@ -1402,7 +1415,7 @@ void CharacterController::update(float duration)
|
|||||||
else //avoid z-rotating for knockdown
|
else //avoid z-rotating for knockdown
|
||||||
world->rotateObject(mPtr, rot.x, rot.y, 0.0f, true);
|
world->rotateObject(mPtr, rot.x, rot.y, 0.0f, true);
|
||||||
|
|
||||||
if (mMovementAnimVelocity == 0)
|
if (!mMovementAnimationControlled)
|
||||||
world->queueMovement(mPtr, vec);
|
world->queueMovement(mPtr, vec);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1446,7 +1459,7 @@ void CharacterController::update(float duration)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update movement
|
// Update movement
|
||||||
if(mMovementAnimVelocity > 0)
|
if(mMovementAnimationControlled && mPtr.getClass().isActor())
|
||||||
world->queueMovement(mPtr, moved);
|
world->queueMovement(mPtr, moved);
|
||||||
}
|
}
|
||||||
else if (mAnimation)
|
else if (mAnimation)
|
||||||
|
@ -147,7 +147,7 @@ class CharacterController
|
|||||||
CharacterState mMovementState;
|
CharacterState mMovementState;
|
||||||
std::string mCurrentMovement;
|
std::string mCurrentMovement;
|
||||||
float mMovementSpeed;
|
float mMovementSpeed;
|
||||||
float mMovementAnimVelocity;
|
bool mMovementAnimationControlled;
|
||||||
|
|
||||||
CharacterState mDeathState;
|
CharacterState mDeathState;
|
||||||
std::string mCurrentDeath;
|
std::string mCurrentDeath;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <OgreSceneNode.h>
|
#include <OgreSceneNode.h>
|
||||||
|
|
||||||
#include "spellcasting.hpp"
|
#include "spellcasting.hpp"
|
||||||
|
#include "autocalcspell.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -155,19 +156,6 @@ namespace MWMechanics
|
|||||||
npcStats.getSkill (index).setBase (
|
npcStats.getSkill (index).setBase (
|
||||||
npcStats.getSkill (index).getBase() + bonus);
|
npcStats.getSkill (index).getBase() + bonus);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i==1)
|
|
||||||
{
|
|
||||||
// Major skill - add starting spells for this skill if existing
|
|
||||||
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
|
||||||
MWWorld::Store<ESM::Spell>::iterator it = store.get<ESM::Spell>().begin();
|
|
||||||
for (; it != store.get<ESM::Spell>().end(); ++it)
|
|
||||||
{
|
|
||||||
if (it->mData.mFlags & ESM::Spell::F_PCStart
|
|
||||||
&& spellSchoolToSkill(getSpellSchool(&*it, ptr)) == index)
|
|
||||||
creatureStats.getSpells().add(it->mId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,6 +178,87 @@ namespace MWMechanics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// F_PCStart spells
|
||||||
|
static const float fPCbaseMagickaMult = esmStore.get<ESM::GameSetting>().find("fPCbaseMagickaMult")->getFloat();
|
||||||
|
|
||||||
|
float baseMagicka = fPCbaseMagickaMult * creatureStats.getAttribute(ESM::Attribute::Intelligence).getBase();
|
||||||
|
bool reachedLimit = false;
|
||||||
|
const ESM::Spell* weakestSpell = NULL;
|
||||||
|
int minCost = INT_MAX;
|
||||||
|
|
||||||
|
std::vector<std::string> selectedSpells;
|
||||||
|
|
||||||
|
const ESM::Race* race = NULL;
|
||||||
|
if (mRaceSelected)
|
||||||
|
race = esmStore.get<ESM::Race>().find(player->mRace);
|
||||||
|
|
||||||
|
int skills[ESM::Skill::Length];
|
||||||
|
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||||
|
skills[i] = npcStats.getSkill(i).getBase();
|
||||||
|
|
||||||
|
int attributes[ESM::Attribute::Length];
|
||||||
|
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||||
|
attributes[i] = npcStats.getAttribute(i).getBase();
|
||||||
|
|
||||||
|
const MWWorld::Store<ESM::Spell> &spells =
|
||||||
|
esmStore.get<ESM::Spell>();
|
||||||
|
for (MWWorld::Store<ESM::Spell>::iterator iter = spells.begin(); iter != spells.end(); ++iter)
|
||||||
|
{
|
||||||
|
const ESM::Spell* spell = &*iter;
|
||||||
|
|
||||||
|
if (spell->mData.mType != ESM::Spell::ST_Spell)
|
||||||
|
continue;
|
||||||
|
if (!(spell->mData.mFlags & ESM::Spell::F_PCStart))
|
||||||
|
continue;
|
||||||
|
if (reachedLimit && spell->mData.mCost <= minCost)
|
||||||
|
continue;
|
||||||
|
if (race && std::find(race->mPowers.mList.begin(), race->mPowers.mList.end(), spell->mId) != race->mPowers.mList.end())
|
||||||
|
continue;
|
||||||
|
if (baseMagicka < spell->mData.mCost)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
static const float fAutoPCSpellChance = esmStore.get<ESM::GameSetting>().find("fAutoPCSpellChance")->getFloat();
|
||||||
|
if (calcAutoCastChance(spell, skills, attributes, -1) < fAutoPCSpellChance)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!attrSkillCheck(spell, skills, attributes))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
selectedSpells.push_back(spell->mId);
|
||||||
|
|
||||||
|
if (reachedLimit)
|
||||||
|
{
|
||||||
|
std::vector<std::string>::iterator it = std::find(selectedSpells.begin(), selectedSpells.end(), weakestSpell->mId);
|
||||||
|
if (it != selectedSpells.end())
|
||||||
|
selectedSpells.erase(it);
|
||||||
|
|
||||||
|
minCost = INT_MAX;
|
||||||
|
for (std::vector<std::string>::iterator weakIt = selectedSpells.begin(); weakIt != selectedSpells.end(); ++weakIt)
|
||||||
|
{
|
||||||
|
const ESM::Spell* testSpell = esmStore.get<ESM::Spell>().find(*weakIt);
|
||||||
|
if (testSpell->mData.mCost < minCost)
|
||||||
|
{
|
||||||
|
minCost = testSpell->mData.mCost;
|
||||||
|
weakestSpell = testSpell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (spell->mData.mCost < minCost)
|
||||||
|
{
|
||||||
|
weakestSpell = spell;
|
||||||
|
minCost = weakestSpell->mData.mCost;
|
||||||
|
}
|
||||||
|
static const unsigned int iAutoPCSpellMax = esmStore.get<ESM::GameSetting>().find("iAutoPCSpellMax")->getInt();
|
||||||
|
if (selectedSpells.size() == iAutoPCSpellMax)
|
||||||
|
reachedLimit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector<std::string>::iterator it = selectedSpells.begin(); it != selectedSpells.end(); ++it)
|
||||||
|
creatureStats.getSpells().add(*it);
|
||||||
|
|
||||||
// forced update and current value adjustments
|
// forced update and current value adjustments
|
||||||
mActors.updateActor (ptr, 0);
|
mActors.updateActor (ptr, 0);
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ namespace MWMechanics
|
|||||||
x *= 0.1 * magicEffect->mData.mBaseCost;
|
x *= 0.1 * magicEffect->mData.mBaseCost;
|
||||||
x *= 0.5 * (it->mMagnMin + it->mMagnMax);
|
x *= 0.5 * (it->mMagnMin + it->mMagnMax);
|
||||||
x *= it->mArea * 0.05 * magicEffect->mData.mBaseCost;
|
x *= it->mArea * 0.05 * magicEffect->mData.mBaseCost;
|
||||||
if (magicEffect->mData.mFlags & ESM::MagicEffect::CastTarget)
|
if (it->mRange == ESM::RT_Target)
|
||||||
x *= 1.5;
|
x *= 1.5;
|
||||||
static const float fEffectCostMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
static const float fEffectCostMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
|
||||||
"fEffectCostMult")->getFloat();
|
"fEffectCostMult")->getFloat();
|
||||||
|
@ -149,6 +149,8 @@ namespace MWRender
|
|||||||
mViewModeToggleQueued = true;
|
mViewModeToggleQueued = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
mViewModeToggleQueued = false;
|
||||||
|
|
||||||
mFirstPersonView = !mFirstPersonView;
|
mFirstPersonView = !mFirstPersonView;
|
||||||
processViewChange();
|
processViewChange();
|
||||||
|
@ -1088,7 +1088,7 @@ public:
|
|||||||
|
|
||||||
void close() { }
|
void close() { }
|
||||||
|
|
||||||
bool update(Ogre::MaterialPtr &mat, Ogre::Rectangle2D *rect, int screen_width, int screen_height)
|
bool update()
|
||||||
{ return false; }
|
{ return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -86,16 +86,24 @@ namespace MWScript
|
|||||||
float ay = Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees();
|
float ay = Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees();
|
||||||
float az = Ogre::Radian(ptr.getRefData().getPosition().rot[2]).valueDegrees();
|
float az = Ogre::Radian(ptr.getRefData().getPosition().rot[2]).valueDegrees();
|
||||||
|
|
||||||
|
MWWorld::LocalRotation localRot = ptr.getRefData().getLocalRotation();
|
||||||
|
|
||||||
if (axis == "x")
|
if (axis == "x")
|
||||||
{
|
{
|
||||||
|
localRot.rot[0] = 0;
|
||||||
|
ptr.getRefData().setLocalRotation(localRot);
|
||||||
MWBase::Environment::get().getWorld()->rotateObject(ptr,angle,ay,az);
|
MWBase::Environment::get().getWorld()->rotateObject(ptr,angle,ay,az);
|
||||||
}
|
}
|
||||||
else if (axis == "y")
|
else if (axis == "y")
|
||||||
{
|
{
|
||||||
|
localRot.rot[1] = 0;
|
||||||
|
ptr.getRefData().setLocalRotation(localRot);
|
||||||
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,angle,az);
|
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,angle,az);
|
||||||
}
|
}
|
||||||
else if (axis == "z")
|
else if (axis == "z")
|
||||||
{
|
{
|
||||||
|
localRot.rot[2] = 0;
|
||||||
|
ptr.getRefData().setLocalRotation(localRot);
|
||||||
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,angle);
|
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,angle);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -364,7 +364,7 @@ namespace MWWorld
|
|||||||
continue; // velocity updated, calculate nextpos again
|
continue; // velocity updated, calculate nextpos again
|
||||||
}
|
}
|
||||||
|
|
||||||
if(newPosition.squaredDistance(nextpos) > 0.00000001*0.00000001)
|
if(newPosition.squaredDistance(nextpos) > 0.0001)
|
||||||
{
|
{
|
||||||
// trace to where character would go if there were no obstructions
|
// trace to where character would go if there were no obstructions
|
||||||
tracer.doTrace(colobj, newPosition, nextpos, engine);
|
tracer.doTrace(colobj, newPosition, nextpos, engine);
|
||||||
|
@ -209,8 +209,6 @@ namespace MWWorld
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setUp() {
|
void setUp() {
|
||||||
//std::sort(mStatic.begin(), mStatic.end(), RecordCmp());
|
|
||||||
|
|
||||||
mShared.clear();
|
mShared.clear();
|
||||||
mShared.reserve(mStatic.size());
|
mShared.reserve(mStatic.size());
|
||||||
typename std::map<std::string, T>::iterator it = mStatic.begin();
|
typename std::map<std::string, T>::iterator it = mStatic.begin();
|
||||||
@ -675,18 +673,15 @@ namespace MWWorld
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setUp() {
|
void setUp() {
|
||||||
//typedef std::vector<ESM::Cell>::iterator Iterator;
|
|
||||||
typedef DynamicExt::iterator ExtIterator;
|
typedef DynamicExt::iterator ExtIterator;
|
||||||
typedef std::map<std::string, ESM::Cell>::iterator IntIterator;
|
typedef std::map<std::string, ESM::Cell>::iterator IntIterator;
|
||||||
|
|
||||||
//std::sort(mInt.begin(), mInt.end(), RecordCmp());
|
|
||||||
mSharedInt.clear();
|
mSharedInt.clear();
|
||||||
mSharedInt.reserve(mInt.size());
|
mSharedInt.reserve(mInt.size());
|
||||||
for (IntIterator it = mInt.begin(); it != mInt.end(); ++it) {
|
for (IntIterator it = mInt.begin(); it != mInt.end(); ++it) {
|
||||||
mSharedInt.push_back(&(it->second));
|
mSharedInt.push_back(&(it->second));
|
||||||
}
|
}
|
||||||
|
|
||||||
//std::sort(mExt.begin(), mExt.end(), ExtCmp());
|
|
||||||
mSharedExt.clear();
|
mSharedExt.clear();
|
||||||
mSharedExt.reserve(mExt.size());
|
mSharedExt.reserve(mExt.size());
|
||||||
for (ExtIterator it = mExt.begin(); it != mExt.end(); ++it) {
|
for (ExtIterator it = mExt.begin(); it != mExt.end(); ++it) {
|
||||||
@ -1147,6 +1142,37 @@ namespace MWWorld
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Specialisation for ESM::Spell to preserve record order as it was in the content files.
|
||||||
|
// The NPC spell autocalc code heavily depends on this order.
|
||||||
|
// We could also do this in the base class, but it's usually not a good idea to depend on record order.
|
||||||
|
template<>
|
||||||
|
inline void Store<ESM::Spell>::clearDynamic()
|
||||||
|
{
|
||||||
|
// remove the dynamic part of mShared
|
||||||
|
mShared.erase(mShared.begin() + mStatic.size(), mShared.end());
|
||||||
|
mDynamic.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void Store<ESM::Spell>::load(ESM::ESMReader &esm, const std::string &id) {
|
||||||
|
std::string idLower = Misc::StringUtils::lowerCase(id);
|
||||||
|
|
||||||
|
std::pair<Static::iterator, bool> inserted = mStatic.insert(std::make_pair(idLower, ESM::Spell()));
|
||||||
|
if (inserted.second)
|
||||||
|
mShared.push_back(&mStatic[idLower]);
|
||||||
|
|
||||||
|
inserted.first->second.mId = idLower;
|
||||||
|
inserted.first->second.load(esm);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void Store<ESM::Spell>::setUp()
|
||||||
|
{
|
||||||
|
// remove the dynamic part of mShared
|
||||||
|
mShared.erase(mShared.begin() + mStatic.size(), mShared.end());
|
||||||
|
}
|
||||||
|
|
||||||
} //end namespace
|
} //end namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1123,7 +1123,10 @@ namespace MWWorld
|
|||||||
|
|
||||||
ptr.getRefData().setPosition(pos);
|
ptr.getRefData().setPosition(pos);
|
||||||
|
|
||||||
mWorldScene->updateObjectRotation(ptr);
|
if (ptr.getClass().isActor())
|
||||||
|
mWorldScene->updateObjectRotation(ptr);
|
||||||
|
else
|
||||||
|
mWorldScene->updateObjectLocalRotation(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::localRotateObject (const Ptr& ptr, float x, float y, float z)
|
void World::localRotateObject (const Ptr& ptr, float x, float y, float z)
|
||||||
@ -2313,15 +2316,10 @@ namespace MWWorld
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If this is a power, check if it was already used in the last 24h
|
// If this is a power, check if it was already used in the last 24h
|
||||||
if (!fail && spell->mData.mType == ESM::Spell::ST_Power)
|
if (!fail && spell->mData.mType == ESM::Spell::ST_Power && !stats.getSpells().canUsePower(spell->mId))
|
||||||
{
|
{
|
||||||
if (stats.getSpells().canUsePower(spell->mId))
|
message = "#{sPowerAlreadyUsed}";
|
||||||
stats.getSpells().usePower(spell->mId);
|
fail = true;
|
||||||
else
|
|
||||||
{
|
|
||||||
message = "#{sPowerAlreadyUsed}";
|
|
||||||
fail = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reduce mana
|
// Reduce mana
|
||||||
@ -2354,6 +2352,10 @@ namespace MWWorld
|
|||||||
if (!selectedSpell.empty())
|
if (!selectedSpell.empty())
|
||||||
{
|
{
|
||||||
const ESM::Spell* spell = getStore().get<ESM::Spell>().search(selectedSpell);
|
const ESM::Spell* spell = getStore().get<ESM::Spell>().search(selectedSpell);
|
||||||
|
|
||||||
|
// A power can be used once per 24h
|
||||||
|
if (spell->mData.mType == ESM::Spell::ST_Power)
|
||||||
|
stats.getSpells().usePower(spell->mId);
|
||||||
|
|
||||||
cast.cast(spell);
|
cast.cast(spell);
|
||||||
}
|
}
|
||||||
@ -2649,6 +2651,8 @@ namespace MWWorld
|
|||||||
{
|
{
|
||||||
mGoToJail = false;
|
mGoToJail = false;
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue);
|
||||||
|
|
||||||
MWWorld::Ptr player = getPlayerPtr();
|
MWWorld::Ptr player = getPlayerPtr();
|
||||||
teleportToClosestMarker(player, "prisonmarker");
|
teleportToClosestMarker(player, "prisonmarker");
|
||||||
int bounty = player.getClass().getNpcStats(player).getBounty();
|
int bounty = player.getClass().getNpcStats(player).getBounty();
|
||||||
|
@ -12,68 +12,3 @@ struct StringOpsTest : public ::testing::Test
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(StringOpsTest, begins_matching)
|
|
||||||
{
|
|
||||||
ASSERT_TRUE(Misc::begins("abc", "a"));
|
|
||||||
ASSERT_TRUE(Misc::begins("abc", "ab"));
|
|
||||||
ASSERT_TRUE(Misc::begins("abc", "abc"));
|
|
||||||
ASSERT_TRUE(Misc::begins("abcd", "abc"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(StringOpsTest, begins_not_matching)
|
|
||||||
{
|
|
||||||
ASSERT_FALSE(Misc::begins("abc", "b"));
|
|
||||||
ASSERT_FALSE(Misc::begins("abc", "bc"));
|
|
||||||
ASSERT_FALSE(Misc::begins("abc", "bcd"));
|
|
||||||
ASSERT_FALSE(Misc::begins("abc", "abcd"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(StringOpsTest, ibegins_matching)
|
|
||||||
{
|
|
||||||
ASSERT_TRUE(Misc::ibegins("Abc", "a"));
|
|
||||||
ASSERT_TRUE(Misc::ibegins("aBc", "ab"));
|
|
||||||
ASSERT_TRUE(Misc::ibegins("abC", "abc"));
|
|
||||||
ASSERT_TRUE(Misc::ibegins("abcD", "abc"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(StringOpsTest, ibegins_not_matching)
|
|
||||||
{
|
|
||||||
ASSERT_FALSE(Misc::ibegins("abc", "b"));
|
|
||||||
ASSERT_FALSE(Misc::ibegins("abc", "bc"));
|
|
||||||
ASSERT_FALSE(Misc::ibegins("abc", "bcd"));
|
|
||||||
ASSERT_FALSE(Misc::ibegins("abc", "abcd"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(StringOpsTest, ends_matching)
|
|
||||||
{
|
|
||||||
ASSERT_TRUE(Misc::ends("abc", "c"));
|
|
||||||
ASSERT_TRUE(Misc::ends("abc", "bc"));
|
|
||||||
ASSERT_TRUE(Misc::ends("abc", "abc"));
|
|
||||||
ASSERT_TRUE(Misc::ends("abcd", "abcd"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(StringOpsTest, ends_not_matching)
|
|
||||||
{
|
|
||||||
ASSERT_FALSE(Misc::ends("abc", "b"));
|
|
||||||
ASSERT_FALSE(Misc::ends("abc", "ab"));
|
|
||||||
ASSERT_FALSE(Misc::ends("abc", "bcd"));
|
|
||||||
ASSERT_FALSE(Misc::ends("abc", "abcd"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(StringOpsTest, iends_matching)
|
|
||||||
{
|
|
||||||
ASSERT_TRUE(Misc::iends("Abc", "c"));
|
|
||||||
ASSERT_TRUE(Misc::iends("aBc", "bc"));
|
|
||||||
ASSERT_TRUE(Misc::iends("abC", "abc"));
|
|
||||||
ASSERT_TRUE(Misc::iends("abcD", "abcd"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(StringOpsTest, iends_not_matching)
|
|
||||||
{
|
|
||||||
ASSERT_FALSE(Misc::iends("abc", "b"));
|
|
||||||
ASSERT_FALSE(Misc::iends("abc", "ab"));
|
|
||||||
ASSERT_FALSE(Misc::iends("abc", "bcd"));
|
|
||||||
ASSERT_FALSE(Misc::iends("abc", "abcd"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -10,8 +10,6 @@ namespace ESM
|
|||||||
|
|
||||||
void NPC::load(ESMReader &esm)
|
void NPC::load(ESMReader &esm)
|
||||||
{
|
{
|
||||||
//mNpdt52.mGold = -10;
|
|
||||||
|
|
||||||
mPersistent = esm.getRecordFlags() & 0x0400;
|
mPersistent = esm.getRecordFlags() & 0x0400;
|
||||||
|
|
||||||
mModel = esm.getHNOString("MODL");
|
mModel = esm.getHNOString("MODL");
|
||||||
@ -63,7 +61,6 @@ void NPC::load(ESMReader &esm)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mAiPackage.load(esm);
|
mAiPackage.load(esm);
|
||||||
esm.skipRecord();
|
|
||||||
}
|
}
|
||||||
void NPC::save(ESMWriter &esm) const
|
void NPC::save(ESMWriter &esm) const
|
||||||
{
|
{
|
||||||
|
@ -27,8 +27,8 @@ struct Spell
|
|||||||
|
|
||||||
enum Flags
|
enum Flags
|
||||||
{
|
{
|
||||||
F_Autocalc = 1,
|
F_Autocalc = 1, // Can be selected by NPC spells auto-calc
|
||||||
F_PCStart = 2,
|
F_PCStart = 2, // Can be selected by player spells auto-calc
|
||||||
F_Always = 4 // Casting always succeeds
|
F_Always = 4 // Casting always succeeds
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,59 +12,6 @@
|
|||||||
namespace Misc
|
namespace Misc
|
||||||
{
|
{
|
||||||
|
|
||||||
bool begins(const char* str1, const char* str2)
|
std::locale StringUtils::mLocale = std::locale::classic();
|
||||||
{
|
|
||||||
while(*str2)
|
|
||||||
{
|
|
||||||
if(*str1 == 0 || *str1 != *str2) return false;
|
|
||||||
|
|
||||||
str1++;
|
|
||||||
str2++;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ends(const char* str1, const char* str2)
|
|
||||||
{
|
|
||||||
int len1 = strlen(str1);
|
|
||||||
int len2 = strlen(str2);
|
|
||||||
|
|
||||||
if(len1 < len2) return false;
|
|
||||||
|
|
||||||
return strcmp(str2, str1+len1-len2) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// True if the given chars match, case insensitive
|
|
||||||
static bool icmp(char a, char b)
|
|
||||||
{
|
|
||||||
if(a >= 'A' && a <= 'Z')
|
|
||||||
a += 'a' - 'A';
|
|
||||||
if(b >= 'A' && b <= 'Z')
|
|
||||||
b += 'a' - 'A';
|
|
||||||
|
|
||||||
return a == b;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ibegins(const char* str1, const char* str2)
|
|
||||||
{
|
|
||||||
while(*str2)
|
|
||||||
{
|
|
||||||
if(*str1 == 0 || !icmp(*str1,*str2)) return false;
|
|
||||||
|
|
||||||
str1++;
|
|
||||||
str2++;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iends(const char* str1, const char* str2)
|
|
||||||
{
|
|
||||||
int len1 = strlen(str1);
|
|
||||||
int len2 = strlen(str2);
|
|
||||||
|
|
||||||
if(len1 < len2) return false;
|
|
||||||
|
|
||||||
return strcasecmp(str2, str1+len1-len2) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,18 @@
|
|||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <locale>
|
||||||
|
|
||||||
namespace Misc
|
namespace Misc
|
||||||
{
|
{
|
||||||
class StringUtils
|
class StringUtils
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static std::locale mLocale;
|
||||||
struct ci
|
struct ci
|
||||||
{
|
{
|
||||||
bool operator()(int x, int y) const {
|
bool operator()(char x, char y) const {
|
||||||
return std::tolower(x) < std::tolower(y);
|
return std::tolower(x, StringUtils::mLocale) < std::tolower(y, StringUtils::mLocale);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -28,7 +31,7 @@ public:
|
|||||||
std::string::const_iterator xit = x.begin();
|
std::string::const_iterator xit = x.begin();
|
||||||
std::string::const_iterator yit = y.begin();
|
std::string::const_iterator yit = y.begin();
|
||||||
for (; xit != x.end(); ++xit, ++yit) {
|
for (; xit != x.end(); ++xit, ++yit) {
|
||||||
if (std::tolower(*xit) != std::tolower(*yit)) {
|
if (std::tolower(*xit, mLocale) != std::tolower(*yit, mLocale)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,7 +45,7 @@ public:
|
|||||||
for(;xit != x.end() && yit != y.end() && len > 0;++xit,++yit,--len)
|
for(;xit != x.end() && yit != y.end() && len > 0;++xit,++yit,--len)
|
||||||
{
|
{
|
||||||
int res = *xit - *yit;
|
int res = *xit - *yit;
|
||||||
if(res != 0 && std::tolower(*xit) != std::tolower(*yit))
|
if(res != 0 && std::tolower(*xit, mLocale) != std::tolower(*yit, mLocale))
|
||||||
return (res > 0) ? 1 : -1;
|
return (res > 0) ? 1 : -1;
|
||||||
}
|
}
|
||||||
if(len > 0)
|
if(len > 0)
|
||||||
@ -57,12 +60,8 @@ public:
|
|||||||
|
|
||||||
/// Transforms input string to lower case w/o copy
|
/// Transforms input string to lower case w/o copy
|
||||||
static std::string &toLower(std::string &inout) {
|
static std::string &toLower(std::string &inout) {
|
||||||
std::transform(
|
for (unsigned int i=0; i<inout.size(); ++i)
|
||||||
inout.begin(),
|
inout[i] = std::tolower(inout[i], mLocale);
|
||||||
inout.end(),
|
|
||||||
inout.begin(),
|
|
||||||
(int (*)(int)) std::tolower
|
|
||||||
);
|
|
||||||
return inout;
|
return inout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,19 +73,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Returns true if str1 begins with substring str2
|
|
||||||
bool begins(const char* str1, const char* str2);
|
|
||||||
|
|
||||||
/// Returns true if str1 ends with substring str2
|
|
||||||
bool ends(const char* str1, const char* str2);
|
|
||||||
|
|
||||||
/// Case insensitive, returns true if str1 begins with substring str2
|
|
||||||
bool ibegins(const char* str1, const char* str2);
|
|
||||||
|
|
||||||
/// Case insensitive, returns true if str1 ends with substring str2
|
|
||||||
bool iends(const char* str1, const char* str2);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
14
extern/shiny/Main/Factory.cpp
vendored
14
extern/shiny/Main/Factory.cpp
vendored
@ -267,10 +267,11 @@ namespace sh
|
|||||||
|
|
||||||
MaterialInstance* Factory::searchInstance (const std::string& name)
|
MaterialInstance* Factory::searchInstance (const std::string& name)
|
||||||
{
|
{
|
||||||
if (mMaterials.find(name) != mMaterials.end())
|
MaterialMap::iterator it = mMaterials.find(name);
|
||||||
return &mMaterials.find(name)->second;
|
if (it != mMaterials.end())
|
||||||
|
return &(it->second);
|
||||||
return NULL;
|
else
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialInstance* Factory::findInstance (const std::string& name)
|
MaterialInstance* Factory::findInstance (const std::string& name)
|
||||||
@ -434,8 +435,9 @@ namespace sh
|
|||||||
|
|
||||||
std::string Factory::retrieveTextureAlias (const std::string& name)
|
std::string Factory::retrieveTextureAlias (const std::string& name)
|
||||||
{
|
{
|
||||||
if (mTextureAliases.find(name) != mTextureAliases.end())
|
TextureAliasMap::iterator it = mTextureAliases.find(name);
|
||||||
return mTextureAliases[name];
|
if (it != mTextureAliases.end())
|
||||||
|
return it->second;
|
||||||
else
|
else
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user