mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-29 07:15:32 +00:00
Merge pull request #10 from cc9cii/master-cherry-pick-3
Merge master (cherry pick 3)
This commit is contained in:
commit
9f4ecc2f8e
119 changed files with 2641 additions and 588 deletions
|
@ -40,8 +40,8 @@ script:
|
|||
- cd ./build
|
||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j2; fi
|
||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi
|
||||
after_script:
|
||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
|
||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi
|
||||
notifications:
|
||||
recipients:
|
||||
- corrmage+travis-ci@gmail.com
|
||||
|
|
|
@ -19,6 +19,7 @@ Programmers
|
|||
Alexander Nadeau (wareya)
|
||||
Alexander Olofsson (Ace)
|
||||
Artem Kotsynyak (greye)
|
||||
artemutin
|
||||
Arthur Moore (EmperorArthur)
|
||||
athile
|
||||
Bret Curtis (psi29a)
|
||||
|
@ -110,6 +111,7 @@ Programmers
|
|||
viadanna
|
||||
Vincent Heuken
|
||||
vocollapse
|
||||
zelurker
|
||||
|
||||
Manual
|
||||
------
|
||||
|
|
9
CI/check_tabs.sh
Executable file
9
CI/check_tabs.sh
Executable file
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
OUTPUT=$(grep -nRP '\t' --include=\*.{cpp,hpp,c,h} apps components)
|
||||
|
||||
if [[ $OUTPUT ]] ; then
|
||||
echo "Error: Tab characters found!"
|
||||
echo $OUTPUT
|
||||
exit 1
|
||||
fi
|
16
CONTRIBUTING.md
Normal file
16
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
Description
|
||||
===========
|
||||
|
||||
Your pull request description should include (if applicable):
|
||||
|
||||
* A link back to the bug report or forum discussion that prompted the change
|
||||
* Summary of the changes made
|
||||
* Reasoning / motivation behind the change
|
||||
* What testing you have carried out to verify the change
|
||||
|
||||
Other notes
|
||||
===========
|
||||
|
||||
* Separate your work into multiple pull requests whenever possible. As a rule of thumb, each feature and each bugfix should go into a separate PR, unless they are closely related or dependent upon each other. Small pull requests are easier to review, and are less likely to require further changes before we can merge them. A "mega" pull request with lots of unrelated commits in it is likely to get held up in review for a long time.
|
||||
* Feel free to submit incomplete pull requests. Even if the work can not be merged yet, pull requests are a great place to collect early feedback. Just make sure to mark it as *[Incomplete]* or *[Do not merge yet]* in the title.
|
||||
* If you plan on contributing often, please read the [Developer Reference](https://wiki.openmw.org/index.php?title=Developer_Reference) on our wiki, especially the [Policies and Standards](https://wiki.openmw.org/index.php?title=Policies_and_Standards).
|
|
@ -493,14 +493,14 @@ void Record<ESM::Book>::print()
|
|||
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
|
||||
if (mPrintPlain)
|
||||
{
|
||||
std::cout << " Text:" << std::endl;
|
||||
std::cout << "START--------------------------------------" << std::endl;
|
||||
std::cout << mData.mText << std::endl;
|
||||
std::cout << "END----------------------------------------" << std::endl;
|
||||
std::cout << " Text:" << std::endl;
|
||||
std::cout << "START--------------------------------------" << std::endl;
|
||||
std::cout << mData.mText << std::endl;
|
||||
std::cout << "END----------------------------------------" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " Text: [skipped]" << std::endl;
|
||||
std::cout << " Text: [skipped]" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -799,14 +799,14 @@ void Record<ESM::DialInfo>::print()
|
|||
{
|
||||
if (mPrintPlain)
|
||||
{
|
||||
std::cout << " Result Script:" << std::endl;
|
||||
std::cout << "START--------------------------------------" << std::endl;
|
||||
std::cout << mData.mResultScript << std::endl;
|
||||
std::cout << "END----------------------------------------" << std::endl;
|
||||
std::cout << " Result Script:" << std::endl;
|
||||
std::cout << "START--------------------------------------" << std::endl;
|
||||
std::cout << mData.mResultScript << std::endl;
|
||||
std::cout << "END----------------------------------------" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " Result Script: [skipped]" << std::endl;
|
||||
std::cout << " Result Script: [skipped]" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -841,19 +841,13 @@ void Record<ESM::Land>::print()
|
|||
std::cout << " Flags: " << landFlags(mData.mFlags) << std::endl;
|
||||
std::cout << " DataTypes: " << mData.mDataTypes << std::endl;
|
||||
|
||||
// Seems like this should done with reference counting in the
|
||||
// loader to me. But I'm not really knowledgable about this
|
||||
// record type yet. --Cory
|
||||
bool wasLoaded = (mData.mDataLoaded != 0);
|
||||
if (mData.mDataTypes) mData.loadData(mData.mDataTypes);
|
||||
if (mData.mDataLoaded)
|
||||
if (const ESM::Land::LandData *data = mData.getLandData (mData.mDataTypes))
|
||||
{
|
||||
std::cout << " Height Offset: " << mData.mLandData->mHeightOffset << std::endl;
|
||||
std::cout << " Height Offset: " << data->mHeightOffset << std::endl;
|
||||
// Lots of missing members.
|
||||
std::cout << " Unknown1: " << mData.mLandData->mUnk1 << std::endl;
|
||||
std::cout << " Unknown2: " << mData.mLandData->mUnk2 << std::endl;
|
||||
std::cout << " Unknown1: " << data->mUnk1 << std::endl;
|
||||
std::cout << " Unknown2: " << data->mUnk2 << std::endl;
|
||||
}
|
||||
if (!wasLoaded) mData.unloadData();
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -1207,14 +1201,14 @@ void Record<ESM::Script>::print()
|
|||
|
||||
if (mPrintPlain)
|
||||
{
|
||||
std::cout << " Script:" << std::endl;
|
||||
std::cout << "START--------------------------------------" << std::endl;
|
||||
std::cout << mData.mScriptText << std::endl;
|
||||
std::cout << "END----------------------------------------" << std::endl;
|
||||
std::cout << " Script:" << std::endl;
|
||||
std::cout << "START--------------------------------------" << std::endl;
|
||||
std::cout << mData.mScriptText << std::endl;
|
||||
std::cout << "END----------------------------------------" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " Script: [skipped]" << std::endl;
|
||||
std::cout << " Script: [skipped]" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace EsmTool
|
|||
}
|
||||
|
||||
void setPrintPlain(bool plain) {
|
||||
mPrintPlain = plain;
|
||||
mPrintPlain = plain;
|
||||
}
|
||||
|
||||
virtual void load(ESM::ESMReader &esm) = 0;
|
||||
|
|
|
@ -296,7 +296,7 @@ namespace ESSImport
|
|||
|
||||
ESM::ESMWriter writer;
|
||||
|
||||
writer.setFormat (ESM::Header::CurrentFormat);
|
||||
writer.setFormat (ESM::SavedGame::sCurrentFormat);
|
||||
|
||||
std::ofstream stream(mOutFile.c_str(), std::ios::binary);
|
||||
// all unused
|
||||
|
|
|
@ -35,13 +35,18 @@ opencs_hdrs_noqt (model/world
|
|||
|
||||
|
||||
opencs_units (model/tools
|
||||
tools reportmodel
|
||||
tools reportmodel mergeoperation
|
||||
)
|
||||
|
||||
opencs_units_noqt (model/tools
|
||||
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
|
||||
birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck
|
||||
startscriptcheck search searchoperation searchstage pathgridcheck soundgencheck magiceffectcheck
|
||||
mergestages
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (model/tools
|
||||
mergestate
|
||||
)
|
||||
|
||||
|
||||
|
@ -62,7 +67,7 @@ opencs_hdrs_noqt (view/doc
|
|||
|
||||
opencs_units (view/world
|
||||
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
|
||||
cellcreator referenceablecreator referencecreator scenesubview
|
||||
cellcreator referenceablecreator startscriptcreator referencecreator scenesubview
|
||||
infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable nestedtable
|
||||
dialoguespinbox recordbuttonbar tableeditidaction scripterrortable extendedcommandconfigurator
|
||||
)
|
||||
|
@ -94,7 +99,7 @@ opencs_hdrs_noqt (view/render
|
|||
|
||||
|
||||
opencs_units (view/tools
|
||||
reportsubview reporttable searchsubview searchbox
|
||||
reportsubview reporttable searchsubview searchbox merge
|
||||
)
|
||||
|
||||
opencs_units_noqt (view/tools
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
|
||||
: mUserSettings (mCfgMgr), mOverlaySystem (0), mDocumentManager (mCfgMgr),
|
||||
mViewManager (mDocumentManager), mPid(""),
|
||||
mLock(), mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL)
|
||||
mLock(), mMerge (mDocumentManager),
|
||||
mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL)
|
||||
{
|
||||
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig();
|
||||
|
||||
|
@ -48,9 +49,12 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
|
|||
|
||||
mNewGame.setLocalData (mLocal);
|
||||
mFileDialog.setLocalData (mLocal);
|
||||
mMerge.setLocalData (mLocal);
|
||||
|
||||
connect (&mDocumentManager, SIGNAL (documentAdded (CSMDoc::Document *)),
|
||||
this, SLOT (documentAdded (CSMDoc::Document *)));
|
||||
connect (&mDocumentManager, SIGNAL (documentAboutToBeRemoved (CSMDoc::Document *)),
|
||||
this, SLOT (documentAboutToBeRemoved (CSMDoc::Document *)));
|
||||
connect (&mDocumentManager, SIGNAL (lastDocumentDeleted()),
|
||||
this, SLOT (lastDocumentDeleted()));
|
||||
|
||||
|
@ -58,6 +62,7 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
|
|||
connect (&mViewManager, SIGNAL (newAddonRequest ()), this, SLOT (createAddon ()));
|
||||
connect (&mViewManager, SIGNAL (loadDocumentRequest ()), this, SLOT (loadDocument ()));
|
||||
connect (&mViewManager, SIGNAL (editSettingsRequest()), this, SLOT (showSettings ()));
|
||||
connect (&mViewManager, SIGNAL (mergeDocument (CSMDoc::Document *)), this, SLOT (mergeDocument (CSMDoc::Document *)));
|
||||
|
||||
connect (&mStartup, SIGNAL (createGame()), this, SLOT (createGame ()));
|
||||
connect (&mStartup, SIGNAL (createAddon()), this, SLOT (createAddon ()));
|
||||
|
@ -490,6 +495,12 @@ void CS::Editor::documentAdded (CSMDoc::Document *document)
|
|||
showSplashMessage();
|
||||
}
|
||||
|
||||
void CS::Editor::documentAboutToBeRemoved (CSMDoc::Document *document)
|
||||
{
|
||||
if (mMerge.getDocument()==document)
|
||||
mMerge.cancel();
|
||||
}
|
||||
|
||||
void CS::Editor::lastDocumentDeleted()
|
||||
{
|
||||
QApplication::quit();
|
||||
|
@ -535,3 +546,11 @@ void CS::Editor::showSplashMessage()
|
|||
splash->raise(); // for X windows
|
||||
}
|
||||
}
|
||||
|
||||
void CS::Editor::mergeDocument (CSMDoc::Document *document)
|
||||
{
|
||||
mMerge.configure (document);
|
||||
mMerge.show();
|
||||
mMerge.raise();
|
||||
mMerge.activateWindow();
|
||||
}
|
||||
|
|
|
@ -32,11 +32,18 @@
|
|||
#include "view/settings/dialog.hpp"
|
||||
#include "view/render/overlaysystem.hpp"
|
||||
|
||||
#include "view/tools/merge.hpp"
|
||||
|
||||
namespace OgreInit
|
||||
{
|
||||
class OgreInit;
|
||||
}
|
||||
|
||||
namespace CSMDoc
|
||||
{
|
||||
class Document;
|
||||
}
|
||||
|
||||
namespace CS
|
||||
{
|
||||
class Editor : public QObject
|
||||
|
@ -59,6 +66,7 @@ namespace CS
|
|||
boost::interprocess::file_lock mLock;
|
||||
boost::filesystem::ofstream mPidFile;
|
||||
bool mFsStrict;
|
||||
CSVTools::Merge mMerge;
|
||||
|
||||
void showSplashMessage();
|
||||
|
||||
|
@ -103,8 +111,12 @@ namespace CS
|
|||
|
||||
void documentAdded (CSMDoc::Document *document);
|
||||
|
||||
void documentAboutToBeRemoved (CSMDoc::Document *document);
|
||||
|
||||
void lastDocumentDeleted();
|
||||
|
||||
void mergeDocument (CSMDoc::Document *document);
|
||||
|
||||
private:
|
||||
|
||||
QString mIpcServerName;
|
||||
|
|
|
@ -2251,14 +2251,14 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
|||
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager,
|
||||
const std::vector<std::string>& blacklistedScripts)
|
||||
: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, resourcesManager),
|
||||
mTools (*this),
|
||||
mTools (*this, encoding),
|
||||
mProjectPath ((configuration.getUserDataPath() / "projects") /
|
||||
(savePath.filename().string() + ".project")),
|
||||
mSavingOperation (*this, mProjectPath, encoding),
|
||||
mSaving (&mSavingOperation),
|
||||
mResDir(resDir),
|
||||
mRunner (mProjectPath), mPhysics(boost::shared_ptr<CSVWorld::PhysicsSystem>()),
|
||||
mIdCompletionManager(mData)
|
||||
mDirty (false), mIdCompletionManager(mData)
|
||||
{
|
||||
if (mContentFiles.empty())
|
||||
throw std::runtime_error ("Empty content file sequence");
|
||||
|
@ -2296,6 +2296,8 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
|||
|
||||
connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
||||
connect (&mTools, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
|
||||
connect (&mTools, SIGNAL (mergeDone (CSMDoc::Document*)),
|
||||
this, SIGNAL (mergeDone (CSMDoc::Document*)));
|
||||
|
||||
connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
||||
connect (&mSaving, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
|
||||
|
@ -2320,7 +2322,7 @@ int CSMDoc::Document::getState() const
|
|||
{
|
||||
int state = 0;
|
||||
|
||||
if (!mUndoStack.isClean())
|
||||
if (!mUndoStack.isClean() || mDirty)
|
||||
state |= State_Modified;
|
||||
|
||||
if (mSaving.isRunning())
|
||||
|
@ -2385,6 +2387,12 @@ void CSMDoc::Document::runSearch (const CSMWorld::UniversalId& searchId, const C
|
|||
emit stateChanged (getState(), this);
|
||||
}
|
||||
|
||||
void CSMDoc::Document::runMerge (std::auto_ptr<CSMDoc::Document> target)
|
||||
{
|
||||
mTools.runMerge (target);
|
||||
emit stateChanged (getState(), this);
|
||||
}
|
||||
|
||||
void CSMDoc::Document::abortOperation (int type)
|
||||
{
|
||||
if (type==State_Saving)
|
||||
|
@ -2406,6 +2414,9 @@ void CSMDoc::Document::reportMessage (const CSMDoc::Message& message, int type)
|
|||
|
||||
void CSMDoc::Document::operationDone (int type, bool failed)
|
||||
{
|
||||
if (type==CSMDoc::State_Saving && !failed)
|
||||
mDirty = false;
|
||||
|
||||
emit stateChanged (getState(), this);
|
||||
}
|
||||
|
||||
|
@ -2490,3 +2501,8 @@ CSMWorld::IdCompletionManager &CSMDoc::Document::getIdCompletionManager()
|
|||
{
|
||||
return mIdCompletionManager;
|
||||
}
|
||||
|
||||
void CSMDoc::Document::flagAsDirty()
|
||||
{
|
||||
mDirty = true;
|
||||
}
|
||||
|
|
|
@ -67,6 +67,8 @@ namespace CSMDoc
|
|||
Blacklist mBlacklist;
|
||||
Runner mRunner;
|
||||
boost::shared_ptr<CSVWorld::PhysicsSystem> mPhysics;
|
||||
bool mDirty;
|
||||
|
||||
CSMWorld::IdCompletionManager mIdCompletionManager;
|
||||
|
||||
// It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is
|
||||
|
@ -125,7 +127,9 @@ namespace CSMDoc
|
|||
CSMWorld::UniversalId newSearch();
|
||||
|
||||
void runSearch (const CSMWorld::UniversalId& searchId, const CSMTools::Search& search);
|
||||
|
||||
|
||||
void runMerge (std::auto_ptr<CSMDoc::Document> target);
|
||||
|
||||
void abortOperation (int type);
|
||||
|
||||
const CSMWorld::Data& getData() const;
|
||||
|
@ -148,12 +152,18 @@ namespace CSMDoc
|
|||
|
||||
CSMWorld::IdCompletionManager &getIdCompletionManager();
|
||||
|
||||
void flagAsDirty();
|
||||
|
||||
signals:
|
||||
|
||||
void stateChanged (int state, CSMDoc::Document *document);
|
||||
|
||||
void progress (int current, int max, int type, int threads, CSMDoc::Document *document);
|
||||
|
||||
/// \attention When this signal is emitted, *this hands over the ownership of the
|
||||
/// document. This signal must be handled to avoid a leak.
|
||||
void mergeDone (CSMDoc::Document *document);
|
||||
|
||||
private slots:
|
||||
|
||||
void modificationStateChanged (bool clean);
|
||||
|
@ -171,4 +181,3 @@ namespace CSMDoc
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -56,10 +56,24 @@ bool CSMDoc::DocumentManager::isEmpty()
|
|||
void CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files, const boost::filesystem::path& savePath,
|
||||
bool new_)
|
||||
{
|
||||
Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager, mBlacklistedScripts);
|
||||
Document *document = makeDocument (files, savePath, new_);
|
||||
insertDocument (document);
|
||||
}
|
||||
|
||||
CSMDoc::Document *CSMDoc::DocumentManager::makeDocument (
|
||||
const std::vector< boost::filesystem::path >& files,
|
||||
const boost::filesystem::path& savePath, bool new_)
|
||||
{
|
||||
return new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager, mBlacklistedScripts);
|
||||
}
|
||||
|
||||
void CSMDoc::DocumentManager::insertDocument (CSMDoc::Document *document)
|
||||
{
|
||||
mDocuments.push_back (document);
|
||||
|
||||
connect (document, SIGNAL (mergeDone (CSMDoc::Document*)),
|
||||
this, SLOT (insertDocument (CSMDoc::Document*)));
|
||||
|
||||
emit loadRequest (document);
|
||||
|
||||
mLoader.hasThingsToDo().wakeAll();
|
||||
|
@ -72,6 +86,8 @@ void CSMDoc::DocumentManager::removeDocument (CSMDoc::Document *document)
|
|||
if (iter==mDocuments.end())
|
||||
throw std::runtime_error ("removing invalid document");
|
||||
|
||||
emit documentAboutToBeRemoved (document);
|
||||
|
||||
mDocuments.erase (iter);
|
||||
document->deleteLater();
|
||||
|
||||
|
|
|
@ -50,6 +50,15 @@ namespace CSMDoc
|
|||
///< \param new_ Do not load the last content file in \a files and instead create in an
|
||||
/// appropriate way.
|
||||
|
||||
/// Create a new document. The ownership of the created document is transferred to
|
||||
/// the calling function. The DocumentManager does not manage it. Loading has not
|
||||
/// taken place at the point when the document is returned.
|
||||
///
|
||||
/// \param new_ Do not load the last content file in \a files and instead create in an
|
||||
/// appropriate way.
|
||||
Document *makeDocument (const std::vector< boost::filesystem::path >& files,
|
||||
const boost::filesystem::path& savePath, bool new_);
|
||||
|
||||
void setResourceDir (const boost::filesystem::path& parResDir);
|
||||
|
||||
void setEncoding (ToUTF8::FromType encoding);
|
||||
|
@ -79,10 +88,16 @@ namespace CSMDoc
|
|||
void removeDocument (CSMDoc::Document *document);
|
||||
///< Emits the lastDocumentDeleted signal, if applicable.
|
||||
|
||||
/// Hand over document to *this. The ownership is transferred. The DocumentManager
|
||||
/// will initiate the load procedure, if necessary
|
||||
void insertDocument (CSMDoc::Document *document);
|
||||
|
||||
signals:
|
||||
|
||||
void documentAdded (CSMDoc::Document *document);
|
||||
|
||||
void documentAboutToBeRemoved (CSMDoc::Document *document);
|
||||
|
||||
void loadRequest (CSMDoc::Document *document);
|
||||
|
||||
void lastDocumentDeleted();
|
||||
|
|
|
@ -83,7 +83,9 @@ namespace CSMDoc
|
|||
|
||||
void executeStage();
|
||||
|
||||
void operationDone();
|
||||
protected slots:
|
||||
|
||||
virtual void operationDone();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -134,23 +134,34 @@ void CSMDoc::WriteDialogueCollectionStage::perform (int stage, Messages& message
|
|||
state==CSMWorld::RecordBase::State_ModifiedOnly ||
|
||||
infoModified)
|
||||
{
|
||||
mState.getWriter().startRecord (topic.mModified.sRecordId);
|
||||
mState.getWriter().writeHNCString ("NAME", topic.mModified.mId);
|
||||
topic.mModified.save (mState.getWriter());
|
||||
mState.getWriter().endRecord (topic.mModified.sRecordId);
|
||||
if (infoModified && state != CSMWorld::RecordBase::State_Modified
|
||||
&& state != CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
{
|
||||
mState.getWriter().startRecord (topic.mBase.sRecordId);
|
||||
mState.getWriter().writeHNCString ("NAME", topic.mBase.mId);
|
||||
topic.mBase.save (mState.getWriter());
|
||||
mState.getWriter().endRecord (topic.mBase.sRecordId);
|
||||
}
|
||||
else
|
||||
{
|
||||
mState.getWriter().startRecord (topic.mModified.sRecordId);
|
||||
mState.getWriter().writeHNCString ("NAME", topic.mModified.mId);
|
||||
topic.mModified.save (mState.getWriter());
|
||||
mState.getWriter().endRecord (topic.mModified.sRecordId);
|
||||
}
|
||||
|
||||
// write modified selected info records
|
||||
for (CSMWorld::InfoCollection::RecordConstIterator iter (range.first); iter!=range.second;
|
||||
++iter)
|
||||
{
|
||||
CSMWorld::RecordBase::State state = iter->mState;
|
||||
CSMWorld::RecordBase::State infoState = iter->mState;
|
||||
|
||||
if (state==CSMWorld::RecordBase::State_Deleted)
|
||||
if (infoState==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
/// \todo wrote record with delete flag
|
||||
}
|
||||
else if (state==CSMWorld::RecordBase::State_Modified ||
|
||||
state==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
else if (infoState==CSMWorld::RecordBase::State_Modified ||
|
||||
infoState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
{
|
||||
ESM::DialInfo info = iter->get();
|
||||
info.mId = info.mId.substr (info.mId.find_last_of ('#')+1);
|
||||
|
@ -415,15 +426,16 @@ void CSMDoc::WriteLandCollectionStage::perform (int stage, Messages& messages)
|
|||
if (land.mState==CSMWorld::RecordBase::State_Modified ||
|
||||
land.mState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
{
|
||||
CSMWorld::Land record = land.get();
|
||||
const CSMWorld::Land& record = land.get();
|
||||
|
||||
mState.getWriter().startRecord (record.mLand->sRecordId);
|
||||
mState.getWriter().startRecord (record.sRecordId);
|
||||
|
||||
record.mLand->save (mState.getWriter());
|
||||
if(record.mLand->mLandData)
|
||||
record.mLand->mLandData->save (mState.getWriter());
|
||||
record.save (mState.getWriter());
|
||||
|
||||
mState.getWriter().endRecord (record.mLand->sRecordId);
|
||||
if (const ESM::Land::LandData *data = record.getLandData (record.mDataTypes))
|
||||
data->save (mState.getWriter());
|
||||
|
||||
mState.getWriter().endRecord (record.sRecordId);
|
||||
}
|
||||
else if (land.mState==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace CSMDoc
|
|||
|
||||
State_Saving = 16,
|
||||
State_Verifying = 32,
|
||||
State_Compiling = 64, // not implemented yet
|
||||
State_Merging = 64,
|
||||
State_Searching = 128,
|
||||
State_Loading = 256 // pseudo-state; can not be encountered in a loaded document
|
||||
};
|
||||
|
|
59
apps/opencs/model/tools/mergeoperation.cpp
Normal file
59
apps/opencs/model/tools/mergeoperation.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
|
||||
#include "mergeoperation.hpp"
|
||||
|
||||
#include "../doc/state.hpp"
|
||||
#include "../doc/document.hpp"
|
||||
|
||||
#include "mergestages.hpp"
|
||||
|
||||
CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document, ToUTF8::FromType encoding)
|
||||
: CSMDoc::Operation (CSMDoc::State_Merging, true), mState (document)
|
||||
{
|
||||
appendStage (new StartMergeStage (mState));
|
||||
|
||||
appendStage (new MergeIdCollectionStage<ESM::Global> (mState, &CSMWorld::Data::getGlobals));
|
||||
appendStage (new MergeIdCollectionStage<ESM::GameSetting> (mState, &CSMWorld::Data::getGmsts));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Skill> (mState, &CSMWorld::Data::getSkills));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Class> (mState, &CSMWorld::Data::getClasses));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Faction> (mState, &CSMWorld::Data::getFactions));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Race> (mState, &CSMWorld::Data::getRaces));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Sound> (mState, &CSMWorld::Data::getSounds));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Script> (mState, &CSMWorld::Data::getScripts));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Region> (mState, &CSMWorld::Data::getRegions));
|
||||
appendStage (new MergeIdCollectionStage<ESM::BirthSign> (mState, &CSMWorld::Data::getBirthsigns));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Spell> (mState, &CSMWorld::Data::getSpells));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Dialogue> (mState, &CSMWorld::Data::getTopics));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Dialogue> (mState, &CSMWorld::Data::getJournals));
|
||||
appendStage (new MergeIdCollectionStage<CSMWorld::Cell> (mState, &CSMWorld::Data::getCells));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Filter> (mState, &CSMWorld::Data::getFilters));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Enchantment> (mState, &CSMWorld::Data::getEnchantments));
|
||||
appendStage (new MergeIdCollectionStage<ESM::BodyPart> (mState, &CSMWorld::Data::getBodyParts));
|
||||
appendStage (new MergeIdCollectionStage<ESM::DebugProfile> (mState, &CSMWorld::Data::getDebugProfiles));
|
||||
appendStage (new MergeIdCollectionStage<ESM::SoundGenerator> (mState, &CSMWorld::Data::getSoundGens));
|
||||
appendStage (new MergeIdCollectionStage<ESM::MagicEffect> (mState, &CSMWorld::Data::getMagicEffects));
|
||||
appendStage (new MergeIdCollectionStage<ESM::StartScript> (mState, &CSMWorld::Data::getStartScripts));
|
||||
appendStage (new MergeIdCollectionStage<CSMWorld::Pathgrid, CSMWorld::SubCellCollection<CSMWorld::Pathgrid> > (mState, &CSMWorld::Data::getPathgrids));
|
||||
appendStage (new MergeIdCollectionStage<CSMWorld::Info, CSMWorld::InfoCollection> (mState, &CSMWorld::Data::getTopicInfos));
|
||||
appendStage (new MergeIdCollectionStage<CSMWorld::Info, CSMWorld::InfoCollection> (mState, &CSMWorld::Data::getJournalInfos));
|
||||
appendStage (new MergeRefIdsStage (mState));
|
||||
appendStage (new MergeReferencesStage (mState));
|
||||
appendStage (new MergeReferencesStage (mState));
|
||||
appendStage (new ListLandTexturesMergeStage (mState));
|
||||
appendStage (new MergeLandTexturesStage (mState));
|
||||
appendStage (new MergeLandStage (mState));
|
||||
|
||||
appendStage (new FinishMergedDocumentStage (mState, encoding));
|
||||
}
|
||||
|
||||
void CSMTools::MergeOperation::setTarget (std::auto_ptr<CSMDoc::Document> document)
|
||||
{
|
||||
mState.mTarget = document;
|
||||
}
|
||||
|
||||
void CSMTools::MergeOperation::operationDone()
|
||||
{
|
||||
CSMDoc::Operation::operationDone();
|
||||
|
||||
if (mState.mCompleted)
|
||||
emit mergeDone (mState.mTarget.release());
|
||||
}
|
45
apps/opencs/model/tools/mergeoperation.hpp
Normal file
45
apps/opencs/model/tools/mergeoperation.hpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#ifndef CSM_TOOLS_MERGEOPERATION_H
|
||||
#define CSM_TOOLS_MERGEOPERATION_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
|
||||
#include "../doc/operation.hpp"
|
||||
|
||||
#include "mergestate.hpp"
|
||||
|
||||
namespace CSMDoc
|
||||
{
|
||||
class Document;
|
||||
}
|
||||
|
||||
namespace CSMTools
|
||||
{
|
||||
class MergeOperation : public CSMDoc::Operation
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
MergeState mState;
|
||||
|
||||
public:
|
||||
|
||||
MergeOperation (CSMDoc::Document& document, ToUTF8::FromType encoding);
|
||||
|
||||
/// \attention Do not call this function while a merge is running.
|
||||
void setTarget (std::auto_ptr<CSMDoc::Document> document);
|
||||
|
||||
protected slots:
|
||||
|
||||
virtual void operationDone();
|
||||
|
||||
signals:
|
||||
|
||||
/// \attention When this signal is emitted, *this hands over the ownership of the
|
||||
/// document. This signal must be handled to avoid a leak.
|
||||
void mergeDone (CSMDoc::Document *document);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
258
apps/opencs/model/tools/mergestages.cpp
Normal file
258
apps/opencs/model/tools/mergestages.cpp
Normal file
|
@ -0,0 +1,258 @@
|
|||
|
||||
#include "mergestages.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "mergestate.hpp"
|
||||
|
||||
#include "../doc/document.hpp"
|
||||
#include "../world/data.hpp"
|
||||
|
||||
|
||||
CSMTools::StartMergeStage::StartMergeStage (MergeState& state)
|
||||
: mState (state)
|
||||
{}
|
||||
|
||||
int CSMTools::StartMergeStage::setup()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CSMTools::StartMergeStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
mState.mCompleted = false;
|
||||
mState.mTextureIndices.clear();
|
||||
}
|
||||
|
||||
|
||||
CSMTools::FinishMergedDocumentStage::FinishMergedDocumentStage (MergeState& state, ToUTF8::FromType encoding)
|
||||
: mState (state), mEncoder (encoding)
|
||||
{}
|
||||
|
||||
int CSMTools::FinishMergedDocumentStage::setup()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CSMTools::FinishMergedDocumentStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
// We know that the content file list contains at least two entries and that the first one
|
||||
// does exist on disc (otherwise it would have been impossible to initiate a merge on that
|
||||
// document).
|
||||
boost::filesystem::path path = mState.mSource.getContentFiles()[0];
|
||||
|
||||
ESM::ESMReader reader;
|
||||
reader.setEncoder (&mEncoder);
|
||||
reader.open (path.string());
|
||||
|
||||
CSMWorld::MetaData source;
|
||||
source.mId = "sys::meta";
|
||||
source.load (reader);
|
||||
|
||||
CSMWorld::MetaData target = mState.mTarget->getData().getMetaData();
|
||||
|
||||
target.mAuthor = source.mAuthor;
|
||||
target.mDescription = source.mDescription;
|
||||
|
||||
mState.mTarget->getData().setMetaData (target);
|
||||
|
||||
mState.mCompleted = true;
|
||||
}
|
||||
|
||||
|
||||
CSMTools::MergeRefIdsStage::MergeRefIdsStage (MergeState& state) : mState (state) {}
|
||||
|
||||
int CSMTools::MergeRefIdsStage::setup()
|
||||
{
|
||||
return mState.mSource.getData().getReferenceables().getSize();
|
||||
}
|
||||
|
||||
void CSMTools::MergeRefIdsStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
mState.mSource.getData().getReferenceables().copyTo (
|
||||
stage, mState.mTarget->getData().getReferenceables());
|
||||
}
|
||||
|
||||
|
||||
CSMTools::MergeReferencesStage::MergeReferencesStage (MergeState& state)
|
||||
: mState (state)
|
||||
{}
|
||||
|
||||
int CSMTools::MergeReferencesStage::setup()
|
||||
{
|
||||
mIndex.clear();
|
||||
return mState.mSource.getData().getReferences().getSize();
|
||||
}
|
||||
|
||||
void CSMTools::MergeReferencesStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
const CSMWorld::Record<CSMWorld::CellRef>& record =
|
||||
mState.mSource.getData().getReferences().getRecord (stage);
|
||||
|
||||
if (!record.isDeleted())
|
||||
{
|
||||
CSMWorld::CellRef ref = record.get();
|
||||
|
||||
ref.mOriginalCell = ref.mCell;
|
||||
|
||||
ref.mRefNum.mIndex = mIndex[Misc::StringUtils::lowerCase (ref.mCell)]++;
|
||||
ref.mRefNum.mContentFile = 0;
|
||||
|
||||
CSMWorld::Record<CSMWorld::CellRef> newRecord (
|
||||
CSMWorld::RecordBase::State_ModifiedOnly, 0, &ref);
|
||||
|
||||
mState.mTarget->getData().getReferences().appendRecord (newRecord);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CSMTools::ListLandTexturesMergeStage::ListLandTexturesMergeStage (MergeState& state)
|
||||
: mState (state)
|
||||
{}
|
||||
|
||||
int CSMTools::ListLandTexturesMergeStage::setup()
|
||||
{
|
||||
return mState.mSource.getData().getLand().getSize();
|
||||
}
|
||||
|
||||
void CSMTools::ListLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
const CSMWorld::Record<CSMWorld::Land>& record =
|
||||
mState.mSource.getData().getLand().getRecord (stage);
|
||||
|
||||
if (!record.isDeleted())
|
||||
{
|
||||
const CSMWorld::Land& land = record.get();
|
||||
|
||||
// make sure record is loaded
|
||||
land.loadData (ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML |
|
||||
ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM);
|
||||
|
||||
if (const ESM::Land::LandData *data = land.getLandData (ESM::Land::DATA_VTEX))
|
||||
{
|
||||
// list texture indices
|
||||
std::pair<uint16_t, int> key;
|
||||
key.second = land.mPlugin;
|
||||
|
||||
for (int i=0; i<ESM::Land::LAND_NUM_TEXTURES; ++i)
|
||||
{
|
||||
key.first = data->mTextures[i];
|
||||
|
||||
mState.mTextureIndices[key] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CSMTools::MergeLandTexturesStage::MergeLandTexturesStage (MergeState& state)
|
||||
: mState (state), mNext (mState.mTextureIndices.end())
|
||||
{}
|
||||
|
||||
int CSMTools::MergeLandTexturesStage::setup()
|
||||
{
|
||||
// Should use the size of mState.mTextureIndices instead, but that is not available at this
|
||||
// point. Unless there are any errors in the land and land texture records this will not
|
||||
// make a difference.
|
||||
return mState.mSource.getData().getLandTextures().getSize();
|
||||
}
|
||||
|
||||
void CSMTools::MergeLandTexturesStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
if (stage==0)
|
||||
mNext = mState.mTextureIndices.begin();
|
||||
|
||||
bool found = false;
|
||||
|
||||
do
|
||||
{
|
||||
if (mNext==mState.mTextureIndices.end())
|
||||
return;
|
||||
|
||||
mNext->second = stage+1;
|
||||
|
||||
std::ostringstream stream;
|
||||
stream << mNext->first.first-1 << "_" << mNext->first.second;
|
||||
|
||||
int index = mState.mSource.getData().getLandTextures().searchId (stream.str());
|
||||
|
||||
if (index!=-1)
|
||||
{
|
||||
CSMWorld::LandTexture texture =
|
||||
mState.mSource.getData().getLandTextures().getRecord (index).get();
|
||||
|
||||
std::ostringstream stream;
|
||||
stream << mNext->second-1 << "_0";
|
||||
|
||||
texture.mIndex = mNext->second-1;
|
||||
texture.mId = stream.str();
|
||||
|
||||
CSMWorld::Record<CSMWorld::LandTexture> newRecord (
|
||||
CSMWorld::RecordBase::State_ModifiedOnly, 0, &texture);
|
||||
|
||||
mState.mTarget->getData().getLandTextures().appendRecord (newRecord);
|
||||
|
||||
found = true;
|
||||
}
|
||||
|
||||
++mNext;
|
||||
}
|
||||
while (!found);
|
||||
}
|
||||
|
||||
|
||||
CSMTools::MergeLandStage::MergeLandStage (MergeState& state) : mState (state) {}
|
||||
|
||||
int CSMTools::MergeLandStage::setup()
|
||||
{
|
||||
return mState.mSource.getData().getLand().getSize();
|
||||
}
|
||||
|
||||
void CSMTools::MergeLandStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
const CSMWorld::Record<CSMWorld::Land>& record =
|
||||
mState.mSource.getData().getLand().getRecord (stage);
|
||||
|
||||
if (!record.isDeleted())
|
||||
{
|
||||
const CSMWorld::Land& land = record.get();
|
||||
|
||||
land.loadData (ESM::Land::DATA_VCLR | ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML |
|
||||
ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM);
|
||||
|
||||
CSMWorld::Land newLand (land);
|
||||
|
||||
newLand.mEsm = 0; // avoid potential dangling pointer (ESMReader isn't needed anyway,
|
||||
// because record is already fully loaded)
|
||||
newLand.mPlugin = 0;
|
||||
|
||||
if (land.mDataTypes & ESM::Land::DATA_VTEX)
|
||||
{
|
||||
// adjust land texture references
|
||||
if (ESM::Land::LandData *data = newLand.getLandData())
|
||||
{
|
||||
std::pair<uint16_t, int> key;
|
||||
key.second = land.mPlugin;
|
||||
|
||||
for (int i=0; i<ESM::Land::LAND_NUM_TEXTURES; ++i)
|
||||
{
|
||||
key.first = data->mTextures[i];
|
||||
std::map<std::pair<uint16_t, int>, int>::const_iterator iter =
|
||||
mState.mTextureIndices.find (key);
|
||||
|
||||
if (iter!=mState.mTextureIndices.end())
|
||||
data->mTextures[i] = iter->second;
|
||||
else
|
||||
data->mTextures[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CSMWorld::Record<CSMWorld::Land> newRecord (
|
||||
CSMWorld::RecordBase::State_ModifiedOnly, 0, &newLand);
|
||||
|
||||
mState.mTarget->getData().getLand().appendRecord (newRecord);
|
||||
}
|
||||
}
|
166
apps/opencs/model/tools/mergestages.hpp
Normal file
166
apps/opencs/model/tools/mergestages.hpp
Normal file
|
@ -0,0 +1,166 @@
|
|||
#ifndef CSM_TOOLS_MERGESTAGES_H
|
||||
#define CSM_TOOLS_MERGESTAGES_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
|
||||
#include "../doc/stage.hpp"
|
||||
|
||||
#include "../world/data.hpp"
|
||||
|
||||
#include "mergestate.hpp"
|
||||
|
||||
namespace CSMTools
|
||||
{
|
||||
class StartMergeStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
|
||||
public:
|
||||
|
||||
StartMergeStage (MergeState& state);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
class FinishMergedDocumentStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
ToUTF8::Utf8Encoder mEncoder;
|
||||
|
||||
public:
|
||||
|
||||
FinishMergedDocumentStage (MergeState& state, ToUTF8::FromType encoding);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
template<typename RecordType, typename Collection = CSMWorld::IdCollection<RecordType> >
|
||||
class MergeIdCollectionStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
Collection& (CSMWorld::Data::*mAccessor)();
|
||||
|
||||
public:
|
||||
|
||||
MergeIdCollectionStage (MergeState& state, Collection& (CSMWorld::Data::*accessor)());
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
template<typename RecordType, typename Collection>
|
||||
MergeIdCollectionStage<RecordType, Collection>::MergeIdCollectionStage (MergeState& state, Collection& (CSMWorld::Data::*accessor)())
|
||||
: mState (state), mAccessor (accessor)
|
||||
{}
|
||||
|
||||
template<typename RecordType, typename Collection>
|
||||
int MergeIdCollectionStage<RecordType, Collection>::setup()
|
||||
{
|
||||
return (mState.mSource.getData().*mAccessor)().getSize();
|
||||
}
|
||||
|
||||
template<typename RecordType, typename Collection>
|
||||
void MergeIdCollectionStage<RecordType, Collection>::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
const Collection& source = (mState.mSource.getData().*mAccessor)();
|
||||
Collection& target = (mState.mTarget->getData().*mAccessor)();
|
||||
|
||||
const CSMWorld::Record<RecordType>& record = source.getRecord (stage);
|
||||
|
||||
if (!record.isDeleted())
|
||||
target.appendRecord (CSMWorld::Record<RecordType> (CSMWorld::RecordBase::State_ModifiedOnly, 0, &record.get()));
|
||||
}
|
||||
|
||||
class MergeRefIdsStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
|
||||
public:
|
||||
|
||||
MergeRefIdsStage (MergeState& state);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
class MergeReferencesStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
std::map<std::string, int> mIndex;
|
||||
|
||||
public:
|
||||
|
||||
MergeReferencesStage (MergeState& state);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
class ListLandTexturesMergeStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
|
||||
public:
|
||||
|
||||
ListLandTexturesMergeStage (MergeState& state);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
class MergeLandTexturesStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
std::map<std::pair<uint16_t, int>, int>::iterator mNext;
|
||||
|
||||
public:
|
||||
|
||||
MergeLandTexturesStage (MergeState& state);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
class MergeLandStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
|
||||
public:
|
||||
|
||||
MergeLandStage (MergeState& state);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
24
apps/opencs/model/tools/mergestate.hpp
Normal file
24
apps/opencs/model/tools/mergestate.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef CSM_TOOLS_MERGESTATE_H
|
||||
#define CSM_TOOLS_MERGESTATE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
#include "../doc/document.hpp"
|
||||
|
||||
namespace CSMTools
|
||||
{
|
||||
struct MergeState
|
||||
{
|
||||
std::auto_ptr<CSMDoc::Document> mTarget;
|
||||
CSMDoc::Document& mSource;
|
||||
bool mCompleted;
|
||||
std::map<std::pair<uint16_t, int>, int> mTextureIndices; // (texture, content file) -> new texture
|
||||
|
||||
MergeState (CSMDoc::Document& source) : mSource (source), mCompleted (false) {}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -468,6 +468,9 @@ void CSMTools::ReferenceableCheckStage::creatureCheck (
|
|||
if (creature.mData.mGold < 0) //It seems that this is for gold in merchant creatures
|
||||
messages.push_back (std::make_pair (id, creature.mId + " has negative gold "));
|
||||
|
||||
if (creature.mScale == 0)
|
||||
messages.push_back (std::make_pair (id, creature.mId + " has zero scale value"));
|
||||
|
||||
// Check that mentioned scripts exist
|
||||
scriptCheck<ESM::Creature>(creature, messages, id.toString());
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "pathgridcheck.hpp"
|
||||
#include "soundgencheck.hpp"
|
||||
#include "magiceffectcheck.hpp"
|
||||
#include "mergeoperation.hpp"
|
||||
|
||||
CSMDoc::OperationHolder *CSMTools::Tools::get (int type)
|
||||
{
|
||||
|
@ -35,6 +36,7 @@ CSMDoc::OperationHolder *CSMTools::Tools::get (int type)
|
|||
{
|
||||
case CSMDoc::State_Verifying: return &mVerifier;
|
||||
case CSMDoc::State_Searching: return &mSearch;
|
||||
case CSMDoc::State_Merging: return &mMerge;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -53,7 +55,7 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier()
|
|||
|
||||
std::vector<QString> settings;
|
||||
settings.push_back ("script-editor/warnings");
|
||||
|
||||
|
||||
mVerifierOperation->configureSettings (settings);
|
||||
|
||||
connect (&mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
|
||||
|
@ -120,9 +122,9 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier()
|
|||
return &mVerifier;
|
||||
}
|
||||
|
||||
CSMTools::Tools::Tools (CSMDoc::Document& document)
|
||||
CSMTools::Tools::Tools (CSMDoc::Document& document, ToUTF8::FromType encoding)
|
||||
: mDocument (document), mData (document.getData()), mVerifierOperation (0),
|
||||
mSearchOperation (0), mNextReportNumber (0)
|
||||
mSearchOperation (0), mMergeOperation (0), mNextReportNumber (0), mEncoding (encoding)
|
||||
{
|
||||
// index 0: load error log
|
||||
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel));
|
||||
|
@ -132,6 +134,10 @@ CSMTools::Tools::Tools (CSMDoc::Document& document)
|
|||
connect (&mSearch, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
|
||||
connect (&mSearch, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
|
||||
this, SLOT (verifierMessage (const CSMDoc::Message&, int)));
|
||||
|
||||
connect (&mMerge, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
|
||||
connect (&mMerge, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
|
||||
// don't need to connect report message, since there are no messages for merge
|
||||
}
|
||||
|
||||
CSMTools::Tools::~Tools()
|
||||
|
@ -148,6 +154,12 @@ CSMTools::Tools::~Tools()
|
|||
delete mSearchOperation;
|
||||
}
|
||||
|
||||
if (mMergeOperation)
|
||||
{
|
||||
mMerge.abortAndWait();
|
||||
delete mMergeOperation;
|
||||
}
|
||||
|
||||
for (std::map<int, ReportModel *>::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter)
|
||||
delete iter->second;
|
||||
}
|
||||
|
@ -159,7 +171,7 @@ CSMWorld::UniversalId CSMTools::Tools::runVerifier (const CSMWorld::UniversalId&
|
|||
|
||||
if (mReports.find (reportNumber)==mReports.end())
|
||||
mReports.insert (std::make_pair (reportNumber, new ReportModel));
|
||||
|
||||
|
||||
mActiveReports[CSMDoc::State_Verifying] = reportNumber;
|
||||
|
||||
getVerifier()->start();
|
||||
|
@ -189,6 +201,25 @@ void CSMTools::Tools::runSearch (const CSMWorld::UniversalId& searchId, const Se
|
|||
mSearch.start();
|
||||
}
|
||||
|
||||
void CSMTools::Tools::runMerge (std::auto_ptr<CSMDoc::Document> target)
|
||||
{
|
||||
// not setting an active report, because merge does not produce messages
|
||||
|
||||
if (!mMergeOperation)
|
||||
{
|
||||
mMergeOperation = new MergeOperation (mDocument, mEncoding);
|
||||
mMerge.setOperation (mMergeOperation);
|
||||
connect (mMergeOperation, SIGNAL (mergeDone (CSMDoc::Document*)),
|
||||
this, SIGNAL (mergeDone (CSMDoc::Document*)));
|
||||
}
|
||||
|
||||
target->flagAsDirty();
|
||||
|
||||
mMergeOperation->setTarget (target);
|
||||
|
||||
mMerge.start();
|
||||
}
|
||||
|
||||
void CSMTools::Tools::abortOperation (int type)
|
||||
{
|
||||
if (CSMDoc::OperationHolder *operation = get (type))
|
||||
|
@ -201,6 +232,7 @@ int CSMTools::Tools::getRunningOperations() const
|
|||
{
|
||||
CSMDoc::State_Verifying,
|
||||
CSMDoc::State_Searching,
|
||||
CSMDoc::State_Merging,
|
||||
-1
|
||||
};
|
||||
|
||||
|
@ -231,4 +263,3 @@ void CSMTools::Tools::verifierMessage (const CSMDoc::Message& message, int type)
|
|||
if (iter!=mActiveReports.end())
|
||||
mReports[iter->second]->add (message);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
#ifndef CSM_TOOLS_TOOLS_H
|
||||
#define CSM_TOOLS_TOOLS_H
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <map>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#include "../doc/operationholder.hpp"
|
||||
|
||||
|
@ -24,6 +29,7 @@ namespace CSMTools
|
|||
class ReportModel;
|
||||
class Search;
|
||||
class SearchOperation;
|
||||
class MergeOperation;
|
||||
|
||||
class Tools : public QObject
|
||||
{
|
||||
|
@ -35,9 +41,12 @@ namespace CSMTools
|
|||
CSMDoc::OperationHolder mVerifier;
|
||||
SearchOperation *mSearchOperation;
|
||||
CSMDoc::OperationHolder mSearch;
|
||||
MergeOperation *mMergeOperation;
|
||||
CSMDoc::OperationHolder mMerge;
|
||||
std::map<int, ReportModel *> mReports;
|
||||
int mNextReportNumber;
|
||||
std::map<int, int> mActiveReports; // type, report number
|
||||
ToUTF8::FromType mEncoding;
|
||||
|
||||
// not implemented
|
||||
Tools (const Tools&);
|
||||
|
@ -53,7 +62,7 @@ namespace CSMTools
|
|||
|
||||
public:
|
||||
|
||||
Tools (CSMDoc::Document& document);
|
||||
Tools (CSMDoc::Document& document, ToUTF8::FromType encoding);
|
||||
|
||||
virtual ~Tools();
|
||||
|
||||
|
@ -67,7 +76,9 @@ namespace CSMTools
|
|||
CSMWorld::UniversalId newSearch();
|
||||
|
||||
void runSearch (const CSMWorld::UniversalId& searchId, const Search& search);
|
||||
|
||||
|
||||
void runMerge (std::auto_ptr<CSMDoc::Document> target);
|
||||
|
||||
void abortOperation (int type);
|
||||
///< \attention The operation is not aborted immediately.
|
||||
|
||||
|
@ -85,6 +96,10 @@ namespace CSMTools
|
|||
void progress (int current, int max, int type);
|
||||
|
||||
void done (int type, bool failed);
|
||||
|
||||
/// \attention When this signal is emitted, *this hands over the ownership of the
|
||||
/// document. This signal must be handled to avoid a leak.
|
||||
void mergeDone (CSMDoc::Document *document);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ bool CSMWorld::ColumnBase::isId (Display display)
|
|||
Display_Video,
|
||||
|
||||
Display_Id,
|
||||
Display_SkillImpact,
|
||||
Display_SkillId,
|
||||
Display_EffectRange,
|
||||
Display_EffectId,
|
||||
Display_PartRefType,
|
||||
|
@ -85,7 +85,10 @@ bool CSMWorld::ColumnBase::isId (Display display)
|
|||
Display_InfoCondFunc,
|
||||
Display_InfoCondVar,
|
||||
Display_InfoCondComp,
|
||||
Display_RaceSkill,
|
||||
|
||||
Display_EffectSkill,
|
||||
Display_EffectAttribute,
|
||||
Display_IngredEffectId,
|
||||
|
||||
Display_None
|
||||
};
|
||||
|
|
|
@ -14,6 +14,13 @@ namespace CSMWorld
|
|||
{
|
||||
struct ColumnBase
|
||||
{
|
||||
enum TableEditModes
|
||||
{
|
||||
TableEdit_None, // no editing
|
||||
TableEdit_Full, // edit cells and add/remove rows
|
||||
TableEdit_FixedRows // edit cells only
|
||||
};
|
||||
|
||||
enum Roles
|
||||
{
|
||||
Role_Flags = Qt::UserRole,
|
||||
|
@ -113,7 +120,7 @@ namespace CSMWorld
|
|||
Display_SoundGeneratorType,
|
||||
Display_School,
|
||||
Display_Id,
|
||||
Display_SkillImpact,
|
||||
Display_SkillId,
|
||||
Display_EffectRange,
|
||||
Display_EffectId,
|
||||
Display_PartRefType,
|
||||
|
@ -121,10 +128,13 @@ namespace CSMWorld
|
|||
Display_InfoCondFunc,
|
||||
Display_InfoCondVar,
|
||||
Display_InfoCondComp,
|
||||
Display_RaceSkill,
|
||||
Display_String32,
|
||||
Display_LongString256,
|
||||
|
||||
Display_EffectSkill, // must display at least one, unlike Display_Skill
|
||||
Display_EffectAttribute, // must display at least one, unlike Display_Attribute
|
||||
Display_IngredEffectId, // display none allowed, unlike Display_EffectId
|
||||
|
||||
//top level columns that nest other columns
|
||||
Display_NestedHeader
|
||||
};
|
||||
|
@ -187,8 +197,8 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct NestedParentColumn : public Column<ESXRecordT>
|
||||
{
|
||||
NestedParentColumn (int id, int flags = ColumnBase::Flag_Dialogue) : Column<ESXRecordT> (id,
|
||||
ColumnBase::Display_NestedHeader, flags)
|
||||
NestedParentColumn (int id, int flags = ColumnBase::Flag_Dialogue, bool fixedRows = false)
|
||||
: Column<ESXRecordT> (id, ColumnBase::Display_NestedHeader, flags), mFixedRows(fixedRows)
|
||||
{}
|
||||
|
||||
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||
|
@ -199,13 +209,20 @@ namespace CSMWorld
|
|||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
return true; // required by IdTree::hasChildren()
|
||||
// by default editable; also see IdTree::hasChildren()
|
||||
if (mFixedRows)
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_FixedRows);
|
||||
else
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
}
|
||||
|
||||
virtual bool isEditable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool mFixedRows;
|
||||
};
|
||||
|
||||
struct NestedChildColumn : public NestableColumn
|
||||
|
@ -220,4 +237,6 @@ namespace CSMWorld
|
|||
};
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(CSMWorld::ColumnBase::TableEditModes)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -71,7 +71,6 @@ namespace CSMWorld
|
|||
{ ColumnId_Weight, "Weight" },
|
||||
{ ColumnId_EnchantmentPoints, "Enchantment Points" },
|
||||
{ ColumnId_Quality, "Quality" },
|
||||
{ ColumnId_Ai, "AI" },
|
||||
{ ColumnId_AiHello, "AI Hello" },
|
||||
{ ColumnId_AiFlee, "AI Flee" },
|
||||
{ ColumnId_AiFight, "AI Fight" },
|
||||
|
@ -199,8 +198,6 @@ namespace CSMWorld
|
|||
{ ColumnId_RotY, "Rotation Y"},
|
||||
{ ColumnId_RotZ, "Rotation Z"},
|
||||
|
||||
{ ColumnId_Skill, "Skill" },
|
||||
|
||||
{ ColumnId_OwnerGlobal, "Owner Global" },
|
||||
{ ColumnId_DefaultProfile, "Default Profile" },
|
||||
{ ColumnId_BypassNewGame, "Bypass New Game" },
|
||||
|
@ -252,7 +249,7 @@ namespace CSMWorld
|
|||
{ ColumnId_AiWanderDist, "Wander Dist" },
|
||||
{ ColumnId_AiDuration, "Ai Duration" },
|
||||
{ ColumnId_AiWanderToD, "Wander ToD" },
|
||||
{ ColumnId_AiWanderIdle, "Wander Idle" },
|
||||
//{ ColumnId_AiWanderIdle, "Wander Idle" },
|
||||
{ ColumnId_AiWanderRepeat, "Wander Repeat" },
|
||||
{ ColumnId_AiActivateName, "Activate" },
|
||||
{ ColumnId_AiTargetId, "Target ID" },
|
||||
|
@ -265,13 +262,13 @@ namespace CSMWorld
|
|||
|
||||
{ ColumnId_LevelledList,"Levelled List" },
|
||||
{ ColumnId_LevelledItemId,"Levelled Item" },
|
||||
{ ColumnId_LevelledItemLevel,"Level" },
|
||||
{ ColumnId_LevelledItemLevel,"Item Level" },
|
||||
{ ColumnId_LevelledItemType, "Calculate all levels <= player" },
|
||||
{ ColumnId_LevelledItemTypeEach, "Select a new item each instance" },
|
||||
{ ColumnId_LevelledItemChanceNone, "Chance None" },
|
||||
|
||||
{ ColumnId_PowerList, "Powers" },
|
||||
{ ColumnId_SkillImpact, "Skills" },
|
||||
{ ColumnId_Skill, "Skill" },
|
||||
|
||||
{ ColumnId_InfoList, "Info List" },
|
||||
{ ColumnId_InfoCondition, "Info Conditions" },
|
||||
|
@ -281,26 +278,24 @@ namespace CSMWorld
|
|||
{ ColumnId_InfoCondValue, "Values" },
|
||||
{ ColumnId_OriginalCell, "Original Cell" },
|
||||
|
||||
{ ColumnId_NpcAttributes, "Attributes" },
|
||||
{ ColumnId_NpcSkills, "Skills" },
|
||||
{ ColumnId_NpcAttributes, "NPC Attributes" },
|
||||
{ ColumnId_NpcSkills, "NPC Skill" },
|
||||
{ ColumnId_UChar, "Value [0..255]" },
|
||||
{ ColumnId_NpcMisc, "Misc" },
|
||||
{ ColumnId_NpcLevel, "Level" },
|
||||
{ ColumnId_NpcMisc, "NPC Misc" },
|
||||
{ ColumnId_Level, "Level" },
|
||||
{ ColumnId_NpcFactionID, "Faction ID" },
|
||||
{ ColumnId_NpcHealth, "Health" },
|
||||
{ ColumnId_NpcMana, "Mana" },
|
||||
{ ColumnId_NpcFatigue, "Fatigue" },
|
||||
{ ColumnId_NpcDisposition, "Disposition" },
|
||||
|
||||
{ ColumnId_Mana, "Mana" },
|
||||
{ ColumnId_Fatigue, "Fatigue" },
|
||||
{ ColumnId_NpcDisposition, "NPC Disposition" },
|
||||
{ ColumnId_NpcReputation, "Reputation" },
|
||||
{ ColumnId_NpcRank, "Rank" },
|
||||
{ ColumnId_NpcGold, "Gold" },
|
||||
{ ColumnId_NpcRank, "NPC Rank" },
|
||||
{ ColumnId_Gold, "Gold" },
|
||||
{ ColumnId_NpcPersistence, "Persistent" },
|
||||
|
||||
{ ColumnId_RaceAttributes, "Attributes" },
|
||||
{ ColumnId_RaceMaleValue, "Male" },
|
||||
{ ColumnId_RaceFemaleValue, "Female" },
|
||||
{ ColumnId_RaceAttributes, "Race Attributes" },
|
||||
{ ColumnId_Male, "Male" },
|
||||
{ ColumnId_RaceSkillBonus, "Skill Bonus" },
|
||||
{ ColumnId_RaceSkill, "Skills" },
|
||||
{ ColumnId_RaceBonus, "Bonus" },
|
||||
|
||||
{ ColumnId_Interior, "Interior" },
|
||||
|
@ -315,6 +310,22 @@ namespace CSMWorld
|
|||
{ ColumnId_FileDescription, "File Description" },
|
||||
{ ColumnId_Author, "Author" },
|
||||
|
||||
{ ColumnId_CreatureAttributes, "Creature Attributes" },
|
||||
{ ColumnId_AttributeValue, "Attrib Value" },
|
||||
{ ColumnId_CreatureAttack, "Creature Attack" },
|
||||
{ ColumnId_MinAttack, "Min Attack" },
|
||||
{ ColumnId_MaxAttack, "Max Attack" },
|
||||
{ ColumnId_CreatureMisc, "Creature Misc" },
|
||||
|
||||
{ ColumnId_Idle1, "Idle 1" },
|
||||
{ ColumnId_Idle2, "Idle 2" },
|
||||
{ ColumnId_Idle3, "Idle 3" },
|
||||
{ ColumnId_Idle4, "Idle 4" },
|
||||
{ ColumnId_Idle5, "Idle 5" },
|
||||
{ ColumnId_Idle6, "Idle 6" },
|
||||
{ ColumnId_Idle7, "Idle 7" },
|
||||
{ ColumnId_Idle8, "Idle 8" },
|
||||
|
||||
{ ColumnId_SpellSrc, "From Race" },
|
||||
{ ColumnId_SpellCost, "Cast Cost" },
|
||||
{ ColumnId_SpellChance, "Cast Chance" },
|
||||
|
@ -574,7 +585,7 @@ namespace
|
|||
case CSMWorld::Columns::ColumnId_MeshType: return sMeshTypes;
|
||||
case CSMWorld::Columns::ColumnId_SoundGeneratorType: return sSoundGeneratorType;
|
||||
case CSMWorld::Columns::ColumnId_School: return sSchools;
|
||||
case CSMWorld::Columns::ColumnId_SkillImpact: return sSkills;
|
||||
case CSMWorld::Columns::ColumnId_Skill: return sSkills;
|
||||
case CSMWorld::Columns::ColumnId_EffectRange: return sEffectRange;
|
||||
case CSMWorld::Columns::ColumnId_EffectId: return sEffectId;
|
||||
case CSMWorld::Columns::ColumnId_PartRefType: return sPartRefType;
|
||||
|
@ -583,7 +594,6 @@ namespace
|
|||
// FIXME: don't have dynamic value enum delegate, use Display_String for now
|
||||
//case CSMWorld::Columns::ColumnId_InfoCond: return sInfoCond;
|
||||
case CSMWorld::Columns::ColumnId_InfoCondComp: return sInfoCondComp;
|
||||
case CSMWorld::Columns::ColumnId_RaceSkill: return sSkills;
|
||||
|
||||
default: return 0;
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace CSMWorld
|
|||
ColumnId_Weight = 50,
|
||||
ColumnId_EnchantmentPoints = 51,
|
||||
ColumnId_Quality = 52,
|
||||
ColumnId_Ai = 53,
|
||||
// unused
|
||||
ColumnId_AiHello = 54,
|
||||
ColumnId_AiFlee = 55,
|
||||
ColumnId_AiFight = 56,
|
||||
|
@ -102,7 +102,7 @@ namespace CSMWorld
|
|||
ColumnId_OriginalCreature = 87,
|
||||
ColumnId_Biped = 88,
|
||||
ColumnId_HasWeapon = 89,
|
||||
// unused
|
||||
// used for SpellSrc
|
||||
ColumnId_Swims = 91,
|
||||
ColumnId_Flies = 92,
|
||||
ColumnId_Walks = 93,
|
||||
|
@ -189,7 +189,7 @@ namespace CSMWorld
|
|||
ColumnId_RotX = 174,
|
||||
ColumnId_RotY = 175,
|
||||
ColumnId_RotZ = 176,
|
||||
ColumnId_Skill = 177,
|
||||
// used for SpellCost
|
||||
ColumnId_OwnerGlobal = 178,
|
||||
ColumnId_DefaultProfile = 179,
|
||||
ColumnId_BypassNewGame = 180,
|
||||
|
@ -241,7 +241,7 @@ namespace CSMWorld
|
|||
ColumnId_AiWanderDist = 221,
|
||||
ColumnId_AiDuration = 222,
|
||||
ColumnId_AiWanderToD = 223,
|
||||
ColumnId_AiWanderIdle = 224,
|
||||
// unused
|
||||
ColumnId_AiWanderRepeat = 225,
|
||||
ColumnId_AiActivateName = 226,
|
||||
// use ColumnId_PosX, etc for AI destinations
|
||||
|
@ -261,7 +261,7 @@ namespace CSMWorld
|
|||
ColumnId_LevelledItemChanceNone = 238,
|
||||
|
||||
ColumnId_PowerList = 239,
|
||||
ColumnId_SkillImpact = 240, // impact from magic effects
|
||||
ColumnId_Skill = 240,
|
||||
|
||||
ColumnId_InfoList = 241,
|
||||
ColumnId_InfoCondition = 242,
|
||||
|
@ -276,22 +276,22 @@ namespace CSMWorld
|
|||
ColumnId_NpcSkills = 249,
|
||||
ColumnId_UChar = 250,
|
||||
ColumnId_NpcMisc = 251,
|
||||
ColumnId_NpcLevel = 252,
|
||||
ColumnId_Level = 252,
|
||||
ColumnId_NpcFactionID = 253,
|
||||
ColumnId_NpcHealth = 254,
|
||||
ColumnId_NpcMana = 255,
|
||||
ColumnId_NpcFatigue = 256,
|
||||
// used for SpellChance
|
||||
ColumnId_Mana = 255,
|
||||
ColumnId_Fatigue = 256,
|
||||
ColumnId_NpcDisposition = 257,
|
||||
ColumnId_NpcReputation = 258,
|
||||
ColumnId_NpcRank = 259,
|
||||
ColumnId_NpcGold = 260,
|
||||
ColumnId_Gold = 260,
|
||||
ColumnId_NpcPersistence = 261,
|
||||
|
||||
ColumnId_RaceAttributes = 262,
|
||||
ColumnId_RaceMaleValue = 263,
|
||||
ColumnId_RaceFemaleValue = 264,
|
||||
ColumnId_Male = 263,
|
||||
// unused
|
||||
ColumnId_RaceSkillBonus = 265,
|
||||
ColumnId_RaceSkill = 266,
|
||||
// unused
|
||||
ColumnId_RaceBonus = 267,
|
||||
|
||||
ColumnId_Interior = 268,
|
||||
|
@ -309,9 +309,25 @@ namespace CSMWorld
|
|||
ColumnId_MinMagnitude = 278,
|
||||
ColumnId_MaxMagnitude = 279,
|
||||
|
||||
ColumnId_SpellSrc = 280,
|
||||
ColumnId_SpellCost = 281,
|
||||
ColumnId_SpellChance = 282,
|
||||
ColumnId_CreatureAttributes = 280,
|
||||
ColumnId_AttributeValue = 281,
|
||||
ColumnId_CreatureAttack = 282,
|
||||
ColumnId_MinAttack = 283,
|
||||
ColumnId_MaxAttack = 284,
|
||||
ColumnId_CreatureMisc = 285,
|
||||
|
||||
ColumnId_Idle1 = 286,
|
||||
ColumnId_Idle2 = 287,
|
||||
ColumnId_Idle3 = 288,
|
||||
ColumnId_Idle4 = 289,
|
||||
ColumnId_Idle5 = 290,
|
||||
ColumnId_Idle6 = 291,
|
||||
ColumnId_Idle7 = 292,
|
||||
ColumnId_Idle8 = 293,
|
||||
|
||||
ColumnId_SpellSrc = 90,
|
||||
ColumnId_SpellCost = 177,
|
||||
ColumnId_SpellChance = 254,
|
||||
|
||||
// Allocated to a separate value range, so we don't get a collision should we ever need
|
||||
// to extend the number of use values.
|
||||
|
|
|
@ -205,22 +205,24 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
|||
mRaces.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_Spell));
|
||||
// Race attributes
|
||||
mRaces.addColumn (new NestedParentColumn<ESM::Race> (Columns::ColumnId_RaceAttributes));
|
||||
mRaces.addColumn (new NestedParentColumn<ESM::Race> (Columns::ColumnId_RaceAttributes,
|
||||
ColumnBase::Flag_Dialogue, true)); // fixed rows table
|
||||
index = mRaces.getColumns()-1;
|
||||
mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceAttributeAdapter()));
|
||||
mRaces.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_RaceAttributes, ColumnBase::Display_String,
|
||||
new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute,
|
||||
ColumnBase::Flag_Dialogue, false));
|
||||
mRaces.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_RaceMaleValue, ColumnBase::Display_Integer));
|
||||
new NestedChildColumn (Columns::ColumnId_Male, ColumnBase::Display_Integer));
|
||||
mRaces.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_RaceFemaleValue, ColumnBase::Display_Integer));
|
||||
new NestedChildColumn (Columns::ColumnId_Female, ColumnBase::Display_Integer));
|
||||
// Race skill bonus
|
||||
mRaces.addColumn (new NestedParentColumn<ESM::Race> (Columns::ColumnId_RaceSkillBonus));
|
||||
mRaces.addColumn (new NestedParentColumn<ESM::Race> (Columns::ColumnId_RaceSkillBonus,
|
||||
ColumnBase::Flag_Dialogue, true)); // fixed rows table
|
||||
index = mRaces.getColumns()-1;
|
||||
mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceSkillsBonusAdapter()));
|
||||
mRaces.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_RaceSkill, ColumnBase::Display_RaceSkill));
|
||||
new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_SkillId));
|
||||
mRaces.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_RaceBonus, ColumnBase::Display_Integer));
|
||||
|
||||
|
@ -282,9 +284,9 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
|||
mSpells.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_EffectId));
|
||||
mSpells.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_SkillImpact, ColumnBase::Display_SkillImpact));
|
||||
new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_EffectSkill));
|
||||
mSpells.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute));
|
||||
new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_EffectAttribute));
|
||||
mSpells.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_EffectRange, ColumnBase::Display_EffectRange));
|
||||
mSpells.getNestableColumn(index)->addColumn(
|
||||
|
@ -398,9 +400,9 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
|||
mEnchantments.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_EffectId));
|
||||
mEnchantments.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_SkillImpact, ColumnBase::Display_SkillImpact));
|
||||
new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_EffectSkill));
|
||||
mEnchantments.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute));
|
||||
new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_EffectAttribute));
|
||||
mEnchantments.getNestableColumn(index)->addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_EffectRange, ColumnBase::Display_EffectRange));
|
||||
mEnchantments.getNestableColumn(index)->addColumn(
|
||||
|
@ -873,11 +875,21 @@ const CSMWorld::IdCollection<CSMWorld::Land>& CSMWorld::Data::getLand() const
|
|||
return mLand;
|
||||
}
|
||||
|
||||
CSMWorld::IdCollection<CSMWorld::Land>& CSMWorld::Data::getLand()
|
||||
{
|
||||
return mLand;
|
||||
}
|
||||
|
||||
const CSMWorld::IdCollection<CSMWorld::LandTexture>& CSMWorld::Data::getLandTextures() const
|
||||
{
|
||||
return mLandTextures;
|
||||
}
|
||||
|
||||
CSMWorld::IdCollection<CSMWorld::LandTexture>& CSMWorld::Data::getLandTextures()
|
||||
{
|
||||
return mLandTextures;
|
||||
}
|
||||
|
||||
const CSMWorld::IdCollection<ESM::SoundGenerator>& CSMWorld::Data::getSoundGens() const
|
||||
{
|
||||
return mSoundGens;
|
||||
|
@ -928,6 +940,12 @@ const CSMWorld::MetaData& CSMWorld::Data::getMetaData() const
|
|||
return mMetaData.getRecord (0).get();
|
||||
}
|
||||
|
||||
void CSMWorld::Data::setMetaData (const MetaData& metaData)
|
||||
{
|
||||
Record<MetaData> record (RecordBase::State_ModifiedOnly, 0, &metaData);
|
||||
mMetaData.setRecord (0, record);
|
||||
}
|
||||
|
||||
QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id)
|
||||
{
|
||||
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
|
||||
|
@ -1039,8 +1057,10 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
|
|||
{
|
||||
int index = mLand.load(*mReader, mBase);
|
||||
|
||||
if (index!=-1 && !mBase)
|
||||
mLand.getRecord (index).mModified.mLand->loadData (
|
||||
// Load all land data for now. A future optimisation may only load non-base data
|
||||
// if a suitable mechanism for avoiding race conditions can be established.
|
||||
if (index!=-1/* && !mBase*/)
|
||||
mLand.getRecord (index).get().loadData (
|
||||
ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR |
|
||||
ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM);
|
||||
|
||||
|
|
|
@ -224,8 +224,12 @@ namespace CSMWorld
|
|||
|
||||
const IdCollection<CSMWorld::Land>& getLand() const;
|
||||
|
||||
IdCollection<CSMWorld::Land>& getLand();
|
||||
|
||||
const IdCollection<CSMWorld::LandTexture>& getLandTextures() const;
|
||||
|
||||
IdCollection<CSMWorld::LandTexture>& getLandTextures();
|
||||
|
||||
const IdCollection<ESM::SoundGenerator>& getSoundGens() const;
|
||||
|
||||
IdCollection<ESM::SoundGenerator>& getSoundGens();
|
||||
|
@ -247,6 +251,8 @@ namespace CSMWorld
|
|||
|
||||
const MetaData& getMetaData() const;
|
||||
|
||||
void setMetaData (const MetaData& metaData);
|
||||
|
||||
QAbstractItemModel *getTableModel (const UniversalId& id);
|
||||
///< If no table model is available for \a id, an exception is thrown.
|
||||
///
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace
|
|||
CSMWorld::InfoTableProxyModel::InfoTableProxyModel(CSMWorld::UniversalId::Type type, QObject *parent)
|
||||
: IdTableProxyModel(parent),
|
||||
mType(type),
|
||||
mInfoColumnId(type == UniversalId::Type_TopicInfos ? Columns::ColumnId_Topic :
|
||||
mInfoColumnId(type == UniversalId::Type_TopicInfos ? Columns::ColumnId_Topic :
|
||||
Columns::ColumnId_Journal),
|
||||
mInfoColumnIndex(-1),
|
||||
mLastAddedSourceRow(-1)
|
||||
|
|
|
@ -4,25 +4,13 @@
|
|||
|
||||
namespace CSMWorld
|
||||
{
|
||||
|
||||
Land::Land()
|
||||
{
|
||||
mLand.reset(new ESM::Land());
|
||||
}
|
||||
|
||||
void Land::load(ESM::ESMReader &esm)
|
||||
{
|
||||
mLand->load(esm);
|
||||
ESM::Land::load(esm);
|
||||
|
||||
std::ostringstream stream;
|
||||
stream << "#" << mLand->mX << " " << mLand->mY;
|
||||
stream << "#" << mX << " " << mY;
|
||||
|
||||
mId = stream.str();
|
||||
}
|
||||
|
||||
void Land::blank()
|
||||
{
|
||||
/// \todo
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define CSM_WORLD_LAND_H
|
||||
|
||||
#include <string>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <components/esm/loadland.hpp>
|
||||
|
||||
namespace CSMWorld
|
||||
|
@ -11,18 +11,12 @@ namespace CSMWorld
|
|||
///
|
||||
/// \todo Add worldspace support to the Land record.
|
||||
/// \todo Add a proper copy constructor (currently worked around using shared_ptr)
|
||||
struct Land
|
||||
struct Land : public ESM::Land
|
||||
{
|
||||
Land();
|
||||
|
||||
boost::shared_ptr<ESM::Land> mLand;
|
||||
|
||||
std::string mId;
|
||||
|
||||
/// Loads the metadata and ID
|
||||
void load (ESM::ESMReader &esm);
|
||||
|
||||
void blank();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -923,7 +923,7 @@ namespace CSMWorld
|
|||
|
||||
switch (subColIndex)
|
||||
{
|
||||
case 0: return QString(ESM::Attribute::sAttributeNames[subRowIndex].c_str());
|
||||
case 0: return subRowIndex;
|
||||
case 1: return race.mData.mAttributeValues[subRowIndex].mMale;
|
||||
case 2: return race.mData.mAttributeValues[subRowIndex].mFemale;
|
||||
default: throw std::runtime_error("Race Attribute subcolumn index out of range");
|
||||
|
|
|
@ -317,8 +317,34 @@ namespace CSMWorld
|
|||
else
|
||||
throw std::runtime_error("Magic effects ID unexpected value");
|
||||
}
|
||||
case 1: return effect.mSkill;
|
||||
case 2: return effect.mAttribute;
|
||||
case 1:
|
||||
{
|
||||
switch (effect.mEffectID)
|
||||
{
|
||||
case ESM::MagicEffect::DrainSkill:
|
||||
case ESM::MagicEffect::DamageSkill:
|
||||
case ESM::MagicEffect::RestoreSkill:
|
||||
case ESM::MagicEffect::FortifySkill:
|
||||
case ESM::MagicEffect::AbsorbSkill:
|
||||
return effect.mSkill;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
switch (effect.mEffectID)
|
||||
{
|
||||
case ESM::MagicEffect::DrainAttribute:
|
||||
case ESM::MagicEffect::DamageAttribute:
|
||||
case ESM::MagicEffect::RestoreAttribute:
|
||||
case ESM::MagicEffect::FortifyAttribute:
|
||||
case ESM::MagicEffect::AbsorbAttribute:
|
||||
return effect.mAttribute;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
if (effect.mRange >=0 && effect.mRange <=2)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <components/esm/loadcont.hpp>
|
||||
#include <components/esm/attr.hpp>
|
||||
#include <components/esm/loadmgef.hpp>
|
||||
|
||||
#include "nestedtablewrapper.hpp"
|
||||
#include "usertype.hpp"
|
||||
|
@ -30,8 +31,9 @@ QVariant CSMWorld::PotionRefIdAdapter::getData (const RefIdColumn *column, const
|
|||
if (column==mAutoCalc)
|
||||
return record.get().mData.mAutoCalc!=0;
|
||||
|
||||
// to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
if (column==mColumns.mEffects)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
return InventoryRefIdAdapter<ESM::Potion>::getData (column, data, index);
|
||||
}
|
||||
|
@ -57,6 +59,156 @@ void CSMWorld::PotionRefIdAdapter::setData (const RefIdColumn *column, RefIdData
|
|||
}
|
||||
|
||||
|
||||
CSMWorld::IngredientColumns::IngredientColumns (const InventoryColumns& columns)
|
||||
: InventoryColumns (columns) {}
|
||||
|
||||
CSMWorld::IngredientRefIdAdapter::IngredientRefIdAdapter (const IngredientColumns& columns)
|
||||
: InventoryRefIdAdapter<ESM::Ingredient> (UniversalId::Type_Ingredient, columns),
|
||||
mColumns(columns)
|
||||
{}
|
||||
|
||||
QVariant CSMWorld::IngredientRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data,
|
||||
int index) const
|
||||
{
|
||||
if (column==mColumns.mEffects)
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_FixedRows);
|
||||
|
||||
return InventoryRefIdAdapter<ESM::Ingredient>::getData (column, data, index);
|
||||
}
|
||||
|
||||
void CSMWorld::IngredientRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
|
||||
const QVariant& value) const
|
||||
{
|
||||
InventoryRefIdAdapter<ESM::Ingredient>::setData (column, data, index, value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
CSMWorld::IngredEffectRefIdAdapter::IngredEffectRefIdAdapter()
|
||||
: mType(UniversalId::Type_Ingredient)
|
||||
{}
|
||||
|
||||
CSMWorld::IngredEffectRefIdAdapter::~IngredEffectRefIdAdapter()
|
||||
{}
|
||||
|
||||
void CSMWorld::IngredEffectRefIdAdapter::addNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int position) const
|
||||
{
|
||||
// Do nothing, this table cannot be changed by the user
|
||||
}
|
||||
|
||||
void CSMWorld::IngredEffectRefIdAdapter::removeNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int rowToRemove) const
|
||||
{
|
||||
// Do nothing, this table cannot be changed by the user
|
||||
}
|
||||
|
||||
void CSMWorld::IngredEffectRefIdAdapter::setNestedTable (const RefIdColumn* column,
|
||||
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const
|
||||
{
|
||||
Record<ESM::Ingredient>& record =
|
||||
static_cast<Record<ESM::Ingredient>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
|
||||
ESM::Ingredient ingredient = record.get();
|
||||
|
||||
ingredient.mData =
|
||||
static_cast<const NestedTableWrapper<std::vector<typename ESM::Ingredient::IRDTstruct> >&>(nestedTable).mNestedTable.at(0);
|
||||
|
||||
record.setModified (ingredient);
|
||||
}
|
||||
|
||||
CSMWorld::NestedTableWrapperBase* CSMWorld::IngredEffectRefIdAdapter::nestedTable (const RefIdColumn* column,
|
||||
const RefIdData& data, int index) const
|
||||
{
|
||||
const Record<ESM::Ingredient>& record =
|
||||
static_cast<const Record<ESM::Ingredient>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
|
||||
|
||||
// return the whole struct
|
||||
std::vector<typename ESM::Ingredient::IRDTstruct> wrap;
|
||||
wrap.push_back(record.get().mData);
|
||||
|
||||
// deleted by dtor of NestedTableStoring
|
||||
return new NestedTableWrapper<std::vector<typename ESM::Ingredient::IRDTstruct> >(wrap);
|
||||
}
|
||||
|
||||
QVariant CSMWorld::IngredEffectRefIdAdapter::getNestedData (const RefIdColumn *column,
|
||||
const RefIdData& data, int index, int subRowIndex, int subColIndex) const
|
||||
{
|
||||
const Record<ESM::Ingredient>& record =
|
||||
static_cast<const Record<ESM::Ingredient>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
|
||||
|
||||
if (subRowIndex < 0 || subRowIndex >= 4)
|
||||
throw std::runtime_error ("index out of range");
|
||||
|
||||
switch (subColIndex)
|
||||
{
|
||||
case 0: return record.get().mData.mEffectID[subRowIndex];
|
||||
case 1:
|
||||
{
|
||||
switch (record.get().mData.mEffectID[subRowIndex])
|
||||
{
|
||||
case ESM::MagicEffect::DrainSkill:
|
||||
case ESM::MagicEffect::DamageSkill:
|
||||
case ESM::MagicEffect::RestoreSkill:
|
||||
case ESM::MagicEffect::FortifySkill:
|
||||
case ESM::MagicEffect::AbsorbSkill:
|
||||
return record.get().mData.mSkills[subRowIndex];
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
switch (record.get().mData.mEffectID[subRowIndex])
|
||||
{
|
||||
case ESM::MagicEffect::DrainAttribute:
|
||||
case ESM::MagicEffect::DamageAttribute:
|
||||
case ESM::MagicEffect::RestoreAttribute:
|
||||
case ESM::MagicEffect::FortifyAttribute:
|
||||
case ESM::MagicEffect::AbsorbAttribute:
|
||||
return record.get().mData.mAttributes[subRowIndex];
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
||||
}
|
||||
}
|
||||
|
||||
void CSMWorld::IngredEffectRefIdAdapter::setNestedData (const RefIdColumn *column,
|
||||
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const
|
||||
{
|
||||
Record<ESM::Ingredient>& record =
|
||||
static_cast<Record<ESM::Ingredient>&> (data.getRecord (RefIdData::LocalIndex (row, mType)));
|
||||
ESM::Ingredient ingredient = record.get();
|
||||
|
||||
if (subRowIndex < 0 || subRowIndex >= 4)
|
||||
throw std::runtime_error ("index out of range");
|
||||
|
||||
switch(subColIndex)
|
||||
{
|
||||
case 0: ingredient.mData.mEffectID[subRowIndex] = value.toInt(); break;
|
||||
case 1: ingredient.mData.mSkills[subRowIndex] = value.toInt(); break;
|
||||
case 2: ingredient.mData.mAttributes[subRowIndex] = value.toInt(); break;
|
||||
default:
|
||||
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
||||
}
|
||||
|
||||
record.setModified (ingredient);
|
||||
}
|
||||
|
||||
int CSMWorld::IngredEffectRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
|
||||
{
|
||||
return 3; // effect, skill, attribute
|
||||
}
|
||||
|
||||
int CSMWorld::IngredEffectRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
|
||||
{
|
||||
return 4; // up to 4 effects
|
||||
}
|
||||
|
||||
|
||||
CSMWorld::ApparatusRefIdAdapter::ApparatusRefIdAdapter (const InventoryColumns& columns,
|
||||
const RefIdColumn *type, const RefIdColumn *quality)
|
||||
: InventoryRefIdAdapter<ESM::Apparatus> (UniversalId::Type_Apparatus, columns),
|
||||
|
@ -123,7 +275,7 @@ QVariant CSMWorld::ArmorRefIdAdapter::getData (const RefIdColumn *column,
|
|||
return record.get().mData.mArmor;
|
||||
|
||||
if (column==mPartRef)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
return EnchantableRefIdAdapter<ESM::Armor>::getData (column, data, index);
|
||||
}
|
||||
|
@ -211,7 +363,7 @@ QVariant CSMWorld::ClothingRefIdAdapter::getData (const RefIdColumn *column,
|
|||
return record.get().mData.mType;
|
||||
|
||||
if (column==mPartRef)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
return EnchantableRefIdAdapter<ESM::Clothing>::getData (column, data, index);
|
||||
}
|
||||
|
@ -259,7 +411,7 @@ QVariant CSMWorld::ContainerRefIdAdapter::getData (const RefIdColumn *column,
|
|||
return (record.get().mFlags & ESM::Container::Respawn)!=0;
|
||||
|
||||
if (column==mContent)
|
||||
return true; // Required to show nested tables in dialogue subview
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
return NameRefIdAdapter<ESM::Container>::getData (column, data, index);
|
||||
}
|
||||
|
@ -301,12 +453,11 @@ void CSMWorld::ContainerRefIdAdapter::setData (const RefIdColumn *column, RefIdD
|
|||
CSMWorld::CreatureColumns::CreatureColumns (const ActorColumns& actorColumns)
|
||||
: ActorColumns (actorColumns),
|
||||
mType(NULL),
|
||||
mSoul(NULL),
|
||||
mScale(NULL),
|
||||
mOriginal(NULL),
|
||||
mCombat(NULL),
|
||||
mMagic(NULL),
|
||||
mStealth(NULL)
|
||||
mAttributes(NULL),
|
||||
mAttacks(NULL),
|
||||
mMisc(NULL)
|
||||
{}
|
||||
|
||||
CSMWorld::CreatureRefIdAdapter::CreatureRefIdAdapter (const CreatureColumns& columns)
|
||||
|
@ -322,23 +473,20 @@ QVariant CSMWorld::CreatureRefIdAdapter::getData (const RefIdColumn *column, con
|
|||
if (column==mColumns.mType)
|
||||
return record.get().mData.mType;
|
||||
|
||||
if (column==mColumns.mSoul)
|
||||
return record.get().mData.mSoul;
|
||||
|
||||
if (column==mColumns.mScale)
|
||||
return record.get().mScale;
|
||||
|
||||
if (column==mColumns.mOriginal)
|
||||
return QString::fromUtf8 (record.get().mOriginal.c_str());
|
||||
|
||||
if (column==mColumns.mCombat)
|
||||
return static_cast<int> (record.get().mData.mCombat);
|
||||
if (column==mColumns.mAttributes)
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_FixedRows);
|
||||
|
||||
if (column==mColumns.mMagic)
|
||||
return static_cast<int> (record.get().mData.mMagic);
|
||||
if (column==mColumns.mAttacks)
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_FixedRows);
|
||||
|
||||
if (column==mColumns.mStealth)
|
||||
return static_cast<int> (record.get().mData.mStealth);
|
||||
if (column==mColumns.mMisc)
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
||||
mColumns.mFlags.find (column);
|
||||
|
@ -359,18 +507,10 @@ void CSMWorld::CreatureRefIdAdapter::setData (const RefIdColumn *column, RefIdDa
|
|||
|
||||
if (column==mColumns.mType)
|
||||
creature.mData.mType = value.toInt();
|
||||
else if (column==mColumns.mSoul)
|
||||
creature.mData.mSoul = value.toInt();
|
||||
else if (column==mColumns.mScale)
|
||||
creature.mScale = value.toFloat();
|
||||
else if (column==mColumns.mOriginal)
|
||||
creature.mOriginal = value.toString().toUtf8().constData();
|
||||
else if (column==mColumns.mCombat)
|
||||
creature.mData.mCombat = value.toInt();
|
||||
else if (column==mColumns.mMagic)
|
||||
creature.mData.mMagic = value.toInt();
|
||||
else if (column==mColumns.mStealth)
|
||||
creature.mData.mStealth = value.toInt();
|
||||
else
|
||||
{
|
||||
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
||||
|
@ -586,13 +726,13 @@ QVariant CSMWorld::NpcRefIdAdapter::getData (const RefIdColumn *column, const Re
|
|||
if (column==mColumns.mAttributes || column==mColumns.mSkills)
|
||||
{
|
||||
if ((record.get().mFlags & ESM::NPC::Autocalc) != 0)
|
||||
return QVariant(QVariant::UserType);
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_None);
|
||||
else
|
||||
return true;
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_FixedRows);
|
||||
}
|
||||
|
||||
if (column==mColumns.mMisc)
|
||||
return true;
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
||||
mColumns.mFlags.find (column);
|
||||
|
@ -744,18 +884,7 @@ QVariant CSMWorld::NpcAttributesRefIdAdapter::getNestedData (const RefIdColumn *
|
|||
const ESM::NPC::NPDTstruct52& npcStruct = npc.mNpdt52;
|
||||
|
||||
if (subColIndex == 0)
|
||||
switch (subRowIndex)
|
||||
{
|
||||
case 0: return QString("Strength");
|
||||
case 1: return QString("Intelligence");
|
||||
case 2: return QString("Willpower");
|
||||
case 3: return QString("Agility");
|
||||
case 4: return QString("Speed");
|
||||
case 5: return QString("Endurance");
|
||||
case 6: return QString("Personality");
|
||||
case 7: return QString("Luck");
|
||||
default: return QVariant(); // throw an exception here?
|
||||
}
|
||||
return subRowIndex;
|
||||
else if (subColIndex == 1)
|
||||
if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS)
|
||||
{
|
||||
|
@ -886,7 +1015,7 @@ QVariant CSMWorld::NpcSkillsRefIdAdapter::getNestedData (const RefIdColumn *colu
|
|||
throw std::runtime_error ("index out of range");
|
||||
|
||||
if (subColIndex == 0)
|
||||
return QString(ESM::Skill::sSkillNames[subRowIndex].c_str());
|
||||
return subRowIndex;
|
||||
else if (subColIndex == 1)
|
||||
{
|
||||
if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS)
|
||||
|
@ -1088,6 +1217,289 @@ int CSMWorld::NpcMiscRefIdAdapter::getNestedRowsCount(const RefIdColumn *column,
|
|||
return 1; // fixed at size 1
|
||||
}
|
||||
|
||||
CSMWorld::CreatureAttributesRefIdAdapter::CreatureAttributesRefIdAdapter()
|
||||
{}
|
||||
|
||||
void CSMWorld::CreatureAttributesRefIdAdapter::addNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int position) const
|
||||
{
|
||||
// Do nothing, this table cannot be changed by the user
|
||||
}
|
||||
|
||||
void CSMWorld::CreatureAttributesRefIdAdapter::removeNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int rowToRemove) const
|
||||
{
|
||||
// Do nothing, this table cannot be changed by the user
|
||||
}
|
||||
|
||||
void CSMWorld::CreatureAttributesRefIdAdapter::setNestedTable (const RefIdColumn* column,
|
||||
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const
|
||||
{
|
||||
Record<ESM::Creature>& record =
|
||||
static_cast<Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
|
||||
ESM::Creature creature = record.get();
|
||||
|
||||
// store the whole struct
|
||||
creature.mData =
|
||||
static_cast<const NestedTableWrapper<std::vector<typename ESM::Creature::NPDTstruct> > &>(nestedTable).mNestedTable.at(0);
|
||||
|
||||
record.setModified (creature);
|
||||
}
|
||||
|
||||
CSMWorld::NestedTableWrapperBase* CSMWorld::CreatureAttributesRefIdAdapter::nestedTable (const RefIdColumn* column,
|
||||
const RefIdData& data, int index) const
|
||||
{
|
||||
const Record<ESM::Creature>& record =
|
||||
static_cast<const Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
|
||||
|
||||
// return the whole struct
|
||||
std::vector<typename ESM::Creature::NPDTstruct> wrap;
|
||||
wrap.push_back(record.get().mData);
|
||||
// deleted by dtor of NestedTableStoring
|
||||
return new NestedTableWrapper<std::vector<typename ESM::Creature::NPDTstruct> >(wrap);
|
||||
}
|
||||
|
||||
QVariant CSMWorld::CreatureAttributesRefIdAdapter::getNestedData (const RefIdColumn *column,
|
||||
const RefIdData& data, int index, int subRowIndex, int subColIndex) const
|
||||
{
|
||||
const Record<ESM::Creature>& record =
|
||||
static_cast<const Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
|
||||
|
||||
const ESM::Creature creature = record.get();
|
||||
|
||||
if (subColIndex == 0)
|
||||
return subRowIndex;
|
||||
else if (subColIndex == 1)
|
||||
switch (subRowIndex)
|
||||
{
|
||||
case 0: return creature.mData.mStrength;
|
||||
case 1: return creature.mData.mIntelligence;
|
||||
case 2: return creature.mData.mWillpower;
|
||||
case 3: return creature.mData.mAgility;
|
||||
case 4: return creature.mData.mSpeed;
|
||||
case 5: return creature.mData.mEndurance;
|
||||
case 6: return creature.mData.mPersonality;
|
||||
case 7: return creature.mData.mLuck;
|
||||
default: return QVariant(); // throw an exception here?
|
||||
}
|
||||
else
|
||||
return QVariant(); // throw an exception here?
|
||||
}
|
||||
|
||||
void CSMWorld::CreatureAttributesRefIdAdapter::setNestedData (const RefIdColumn *column,
|
||||
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const
|
||||
{
|
||||
Record<ESM::Creature>& record =
|
||||
static_cast<Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Creature)));
|
||||
ESM::Creature creature = record.get();
|
||||
|
||||
if (subColIndex == 1)
|
||||
switch(subRowIndex)
|
||||
{
|
||||
case 0: creature.mData.mStrength = value.toInt(); break;
|
||||
case 1: creature.mData.mIntelligence = value.toInt(); break;
|
||||
case 2: creature.mData.mWillpower = value.toInt(); break;
|
||||
case 3: creature.mData.mAgility = value.toInt(); break;
|
||||
case 4: creature.mData.mSpeed = value.toInt(); break;
|
||||
case 5: creature.mData.mEndurance = value.toInt(); break;
|
||||
case 6: creature.mData.mPersonality = value.toInt(); break;
|
||||
case 7: creature.mData.mLuck = value.toInt(); break;
|
||||
default: return; // throw an exception here?
|
||||
}
|
||||
else
|
||||
return; // throw an exception here?
|
||||
|
||||
record.setModified (creature);
|
||||
}
|
||||
|
||||
int CSMWorld::CreatureAttributesRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
int CSMWorld::CreatureAttributesRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
|
||||
{
|
||||
// There are 8 attributes
|
||||
return 8;
|
||||
}
|
||||
|
||||
CSMWorld::CreatureAttackRefIdAdapter::CreatureAttackRefIdAdapter()
|
||||
{}
|
||||
|
||||
void CSMWorld::CreatureAttackRefIdAdapter::addNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int position) const
|
||||
{
|
||||
// Do nothing, this table cannot be changed by the user
|
||||
}
|
||||
|
||||
void CSMWorld::CreatureAttackRefIdAdapter::removeNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int rowToRemove) const
|
||||
{
|
||||
// Do nothing, this table cannot be changed by the user
|
||||
}
|
||||
|
||||
void CSMWorld::CreatureAttackRefIdAdapter::setNestedTable (const RefIdColumn* column,
|
||||
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const
|
||||
{
|
||||
Record<ESM::Creature>& record =
|
||||
static_cast<Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
|
||||
ESM::Creature creature = record.get();
|
||||
|
||||
// store the whole struct
|
||||
creature.mData =
|
||||
static_cast<const NestedTableWrapper<std::vector<typename ESM::Creature::NPDTstruct> > &>(nestedTable).mNestedTable.at(0);
|
||||
|
||||
record.setModified (creature);
|
||||
}
|
||||
|
||||
CSMWorld::NestedTableWrapperBase* CSMWorld::CreatureAttackRefIdAdapter::nestedTable (const RefIdColumn* column,
|
||||
const RefIdData& data, int index) const
|
||||
{
|
||||
const Record<ESM::Creature>& record =
|
||||
static_cast<const Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
|
||||
|
||||
// return the whole struct
|
||||
std::vector<typename ESM::Creature::NPDTstruct> wrap;
|
||||
wrap.push_back(record.get().mData);
|
||||
// deleted by dtor of NestedTableStoring
|
||||
return new NestedTableWrapper<std::vector<typename ESM::Creature::NPDTstruct> >(wrap);
|
||||
}
|
||||
|
||||
QVariant CSMWorld::CreatureAttackRefIdAdapter::getNestedData (const RefIdColumn *column,
|
||||
const RefIdData& data, int index, int subRowIndex, int subColIndex) const
|
||||
{
|
||||
const Record<ESM::Creature>& record =
|
||||
static_cast<const Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
|
||||
|
||||
const ESM::Creature creature = record.get();
|
||||
|
||||
if (subRowIndex < 0 || subRowIndex > 2 || subColIndex < 0 || subColIndex > 2)
|
||||
throw std::runtime_error ("index out of range");
|
||||
|
||||
if (subColIndex == 0)
|
||||
return subRowIndex + 1;
|
||||
else if (subColIndex < 3) // 1 or 2
|
||||
return creature.mData.mAttack[(subRowIndex * 2) + (subColIndex - 1)];
|
||||
else
|
||||
return QVariant(); // throw an exception here?
|
||||
}
|
||||
|
||||
void CSMWorld::CreatureAttackRefIdAdapter::setNestedData (const RefIdColumn *column,
|
||||
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const
|
||||
{
|
||||
Record<ESM::Creature>& record =
|
||||
static_cast<Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Creature)));
|
||||
ESM::Creature creature = record.get();
|
||||
|
||||
if (subRowIndex < 0 || subRowIndex > 2)
|
||||
throw std::runtime_error ("index out of range");
|
||||
|
||||
if (subColIndex == 1 || subColIndex == 2)
|
||||
creature.mData.mAttack[(subRowIndex * 2) + (subColIndex - 1)] = value.toInt();
|
||||
else
|
||||
return; // throw an exception here?
|
||||
|
||||
record.setModified (creature);
|
||||
}
|
||||
|
||||
int CSMWorld::CreatureAttackRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
int CSMWorld::CreatureAttackRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
|
||||
{
|
||||
// There are 3 attacks
|
||||
return 3;
|
||||
}
|
||||
|
||||
CSMWorld::CreatureMiscRefIdAdapter::CreatureMiscRefIdAdapter()
|
||||
{}
|
||||
|
||||
CSMWorld::CreatureMiscRefIdAdapter::~CreatureMiscRefIdAdapter()
|
||||
{}
|
||||
|
||||
void CSMWorld::CreatureMiscRefIdAdapter::addNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int position) const
|
||||
{
|
||||
throw std::logic_error ("cannot add a row to a fixed table");
|
||||
}
|
||||
|
||||
void CSMWorld::CreatureMiscRefIdAdapter::removeNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int rowToRemove) const
|
||||
{
|
||||
throw std::logic_error ("cannot remove a row to a fixed table");
|
||||
}
|
||||
|
||||
void CSMWorld::CreatureMiscRefIdAdapter::setNestedTable (const RefIdColumn* column,
|
||||
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const
|
||||
{
|
||||
throw std::logic_error ("table operation not supported");
|
||||
}
|
||||
|
||||
CSMWorld::NestedTableWrapperBase* CSMWorld::CreatureMiscRefIdAdapter::nestedTable (const RefIdColumn* column,
|
||||
const RefIdData& data, int index) const
|
||||
{
|
||||
throw std::logic_error ("table operation not supported");
|
||||
}
|
||||
|
||||
QVariant CSMWorld::CreatureMiscRefIdAdapter::getNestedData (const RefIdColumn *column,
|
||||
const RefIdData& data, int index, int subRowIndex, int subColIndex) const
|
||||
{
|
||||
const Record<ESM::Creature>& record =
|
||||
static_cast<const Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
|
||||
|
||||
const ESM::Creature creature = record.get();
|
||||
|
||||
switch (subColIndex)
|
||||
{
|
||||
case 0: return creature.mData.mLevel;
|
||||
case 1: return creature.mData.mHealth;
|
||||
case 2: return creature.mData.mMana;
|
||||
case 3: return creature.mData.mFatigue;
|
||||
case 4: return creature.mData.mSoul;
|
||||
case 5: return creature.mData.mCombat;
|
||||
case 6: return creature.mData.mMagic;
|
||||
case 7: return creature.mData.mStealth;
|
||||
case 8: return creature.mData.mGold;
|
||||
default: return QVariant(); // throw an exception here?
|
||||
}
|
||||
}
|
||||
|
||||
void CSMWorld::CreatureMiscRefIdAdapter::setNestedData (const RefIdColumn *column,
|
||||
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const
|
||||
{
|
||||
Record<ESM::Creature>& record =
|
||||
static_cast<Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Creature)));
|
||||
ESM::Creature creature = record.get();
|
||||
|
||||
switch(subColIndex)
|
||||
{
|
||||
case 0: creature.mData.mLevel = value.toInt(); break;
|
||||
case 1: creature.mData.mHealth = value.toInt(); break;
|
||||
case 2: creature.mData.mMana = value.toInt(); break;
|
||||
case 3: creature.mData.mFatigue = value.toInt(); break;
|
||||
case 4: creature.mData.mSoul = value.toInt(); break;
|
||||
case 5: creature.mData.mCombat = value.toInt(); break;
|
||||
case 6: creature.mData.mMagic = value.toInt(); break;
|
||||
case 7: creature.mData.mStealth = value.toInt(); break;
|
||||
case 8: creature.mData.mGold = value.toInt(); break;
|
||||
default: return; // throw an exception here?
|
||||
}
|
||||
|
||||
record.setModified (creature);
|
||||
}
|
||||
|
||||
int CSMWorld::CreatureMiscRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
|
||||
{
|
||||
return 9; // Level, Health, Mana, Fatigue, Soul, Combat, Magic, Steath, Gold
|
||||
}
|
||||
|
||||
int CSMWorld::CreatureMiscRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
|
||||
{
|
||||
return 1; // fixed at size 1
|
||||
}
|
||||
|
||||
CSMWorld::WeaponColumns::WeaponColumns (const EnchantableColumns& columns)
|
||||
: EnchantableColumns (columns) {}
|
||||
|
||||
|
@ -1187,9 +1599,6 @@ QVariant ActorRefIdAdapter<ESM::NPC>::getData (const RefIdColumn *column, const
|
|||
const Record<ESM::NPC>& record = static_cast<const Record<ESM::NPC>&> (
|
||||
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<ESM::NPC>::getType())));
|
||||
|
||||
if (column==mActors.mHasAi)
|
||||
return record.get().mHasAI!=0;
|
||||
|
||||
if (column==mActors.mHello)
|
||||
return record.get().mAiData.mHello;
|
||||
|
||||
|
@ -1203,21 +1612,21 @@ QVariant ActorRefIdAdapter<ESM::NPC>::getData (const RefIdColumn *column, const
|
|||
return record.get().mAiData.mAlarm;
|
||||
|
||||
if (column==mActors.mInventory)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
if (column==mActors.mSpells)
|
||||
{
|
||||
if ((record.get().mFlags & ESM::NPC::Autocalc) != 0)
|
||||
return QVariant(QVariant::UserType);
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_None);
|
||||
else
|
||||
return true;
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
}
|
||||
|
||||
if (column==mActors.mDestinations)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
if (column==mActors.mAiPackages)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
||||
mActors.mServices.find (column);
|
||||
|
@ -1371,9 +1780,6 @@ QVariant ActorRefIdAdapter<ESM::Creature>::getData (const RefIdColumn *column, c
|
|||
const Record<ESM::Creature>& record = static_cast<const Record<ESM::Creature>&> (
|
||||
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<ESM::Creature>::getType())));
|
||||
|
||||
if (column==mActors.mHasAi)
|
||||
return record.get().mHasAI!=0;
|
||||
|
||||
if (column==mActors.mHello)
|
||||
return record.get().mAiData.mHello;
|
||||
|
||||
|
@ -1387,16 +1793,16 @@ QVariant ActorRefIdAdapter<ESM::Creature>::getData (const RefIdColumn *column, c
|
|||
return record.get().mAiData.mAlarm;
|
||||
|
||||
if (column==mActors.mInventory)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
if (column==mActors.mSpells)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
if (column==mActors.mDestinations)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
if (column==mActors.mAiPackages)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
||||
mActors.mServices.find (column);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <components/esm/loadclas.hpp>
|
||||
#include <components/esm/loadrace.hpp>
|
||||
|
||||
#include "columnbase.hpp"
|
||||
#include "record.hpp"
|
||||
#include "refiddata.hpp"
|
||||
#include "universalid.hpp"
|
||||
|
@ -346,6 +347,66 @@ namespace CSMWorld
|
|||
///< If the data type does not match an exception is thrown.
|
||||
};
|
||||
|
||||
struct IngredientColumns : public InventoryColumns
|
||||
{
|
||||
const RefIdColumn *mEffects;
|
||||
|
||||
IngredientColumns (const InventoryColumns& columns);
|
||||
};
|
||||
|
||||
class IngredientRefIdAdapter : public InventoryRefIdAdapter<ESM::Ingredient>
|
||||
{
|
||||
IngredientColumns mColumns;
|
||||
|
||||
public:
|
||||
|
||||
IngredientRefIdAdapter (const IngredientColumns& columns);
|
||||
|
||||
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
|
||||
const;
|
||||
|
||||
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
|
||||
const QVariant& value) const;
|
||||
///< If the data type does not match an exception is thrown.
|
||||
};
|
||||
|
||||
class IngredEffectRefIdAdapter : public NestedRefIdAdapterBase
|
||||
{
|
||||
UniversalId::Type mType;
|
||||
|
||||
// not implemented
|
||||
IngredEffectRefIdAdapter (const IngredEffectRefIdAdapter&);
|
||||
IngredEffectRefIdAdapter& operator= (const IngredEffectRefIdAdapter&);
|
||||
|
||||
public:
|
||||
|
||||
IngredEffectRefIdAdapter();
|
||||
|
||||
virtual ~IngredEffectRefIdAdapter();
|
||||
|
||||
virtual void addNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int position) const;
|
||||
|
||||
virtual void removeNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int rowToRemove) const;
|
||||
|
||||
virtual void setNestedTable (const RefIdColumn* column,
|
||||
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const;
|
||||
|
||||
virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column,
|
||||
const RefIdData& data, int index) const;
|
||||
|
||||
virtual QVariant getNestedData (const RefIdColumn *column,
|
||||
const RefIdData& data, int index, int subRowIndex, int subColIndex) const;
|
||||
|
||||
virtual void setNestedData (const RefIdColumn *column,
|
||||
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const;
|
||||
|
||||
virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const;
|
||||
|
||||
virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const;
|
||||
};
|
||||
|
||||
struct EnchantableColumns : public InventoryColumns
|
||||
{
|
||||
const RefIdColumn *mEnchantment;
|
||||
|
@ -485,7 +546,6 @@ namespace CSMWorld
|
|||
|
||||
struct ActorColumns : public NameColumns
|
||||
{
|
||||
const RefIdColumn *mHasAi;
|
||||
const RefIdColumn *mHello;
|
||||
const RefIdColumn *mFlee;
|
||||
const RefIdColumn *mFight;
|
||||
|
@ -531,9 +591,7 @@ namespace CSMWorld
|
|||
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
|
||||
|
||||
RecordT record2 = record.get();
|
||||
if (column==mActors.mHasAi)
|
||||
record2.mHasAI = value.toInt();
|
||||
else if (column==mActors.mHello)
|
||||
if (column==mActors.mHello)
|
||||
record2.mAiData.mHello = value.toInt();
|
||||
else if (column==mActors.mFlee)
|
||||
record2.mAiData.mFlee = value.toInt();
|
||||
|
@ -659,12 +717,11 @@ namespace CSMWorld
|
|||
{
|
||||
std::map<const RefIdColumn *, unsigned int> mFlags;
|
||||
const RefIdColumn *mType;
|
||||
const RefIdColumn *mSoul;
|
||||
const RefIdColumn *mScale;
|
||||
const RefIdColumn *mOriginal;
|
||||
const RefIdColumn *mCombat;
|
||||
const RefIdColumn *mMagic;
|
||||
const RefIdColumn *mStealth;
|
||||
const RefIdColumn *mAttributes;
|
||||
const RefIdColumn *mAttacks;
|
||||
const RefIdColumn *mMisc;
|
||||
|
||||
CreatureColumns (const ActorColumns& actorColumns);
|
||||
};
|
||||
|
@ -908,6 +965,97 @@ namespace CSMWorld
|
|||
virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const;
|
||||
};
|
||||
|
||||
class CreatureAttributesRefIdAdapter : public NestedRefIdAdapterBase
|
||||
{
|
||||
public:
|
||||
|
||||
CreatureAttributesRefIdAdapter ();
|
||||
|
||||
virtual void addNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int position) const;
|
||||
|
||||
virtual void removeNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int rowToRemove) const;
|
||||
|
||||
virtual void setNestedTable (const RefIdColumn* column,
|
||||
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const;
|
||||
|
||||
virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column,
|
||||
const RefIdData& data, int index) const;
|
||||
|
||||
virtual QVariant getNestedData (const RefIdColumn *column,
|
||||
const RefIdData& data, int index, int subRowIndex, int subColIndex) const;
|
||||
|
||||
virtual void setNestedData (const RefIdColumn *column,
|
||||
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const;
|
||||
|
||||
virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const;
|
||||
|
||||
virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const;
|
||||
};
|
||||
|
||||
class CreatureAttackRefIdAdapter : public NestedRefIdAdapterBase
|
||||
{
|
||||
public:
|
||||
|
||||
CreatureAttackRefIdAdapter ();
|
||||
|
||||
virtual void addNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int position) const;
|
||||
|
||||
virtual void removeNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int rowToRemove) const;
|
||||
|
||||
virtual void setNestedTable (const RefIdColumn* column,
|
||||
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const;
|
||||
|
||||
virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column,
|
||||
const RefIdData& data, int index) const;
|
||||
|
||||
virtual QVariant getNestedData (const RefIdColumn *column,
|
||||
const RefIdData& data, int index, int subRowIndex, int subColIndex) const;
|
||||
|
||||
virtual void setNestedData (const RefIdColumn *column,
|
||||
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const;
|
||||
|
||||
virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const;
|
||||
|
||||
virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const;
|
||||
};
|
||||
|
||||
class CreatureMiscRefIdAdapter : public NestedRefIdAdapterBase
|
||||
{
|
||||
CreatureMiscRefIdAdapter (const CreatureMiscRefIdAdapter&);
|
||||
CreatureMiscRefIdAdapter& operator= (const CreatureMiscRefIdAdapter&);
|
||||
|
||||
public:
|
||||
|
||||
CreatureMiscRefIdAdapter ();
|
||||
virtual ~CreatureMiscRefIdAdapter();
|
||||
|
||||
virtual void addNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int position) const;
|
||||
|
||||
virtual void removeNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int rowToRemove) const;
|
||||
|
||||
virtual void setNestedTable (const RefIdColumn* column,
|
||||
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const;
|
||||
|
||||
virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column,
|
||||
const RefIdData& data, int index) const;
|
||||
|
||||
virtual QVariant getNestedData (const RefIdColumn *column,
|
||||
const RefIdData& data, int index, int subRowIndex, int subColIndex) const;
|
||||
|
||||
virtual void setNestedData (const RefIdColumn *column,
|
||||
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const;
|
||||
|
||||
virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const;
|
||||
|
||||
virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const;
|
||||
};
|
||||
|
||||
template<typename ESXRecordT>
|
||||
class EffectsListAdapter;
|
||||
|
||||
|
@ -1348,6 +1496,8 @@ namespace CSMWorld
|
|||
|
||||
virtual ~ActorAiRefIdAdapter() {}
|
||||
|
||||
// FIXME: should check if the AI package type is already in the list and use a default
|
||||
// that wasn't used already (in extreme case do not add anything at all?
|
||||
virtual void addNestedRow (const RefIdColumn *column,
|
||||
RefIdData& data, int index, int position) const
|
||||
{
|
||||
|
@ -1431,6 +1581,7 @@ namespace CSMWorld
|
|||
switch (subColIndex)
|
||||
{
|
||||
case 0:
|
||||
// FIXME: should more than one AI package type be allowed? Check vanilla
|
||||
switch (content.mType)
|
||||
{
|
||||
case ESM::AI_Wander: return 0;
|
||||
|
@ -1458,47 +1609,52 @@ namespace CSMWorld
|
|||
else
|
||||
return QVariant();
|
||||
case 4: // wander idle
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
if (content.mType == ESM::AI_Wander)
|
||||
{
|
||||
return static_cast<int>(content.mWander.mIdle[0]); // FIXME:
|
||||
}
|
||||
return static_cast<int>(content.mWander.mIdle[subColIndex-4]);
|
||||
else
|
||||
return QVariant();
|
||||
case 5: // wander repeat
|
||||
case 12: // wander repeat
|
||||
if (content.mType == ESM::AI_Wander)
|
||||
return content.mWander.mShouldRepeat != 0;
|
||||
else
|
||||
return QVariant();
|
||||
case 6: // activate name
|
||||
case 13: // activate name
|
||||
if (content.mType == ESM::AI_Activate)
|
||||
return QString(content.mActivate.mName.toString().c_str());
|
||||
else
|
||||
return QVariant();
|
||||
case 7: // target id
|
||||
case 14: // target id
|
||||
if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
||||
return QString(content.mTarget.mId.toString().c_str());
|
||||
else
|
||||
return QVariant();
|
||||
case 8: // target cell
|
||||
case 15: // target cell
|
||||
if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
||||
return QString::fromUtf8(content.mCellName.c_str());
|
||||
else
|
||||
return QVariant();
|
||||
case 9:
|
||||
case 16:
|
||||
if (content.mType == ESM::AI_Travel)
|
||||
return content.mTravel.mX;
|
||||
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
||||
return content.mTarget.mX;
|
||||
else
|
||||
return QVariant();
|
||||
case 10:
|
||||
case 17:
|
||||
if (content.mType == ESM::AI_Travel)
|
||||
return content.mTravel.mY;
|
||||
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
||||
return content.mTarget.mY;
|
||||
else
|
||||
return QVariant();
|
||||
case 11:
|
||||
case 18:
|
||||
if (content.mType == ESM::AI_Travel)
|
||||
return content.mTravel.mZ;
|
||||
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
||||
|
@ -1528,11 +1684,12 @@ namespace CSMWorld
|
|||
case 0: // ai package type
|
||||
switch (value.toInt())
|
||||
{
|
||||
case 0: content.mType = ESM::AI_Wander;
|
||||
case 1: content.mType = ESM::AI_Travel;
|
||||
case 2: content.mType = ESM::AI_Follow;
|
||||
case 3: content.mType = ESM::AI_Escort;
|
||||
case 4: content.mType = ESM::AI_Activate;
|
||||
case 0: content.mType = ESM::AI_Wander; break;
|
||||
case 1: content.mType = ESM::AI_Travel; break;
|
||||
case 2: content.mType = ESM::AI_Follow; break;
|
||||
case 3: content.mType = ESM::AI_Escort; break;
|
||||
case 4: content.mType = ESM::AI_Activate; break;
|
||||
default: return; // return without saving
|
||||
}
|
||||
break; // always save
|
||||
|
||||
|
@ -1541,6 +1698,8 @@ namespace CSMWorld
|
|||
content.mWander.mDistance = static_cast<short>(value.toInt());
|
||||
else
|
||||
return; // return without saving
|
||||
|
||||
break; // always save
|
||||
case 2:
|
||||
if (content.mType == ESM::AI_Wander ||
|
||||
content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
||||
|
@ -1552,62 +1711,77 @@ namespace CSMWorld
|
|||
content.mWander.mTimeOfDay = static_cast<unsigned char>(value.toInt());
|
||||
else
|
||||
return; // return without saving
|
||||
|
||||
break; // always save
|
||||
case 4:
|
||||
if (content.mType == ESM::AI_Wander)
|
||||
break; // FIXME: idle
|
||||
else
|
||||
return; // return without saving
|
||||
case 5:
|
||||
if (content.mType == ESM::AI_Wander)
|
||||
{
|
||||
content.mWander.mShouldRepeat = static_cast<unsigned char>(value.toInt());
|
||||
break;
|
||||
}
|
||||
case 6: // NAME32
|
||||
if (content.mType == ESM::AI_Activate)
|
||||
{
|
||||
content.mActivate.mName.assign(value.toString().toUtf8().constData());
|
||||
break;
|
||||
}
|
||||
else
|
||||
return; // return without saving
|
||||
case 7: // NAME32
|
||||
if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
||||
{
|
||||
content.mTarget.mId.assign(value.toString().toUtf8().constData());
|
||||
break;
|
||||
}
|
||||
else
|
||||
return; // return without saving
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
||||
{
|
||||
content.mCellName = std::string(value.toString().toUtf8().constData());
|
||||
break;
|
||||
}
|
||||
else
|
||||
return; // return without saving
|
||||
case 9:
|
||||
if (content.mType == ESM::AI_Travel)
|
||||
content.mTravel.mZ = value.toFloat();
|
||||
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
||||
content.mTarget.mZ = value.toFloat();
|
||||
else
|
||||
return; // return without saving
|
||||
case 10:
|
||||
if (content.mType == ESM::AI_Travel)
|
||||
content.mTravel.mZ = value.toFloat();
|
||||
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
||||
content.mTarget.mZ = value.toFloat();
|
||||
else
|
||||
return; // return without saving
|
||||
case 11:
|
||||
if (content.mType == ESM::AI_Wander)
|
||||
content.mWander.mIdle[subColIndex-4] = static_cast<unsigned char>(value.toInt());
|
||||
else
|
||||
return; // return without saving
|
||||
|
||||
break; // always save
|
||||
case 12:
|
||||
if (content.mType == ESM::AI_Wander)
|
||||
content.mWander.mShouldRepeat = static_cast<unsigned char>(value.toInt());
|
||||
else
|
||||
return; // return without saving
|
||||
|
||||
break; // always save
|
||||
case 13: // NAME32
|
||||
if (content.mType == ESM::AI_Activate)
|
||||
content.mActivate.mName.assign(value.toString().toUtf8().constData());
|
||||
else
|
||||
return; // return without saving
|
||||
|
||||
break; // always save
|
||||
case 14: // NAME32
|
||||
if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
||||
content.mTarget.mId.assign(value.toString().toUtf8().constData());
|
||||
else
|
||||
return; // return without saving
|
||||
|
||||
break; // always save
|
||||
case 15:
|
||||
if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
||||
content.mCellName = std::string(value.toString().toUtf8().constData());
|
||||
else
|
||||
return; // return without saving
|
||||
|
||||
break; // always save
|
||||
case 16:
|
||||
if (content.mType == ESM::AI_Travel)
|
||||
content.mTravel.mZ = value.toFloat();
|
||||
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
||||
content.mTarget.mZ = value.toFloat();
|
||||
else
|
||||
return; // return without saving
|
||||
|
||||
break; // always save
|
||||
case 17:
|
||||
if (content.mType == ESM::AI_Travel)
|
||||
content.mTravel.mZ = value.toFloat();
|
||||
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
||||
content.mTarget.mZ = value.toFloat();
|
||||
else
|
||||
return; // return without saving
|
||||
|
||||
break; // always save
|
||||
case 18:
|
||||
if (content.mType == ESM::AI_Travel)
|
||||
content.mTravel.mZ = value.toFloat();
|
||||
else if (content.mType == ESM::AI_Follow || content.mType == ESM::AI_Escort)
|
||||
content.mTarget.mZ = value.toFloat();
|
||||
else
|
||||
return; // return without saving
|
||||
|
||||
break; // always save
|
||||
default:
|
||||
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
||||
}
|
||||
|
@ -1617,7 +1791,7 @@ namespace CSMWorld
|
|||
|
||||
virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
|
||||
{
|
||||
return 12;
|
||||
return 19;
|
||||
}
|
||||
|
||||
virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
|
||||
|
@ -1810,7 +1984,7 @@ namespace CSMWorld
|
|||
int index) const
|
||||
{
|
||||
if (column==mLevList.mLevList || column == mLevList.mNestedListLevList)
|
||||
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
|
||||
return BaseRefIdAdapter<RecordT>::getData (column, data, index);
|
||||
}
|
||||
|
|
|
@ -72,6 +72,21 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data)
|
|||
mColumns.push_back (RefIdColumn (Columns::ColumnId_CoinValue, ColumnBase::Display_Integer));
|
||||
inventoryColumns.mValue = &mColumns.back();
|
||||
|
||||
IngredientColumns ingredientColumns (inventoryColumns);
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_EffectList,
|
||||
ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue));
|
||||
ingredientColumns.mEffects = &mColumns.back();
|
||||
std::map<UniversalId::Type, NestedRefIdAdapterBase*> ingredientEffectsMap;
|
||||
ingredientEffectsMap.insert(std::make_pair(UniversalId::Type_Ingredient,
|
||||
new IngredEffectRefIdAdapter ()));
|
||||
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), ingredientEffectsMap));
|
||||
mColumns.back().addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_IngredEffectId));
|
||||
mColumns.back().addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_EffectSkill));
|
||||
mColumns.back().addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_EffectAttribute));
|
||||
|
||||
// nested table
|
||||
PotionColumns potionColumns (inventoryColumns);
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_EffectList,
|
||||
|
@ -84,9 +99,9 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data)
|
|||
mColumns.back().addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_EffectId, ColumnBase::Display_EffectId));
|
||||
mColumns.back().addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_SkillImpact, ColumnBase::Display_SkillImpact));
|
||||
new NestedChildColumn (Columns::ColumnId_Skill, ColumnBase::Display_EffectSkill));
|
||||
mColumns.back().addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_Attribute));
|
||||
new NestedChildColumn (Columns::ColumnId_Attribute, ColumnBase::Display_EffectAttribute));
|
||||
mColumns.back().addColumn(
|
||||
new NestedChildColumn (Columns::ColumnId_EffectRange, ColumnBase::Display_EffectRange));
|
||||
mColumns.back().addColumn(
|
||||
|
@ -114,8 +129,6 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data)
|
|||
|
||||
ActorColumns actorsColumns (nameColumns);
|
||||
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Ai, ColumnBase::Display_Boolean));
|
||||
actorsColumns.mHasAi = &mColumns.back();
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiHello, ColumnBase::Display_Integer));
|
||||
actorsColumns.mHello = &mColumns.back();
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_AiFlee, ColumnBase::Display_Integer));
|
||||
|
@ -205,8 +218,24 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data)
|
|||
new RefIdColumn (Columns::ColumnId_AiDuration, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_AiWanderToD, CSMWorld::ColumnBase::Display_Integer));
|
||||
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_AiWanderIdle, CSMWorld::ColumnBase::Display_Integer));
|
||||
new RefIdColumn (Columns::ColumnId_Idle1, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Idle2, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Idle3, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Idle4, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Idle5, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Idle6, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Idle7, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Idle8, CSMWorld::ColumnBase::Display_Integer));
|
||||
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_AiWanderRepeat, CSMWorld::ColumnBase::Display_Boolean));
|
||||
mColumns.back().addColumn(
|
||||
|
@ -307,21 +336,10 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data)
|
|||
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_CreatureType, ColumnBase::Display_CreatureType));
|
||||
creatureColumns.mType = &mColumns.back();
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_SoulPoints, ColumnBase::Display_Integer));
|
||||
creatureColumns.mSoul = &mColumns.back();
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Scale, ColumnBase::Display_Float));
|
||||
creatureColumns.mScale = &mColumns.back();
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_OriginalCreature, ColumnBase::Display_Creature));
|
||||
creatureColumns.mOriginal = &mColumns.back();
|
||||
mColumns.push_back (
|
||||
RefIdColumn (Columns::ColumnId_CombatState, ColumnBase::Display_Integer));
|
||||
creatureColumns.mCombat = &mColumns.back();
|
||||
mColumns.push_back (
|
||||
RefIdColumn (Columns::ColumnId_MagicState, ColumnBase::Display_Integer));
|
||||
creatureColumns.mMagic = &mColumns.back();
|
||||
mColumns.push_back (
|
||||
RefIdColumn (Columns::ColumnId_StealthState, ColumnBase::Display_Integer));
|
||||
creatureColumns.mStealth = &mColumns.back();
|
||||
|
||||
static const struct
|
||||
{
|
||||
|
@ -360,6 +378,59 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data)
|
|||
|
||||
creatureColumns.mFlags.insert (std::make_pair (respawn, ESM::Creature::Respawn));
|
||||
|
||||
// Nested table
|
||||
mColumns.push_back(RefIdColumn (Columns::ColumnId_CreatureAttributes,
|
||||
ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue));
|
||||
creatureColumns.mAttributes = &mColumns.back();
|
||||
std::map<UniversalId::Type, NestedRefIdAdapterBase*> creaAttrMap;
|
||||
creaAttrMap.insert(std::make_pair(UniversalId::Type_Creature, new CreatureAttributesRefIdAdapter()));
|
||||
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), creaAttrMap));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Attribute, CSMWorld::ColumnBase::Display_Attribute, false, false));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_AttributeValue, CSMWorld::ColumnBase::Display_Integer));
|
||||
|
||||
// Nested table
|
||||
mColumns.push_back(RefIdColumn (Columns::ColumnId_CreatureAttack,
|
||||
ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue));
|
||||
creatureColumns.mAttacks = &mColumns.back();
|
||||
std::map<UniversalId::Type, NestedRefIdAdapterBase*> attackMap;
|
||||
attackMap.insert(std::make_pair(UniversalId::Type_Creature, new CreatureAttackRefIdAdapter()));
|
||||
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), attackMap));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_CreatureAttack, CSMWorld::ColumnBase::Display_Integer, false, false));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_MinAttack, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_MaxAttack, CSMWorld::ColumnBase::Display_Integer));
|
||||
|
||||
// Nested list
|
||||
mColumns.push_back(RefIdColumn (Columns::ColumnId_CreatureMisc,
|
||||
ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_List));
|
||||
creatureColumns.mMisc = &mColumns.back();
|
||||
std::map<UniversalId::Type, NestedRefIdAdapterBase*> creaMiscMap;
|
||||
creaMiscMap.insert(std::make_pair(UniversalId::Type_Creature, new CreatureMiscRefIdAdapter()));
|
||||
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), creaMiscMap));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Level, CSMWorld::ColumnBase::Display_Integer,
|
||||
ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Health, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Mana, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Fatigue, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_SoulPoints, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_CombatState, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_MagicState, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_StealthState, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_Gold, CSMWorld::ColumnBase::Display_Integer));
|
||||
|
||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_OpenSound, ColumnBase::Display_Sound));
|
||||
const RefIdColumn *openSound = &mColumns.back();
|
||||
|
||||
|
@ -449,7 +520,7 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data)
|
|||
attrMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcAttributesRefIdAdapter(data)));
|
||||
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), attrMap));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_NpcAttributes, CSMWorld::ColumnBase::Display_String, false, false));
|
||||
new RefIdColumn (Columns::ColumnId_Attribute, CSMWorld::ColumnBase::Display_Attribute, false, false));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_UChar, CSMWorld::ColumnBase::Display_Integer));
|
||||
|
||||
|
@ -461,7 +532,7 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data)
|
|||
skillsMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcSkillsRefIdAdapter(data)));
|
||||
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), skillsMap));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_NpcSkills, CSMWorld::ColumnBase::Display_String, false, false));
|
||||
new RefIdColumn (Columns::ColumnId_Skill, CSMWorld::ColumnBase::Display_SkillId, false, false));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_UChar, CSMWorld::ColumnBase::Display_Integer));
|
||||
|
||||
|
@ -473,16 +544,16 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data)
|
|||
miscMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcMiscRefIdAdapter(data)));
|
||||
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), miscMap));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_NpcLevel, CSMWorld::ColumnBase::Display_Integer,
|
||||
new RefIdColumn (Columns::ColumnId_Level, CSMWorld::ColumnBase::Display_Integer,
|
||||
ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_NpcFactionID, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_NpcHealth, CSMWorld::ColumnBase::Display_Integer));
|
||||
new RefIdColumn (Columns::ColumnId_Health, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_NpcMana, CSMWorld::ColumnBase::Display_Integer));
|
||||
new RefIdColumn (Columns::ColumnId_Mana, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_NpcFatigue, CSMWorld::ColumnBase::Display_Integer));
|
||||
new RefIdColumn (Columns::ColumnId_Fatigue, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_NpcDisposition, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
|
@ -490,7 +561,7 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data)
|
|||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_NpcRank, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_NpcGold, CSMWorld::ColumnBase::Display_Integer));
|
||||
new RefIdColumn (Columns::ColumnId_Gold, CSMWorld::ColumnBase::Display_Integer));
|
||||
mColumns.back().addColumn(
|
||||
new RefIdColumn (Columns::ColumnId_NpcPersistence, CSMWorld::ColumnBase::Display_Boolean));
|
||||
|
||||
|
@ -606,7 +677,7 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data)
|
|||
mAdapters.insert (std::make_pair (UniversalId::Type_Door,
|
||||
new DoorRefIdAdapter (nameColumns, openSound, closeSound)));
|
||||
mAdapters.insert (std::make_pair (UniversalId::Type_Ingredient,
|
||||
new InventoryRefIdAdapter<ESM::Ingredient> (UniversalId::Type_Ingredient, inventoryColumns)));
|
||||
new IngredientRefIdAdapter (ingredientColumns)));
|
||||
mAdapters.insert (std::make_pair (UniversalId::Type_CreatureLevelledList,
|
||||
new LevelledListRefIdAdapter<ESM::CreatureLevList> (
|
||||
UniversalId::Type_CreatureLevelledList, levListColumns)));
|
||||
|
@ -924,3 +995,8 @@ const CSMWorld::NestedRefIdAdapterBase& CSMWorld::RefIdCollection::getNestedAdap
|
|||
}
|
||||
throw std::runtime_error("No such column in the nestedadapters");
|
||||
}
|
||||
|
||||
void CSMWorld::RefIdCollection::copyTo (int index, RefIdCollection& target) const
|
||||
{
|
||||
mData.copyTo (index, target.mData);
|
||||
}
|
||||
|
|
|
@ -140,6 +140,7 @@ namespace CSMWorld
|
|||
void save (int index, ESM::ESMWriter& writer) const;
|
||||
|
||||
const RefIdData& getDataSet() const; //I can't figure out a better name for this one :(
|
||||
void copyTo (int index, RefIdCollection& target) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "refiddata.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
|
@ -344,7 +345,7 @@ const CSMWorld::RefIdDataContainer< ESM::Static >& CSMWorld::RefIdData::getStati
|
|||
return mStatics;
|
||||
}
|
||||
|
||||
void CSMWorld::RefIdData::insertRecord(CSMWorld::RecordBase& record, CSMWorld::UniversalId::Type type, const std::string& id)
|
||||
void CSMWorld::RefIdData::insertRecord (CSMWorld::RecordBase& record, CSMWorld::UniversalId::Type type, const std::string& id)
|
||||
{
|
||||
std::map<UniversalId::Type, RefIdDataContainerBase *>::iterator iter =
|
||||
mRecordContainers.find (type);
|
||||
|
@ -357,3 +358,16 @@ void CSMWorld::RefIdData::insertRecord(CSMWorld::RecordBase& record, CSMWorld::U
|
|||
mIndex.insert (std::make_pair (Misc::StringUtils::lowerCase (id),
|
||||
LocalIndex (iter->second->getSize()-1, type)));
|
||||
}
|
||||
|
||||
void CSMWorld::RefIdData::copyTo (int index, RefIdData& target) const
|
||||
{
|
||||
LocalIndex localIndex = globalToLocalIndex (index);
|
||||
|
||||
RefIdDataContainerBase *source = mRecordContainers.find (localIndex.second)->second;
|
||||
|
||||
std::string id = source->getId (localIndex.first);
|
||||
|
||||
std::auto_ptr<CSMWorld::RecordBase> newRecord (source->getRecord (localIndex.first).modifiedCopy());
|
||||
|
||||
target.insertRecord (*newRecord, localIndex.second, id);
|
||||
}
|
||||
|
|
|
@ -210,7 +210,8 @@ namespace CSMWorld
|
|||
|
||||
void erase (int index, int count);
|
||||
|
||||
void insertRecord(CSMWorld::RecordBase& record, CSMWorld::UniversalId::Type type, const std::string& id);
|
||||
void insertRecord (CSMWorld::RecordBase& record, CSMWorld::UniversalId::Type type,
|
||||
const std::string& id);
|
||||
|
||||
const RecordBase& getRecord (const LocalIndex& index) const;
|
||||
|
||||
|
@ -252,11 +253,9 @@ namespace CSMWorld
|
|||
const RefIdDataContainer<ESM::Probe >& getProbes() const;
|
||||
const RefIdDataContainer<ESM::Repair>& getRepairs() const;
|
||||
const RefIdDataContainer<ESM::Static>& getStatics() const;
|
||||
|
||||
void copyTo (int index, RefIdData& target) const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -39,8 +39,6 @@ char CSMWorld::ScriptContext::getGlobalType (const std::string& name) const
|
|||
std::pair<char, bool> CSMWorld::ScriptContext::getMemberType (const std::string& name,
|
||||
const std::string& id) const
|
||||
{
|
||||
/// \todo invalidate locals cache on change to scripts
|
||||
|
||||
std::string id2 = Misc::StringUtils::lowerCase (id);
|
||||
|
||||
int index = mData.getScripts().searchId (id2);
|
||||
|
@ -120,3 +118,18 @@ void CSMWorld::ScriptContext::clear()
|
|||
mIdsUpdated = false;
|
||||
mLocals.clear();
|
||||
}
|
||||
|
||||
bool CSMWorld::ScriptContext::clearLocals (const std::string& script)
|
||||
{
|
||||
std::map<std::string, Compiler::Locals>::iterator iter =
|
||||
mLocals.find (Misc::StringUtils::lowerCase (script));
|
||||
|
||||
if (iter!=mLocals.end())
|
||||
{
|
||||
mLocals.erase (iter);
|
||||
mIdsUpdated = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,9 @@ namespace CSMWorld
|
|||
|
||||
void clear();
|
||||
///< Remove all cached data.
|
||||
|
||||
/// \return Were there any locals that needed clearing?
|
||||
bool clearLocals (const std::string& script);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon)
|
|||
QString message;
|
||||
|
||||
mValid = (!name.isEmpty());
|
||||
bool warning = false;
|
||||
|
||||
if (!mValid)
|
||||
{
|
||||
|
@ -105,13 +106,14 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon)
|
|||
{
|
||||
/// \todo add an user setting to make this an error.
|
||||
message += "<p>A file with the same name already exists. If you continue, it will be overwritten.";
|
||||
warning = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mMessage->setText (message);
|
||||
mIcon->setPixmap (style()->standardIcon (
|
||||
mValid ? QStyle::SP_MessageBoxInformation : QStyle::SP_MessageBoxWarning).
|
||||
mValid ? (warning ? QStyle::SP_MessageBoxWarning : QStyle::SP_MessageBoxInformation) : QStyle::SP_MessageBoxCritical).
|
||||
pixmap (QSize (16, 16)));
|
||||
|
||||
emit stateChanged (mValid);
|
||||
|
|
|
@ -55,3 +55,11 @@ void CSVDoc::FileWidget::extensionLabelIsVisible(bool visible)
|
|||
{
|
||||
mType->setVisible(visible);
|
||||
}
|
||||
|
||||
void CSVDoc::FileWidget::setName (const std::string& text)
|
||||
{
|
||||
QString text2 = QString::fromUtf8 (text.c_str());
|
||||
|
||||
mInput->setText (text2);
|
||||
textChanged (text2);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <QWidget>
|
||||
|
||||
#include <string>
|
||||
|
||||
class QLabel;
|
||||
class QString;
|
||||
class QLineEdit;
|
||||
|
@ -29,6 +31,8 @@ namespace CSVDoc
|
|||
|
||||
void extensionLabelIsVisible(bool visible);
|
||||
|
||||
void setName (const std::string& text);
|
||||
|
||||
private slots:
|
||||
|
||||
void textChanged (const QString& text);
|
||||
|
|
|
@ -19,6 +19,7 @@ void CSVDoc::Operation::updateLabel (int threads)
|
|||
case CSMDoc::State_Saving: name = "saving"; break;
|
||||
case CSMDoc::State_Verifying: name = "verifying"; break;
|
||||
case CSMDoc::State_Searching: name = "searching"; break;
|
||||
case CSMDoc::State_Merging: name = "merging"; break;
|
||||
}
|
||||
|
||||
std::ostringstream stream;
|
||||
|
@ -122,7 +123,7 @@ void CSVDoc::Operation::setBarColor (int type)
|
|||
bottomColor = "#9ECB2D"; //green gloss
|
||||
break;
|
||||
|
||||
case CSMDoc::State_Compiling:
|
||||
case CSMDoc::State_Merging:
|
||||
|
||||
topColor = "#F3E2C7";
|
||||
midTopColor = "#C19E67";
|
||||
|
|
|
@ -83,6 +83,10 @@ void CSVDoc::View::setupFileMenu()
|
|||
connect (mVerify, SIGNAL (triggered()), this, SLOT (verify()));
|
||||
file->addAction (mVerify);
|
||||
|
||||
mMerge = new QAction (tr ("Merge"), this);
|
||||
connect (mMerge, SIGNAL (triggered()), this, SLOT (merge()));
|
||||
file->addAction (mMerge);
|
||||
|
||||
QAction *loadErrors = new QAction (tr ("Load Error Log"), this);
|
||||
connect (loadErrors, SIGNAL (triggered()), this, SLOT (loadErrorLog()));
|
||||
file->addAction (loadErrors);
|
||||
|
@ -418,6 +422,9 @@ void CSVDoc::View::updateActions()
|
|||
|
||||
mGlobalDebugProfileMenu->updateActions (running);
|
||||
mStopDebug->setEnabled (running);
|
||||
|
||||
mMerge->setEnabled (mDocument->getContentFiles().size()>1 &&
|
||||
!(mDocument->getState() & CSMDoc::State_Merging));
|
||||
}
|
||||
|
||||
CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews)
|
||||
|
@ -467,6 +474,8 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to
|
|||
mOperations = new Operations;
|
||||
addDockWidget (Qt::BottomDockWidgetArea, mOperations);
|
||||
|
||||
setContextMenuPolicy(Qt::NoContextMenu);
|
||||
|
||||
updateTitle();
|
||||
|
||||
setupUi();
|
||||
|
@ -510,6 +519,7 @@ void CSVDoc::View::updateDocumentState()
|
|||
static const int operations[] =
|
||||
{
|
||||
CSMDoc::State_Saving, CSMDoc::State_Verifying, CSMDoc::State_Searching,
|
||||
CSMDoc::State_Merging,
|
||||
-1 // end marker
|
||||
};
|
||||
|
||||
|
@ -1053,3 +1063,8 @@ void CSVDoc::View::updateScrollbar()
|
|||
else
|
||||
mSubViewWindow.setMinimumWidth(0);
|
||||
}
|
||||
|
||||
void CSVDoc::View::merge()
|
||||
{
|
||||
emit mergeDocument (mDocument);
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace CSVDoc
|
|||
QAction *mVerify;
|
||||
QAction *mShowStatusBar;
|
||||
QAction *mStopDebug;
|
||||
QAction *mMerge;
|
||||
std::vector<QAction *> mEditingActions;
|
||||
Operations *mOperations;
|
||||
SubViewFactoryManager mSubViewFactory;
|
||||
|
@ -117,9 +118,6 @@ namespace CSVDoc
|
|||
|
||||
Operations *getOperations() const;
|
||||
|
||||
/// Function called by view manager when user preferences are updated
|
||||
void updateEditorSetting (const QString &, const QString &);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void moveEvent(QMoveEvent * event);
|
||||
|
@ -137,6 +135,8 @@ namespace CSVDoc
|
|||
|
||||
void editSettingsRequest();
|
||||
|
||||
void mergeDocument (CSMDoc::Document *document);
|
||||
|
||||
public slots:
|
||||
|
||||
void addSubView (const CSMWorld::UniversalId& id, const std::string& hint = "");
|
||||
|
@ -251,6 +251,8 @@ namespace CSVDoc
|
|||
void saveWindowState();
|
||||
|
||||
void moveScrollBarToEnd(int min, int max);
|
||||
|
||||
void merge();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -97,14 +97,16 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
|
|||
{ CSMWorld::ColumnBase::Display_Gender, CSMWorld::Columns::ColumnId_Gender, true },
|
||||
{ CSMWorld::ColumnBase::Display_SoundGeneratorType, CSMWorld::Columns::ColumnId_SoundGeneratorType, false },
|
||||
{ CSMWorld::ColumnBase::Display_School, CSMWorld::Columns::ColumnId_School, false },
|
||||
{ CSMWorld::ColumnBase::Display_SkillImpact, CSMWorld::Columns::ColumnId_SkillImpact, true },
|
||||
{ CSMWorld::ColumnBase::Display_SkillId, CSMWorld::Columns::ColumnId_Skill, true },
|
||||
{ CSMWorld::ColumnBase::Display_EffectRange, CSMWorld::Columns::ColumnId_EffectRange, false },
|
||||
{ CSMWorld::ColumnBase::Display_EffectId, CSMWorld::Columns::ColumnId_EffectId, false },
|
||||
{ CSMWorld::ColumnBase::Display_PartRefType, CSMWorld::Columns::ColumnId_PartRefType, false },
|
||||
{ CSMWorld::ColumnBase::Display_AiPackageType, CSMWorld::Columns::ColumnId_AiPackageType, false },
|
||||
{ CSMWorld::ColumnBase::Display_InfoCondFunc, CSMWorld::Columns::ColumnId_InfoCondFunc, false },
|
||||
{ CSMWorld::ColumnBase::Display_InfoCondComp, CSMWorld::Columns::ColumnId_InfoCondComp, false },
|
||||
{ CSMWorld::ColumnBase::Display_RaceSkill, CSMWorld::Columns::ColumnId_RaceSkill, true },
|
||||
{ CSMWorld::ColumnBase::Display_IngredEffectId, CSMWorld::Columns::ColumnId_EffectId, true },
|
||||
{ CSMWorld::ColumnBase::Display_EffectSkill, CSMWorld::Columns::ColumnId_Skill, false },
|
||||
{ CSMWorld::ColumnBase::Display_EffectAttribute, CSMWorld::Columns::ColumnId_Attribute, false },
|
||||
};
|
||||
|
||||
for (std::size_t i=0; i<sizeof (sMapping)/sizeof (Mapping); ++i)
|
||||
|
@ -173,6 +175,7 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document)
|
|||
connect (view, SIGNAL (newAddonRequest ()), this, SIGNAL (newAddonRequest()));
|
||||
connect (view, SIGNAL (loadDocumentRequest ()), this, SIGNAL (loadDocumentRequest()));
|
||||
connect (view, SIGNAL (editSettingsRequest()), this, SIGNAL (editSettingsRequest()));
|
||||
connect (view, SIGNAL (mergeDocument (CSMDoc::Document *)), this, SIGNAL (mergeDocument (CSMDoc::Document *)));
|
||||
|
||||
connect (&CSMSettings::UserSettings::instance(),
|
||||
SIGNAL (userSettingUpdated(const QString &, const QStringList &)),
|
||||
|
|
|
@ -77,6 +77,8 @@ namespace CSVDoc
|
|||
|
||||
void editSettingsRequest();
|
||||
|
||||
void mergeDocument (CSMDoc::Document *document);
|
||||
|
||||
public slots:
|
||||
|
||||
void exitApplication (CSVDoc::View *view);
|
||||
|
|
|
@ -5,14 +5,17 @@
|
|||
#include <QApplication>
|
||||
|
||||
#include "../../model/world/data.hpp"
|
||||
#include "../../model/world/idtablebase.hpp"
|
||||
#include "../../model/world/columns.hpp"
|
||||
|
||||
CSVFilter::EditWidget::EditWidget (CSMWorld::Data& data, QWidget *parent)
|
||||
: QLineEdit (parent), mParser (data)
|
||||
: QLineEdit (parent), mParser (data), mIsEmpty(true)
|
||||
{
|
||||
mPalette = palette();
|
||||
connect (this, SIGNAL (textChanged (const QString&)), this, SLOT (textChanged (const QString&)));
|
||||
|
||||
QAbstractItemModel *model = data.getTableModel (CSMWorld::UniversalId::Type_Filters);
|
||||
const CSMWorld::IdTableBase *model =
|
||||
static_cast<const CSMWorld::IdTableBase *> (data.getTableModel (CSMWorld::UniversalId::Type_Filters));
|
||||
|
||||
connect (model, SIGNAL (dataChanged (const QModelIndex &, const QModelIndex&)),
|
||||
this, SLOT (filterDataChanged (const QModelIndex &, const QModelIndex&)),
|
||||
|
@ -23,10 +26,23 @@ CSVFilter::EditWidget::EditWidget (CSMWorld::Data& data, QWidget *parent)
|
|||
connect (model, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
|
||||
this, SLOT (filterRowsInserted (const QModelIndex&, int, int)),
|
||||
Qt::QueuedConnection);
|
||||
|
||||
mStateColumnIndex = model->findColumnIndex(CSMWorld::Columns::ColumnId_Modification);
|
||||
mDescColumnIndex = model->findColumnIndex(CSMWorld::Columns::ColumnId_Description);
|
||||
}
|
||||
|
||||
void CSVFilter::EditWidget::textChanged (const QString& text)
|
||||
{
|
||||
//no need to parse and apply filter if it was empty and now is empty too.
|
||||
//e.g. - we modifiing content of filter with already opened some other (big) tables.
|
||||
if (text.length() == 0){
|
||||
if (mIsEmpty)
|
||||
return;
|
||||
else
|
||||
mIsEmpty = true;
|
||||
}else
|
||||
mIsEmpty = false;
|
||||
|
||||
if (mParser.parse (text.toUtf8().constData()))
|
||||
{
|
||||
setPalette (mPalette);
|
||||
|
@ -45,7 +61,9 @@ void CSVFilter::EditWidget::textChanged (const QString& text)
|
|||
void CSVFilter::EditWidget::filterDataChanged (const QModelIndex& topLeft,
|
||||
const QModelIndex& bottomRight)
|
||||
{
|
||||
textChanged (text());
|
||||
for (int i = topLeft.column(); i <= bottomRight.column(); ++i)
|
||||
if (i != mStateColumnIndex && i != mDescColumnIndex)
|
||||
textChanged (text());
|
||||
}
|
||||
|
||||
void CSVFilter::EditWidget::filterRowsRemoved (const QModelIndex& parent, int start, int end)
|
||||
|
|
|
@ -25,6 +25,9 @@ namespace CSVFilter
|
|||
|
||||
CSMFilter::Parser mParser;
|
||||
QPalette mPalette;
|
||||
bool mIsEmpty;
|
||||
int mStateColumnIndex;
|
||||
int mDescColumnIndex;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ bool CSVRender::Cell::addObjects (int start, int end)
|
|||
bool modified = false;
|
||||
|
||||
const CSMWorld::RefCollection& collection = mData.getReferences();
|
||||
|
||||
|
||||
for (int i=start; i<=end; ++i)
|
||||
{
|
||||
std::string cell = Misc::StringUtils::lowerCase (collection.getRecord (i).get().mCell);
|
||||
|
@ -70,20 +70,22 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager,
|
|||
int landIndex = land.searchId(mId);
|
||||
if (landIndex != -1)
|
||||
{
|
||||
const ESM::Land* esmLand = land.getRecord(mId).get().mLand.get();
|
||||
if(esmLand && esmLand->mDataTypes&ESM::Land::DATA_VHGT)
|
||||
const ESM::Land& esmLand = land.getRecord(mId).get();
|
||||
|
||||
if (esmLand.getLandData (ESM::Land::DATA_VHGT))
|
||||
{
|
||||
mTerrain.reset(new Terrain::TerrainGrid(sceneManager, new TerrainStorage(mData), Element_Terrain, true,
|
||||
Terrain::Align_XY));
|
||||
mTerrain->loadCell(esmLand->mX,
|
||||
esmLand->mY);
|
||||
mTerrain->loadCell(esmLand.mX,
|
||||
esmLand.mY);
|
||||
|
||||
float verts = ESM::Land::LAND_SIZE;
|
||||
float worldsize = ESM::Land::REAL_SIZE;
|
||||
mX = esmLand->mX;
|
||||
mY = esmLand->mY;
|
||||
mX = esmLand.mX;
|
||||
mY = esmLand.mY;
|
||||
|
||||
mPhysics->addHeightField(sceneManager,
|
||||
esmLand->mLandData->mHeights, mX, mY, 0, worldsize / (verts-1), verts);
|
||||
esmLand.getLandData(ESM::Land::DATA_VHGT)->mHeights, mX, mY, 0, worldsize / (verts-1), verts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace CSVRender
|
|||
{
|
||||
}
|
||||
|
||||
ESM::Land* TerrainStorage::getLand(int cellX, int cellY)
|
||||
const ESM::Land* TerrainStorage::getLand(int cellX, int cellY)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << "#" << cellX << " " << cellY;
|
||||
|
@ -19,11 +19,10 @@ namespace CSVRender
|
|||
if (index == -1)
|
||||
return NULL;
|
||||
|
||||
ESM::Land* land = mData.getLand().getRecord(index).get().mLand.get();
|
||||
const ESM::Land& land = mData.getLand().getRecord(index).get();
|
||||
int mask = ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX;
|
||||
if (!land->isDataLoaded(mask))
|
||||
land->loadData(mask);
|
||||
return land;
|
||||
land.loadData (mask);
|
||||
return &land;
|
||||
}
|
||||
|
||||
const ESM::LandTexture* TerrainStorage::getLandTexture(int index, short plugin)
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace CSVRender
|
|||
private:
|
||||
const CSMWorld::Data& mData;
|
||||
|
||||
virtual ESM::Land* getLand (int cellX, int cellY);
|
||||
virtual const ESM::Land* getLand (int cellX, int cellY);
|
||||
virtual const ESM::LandTexture* getLandTexture(int index, short plugin);
|
||||
|
||||
virtual void getBounds(float& minX, float& maxX, float& minY, float& maxY);
|
||||
|
|
142
apps/opencs/view/tools/merge.cpp
Normal file
142
apps/opencs/view/tools/merge.cpp
Normal file
|
@ -0,0 +1,142 @@
|
|||
|
||||
#include "merge.hpp"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QSplitter>
|
||||
#include <QPushButton>
|
||||
#include <QListWidget>
|
||||
#include <QLabel>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "../../model/doc/document.hpp"
|
||||
#include "../../model/doc/documentmanager.hpp"
|
||||
|
||||
#include "../doc/filewidget.hpp"
|
||||
#include "../doc/adjusterwidget.hpp"
|
||||
|
||||
void CSVTools::Merge::keyPressEvent (QKeyEvent *event)
|
||||
{
|
||||
if (event->key()==Qt::Key_Escape)
|
||||
{
|
||||
event->accept();
|
||||
cancel();
|
||||
}
|
||||
else
|
||||
QWidget::keyPressEvent (event);
|
||||
}
|
||||
|
||||
CSVTools::Merge::Merge (CSMDoc::DocumentManager& documentManager, QWidget *parent)
|
||||
: QWidget (parent), mDocument (0), mDocumentManager (documentManager)
|
||||
{
|
||||
setWindowTitle ("Merge Content Files into a new Game File");
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
setLayout (mainLayout);
|
||||
|
||||
QSplitter *splitter = new QSplitter (Qt::Horizontal, this);
|
||||
|
||||
mainLayout->addWidget (splitter, 1);
|
||||
|
||||
// left panel (files to be merged)
|
||||
QWidget *left = new QWidget (this);
|
||||
left->setContentsMargins (0, 0, 0, 0);
|
||||
splitter->addWidget (left);
|
||||
|
||||
QVBoxLayout *leftLayout = new QVBoxLayout;
|
||||
left->setLayout (leftLayout);
|
||||
|
||||
leftLayout->addWidget (new QLabel ("Files to be merged", this));
|
||||
|
||||
mFiles = new QListWidget (this);
|
||||
leftLayout->addWidget (mFiles, 1);
|
||||
|
||||
// right panel (new game file)
|
||||
QWidget *right = new QWidget (this);
|
||||
right->setContentsMargins (0, 0, 0, 0);
|
||||
splitter->addWidget (right);
|
||||
|
||||
QVBoxLayout *rightLayout = new QVBoxLayout;
|
||||
rightLayout->setAlignment (Qt::AlignTop);
|
||||
right->setLayout (rightLayout);
|
||||
|
||||
rightLayout->addWidget (new QLabel ("New game file", this));
|
||||
|
||||
mNewFile = new CSVDoc::FileWidget (this);
|
||||
mNewFile->setType (false);
|
||||
mNewFile->extensionLabelIsVisible (true);
|
||||
rightLayout->addWidget (mNewFile);
|
||||
|
||||
mAdjuster = new CSVDoc::AdjusterWidget (this);
|
||||
|
||||
rightLayout->addWidget (mAdjuster);
|
||||
|
||||
connect (mNewFile, SIGNAL (nameChanged (const QString&, bool)),
|
||||
mAdjuster, SLOT (setName (const QString&, bool)));
|
||||
connect (mAdjuster, SIGNAL (stateChanged (bool)), this, SLOT (stateChanged (bool)));
|
||||
|
||||
// buttons
|
||||
QDialogButtonBox *buttons = new QDialogButtonBox (QDialogButtonBox::Cancel, Qt::Horizontal, this);
|
||||
|
||||
connect (buttons->button (QDialogButtonBox::Cancel), SIGNAL (clicked()), this, SLOT (cancel()));
|
||||
|
||||
mOkay = new QPushButton ("Merge", this);
|
||||
connect (mOkay, SIGNAL (clicked()), this, SLOT (accept()));
|
||||
mOkay->setDefault (true);
|
||||
buttons->addButton (mOkay, QDialogButtonBox::AcceptRole);
|
||||
|
||||
mainLayout->addWidget (buttons);
|
||||
}
|
||||
|
||||
void CSVTools::Merge::configure (CSMDoc::Document *document)
|
||||
{
|
||||
mDocument = document;
|
||||
|
||||
mNewFile->setName ("");
|
||||
|
||||
// content files
|
||||
while (mFiles->count())
|
||||
delete mFiles->takeItem (0);
|
||||
|
||||
std::vector<boost::filesystem::path> files = document->getContentFiles();
|
||||
|
||||
for (std::vector<boost::filesystem::path>::const_iterator iter (files.begin());
|
||||
iter!=files.end(); ++iter)
|
||||
mFiles->addItem (QString::fromUtf8 (iter->filename().string().c_str()));
|
||||
}
|
||||
|
||||
void CSVTools::Merge::setLocalData (const boost::filesystem::path& localData)
|
||||
{
|
||||
mAdjuster->setLocalData (localData);
|
||||
}
|
||||
|
||||
CSMDoc::Document *CSVTools::Merge::getDocument() const
|
||||
{
|
||||
return mDocument;
|
||||
}
|
||||
|
||||
void CSVTools::Merge::cancel()
|
||||
{
|
||||
mDocument = 0;
|
||||
hide();
|
||||
}
|
||||
|
||||
void CSVTools::Merge::accept()
|
||||
{
|
||||
if ((mDocument->getState() & CSMDoc::State_Merging)==0)
|
||||
{
|
||||
std::vector< boost::filesystem::path > files (1, mAdjuster->getPath());
|
||||
|
||||
std::auto_ptr<CSMDoc::Document> target (
|
||||
mDocumentManager.makeDocument (files, files[0], true));
|
||||
|
||||
mDocument->runMerge (target);
|
||||
|
||||
hide();
|
||||
}
|
||||
}
|
||||
|
||||
void CSVTools::Merge::stateChanged (bool valid)
|
||||
{
|
||||
mOkay->setEnabled (valid);
|
||||
}
|
61
apps/opencs/view/tools/merge.hpp
Normal file
61
apps/opencs/view/tools/merge.hpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
#ifndef CSV_TOOLS_REPORTTABLE_H
|
||||
#define CSV_TOOLS_REPORTTABLE_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
class QPushButton;
|
||||
class QListWidget;
|
||||
|
||||
namespace CSMDoc
|
||||
{
|
||||
class Document;
|
||||
class DocumentManager;
|
||||
}
|
||||
|
||||
namespace CSVDoc
|
||||
{
|
||||
class FileWidget;
|
||||
class AdjusterWidget;
|
||||
}
|
||||
|
||||
namespace CSVTools
|
||||
{
|
||||
class Merge : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
CSMDoc::Document *mDocument;
|
||||
QPushButton *mOkay;
|
||||
QListWidget *mFiles;
|
||||
CSVDoc::FileWidget *mNewFile;
|
||||
CSVDoc::AdjusterWidget *mAdjuster;
|
||||
CSMDoc::DocumentManager& mDocumentManager;
|
||||
|
||||
void keyPressEvent (QKeyEvent *event);
|
||||
|
||||
public:
|
||||
|
||||
Merge (CSMDoc::DocumentManager& documentManager, QWidget *parent = 0);
|
||||
|
||||
/// Configure dialogue for a new merge
|
||||
void configure (CSMDoc::Document *document);
|
||||
|
||||
void setLocalData (const boost::filesystem::path& localData);
|
||||
|
||||
CSMDoc::Document *getDocument() const;
|
||||
|
||||
public slots:
|
||||
|
||||
void cancel();
|
||||
|
||||
private slots:
|
||||
|
||||
void accept();
|
||||
|
||||
void stateChanged (bool valid);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -35,7 +35,7 @@ void CSVWidget::DropLineEdit::dropEvent(QDropEvent *event)
|
|||
if (CSVWorld::DragDropUtils::canAcceptData(*event, mDropType))
|
||||
{
|
||||
CSMWorld::UniversalId id = CSVWorld::DragDropUtils::getAcceptedData(*event, mDropType);
|
||||
setText(QString::fromUtf8(id.getId().c_str()));
|
||||
setText(QString::fromUtf8(id.getId().c_str()));
|
||||
emit tableMimeDataDropped(id, CSVWorld::DragDropUtils::getTableMimeData(*event)->getDocumentPtr());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -564,8 +564,22 @@ void CSVWorld::EditWidget::remake(int row)
|
|||
static_cast<CSMWorld::UniversalId::Type> (mTable->data (mTable->index (row, typeColumn)).toInt()),
|
||||
mTable->data (mTable->index (row, idColumn)).toString().toUtf8().constData());
|
||||
|
||||
bool editable = mTable->index(row, i).data().type() != QVariant::UserType;
|
||||
NestedTable* table = new NestedTable(mDocument, id, mNestedModels.back(), this, editable);
|
||||
bool editable = true;
|
||||
bool fixedRows = false;
|
||||
QVariant v = mTable->index(row, i).data();
|
||||
if (v.canConvert<CSMWorld::ColumnBase::TableEditModes>())
|
||||
{
|
||||
assert (QString(v.typeName()) == "CSMWorld::ColumnBase::TableEditModes");
|
||||
|
||||
if (v.value<CSMWorld::ColumnBase::TableEditModes>() == CSMWorld::ColumnBase::TableEdit_None)
|
||||
editable = false;
|
||||
else if (v.value<CSMWorld::ColumnBase::TableEditModes>() == CSMWorld::ColumnBase::TableEdit_FixedRows)
|
||||
fixedRows = true;
|
||||
}
|
||||
|
||||
NestedTable* table =
|
||||
new NestedTable(mDocument, id, mNestedModels.back(), this, editable, fixedRows);
|
||||
table->resizeColumnsToContents();
|
||||
if (!editable)
|
||||
{
|
||||
table->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
|
@ -588,7 +602,7 @@ void CSVWorld::EditWidget::remake(int row)
|
|||
new QLabel (mTable->headerData (i, Qt::Horizontal, Qt::DisplayRole).toString(), mMainWidget);
|
||||
|
||||
label->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
if(mTable->index(row, i).data().type() == QVariant::UserType)
|
||||
if(!editable)
|
||||
label->setEnabled(false);
|
||||
|
||||
tablesLayout->addWidget(label);
|
||||
|
|
|
@ -47,6 +47,16 @@ std::string CSVWorld::GenericCreator::getId() const
|
|||
return mId->text().toUtf8().constData();
|
||||
}
|
||||
|
||||
std::string CSVWorld::GenericCreator::getIdValidatorResult() const
|
||||
{
|
||||
std::string errors;
|
||||
|
||||
if (!mId->hasAcceptableInput())
|
||||
errors = mValidator->getError();
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const {}
|
||||
|
||||
void CSVWorld::GenericCreator::pushCommand (std::auto_ptr<CSMWorld::CreateCommand> command,
|
||||
|
|
|
@ -60,6 +60,8 @@ namespace CSVWorld
|
|||
|
||||
virtual std::string getId() const;
|
||||
|
||||
virtual std::string getIdValidatorResult() const;
|
||||
|
||||
/// Allow subclasses to add additional data to \a command.
|
||||
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
|
||||
|
||||
|
|
|
@ -17,9 +17,12 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document,
|
|||
CSMWorld::UniversalId id,
|
||||
CSMWorld::NestedTableProxyModel* model,
|
||||
QWidget* parent,
|
||||
bool editable)
|
||||
bool editable,
|
||||
bool fixedRows)
|
||||
: DragRecordTable(document, parent),
|
||||
mEditIdAction(0),
|
||||
mAddNewRowAction(NULL),
|
||||
mRemoveRowAction(NULL),
|
||||
mEditIdAction(NULL),
|
||||
mModel(model)
|
||||
{
|
||||
mDispatcher = new CSMWorld::CommandDispatcher (document, id, this);
|
||||
|
@ -53,15 +56,18 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document,
|
|||
|
||||
if (editable)
|
||||
{
|
||||
mAddNewRowAction = new QAction (tr ("Add new row"), this);
|
||||
if (!fixedRows)
|
||||
{
|
||||
mAddNewRowAction = new QAction (tr ("Add new row"), this);
|
||||
|
||||
connect(mAddNewRowAction, SIGNAL(triggered()),
|
||||
this, SLOT(addNewRowActionTriggered()));
|
||||
connect(mAddNewRowAction, SIGNAL(triggered()),
|
||||
this, SLOT(addNewRowActionTriggered()));
|
||||
|
||||
mRemoveRowAction = new QAction (tr ("Remove row"), this);
|
||||
mRemoveRowAction = new QAction (tr ("Remove row"), this);
|
||||
|
||||
connect(mRemoveRowAction, SIGNAL(triggered()),
|
||||
this, SLOT(removeRowActionTriggered()));
|
||||
connect(mRemoveRowAction, SIGNAL(triggered()),
|
||||
this, SLOT(removeRowActionTriggered()));
|
||||
}
|
||||
|
||||
mEditIdAction = new TableEditIdAction(*this, this);
|
||||
connect(mEditIdAction, SIGNAL(triggered()), this, SLOT(editCell()));
|
||||
|
@ -92,10 +98,13 @@ void CSVWorld::NestedTable::contextMenuEvent (QContextMenuEvent *event)
|
|||
menu.addSeparator();
|
||||
}
|
||||
|
||||
if (selectionModel()->selectedRows().size() == 1)
|
||||
menu.addAction(mRemoveRowAction);
|
||||
if (mAddNewRowAction && mRemoveRowAction)
|
||||
{
|
||||
if (selectionModel()->selectedRows().size() == 1)
|
||||
menu.addAction(mRemoveRowAction);
|
||||
|
||||
menu.addAction(mAddNewRowAction);
|
||||
menu.addAction(mAddNewRowAction);
|
||||
}
|
||||
|
||||
menu.exec (event->globalPos());
|
||||
}
|
||||
|
|
|
@ -39,7 +39,8 @@ namespace CSVWorld
|
|||
CSMWorld::UniversalId id,
|
||||
CSMWorld::NestedTableProxyModel* model,
|
||||
QWidget* parent = NULL,
|
||||
bool editable = true);
|
||||
bool editable = true,
|
||||
bool fixedRows = false);
|
||||
|
||||
virtual std::vector<CSMWorld::UniversalId> getDraggedRecords() const;
|
||||
|
||||
|
|
|
@ -181,7 +181,7 @@ namespace CSVWorld
|
|||
}
|
||||
|
||||
void PhysicsSystem::addHeightField(Ogre::SceneManager *sceneManager,
|
||||
float* heights, int x, int y, float yoffset, float triSize, float sqrtVerts)
|
||||
const float* heights, int x, int y, float yoffset, float triSize, float sqrtVerts)
|
||||
{
|
||||
std::string name = "HeightField_"
|
||||
+ QString::number(x).toStdString() + "_" + QString::number(y).toStdString();
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace CSVWorld
|
|||
void moveSceneNodes(const std::string sceneNodeName, const Ogre::Vector3 &position);
|
||||
|
||||
void addHeightField(Ogre::SceneManager *sceneManager,
|
||||
float* heights, int x, int y, float yoffset, float triSize, float sqrtVerts);
|
||||
const float* heights, int x, int y, float yoffset, float triSize, float sqrtVerts);
|
||||
|
||||
void removeHeightField(Ogre::SceneManager *sceneManager, int x, int y);
|
||||
|
||||
|
|
|
@ -132,11 +132,6 @@ void CSVWorld::SceneSubView::setEditLock (bool locked)
|
|||
|
||||
}
|
||||
|
||||
void CSVWorld::SceneSubView::updateEditorSetting(const QString &settingName, const QString &settingValue)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CSVWorld::SceneSubView::setStatusBar (bool show)
|
||||
{
|
||||
mBottom->setStatusBar (show);
|
||||
|
@ -247,8 +242,6 @@ void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceW
|
|||
mToolbar = toolbar;
|
||||
|
||||
connect (mScene, SIGNAL (focusToolbarRequest()), mToolbar, SLOT (setFocus()));
|
||||
connect (this, SIGNAL (updateSceneUserSetting(const QString &, const QStringList &)),
|
||||
mScene, SLOT (updateUserSetting(const QString &, const QStringList &)));
|
||||
connect (mToolbar, SIGNAL (focusSceneRequest()), mScene, SLOT (setFocus()));
|
||||
|
||||
mLayout->addWidget (mToolbar, 0);
|
||||
|
@ -257,8 +250,3 @@ void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceW
|
|||
mScene->selectDefaultNavigationMode();
|
||||
setFocusProxy (mScene);
|
||||
}
|
||||
|
||||
void CSVWorld::SceneSubView::updateUserSetting (const QString &key, const QStringList &list)
|
||||
{
|
||||
emit updateSceneUserSetting(key, list);
|
||||
}
|
||||
|
|
|
@ -52,8 +52,6 @@ namespace CSVWorld
|
|||
|
||||
virtual void setEditLock (bool locked);
|
||||
|
||||
virtual void updateEditorSetting (const QString& key, const QString& value);
|
||||
|
||||
virtual void setStatusBar (bool show);
|
||||
|
||||
virtual void useHint (const std::string& hint);
|
||||
|
@ -83,14 +81,6 @@ namespace CSVWorld
|
|||
void cellSelectionChanged (const CSMWorld::UniversalId& id);
|
||||
|
||||
void handleDrop(const std::vector<CSMWorld::UniversalId>& data);
|
||||
|
||||
public slots:
|
||||
|
||||
void updateUserSetting (const QString &, const QStringList &);
|
||||
|
||||
signals:
|
||||
|
||||
void updateSceneUserSetting (const QString &, const QStringList &);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -131,6 +131,11 @@ void CSVWorld::ScriptErrorTable::clear()
|
|||
setRowCount (0);
|
||||
}
|
||||
|
||||
bool CSVWorld::ScriptErrorTable::clearLocals (const std::string& script)
|
||||
{
|
||||
return mContext.clearLocals (script);
|
||||
}
|
||||
|
||||
void CSVWorld::ScriptErrorTable::cellClicked (int row, int column)
|
||||
{
|
||||
if (item (row, 1))
|
||||
|
|
|
@ -44,6 +44,11 @@ namespace CSVWorld
|
|||
|
||||
void clear();
|
||||
|
||||
/// Clear local variable cache for \a script.
|
||||
///
|
||||
/// \return Were there any locals that needed clearing?
|
||||
bool clearLocals (const std::string& script);
|
||||
|
||||
private slots:
|
||||
|
||||
void cellClicked (int row, int column);
|
||||
|
|
|
@ -89,6 +89,7 @@ CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc:
|
|||
*document.getData().getTableModel (CSMWorld::UniversalId::Type_Scripts));
|
||||
|
||||
mColumn = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_ScriptText);
|
||||
mIdColumn = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
|
||||
mStateColumn = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Modification);
|
||||
|
||||
QString source = mModel->data (mModel->getModelIndex (id.getId(), mColumn)).toString();
|
||||
|
@ -197,26 +198,41 @@ void CSVWorld::ScriptSubView::useHint (const std::string& hint)
|
|||
if (hint.empty())
|
||||
return;
|
||||
|
||||
if (hint[0]=='l')
|
||||
{
|
||||
std::istringstream stream (hint.c_str()+1);
|
||||
|
||||
char ignore;
|
||||
int line;
|
||||
int column;
|
||||
|
||||
if (stream >> ignore >> line >> column)
|
||||
unsigned line = 0, column = 0;
|
||||
char c;
|
||||
std::istringstream stream (hint.c_str()+1);
|
||||
switch(hint[0]){
|
||||
case 'R':
|
||||
case 'r':
|
||||
{
|
||||
QTextCursor cursor = mEditor->textCursor();
|
||||
QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn);
|
||||
QString source = mModel->data (index).toString();
|
||||
unsigned pos, dummy;
|
||||
if (!(stream >> c >> dummy >> pos) )
|
||||
return;
|
||||
|
||||
cursor.movePosition (QTextCursor::Start);
|
||||
if (cursor.movePosition (QTextCursor::Down, QTextCursor::MoveAnchor, line))
|
||||
cursor.movePosition (QTextCursor::Right, QTextCursor::MoveAnchor, column);
|
||||
|
||||
mEditor->setFocus();
|
||||
mEditor->setTextCursor (cursor);
|
||||
for (unsigned i = 0; i <= pos; ++i){
|
||||
if (source[i] == '\n'){
|
||||
++line;
|
||||
column = i+1;
|
||||
}
|
||||
}
|
||||
column = pos - column;
|
||||
break;
|
||||
}
|
||||
case 'l':
|
||||
if (!(stream >> c >> line >> column))
|
||||
return;
|
||||
}
|
||||
|
||||
QTextCursor cursor = mEditor->textCursor();
|
||||
|
||||
cursor.movePosition (QTextCursor::Start);
|
||||
if (cursor.movePosition (QTextCursor::Down, QTextCursor::MoveAnchor, line))
|
||||
cursor.movePosition (QTextCursor::Right, QTextCursor::MoveAnchor, column);
|
||||
|
||||
mEditor->setFocus();
|
||||
mEditor->setTextCursor (cursor);
|
||||
}
|
||||
|
||||
void CSVWorld::ScriptSubView::textChanged()
|
||||
|
@ -241,6 +257,15 @@ void CSVWorld::ScriptSubView::dataChanged (const QModelIndex& topLeft, const QMo
|
|||
|
||||
ScriptEdit::ChangeLock lock (*mEditor);
|
||||
|
||||
bool updateRequired = false;
|
||||
|
||||
for (int i=topLeft.row(); i<=bottomRight.row(); ++i)
|
||||
{
|
||||
std::string id = mModel->data (mModel->index (i, mIdColumn)).toString().toUtf8().constData();
|
||||
if (mErrors->clearLocals (id))
|
||||
updateRequired = true;
|
||||
}
|
||||
|
||||
QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn);
|
||||
|
||||
if (index.row()>=topLeft.row() && index.row()<=bottomRight.row())
|
||||
|
@ -256,13 +281,28 @@ void CSVWorld::ScriptSubView::dataChanged (const QModelIndex& topLeft, const QMo
|
|||
mEditor->setPlainText (source);
|
||||
mEditor->setTextCursor (cursor);
|
||||
|
||||
recompile();
|
||||
updateRequired = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (updateRequired)
|
||||
recompile();
|
||||
}
|
||||
|
||||
void CSVWorld::ScriptSubView::rowsAboutToBeRemoved (const QModelIndex& parent, int start, int end)
|
||||
{
|
||||
bool updateRequired = false;
|
||||
|
||||
for (int i=start; i<=end; ++i)
|
||||
{
|
||||
std::string id = mModel->data (mModel->index (i, mIdColumn)).toString().toUtf8().constData();
|
||||
if (mErrors->clearLocals (id))
|
||||
updateRequired = true;
|
||||
}
|
||||
|
||||
if (updateRequired)
|
||||
recompile();
|
||||
|
||||
QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn);
|
||||
|
||||
if (!parent.isValid() && index.row()>=start && index.row()<=end)
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace CSVWorld
|
|||
CSMDoc::Document& mDocument;
|
||||
CSMWorld::IdTable *mModel;
|
||||
int mColumn;
|
||||
int mIdColumn;
|
||||
int mStateColumn;
|
||||
TableBottomBox *mBottom;
|
||||
RecordButtonBar *mButtons;
|
||||
|
|
20
apps/opencs/view/world/startscriptcreator.cpp
Normal file
20
apps/opencs/view/world/startscriptcreator.cpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#include "startscriptcreator.hpp"
|
||||
|
||||
CSVWorld::StartScriptCreator::StartScriptCreator(CSMWorld::Data &data, QUndoStack &undoStack, const CSMWorld::UniversalId &id, bool relaxedIdRules):
|
||||
GenericCreator (data, undoStack, id, true)
|
||||
{}
|
||||
|
||||
std::string CSVWorld::StartScriptCreator::getErrors() const
|
||||
{
|
||||
std::string errors;
|
||||
|
||||
errors = getIdValidatorResult();
|
||||
if (errors.length() > 0)
|
||||
return errors;
|
||||
else if (getData().getScripts().searchId(getId()) == -1)
|
||||
errors = "Script ID not found";
|
||||
else if (getData().getStartScripts().searchId(getId()) > -1 )
|
||||
errors = "Script with this ID already registered as Start Script";
|
||||
|
||||
return errors;
|
||||
}
|
25
apps/opencs/view/world/startscriptcreator.hpp
Normal file
25
apps/opencs/view/world/startscriptcreator.hpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#ifndef STARTSCRIPTCREATOR_HPP
|
||||
#define STARTSCRIPTCREATOR_HPP
|
||||
|
||||
#include "genericcreator.hpp"
|
||||
|
||||
namespace CSVWorld {
|
||||
|
||||
class StartScriptCreator : public GenericCreator
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
StartScriptCreator(CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id, bool relaxedIdRules = false);
|
||||
|
||||
virtual std::string getErrors() const;
|
||||
///< Return formatted error descriptions for the current state of the creator. if an empty
|
||||
/// string is returned, there is no error.
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // STARTSCRIPTCREATOR_HPP
|
|
@ -10,6 +10,7 @@
|
|||
#include "cellcreator.hpp"
|
||||
#include "referenceablecreator.hpp"
|
||||
#include "referencecreator.hpp"
|
||||
#include "startscriptcreator.hpp"
|
||||
#include "scenesubview.hpp"
|
||||
#include "dialoguecreator.hpp"
|
||||
#include "infocreator.hpp"
|
||||
|
@ -53,6 +54,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
|||
manager.add (sTableTypes[i],
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<GenericCreator> >);
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_StartScripts,
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<StartScriptCreator> >);
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Cells,
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<CellCreator> >);
|
||||
|
||||
|
@ -125,7 +129,6 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
|||
CSMWorld::UniversalId::Type_BodyPart,
|
||||
CSMWorld::UniversalId::Type_SoundGen,
|
||||
CSMWorld::UniversalId::Type_Pathgrid,
|
||||
CSMWorld::UniversalId::Type_StartScript,
|
||||
|
||||
CSMWorld::UniversalId::Type_None // end marker
|
||||
};
|
||||
|
@ -135,6 +138,10 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
|||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView,
|
||||
CreatorFactory<GenericCreator> > (false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_StartScript,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView,
|
||||
CreatorFactory<StartScriptCreator> > (false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Skill,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, NullCreatorFactory > (false));
|
||||
|
||||
|
|
|
@ -7,21 +7,21 @@ int argcData;
|
|||
extern "C" void releaseArgv();
|
||||
|
||||
void releaseArgv() {
|
||||
delete[] argvData;
|
||||
delete[] argvData;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_ui_activity_GameActivity_commandLine(JNIEnv *env,
|
||||
jobject obj, jint argc, jobjectArray stringArray) {
|
||||
jboolean iscopy;
|
||||
argcData = (int) argc;
|
||||
argvData = new const char *[argcData + 1];
|
||||
argvData[0] = "openmw";
|
||||
for (int i = 1; i < argcData + 1; i++) {
|
||||
jstring string = (jstring) (env)->GetObjectArrayElement(stringArray,
|
||||
i - 1);
|
||||
argvData[i] = (env)->GetStringUTFChars(string, &iscopy);
|
||||
(env)->DeleteLocalRef(string);
|
||||
}
|
||||
(env)->DeleteLocalRef(stringArray);
|
||||
jobject obj, jint argc, jobjectArray stringArray) {
|
||||
jboolean iscopy;
|
||||
argcData = (int) argc;
|
||||
argvData = new const char *[argcData + 1];
|
||||
argvData[0] = "openmw";
|
||||
for (int i = 1; i < argcData + 1; i++) {
|
||||
jstring string = (jstring) (env)->GetObjectArrayElement(stringArray,
|
||||
i - 1);
|
||||
argvData[i] = (env)->GetStringUTFChars(string, &iscopy);
|
||||
(env)->DeleteLocalRef(string);
|
||||
}
|
||||
(env)->DeleteLocalRef(stringArray);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,22 +16,22 @@ extern const char **argvData;
|
|||
void releaseArgv();
|
||||
|
||||
int Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls,
|
||||
jobject obj) {
|
||||
jobject obj) {
|
||||
|
||||
SDL_Android_Init(env, cls);
|
||||
SDL_Android_Init(env, cls);
|
||||
|
||||
SDL_SetMainReady();
|
||||
SDL_SetMainReady();
|
||||
|
||||
/* Run the application code! */
|
||||
/* Run the application code! */
|
||||
|
||||
int status;
|
||||
int status;
|
||||
|
||||
status = main(argcData+1, argvData);
|
||||
releaseArgv();
|
||||
/* Do not issue an exit or the whole application will terminate instead of just the SDL thread */
|
||||
/* exit(status); */
|
||||
status = main(argcData+1, argvData);
|
||||
releaseArgv();
|
||||
/* Do not issue an exit or the whole application will terminate instead of just the SDL thread */
|
||||
/* exit(status); */
|
||||
|
||||
return status;
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* __ANDROID__ */
|
||||
|
|
|
@ -37,8 +37,8 @@ static const char pipe_err[] = "!!! Failed to create pipe\n";
|
|||
static const char fork_err[] = "!!! Failed to fork debug process\n";
|
||||
static const char exec_err[] = "!!! Failed to exec debug process\n";
|
||||
|
||||
#ifndef PATH_MAX /* Not all platforms (GNU Hurd) have this. */
|
||||
# define PATH_MAX 256
|
||||
#ifndef PATH_MAX /* Not all platforms (GNU Hurd) have this. */
|
||||
# define PATH_MAX 256
|
||||
#endif
|
||||
|
||||
static char argv0[PATH_MAX];
|
||||
|
|
|
@ -807,27 +807,25 @@ namespace MWClass
|
|||
|
||||
const ESM::CreatureState& state2 = dynamic_cast<const ESM::CreatureState&> (state);
|
||||
|
||||
ensureCustomData(ptr);
|
||||
|
||||
// If we do the following instead we get a sizable speedup, but this causes compatibility issues
|
||||
// with 0.30 savegames, where some state in CreatureStats was not saved yet,
|
||||
// and therefore needs to be loaded from ESM records. TODO: re-enable this in a future release.
|
||||
/*
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
if (state.mVersion > 0)
|
||||
{
|
||||
// Create a CustomData, but don't fill it from ESM records (not needed)
|
||||
std::auto_ptr<CreatureCustomData> data (new CreatureCustomData);
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
{
|
||||
// Create a CustomData, but don't fill it from ESM records (not needed)
|
||||
std::auto_ptr<CreatureCustomData> data (new CreatureCustomData);
|
||||
|
||||
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
|
||||
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
|
||||
|
||||
if (ref->mBase->mFlags & ESM::Creature::Weapon)
|
||||
data->mContainerStore = new MWWorld::InventoryStore();
|
||||
else
|
||||
data->mContainerStore = new MWWorld::ContainerStore();
|
||||
if (ref->mBase->mFlags & ESM::Creature::Weapon)
|
||||
data->mContainerStore = new MWWorld::InventoryStore();
|
||||
else
|
||||
data->mContainerStore = new MWWorld::ContainerStore();
|
||||
|
||||
ptr.getRefData().setCustomData (data.release());
|
||||
ptr.getRefData().setCustomData (data.release());
|
||||
}
|
||||
}
|
||||
*/
|
||||
else
|
||||
ensureCustomData(ptr); // in openmw 0.30 savegames not all state was saved yet, so need to load it regardless.
|
||||
|
||||
CreatureCustomData& customData = dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData());
|
||||
|
||||
|
|
|
@ -1103,18 +1103,17 @@ namespace MWClass
|
|||
|
||||
const ESM::NpcState& state2 = dynamic_cast<const ESM::NpcState&> (state);
|
||||
|
||||
ensureCustomData(ptr);
|
||||
// If we do the following instead we get a sizable speedup, but this causes compatibility issues
|
||||
// with 0.30 savegames, where some state in CreatureStats was not saved yet,
|
||||
// and therefore needs to be loaded from ESM records. TODO: re-enable this in a future release.
|
||||
/*
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
if (state.mVersion > 0)
|
||||
{
|
||||
// Create a CustomData, but don't fill it from ESM records (not needed)
|
||||
std::auto_ptr<NpcCustomData> data (new NpcCustomData);
|
||||
ptr.getRefData().setCustomData (data.release());
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
{
|
||||
// Create a CustomData, but don't fill it from ESM records (not needed)
|
||||
std::auto_ptr<NpcCustomData> data (new NpcCustomData);
|
||||
ptr.getRefData().setCustomData (data.release());
|
||||
}
|
||||
}
|
||||
*/
|
||||
else
|
||||
ensureCustomData(ptr); // in openmw 0.30 savegames not all state was saved yet, so need to load it regardless.
|
||||
|
||||
NpcCustomData& customData = dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData());
|
||||
|
||||
|
|
|
@ -18,9 +18,9 @@ namespace
|
|||
float accumulated_time=0,parent_time = pit->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : pit->Get_Current_Parent_Total_Time();
|
||||
int i,j;
|
||||
int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset();
|
||||
for (i=0;i<spacing;i++) os << ".";
|
||||
for (i=0;i<spacing;i++) os << ".";
|
||||
os << "----------------------------------\n";
|
||||
for (i=0;i<spacing;i++) os << ".";
|
||||
for (i=0;i<spacing;i++) os << ".";
|
||||
std::string s = "Profiling: "+
|
||||
std::string(pit->Get_Current_Parent_Name())+" (total running time: "+MyGUI::utility::toString(parent_time,3)+" ms) ---\n";
|
||||
os << s;
|
||||
|
@ -35,7 +35,7 @@ namespace
|
|||
accumulated_time += current_total_time;
|
||||
float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
|
||||
|
||||
for (j=0;j<spacing;j++) os << ".";
|
||||
for (j=0;j<spacing;j++) os << ".";
|
||||
double ms = (current_total_time / (double)frames_since_reset);
|
||||
s = MyGUI::utility::toString(i)+" -- "+pit->Get_Current_Name()+" ("+MyGUI::utility::toString(fraction,2)+" %) :: "+MyGUI::utility::toString(ms,3)+" ms / frame ("+MyGUI::utility::toString(pit->Get_Current_Total_Calls())+" calls)\n";
|
||||
os << s;
|
||||
|
@ -47,7 +47,7 @@ namespace
|
|||
{
|
||||
os << "what's wrong\n";
|
||||
}
|
||||
for (i=0;i<spacing;i++) os << ".";
|
||||
for (i=0;i<spacing;i++) os << ".";
|
||||
double unaccounted= parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f;
|
||||
s = "Unaccounted: ("+MyGUI::utility::toString(unaccounted,3)+" %) :: "+MyGUI::utility::toString(parent_time - accumulated_time,3)+" ms\n";
|
||||
os << s;
|
||||
|
|
|
@ -106,7 +106,7 @@ namespace MWGui
|
|||
|
||||
static std::string sSchoolNames[6];
|
||||
|
||||
int mHorizontalScrollIndex;
|
||||
int mHorizontalScrollIndex;
|
||||
|
||||
|
||||
float mDelay;
|
||||
|
|
|
@ -607,7 +607,7 @@ namespace MWGui
|
|||
controller->eventRepeatClick += newDelegate(this, &MWScrollBar::repeatClick);
|
||||
controller->setEnabled(mEnableRepeat);
|
||||
controller->setRepeat(mRepeatTriggerTime, mRepeatStepTime);
|
||||
MyGUI::ControllerManager::getInstance().addItem(this, controller);
|
||||
MyGUI::ControllerManager::getInstance().addItem(this, controller);
|
||||
}
|
||||
|
||||
void MWScrollBar::onDecreaseButtonReleased(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
|
||||
|
@ -623,7 +623,7 @@ namespace MWGui
|
|||
controller->eventRepeatClick += newDelegate(this, &MWScrollBar::repeatClick);
|
||||
controller->setEnabled(mEnableRepeat);
|
||||
controller->setRepeat(mRepeatTriggerTime, mRepeatStepTime);
|
||||
MyGUI::ControllerManager::getInstance().addItem(this, controller);
|
||||
MyGUI::ControllerManager::getInstance().addItem(this, controller);
|
||||
}
|
||||
|
||||
void MWScrollBar::onIncreaseButtonReleased(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
|
||||
|
|
|
@ -159,9 +159,9 @@ namespace MWInput
|
|||
mControlSwitch["playerviewswitch"] = true;
|
||||
mControlSwitch["vanitymode"] = true;
|
||||
|
||||
/* Joystick Init */
|
||||
/* Joystick Init */
|
||||
|
||||
//Load controller mappings
|
||||
// Load controller mappings
|
||||
#if SDL_VERSION_ATLEAST(2,0,2)
|
||||
if(controllerBindingsFile!="")
|
||||
{
|
||||
|
@ -169,10 +169,10 @@ namespace MWInput
|
|||
}
|
||||
#endif
|
||||
|
||||
//Open all presently connected sticks
|
||||
int numSticks = SDL_NumJoysticks();
|
||||
for(int i = 0; i < numSticks; i++)
|
||||
{
|
||||
// Open all presently connected sticks
|
||||
int numSticks = SDL_NumJoysticks();
|
||||
for(int i = 0; i < numSticks; i++)
|
||||
{
|
||||
if(SDL_IsGameController(i))
|
||||
{
|
||||
SDL_ControllerDeviceEvent evt;
|
||||
|
@ -183,7 +183,7 @@ namespace MWInput
|
|||
{
|
||||
//ICS_LOG(std::string("Unusable controller plugged in: ")+SDL_JoystickNameForIndex(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputManager::clear()
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace
|
|||
Ogre::Vector3 dir = to - from;
|
||||
dir.z = 0;
|
||||
dir.normalise();
|
||||
float verticalOffset = 200; // instead of '200' here we want the height of the actor
|
||||
float verticalOffset = 200; // instead of '200' here we want the height of the actor
|
||||
Ogre::Vector3 _from = from + dir*offsetXY + Ogre::Vector3::UNIT_Z * verticalOffset;
|
||||
|
||||
// cast up-down ray and find height in world space of hit
|
||||
|
|
|
@ -83,6 +83,9 @@ namespace MWRender
|
|||
land->loadData(mask);
|
||||
}
|
||||
|
||||
const ESM::Land::LandData *landData =
|
||||
land ? land->getLandData (ESM::Land::DATA_WNAM) : 0;
|
||||
|
||||
for (int cellY=0; cellY<mCellSize; ++cellY)
|
||||
{
|
||||
for (int cellX=0; cellX<mCellSize; ++cellX)
|
||||
|
@ -90,15 +93,14 @@ namespace MWRender
|
|||
int vertexX = static_cast<int>(float(cellX)/float(mCellSize) * 9);
|
||||
int vertexY = static_cast<int>(float(cellY) / float(mCellSize) * 9);
|
||||
|
||||
|
||||
int texelX = (x-mMinX) * mCellSize + cellX;
|
||||
int texelY = (mHeight-1) - ((y-mMinY) * mCellSize + cellY);
|
||||
|
||||
unsigned char r,g,b;
|
||||
|
||||
float y = 0;
|
||||
if (land && land->mDataTypes & ESM::Land::DATA_WNAM)
|
||||
y = (land->mLandData->mWnam[vertexY * 9 + vertexX] << 4) / 2048.f;
|
||||
if (landData)
|
||||
y = (landData->mWnam[vertexY * 9 + vertexX] << 4) / 2048.f;
|
||||
else
|
||||
y = (SCHAR_MIN << 4) / 2048.f;
|
||||
if (y < 0)
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace MWRender
|
|||
maxY += 1;
|
||||
}
|
||||
|
||||
ESM::Land* TerrainStorage::getLand(int cellX, int cellY)
|
||||
const ESM::Land* TerrainStorage::getLand(int cellX, int cellY)
|
||||
{
|
||||
const MWWorld::ESMStore &esmStore =
|
||||
MWBase::Environment::get().getWorld()->getStore();
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace MWRender
|
|||
class TerrainStorage : public ESMTerrain::Storage
|
||||
{
|
||||
private:
|
||||
virtual ESM::Land* getLand (int cellX, int cellY);
|
||||
virtual const ESM::Land* getLand (int cellX, int cellY);
|
||||
virtual const ESM::LandTexture* getLandTexture(int index, short plugin);
|
||||
public:
|
||||
|
||||
|
|
|
@ -28,9 +28,6 @@ void MWState::Character::addSlot (const boost::filesystem::path& path, const std
|
|||
ESM::ESMReader reader;
|
||||
reader.open (slot.mPath.string());
|
||||
|
||||
if (reader.getFormat()>ESM::Header::CurrentFormat)
|
||||
return; // format is too new -> ignore
|
||||
|
||||
if (reader.getRecName()!=ESM::REC_SAVE)
|
||||
return; // invalid save file -> ignore
|
||||
|
||||
|
|
|
@ -201,7 +201,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
|||
++iter)
|
||||
writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0
|
||||
|
||||
writer.setFormat (ESM::Header::CurrentFormat);
|
||||
writer.setFormat (ESM::SavedGame::sCurrentFormat);
|
||||
|
||||
// all unused
|
||||
writer.setVersion(0);
|
||||
|
@ -310,8 +310,6 @@ void MWState::StateManager::loadGame(const std::string& filepath)
|
|||
// have to peek into the save file to get the player name
|
||||
ESM::ESMReader reader;
|
||||
reader.open (filepath);
|
||||
if (reader.getFormat()>ESM::Header::CurrentFormat)
|
||||
return; // format is too new -> ignore
|
||||
if (reader.getRecName()!=ESM::REC_SAVE)
|
||||
return; // invalid save file -> ignore
|
||||
reader.getRecHeader();
|
||||
|
@ -333,6 +331,9 @@ void MWState::StateManager::loadGame (const Character *character, const std::str
|
|||
ESM::ESMReader reader;
|
||||
reader.open (filepath);
|
||||
|
||||
if (reader.getFormat() > ESM::SavedGame::sCurrentFormat)
|
||||
throw std::runtime_error("This save file was created using a newer version of OpenMW and is thus not supported. Please upgrade to the newest OpenMW version to load this file.");
|
||||
|
||||
std::map<int, int> contentFileMap = buildContentFileIndexMap (reader);
|
||||
|
||||
Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
||||
|
|
|
@ -660,7 +660,7 @@ namespace MWWorld
|
|||
return MovementSolver::traceDown(ptr, mEngine, maxHeight);
|
||||
}
|
||||
|
||||
void PhysicsSystem::addHeightField (float* heights,
|
||||
void PhysicsSystem::addHeightField (const float* heights,
|
||||
int x, int y, float yoffset,
|
||||
float triSize, float sqrtVerts)
|
||||
{
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace MWWorld
|
|||
|
||||
void addActor (const MWWorld::Ptr& ptr, const std::string& mesh);
|
||||
|
||||
void addHeightField (float* heights,
|
||||
void addHeightField (const float* heights,
|
||||
int x, int y, float yoffset,
|
||||
float triSize, float sqrtVerts);
|
||||
|
||||
|
|
|
@ -236,16 +236,10 @@ namespace MWWorld
|
|||
// Actually only VHGT is needed here, but we'll need the rest for rendering anyway.
|
||||
// Load everything now to reduce IO overhead.
|
||||
const int flags = ESM::Land::DATA_VCLR|ESM::Land::DATA_VHGT|ESM::Land::DATA_VNML|ESM::Land::DATA_VTEX;
|
||||
if (!land->isDataLoaded(flags))
|
||||
land->loadData(flags);
|
||||
mPhysics->addHeightField (
|
||||
land->mLandData->mHeights,
|
||||
cell->getCell()->getGridX(),
|
||||
cell->getCell()->getGridY(),
|
||||
0,
|
||||
worldsize / (verts-1),
|
||||
verts)
|
||||
;
|
||||
|
||||
const ESM::Land::LandData *data = land->getLandData (flags);
|
||||
mPhysics->addHeightField (data->mHeights, cell->getCell()->getGridX(), cell->getCell()->getGridY(),
|
||||
0, worldsize / (verts-1), verts);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -287,7 +287,7 @@ namespace MWWorld
|
|||
|
||||
if (mPlayer)
|
||||
{
|
||||
mPlayer->clear();
|
||||
mPlayer->clear();
|
||||
mPlayer->setCell(0);
|
||||
mPlayer->getPlayer().getRefData() = RefData();
|
||||
mPlayer->set(mStore.get<ESM::NPC>().find ("player"));
|
||||
|
|
|
@ -182,11 +182,12 @@ IF (MYGUI_FOUND)
|
|||
IF (NOT MYGUI_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "MyGUI version: ${MYGUI_VERSION}")
|
||||
ENDIF (NOT MYGUI_FIND_QUIETLY)
|
||||
|
||||
ELSE (MYGUI_FOUND)
|
||||
IF (MYGUI_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find MYGUI")
|
||||
ENDIF (MYGUI_FIND_REQUIRED)
|
||||
ENDIF (MYGUI_FOUND)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MyGUI DEFAULT_MSG
|
||||
MYGUI_INCLUDE_DIRS
|
||||
FREETYPE_LIBRARIES
|
||||
MYGUI_LIBRARIES)
|
||||
|
||||
CMAKE_POLICY(POP)
|
||||
|
|
|
@ -652,6 +652,13 @@ namespace Compiler
|
|||
return true;
|
||||
}
|
||||
|
||||
if (code ==Scanner::S_plus && mNextOperand)
|
||||
{
|
||||
// Also unary, but +, just ignore it
|
||||
mTokenLoc = loc;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (code==Scanner::S_open)
|
||||
{
|
||||
if (mNextOperand)
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace Compiler
|
|||
|
||||
namespace Gui
|
||||
{
|
||||
void registerExtensions (Extensions& extensions);
|
||||
void registerExtensions (Extensions& extensions);
|
||||
}
|
||||
|
||||
namespace Misc
|
||||
|
|
|
@ -65,7 +65,6 @@ namespace Compiler
|
|||
if (mState==BeginState && keyword==Scanner::K_begin)
|
||||
{
|
||||
mState = NameState;
|
||||
scanner.allowNameStartingwithDigit();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -112,7 +111,6 @@ namespace Compiler
|
|||
scanner.scan (mScriptParser);
|
||||
|
||||
mState = EndNameState;
|
||||
scanner.allowNameStartingwithDigit();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -555,7 +555,7 @@ namespace Compiler
|
|||
}
|
||||
|
||||
if (mAllowExpression && mState==BeginState &&
|
||||
(code==Scanner::S_open || code==Scanner::S_minus))
|
||||
(code==Scanner::S_open || code==Scanner::S_minus || code==Scanner::S_plus))
|
||||
{
|
||||
scanner.putbackSpecial (code, loc);
|
||||
parseExpression (scanner, loc);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue