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

actorid
scrawl 12 years ago
commit e4717d7c92

@ -23,8 +23,7 @@ struct ESMData
std::string author;
std::string description;
int version;
int type;
ESM::ESMReader::MasterList masters;
std::vector<ESM::Header::MasterData> masters;
std::deque<EsmTool::RecordBase *> mRecords;
std::map<ESM::Cell *, std::deque<ESM::CellRef> > mCellRefs;
@ -284,16 +283,13 @@ int load(Arguments& info)
info.data.author = esm.getAuthor();
info.data.description = esm.getDesc();
info.data.masters = esm.getMasters();
info.data.version = esm.getVer();
info.data.type = esm.getType();
if (!quiet)
{
std::cout << "Author: " << esm.getAuthor() << std::endl
<< "Description: " << esm.getDesc() << std::endl
<< "File format version: " << esm.getFVer() << std::endl
<< "Special flag: " << esm.getSpecial() << std::endl;
ESM::ESMReader::MasterList m = esm.getMasters();
<< "File format version: " << esm.getFVer() << std::endl;
std::vector<ESM::Header::MasterData> m = esm.getMasters();
if (!m.empty())
{
std::cout << "Masters:" << std::endl;
@ -430,9 +426,9 @@ int clone(Arguments& info)
esm.setAuthor(info.data.author);
esm.setDescription(info.data.description);
esm.setVersion(info.data.version);
esm.setType(info.data.type);
esm.setRecordCount (recordCount);
for (ESM::ESMReader::MasterList::iterator it = info.data.masters.begin(); it != info.data.masters.end(); ++it)
for (std::vector<ESM::Header::MasterData>::iterator it = info.data.masters.begin(); it != info.data.masters.end(); ++it)
esm.addMaster(it->name, it->size);
std::fstream save(info.outname.c_str(), std::fstream::out | std::fstream::binary);

@ -1,4 +1,3 @@
set (OPENCS_SRC main.cpp)
opencs_units (. editor)

@ -113,5 +113,7 @@ int CS::Editor::run()
{
mStartup.show();
QApplication::setQuitOnLastWindowClosed (true);
return QApplication::exec();
}

@ -2,7 +2,7 @@
#include "document.hpp"
#include <cassert>
#include <QDebug>
void CSMDoc::Document::load (const std::vector<boost::filesystem::path>::const_iterator& begin,
const std::vector<boost::filesystem::path>::const_iterator& end, bool lastAsModified)
{
@ -237,6 +237,9 @@ CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, b
connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving()));
}
CSMDoc::Document::~Document()
{}
QUndoStack& CSMDoc::Document::getUndoStack()
{
return mUndoStack;
@ -290,11 +293,13 @@ void CSMDoc::Document::abortOperation (int type)
}
}
void CSMDoc::Document::modificationStateChanged (bool clean)
{
emit stateChanged (getState(), this);
}
void CSMDoc::Document::operationDone (int type)
{
emit stateChanged (getState(), this);
@ -308,9 +313,12 @@ void CSMDoc::Document::saving()
if (mSaveCount>15)
{
//clear the stack before resetting the save state
//to avoid emitting incorrect states
mUndoStack.setClean();
mSaveCount = 0;
mSaveTimer.stop();
mUndoStack.setClean();
emit stateChanged (getState(), this);
}
}

@ -63,6 +63,7 @@ namespace CSMDoc
public:
Document (const std::vector<boost::filesystem::path>& files, bool new_);
~Document();
QUndoStack& getUndoStack();
@ -105,4 +106,4 @@ namespace CSMDoc
};
}
#endif
#endif

@ -56,7 +56,7 @@ void CSVDoc::Operations::quitOperation (int type)
mLayout->removeItem ((*iter)->getLayout());
delete *iter;
(*iter)->deleteLater();
mOperations.erase (iter);
if (oldCount > 1)

@ -7,6 +7,7 @@
#include <QMenuBar>
#include <QMdiArea>
#include <QDockWidget>
#include <QtGui/QApplication>
#include "../../model/doc/document.hpp"
@ -39,6 +40,16 @@ void CSVDoc::View::setupFileMenu()
mSave = new QAction (tr ("&Save"), this);
connect (mSave, SIGNAL (triggered()), this, SLOT (save()));
file->addAction (mSave);
QAction *close = new QAction (tr ("&Close"), this);
connect (close, SIGNAL (triggered()), this, SLOT (close()));
file->addAction(close);
QAction *exit = new QAction (tr ("&Exit"), this);
connect (exit, SIGNAL (triggered()), this, SLOT (exit()));
connect (this, SIGNAL(exitApplicationRequest(CSVDoc::View *)), &mViewManager, SLOT(exitApplication(CSVDoc::View *)));
file->addAction(exit);
}
void CSVDoc::View::setupEditMenu()
@ -117,15 +128,15 @@ void CSVDoc::View::updateActions()
mVerify->setEnabled (!(mDocument->getState() & CSMDoc::State_Verifying));
}
CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews, QMainWindow *viewParent)
: mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), mViewTotal (totalViews), QMainWindow (viewParent)
CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews)
: mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1),
mViewTotal (totalViews)
{
setDockOptions (QMainWindow::AllowNestedDocks);
resize (300, 300); /// \todo get default size from settings and set reasonable minimal size
mSubViewWindow = new QMainWindow();
setCentralWidget (mSubViewWindow);
mSubViewWindow.setDockOptions (QMainWindow::AllowNestedDocks);
setCentralWidget (&mSubViewWindow);
mOperations = new Operations;
addDockWidget (Qt::BottomDockWidgetArea, mOperations);
@ -200,7 +211,7 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id)
/// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis)
SubView *view = mSubViewFactory.makeSubView (id, *mDocument);
mSubViewWindow->addDockWidget (Qt::TopDockWidgetArea, view);
mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view);
connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&)), this,
SLOT (addSubView (const CSMWorld::UniversalId&)));
@ -239,7 +250,12 @@ void CSVDoc::View::abortOperation (int type)
updateActions();
}
QDockWidget *CSVDoc::View::getOperations() const
CSVDoc::Operations *CSVDoc::View::getOperations() const
{
return mOperations;
}
void CSVDoc::View::exit()
{
emit exitApplicationRequest (this);
}

@ -41,7 +41,8 @@ namespace CSVDoc
std::vector<QAction *> mEditingActions;
Operations *mOperations;
SubViewFactoryManager mSubViewFactory;
QMainWindow* mSubViewWindow;
QMainWindow mSubViewWindow;
// not implemented
View (const View&);
@ -65,9 +66,12 @@ namespace CSVDoc
void updateActions();
void exitApplication();
public:
View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews, QMainWindow *viewParent);
View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews);
///< The ownership of \a document is not transferred to *this.
virtual ~View();
@ -82,7 +86,7 @@ namespace CSVDoc
void updateProgress (int current, int max, int type, int threads);
QDockWidget *getOperations() const;
Operations *getOperations() const;
signals:
@ -90,23 +94,28 @@ namespace CSVDoc
void loadDocumentRequest();
void exitApplicationRequest (CSVDoc::View *view);
public slots:
void addSubView (const CSMWorld::UniversalId& id);
void abortOperation (int type);
private slots:
void newView();
void save();
void exit();
void verify();
void addGlobalsSubView();
void addGmstsSubView();
void abortOperation (int type);
};
}

@ -12,6 +12,11 @@
#include "view.hpp"
#include <QMessageBox>
#include <QPushButton>
#include <QtGui/QApplication>
#include <QDebug>
void CSVDoc::ViewManager::updateIndices()
{
std::map<CSMDoc::Document *, std::pair<int, int> > documents;
@ -31,7 +36,7 @@ void CSVDoc::ViewManager::updateIndices()
}
CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
: mDocumentManager (documentManager)
: mDocumentManager (documentManager), mExitOnSaveStateChange(false), mUserWarned(false)
{
mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection;
@ -40,7 +45,6 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType,
new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float));
}
CSVDoc::ViewManager::~ViewManager()
@ -63,9 +67,8 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document)
this, SLOT (progress (int, int, int, int, CSMDoc::Document *)));
}
QMainWindow *mainWindow = new QMainWindow;
View *view = new View (*this, document, countViews (document)+1);
View *view = new View (*this, document, countViews (document)+1, mainWindow);
mViews.push_back (view);
@ -94,23 +97,143 @@ bool CSVDoc::ViewManager::closeRequest (View *view)
{
std::vector<View *>::iterator iter = std::find (mViews.begin(), mViews.end(), view);
bool continueWithClose = true;
if (iter!=mViews.end())
{
bool last = countViews (view->getDocument())<=1;
/// \todo check if save is in progress -> warn user about possible data loss
/// \todo check if document has not been saved -> return false and start close dialogue
mViews.erase (iter);
view->deleteLater();
if (last)
mDocumentManager.removeDocument (view->getDocument());
continueWithClose = notifySaveOnClose (view);
else
{
(*iter)->deleteLater();
mViews.erase (iter);
updateIndices();
}
}
return true;
return continueWithClose;
}
bool CSVDoc::ViewManager::notifySaveOnClose (CSVDoc::View *view)
{
bool result = true;
CSMDoc::Document *document = view->getDocument();
//notify user of saving in progress
if ( (document->getState() & CSMDoc::State_Saving) )
result = showSaveInProgressMessageBox (view);
//notify user of unsaved changes and process response
else if ( document->getState() & CSMDoc::State_Modified)
result = showModifiedDocumentMessageBox (view);
return result;
}
bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (CSVDoc::View *view)
{
QMessageBox messageBox;
CSMDoc::Document *document = view->getDocument();
messageBox.setText ("The document has been modified.");
messageBox.setInformativeText ("Do you want to save your changes?");
messageBox.setStandardButtons (QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
messageBox.setDefaultButton (QMessageBox::Save);
bool retVal = true;
connect (this, SIGNAL (closeMessageBox()), &messageBox, SLOT (close()));
connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
mUserWarned = true;
int response = messageBox.exec();
mUserWarned = false;
switch (response)
{
case QMessageBox::Save:
document->save();
mExitOnSaveStateChange = true;
retVal = false;
break;
case QMessageBox::Discard:
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
break;
case QMessageBox::Cancel:
//disconnect to prevent unintended view closures
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
retVal = false;
break;
default:
break;
}
return retVal;
}
bool CSVDoc::ViewManager::showSaveInProgressMessageBox (CSVDoc::View *view)
{
QMessageBox messageBox;
CSMDoc::Document *document = view->getDocument();
messageBox.setText ("The document is currently being saved.");
messageBox.setInformativeText("Do you want to close now and abort saving, or wait until saving has completed?");
QPushButton* waitButton = messageBox.addButton (tr("Wait"), QMessageBox::YesRole);
QPushButton* closeButton = messageBox.addButton (tr("Close Now"), QMessageBox::RejectRole);
QPushButton* cancelButton = messageBox.addButton (tr("Cancel"), QMessageBox::NoRole);
messageBox.setDefaultButton (waitButton);
bool retVal = true;
//Connections shut down message box if operation ends before user makes a decision.
connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
connect (this, SIGNAL (closeMessageBox()), &messageBox, SLOT (close()));
//set / clear the user warned flag to indicate whether or not the message box is currently active.
mUserWarned = true;
messageBox.exec();
mUserWarned = false;
//if closed by the warning handler, defaults to the RejectRole button (closeButton)
if (messageBox.clickedButton() == waitButton)
{
//save the View iterator for shutdown after the save operation ends
mExitOnSaveStateChange = true;
retVal = false;
}
else if (messageBox.clickedButton() == closeButton)
{
//disconnect to avoid segmentation fault
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
view->abortOperation(CSMDoc::State_Saving);
mExitOnSaveStateChange = true;
}
else if (messageBox.clickedButton() == cancelButton)
{
//abort shutdown, allow save to complete
//disconnection to prevent unintended view closures
mExitOnSaveStateChange = false;
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
retVal = false;
}
return retVal;
}
void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *document)
@ -126,3 +249,25 @@ void CSVDoc::ViewManager::progress (int current, int max, int type, int threads,
if ((*iter)->getDocument()==document)
(*iter)->updateProgress (current, max, type, threads);
}
void CSVDoc::ViewManager::onExitWarningHandler (int state, CSMDoc::Document *document)
{
if ( !(state & CSMDoc::State_Saving) )
{
//if the user is being warned (message box is active), shut down the message box,
//as there is no save operation currently running
if ( mUserWarned )
emit closeMessageBox();
//otherwise, the user has closed the message box before the save operation ended.
//exit the application
else if (mExitOnSaveStateChange)
QApplication::instance()->exit();
}
}
void CSVDoc::ViewManager::exitApplication (CSVDoc::View *view)
{
if (notifySaveOnClose (view))
QApplication::instance()->exit();
}

@ -27,12 +27,17 @@ namespace CSVDoc
CSMDoc::DocumentManager& mDocumentManager;
std::vector<View *> mViews;
CSVWorld::CommandDelegateFactoryCollection *mDelegateFactories;
bool mExitOnSaveStateChange;
bool mUserWarned;
// not implemented
ViewManager (const ViewManager&);
ViewManager& operator= (const ViewManager&);
void updateIndices();
bool notifySaveOnClose (View *view = 0);
bool showModifiedDocumentMessageBox (View *view);
bool showSaveInProgressMessageBox (View *view);
public:
@ -54,13 +59,21 @@ namespace CSVDoc
void loadDocumentRequest();
void closeMessageBox();
public slots:
void exitApplication (CSVDoc::View *view);
private slots:
void documentStateChanged (int state, CSMDoc::Document *document);
void progress (int current, int max, int type, int threads, CSMDoc::Document *document);
void onExitWarningHandler(int state, CSMDoc::Document* document);
};
}
#endif
#endif

@ -27,14 +27,15 @@ void ESMStore::load(ESM::ESMReader &esm)
ESM::Dialogue *dialogue = 0;
/// \todo Move this to somewhere else. ESMReader?
// Cache parent esX files by tracking their indices in the global list of
// all files/readers used by the engine. This will greaty accelerate
// refnumber mangling, as required for handling moved references.
int index = ~0;
const ESM::ESMReader::MasterList &masters = esm.getMasters();
const std::vector<ESM::Header::MasterData> &masters = esm.getMasters();
std::vector<ESM::ESMReader> *allPlugins = esm.getGlobalReaderList();
for (size_t j = 0; j < masters.size(); j++) {
ESM::MasterData &mast = const_cast<ESM::MasterData&>(masters[j]);
ESM::Header::MasterData &mast = const_cast<ESM::Header::MasterData&>(masters[j]);
std::string fname = mast.name;
for (int i = 0; i < esm.getIndex(); i++) {
const std::string &candidate = allPlugins->at(i).getContext().filename;

@ -39,7 +39,7 @@ add_component_dir (esm
loadclas loadclot loadcont loadcrea loadcrec loaddial loaddoor loadench loadfact loadglob loadgmst
loadinfo loadingr loadland loadlevlist loadligh loadlocks loadltex loadmgef loadmisc loadnpcc
loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat
loadweap records aipackage effectlist spelllist variant variantimp
loadweap records aipackage effectlist spelllist variant variantimp loadtes3
)
add_component_dir (misc

@ -2,6 +2,7 @@
#define OPENMW_ESM_COMMON_H
#include <string>
#include <cstring>
#include <libs/platform/stdint.h>
#include <libs/platform/string.h>
@ -14,24 +15,6 @@ enum Version
VER_13 = 0x3fa66666
};
enum FileType
{
FT_ESP = 0, // Plugin
FT_ESM = 1, // Master
FT_ESS = 32 // Savegame
};
// Used to mark special files. The original ESM files are given
// special treatment in a few places, most noticably in loading and
// filtering out "dirtly" GMST entries correctly.
enum SpecialFile
{
SF_Other,
SF_Morrowind,
SF_Tribunal,
SF_Bloodmoon
};
/* A structure used for holding fixed-length strings. In the case of
LEN=4, it can be more efficient to match the string as a 32 bit
number, therefore the struct is implemented as a union with an int.
@ -41,7 +24,7 @@ union NAME_T
{
char name[LEN];
int32_t val;
bool operator==(const char *str) const
{
for(int i=0; i<LEN; i++)
@ -61,6 +44,8 @@ union NAME_T
bool operator!=(int v) const { return v != val; }
std::string toString() const { return std::string(name, strnlen(name, LEN)); }
void assign (const std::string& value) { std::strncpy (name, value.c_str(), LEN); }
};
typedef NAME_T<4> NAME;
@ -70,28 +55,6 @@ typedef NAME_T<256> NAME256;
#pragma pack(push)
#pragma pack(1)
/// File header data for all ES files
struct HEDRstruct
{
/* File format version. This is actually a float, the supported
versions are 1.2 and 1.3. These correspond to:
1.2 = 0x3f99999a and 1.3 = 0x3fa66666
*/
int version;
int type; // 0=esp, 1=esm, 32=ess
NAME32 author; // Author's name
NAME256 desc; // File description
int records; // Number of records? Not used.
};
// Defines another files (esm or esp) that this file depends upon.
struct MasterData
{
std::string name;
uint64_t size;
int index; // Position of the parent file in the global list of loaded files
};
// Data that is only present in save game files
struct SaveData
{
@ -113,7 +76,6 @@ struct ESM_Context
uint32_t leftRec, leftSub;
size_t leftFile;
NAME recName, subName;
HEDRstruct header;
// When working with multiple esX files, we will generate lists of all files that
// actually contribute to a specific cell. Therefore, we need to store the index
// of the file belonging to this contest. See CellStore::(list/load)refs for details.

@ -15,11 +15,16 @@ ESM_Context ESMReader::getContext()
return mCtx;
}
ESMReader::ESMReader(void):
ESMReader::ESMReader():
mBuffer(50*1024)
{
}
int ESMReader::getFormat() const
{
return mHeader.mFormat;
}
void ESMReader::restoreContext(const ESM_Context &rc)
{
// Reopen the file if necessary
@ -51,18 +56,6 @@ void ESMReader::openRaw(Ogre::DataStreamPtr _esm, const std::string &name)
mEsm = _esm;
mCtx.filename = name;
mCtx.leftFile = mEsm->size();
// Flag certain files for special treatment, based on the file
// name.
const char *cstr = mCtx.filename.c_str();
if (iends(cstr, "Morrowind.esm"))
mSpf = SF_Morrowind;
else if (iends(cstr, "Tribunal.esm"))
mSpf = SF_Tribunal;
else if (iends(cstr, "Bloodmoon.esm"))
mSpf = SF_Bloodmoon;
else
mSpf = SF_Other;
}
void ESMReader::open(Ogre::DataStreamPtr _esm, const std::string &name)
@ -74,42 +67,7 @@ void ESMReader::open(Ogre::DataStreamPtr _esm, const std::string &name)
getRecHeader();
// Get the header
getHNT(mCtx.header, "HEDR", 300);
// Some mods abuse the header.version field for the version of the mod instead of the version of the file format, so we can only ignore it.
while (isNextSub("MAST"))
{
MasterData m;
m.name = getHString();
m.size = getHNLong("DATA");
mMasters.push_back(m);
}
if (mCtx.header.type == FT_ESS)
{
// Savegame-related data
// Player position etc
getHNT(mSaveData, "GMDT", 124);
/* Image properties, five ints. Is always:
Red-mask: 0xff0000
Blue-mask: 0x00ff00
Green-mask: 0x0000ff
Alpha-mask: 0x000000
Bpp: 32
*/
getSubNameIs("SCRD");
skipHSubSize(20);
/* Savegame screenshot:
128x128 pixels * 4 bytes per pixel
*/
getSubNameIs("SCRS");
skipHSubSize(65536);
}
mHeader.load (*this);
}
void ESMReader::open(const std::string &file)

@ -12,7 +12,9 @@
#include <components/misc/stringops.hpp>
#include <components/to_utf8/to_utf8.hpp>
#include "esmcommon.hpp"
#include "loadtes3.hpp"
namespace ESM {
@ -20,15 +22,7 @@ class ESMReader
{
public:
ESMReader(void);
/*************************************************************************
*
* Public type definitions
*
*************************************************************************/
typedef std::vector<MasterData> MasterList;
ESMReader();
/*************************************************************************
*
@ -36,14 +30,12 @@ public:
*
*************************************************************************/
int getVer() const { return mCtx.header.version; }
float getFVer() const { if(mCtx.header.version == VER_12) return 1.2; else return 1.3; }
int getSpecial() const { return mSpf; }
int getType() const { return mCtx.header.type; }
const std::string getAuthor() const { return mCtx.header.author.toString(); }
const std::string getDesc() const { return mCtx.header.desc.toString(); }
const SaveData &getSaveData() const { return mSaveData; }
const MasterList &getMasters() const { return mMasters; }
int getVer() const { return mHeader.mData.version; }
float getFVer() const { if(mHeader.mData.version == VER_12) return 1.2; else return 1.3; }
const std::string getAuthor() const { return mHeader.mData.author.toString(); }
const std::string getDesc() const { return mHeader.mData.desc.toString(); }
const std::vector<Header::MasterData> &getMasters() const { return mHeader.mMaster; }
int getFormat() const;
const NAME &retSubName() const { return mCtx.subName; }
uint32_t getSubSize() const { return mCtx.leftSub; }
@ -263,13 +255,12 @@ private:
ESM_Context mCtx;
// Special file signifier (see SpecialFile enum above)
int mSpf;
// Buffer for ESM strings
std::vector<char> mBuffer;
SaveData mSaveData;
MasterList mMasters;
Header mHeader;
std::vector<ESMReader> *mGlobalReaderList;
ToUTF8::Utf8Encoder* mEncoder;
};

@ -1,6 +1,8 @@
#include "esmwriter.hpp"
#include <cassert>
#include <fstream>
#include <cstring>
#include <iostream>
bool count = true;
@ -9,40 +11,40 @@ namespace ESM
int ESMWriter::getVersion()
{
return m_header.version;
return mHeader.mData.version;
}
void ESMWriter::setVersion(int ver)
{
m_header.version = ver;
mHeader.mData.version = ver;
}
int ESMWriter::getType()
void ESMWriter::setAuthor(const std::string& auth)
{
return m_header.type;
mHeader.mData.author.assign (auth);
}
void ESMWriter::setType(int type)
void ESMWriter::setDescription(const std::string& desc)
{
m_header.type = type;
mHeader.mData.desc.assign (desc);
}
void ESMWriter::setAuthor(const std::string& auth)
void ESMWriter::setRecordCount (int count)
{
strncpy((char*)&m_header.author, auth.c_str(), 32);
mHeader.mData.records = count;
}
void ESMWriter::setDescription(const std::string& desc)
void ESMWriter::setFormat (int format)
{
strncpy((char*)&m_header.desc, desc.c_str(), 256);
mHeader.mFormat = format;
}
void ESMWriter::addMaster(const std::string& name, uint64_t size)
{
MasterData d;
Header::MasterData d;
d.name = name;
d.size = size;
m_masters.push_back(d);
mHeader.mMaster.push_back(d);
}
void ESMWriter::save(const std::string& file)
@ -58,25 +60,13 @@ void ESMWriter::save(std::ostream& file)
startRecord("TES3", 0);
m_header.records = 0;
writeHNT("HEDR", m_header, 300);
m_headerPos = m_stream->tellp() - (std::streampos)4;
for (std::list<MasterData>::iterator it = m_masters.begin(); it != m_masters.end(); ++it)
{
writeHNCString("MAST", it->name);
writeHNT("DATA", it->size);
}
mHeader.save (*this);
endRecord("TES3");
}
void ESMWriter::close()
{
std::cout << "Writing amount of saved records (" << m_recordCount - 1 << ")" << std::endl;
m_stream->seekp(m_headerPos);
writeT<int>(m_recordCount-1);
m_stream->seekp(0, std::ios::end);
m_stream->flush();
if (!m_records.empty())
@ -86,7 +76,7 @@ void ESMWriter::close()
void ESMWriter::startRecord(const std::string& name, uint32_t flags)
{
m_recordCount++;
writeName(name);
RecordData rec;
rec.name = name;
@ -109,7 +99,7 @@ void ESMWriter::startSubRecord(const std::string& name)
rec.size = 0;
writeT<int>(0); // Size goes here
m_records.push_back(rec);
assert(m_records.back().size == 0);
}
@ -118,7 +108,7 @@ void ESMWriter::endRecord(const std::string& name)
RecordData rec = m_records.back();
assert(rec.name == name);
m_records.pop_back();
m_stream->seekp(rec.position);
count = false;

@ -1,13 +1,14 @@
#ifndef OPENMW_ESM_WRITER_H
#define OPENMW_ESM_WRITER_H
#include <iostream>
#include <iosfwd>
#include <list>
#include <assert.h>
#include "esmcommon.hpp"
#include <components/to_utf8/to_utf8.hpp>
#include "esmcommon.hpp"
#include "loadtes3.hpp"
namespace ESM {
class ESMWriter
@ -22,11 +23,11 @@ class ESMWriter
public:
int getVersion();
void setVersion(int ver);
int getType();
void setType(int type);
void setEncoder(ToUTF8::Utf8Encoder *encoding); // Write strings as UTF-8?
void setAuthor(const std::string& author);
void setDescription(const std::string& desc);
void setRecordCount (int count);
void setFormat (int format);
void addMaster(const std::string& name, uint64_t size);
@ -80,7 +81,7 @@ public:
{
write((char*)&data, size);
}
void startRecord(const std::string& name, uint32_t flags);
void startSubRecord(const std::string& name);
void endRecord(const std::string& name);
@ -90,14 +91,13 @@ public:
void write(const char* data, size_t size);
private:
std::list<MasterData> m_masters;
std::list<RecordData> m_records;
std::ostream* m_stream;
std::streampos m_headerPos;
ToUTF8::Utf8Encoder* m_encoder;
int m_recordCount;
HEDRstruct m_header;
Header mHeader;
};
}

@ -245,7 +245,7 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
// If the most significant 8 bits are used, then this reference already exists.
// In this case, do not spawn a new reference, but overwrite the old one.
ref.mRefnum &= 0x00ffffff; // delete old plugin ID
const ESM::ESMReader::MasterList &masters = esm.getMasters();
const std::vector<Header::MasterData> &masters = esm.getMasters();
global = masters[local-1].index + 1;
ref.mRefnum |= global << 24; // insert global plugin ID
}
@ -348,7 +348,7 @@ bool Cell::getNextMVRF(ESMReader &esm, MovedCellRef &mref)
int local = (mref.mRefnum & 0xff000000) >> 24;
size_t global = esm.getIndex() + 1;
mref.mRefnum &= 0x00ffffff; // delete old plugin ID
const ESM::ESMReader::MasterList &masters = esm.getMasters();
const std::vector<Header::MasterData> &masters = esm.getMasters();
global = masters[local-1].index + 1;
mref.mRefnum |= global << 24; // insert global plugin ID

@ -0,0 +1,53 @@
#include "loadtes3.hpp"
#include "esmcommon.hpp"
#include "esmreader.hpp"
#include "esmwriter.hpp"
void ESM::Header::blank()
{
mData.version = ESM::VER_13;
mData.type = 0;
mData.author.assign ("");
mData.desc.assign ("");
mData.records = 0;
mFormat = CurrentFormat;
}
void ESM::Header::load (ESMReader &esm)
{
esm.getHNT (mData, "HEDR", 300);
if (esm.isNextSub ("FORM"))
{
esm.getHT (mFormat);
if (mFormat<0)
esm.fail ("invalid format code");
}
else
mFormat = 0;
while (esm.isNextSub ("MAST"))
{
MasterData m;
m.name = esm.getHString();
m.size = esm.getHNLong ("DATA");
mMaster.push_back (m);
}
}
void ESM::Header::save (ESMWriter &esm)
{
esm.writeHNT ("HEDR", mData, 300);
if (mFormat>0)
esm.writeHNT ("FORM", mFormat);
for (std::vector<Header::MasterData>::iterator iter = mMaster.begin();
iter != mMaster.end(); ++iter)
{
esm.writeHNCString ("MAST", iter->name);
esm.writeHNT ("DATA", iter->size);
}
}

@ -0,0 +1,55 @@
#ifndef COMPONENT_ESM_TES3_H
#define COMPONENT_ESM_TES3_H
#include <vector>
#include "esmcommon.hpp"
namespace ESM
{
class ESMReader;
class ESMWriter;
#pragma pack(push)
#pragma pack(1)
/// \brief File header record
struct Header
{
static const int CurrentFormat = 0; // most recent known format
struct Data
{
/* File format version. This is actually a float, the supported
versions are 1.2 and 1.3. These correspond to:
1.2 = 0x3f99999a and 1.3 = 0x3fa66666
*/
int version;
int type; // 0=esp, 1=esm, 32=ess (unused)
NAME32 author; // Author's name
NAME256 desc; // File description
int records; // Number of records? Not used.
};
// Defines another files (esm or esp) that this file depends upon.
struct MasterData
{
std::string name;
uint64_t size;
int index; // Position of the parent file in the global list of loaded files
};
Data mData;
int mFormat;
std::vector<MasterData> mMaster;
void blank();
void load (ESMReader &esm);
void save (ESMWriter &esm);
};
#pragma pack(pop)
}
#endif

@ -1,6 +1,6 @@
#include <QDebug>
#include <QFileInfo>
#include <QDir>
#include <QDebug>
#include <stdexcept>
@ -157,7 +157,7 @@ Qt::ItemFlags DataFilesModel::flags(const QModelIndex &index) const
if (!file)
return Qt::NoItemFlags;
if (canBeChecked(file)) {
if (canBeChecked(file)) {
if (index.column() == 0) {
return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
} else {
@ -226,7 +226,7 @@ bool lessThanEsmFile(const EsmFile *e1, const EsmFile *e2)
return true;
if (!e1->fileName().endsWith(".esm") && e2->fileName().endsWith(".esm"))
return false;
return e1->fileName().toLower() < e2->fileName().toLower();
}
@ -281,7 +281,7 @@ void DataFilesModel::addFiles(const QString &path)
fileReader.setEncoder(&encoder);
fileReader.open(dir.absoluteFilePath(path).toStdString());
ESM::ESMReader::MasterList mlist = fileReader.getMasters();
std::vector<ESM::Header::MasterData> mlist = fileReader.getMasters();
QStringList masters;
for (unsigned int i = 0; i < mlist.size(); ++i) {
@ -369,10 +369,10 @@ QStringList DataFilesModel::checkedItems()
QStringList DataFilesModel::checkedItemsPaths()
{
QStringList list;
QList<EsmFile *>::ConstIterator it;
QList<EsmFile *>::ConstIterator itEnd = mFiles.constEnd();
int i = 0;
for (it = mFiles.constBegin(); it != itEnd; ++it) {
EsmFile *file = item(i);
@ -381,7 +381,7 @@ QStringList DataFilesModel::checkedItemsPaths()
if (mCheckStates[file->fileName()] == Qt::Checked && canBeChecked(file))
list << file->path();
}
return list;
}

Loading…
Cancel
Save