mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-27 05:10:26 +00:00
merge from saving
Merge branch 'saving' of https://github.com/zinnschlag/openmw into esxSelector Conflicts: apps/launcher/datafilespage.cpp apps/opencs/editor.cpp apps/opencs/view/doc/filedialog.cpp apps/opencs/view/doc/filedialog.hpp
This commit is contained in:
commit
9ce4a04a2d
176 changed files with 2335 additions and 726 deletions
|
@ -320,6 +320,9 @@ configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
|
||||||
configure_file(${OpenMW_SOURCE_DIR}/files/opencs.cfg
|
configure_file(${OpenMW_SOURCE_DIR}/files/opencs.cfg
|
||||||
"${OpenMW_BINARY_DIR}/opencs.cfg")
|
"${OpenMW_BINARY_DIR}/opencs.cfg")
|
||||||
|
|
||||||
|
configure_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters
|
||||||
|
"${OpenMW_BINARY_DIR}/resources/defaultfilters" COPYONLY)
|
||||||
|
|
||||||
if (NOT WIN32 AND NOT APPLE)
|
if (NOT WIN32 AND NOT APPLE)
|
||||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
|
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
|
||||||
"${OpenMW_BINARY_DIR}/openmw.desktop")
|
"${OpenMW_BINARY_DIR}/openmw.desktop")
|
||||||
|
|
|
@ -161,8 +161,42 @@ void Launcher::DataFilesPage::slotProfileDeleted (const QString &item)
|
||||||
|
|
||||||
void Launcher::DataFilesPage::slotProfileChangedByUser(const QString &previous, const QString ¤t)
|
void Launcher::DataFilesPage::slotProfileChangedByUser(const QString &previous, const QString ¤t)
|
||||||
{
|
{
|
||||||
|
<<<<<<< HEAD
|
||||||
setProfile(previous, current, true);
|
setProfile(previous, current, true);
|
||||||
emit signalProfileChanged (ui.profilesComboBox->findText(current));
|
emit signalProfileChanged (ui.profilesComboBox->findText(current));
|
||||||
|
=======
|
||||||
|
if (mContentModel->rowCount() < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString profile = mLauncherSettings.value(QString("Profiles/currentprofile"));
|
||||||
|
|
||||||
|
if (profile.isEmpty()) {
|
||||||
|
profile = profilesComboBox->currentText();
|
||||||
|
mLauncherSettings.setValue(QString("Profiles/currentprofile"), profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
mLauncherSettings.remove(QString("Profiles/") + profile + QString("/master"));
|
||||||
|
mLauncherSettings.remove(QString("Profiles/") + profile + QString("/plugin"));
|
||||||
|
|
||||||
|
mGameSettings.remove(QString("master"));
|
||||||
|
mGameSettings.remove(QString("plugins"));
|
||||||
|
mGameSettings.remove(QString("content"));
|
||||||
|
|
||||||
|
ContentSelectorModel::ContentFileList items = mContentModel->checkedItems();
|
||||||
|
|
||||||
|
foreach(const ContentSelectorModel::EsmFile *item, items) {
|
||||||
|
|
||||||
|
if (item->gameFiles().size() == 0) {
|
||||||
|
mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/master"), item->fileName());
|
||||||
|
mGameSettings.setMultiValue(QString("content"), item->fileName());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
mLauncherSettings.setMultiValue(QString("Profiles/") + profile + QString("/plugin"), item->fileName());
|
||||||
|
mGameSettings.setMultiValue(QString("content"), item->fileName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
>>>>>>> 3146af34d642a28b15b55f7eb9999d8ac50168a0
|
||||||
}
|
}
|
||||||
|
|
||||||
void Launcher::DataFilesPage::slotProfileRenamed(const QString &previous, const QString ¤t)
|
void Launcher::DataFilesPage::slotProfileRenamed(const QString &previous, const QString ¤t)
|
||||||
|
|
|
@ -163,12 +163,12 @@ bool Launcher::GameSettings::writeFile(QTextStream &stream)
|
||||||
|
|
||||||
QStringList masters = mSettings.values(QString("master"));
|
QStringList masters = mSettings.values(QString("master"));
|
||||||
for (int i = masters.count(); i--;) {
|
for (int i = masters.count(); i--;) {
|
||||||
stream << "master=" << masters.at(i) << "\n";
|
stream << "content=" << masters.at(i) << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList plugins = mSettings.values(QString("plugin"));
|
QStringList plugins = mSettings.values(QString("plugin"));
|
||||||
for (int i = plugins.count(); i--;) {
|
for (int i = plugins.count(); i--;) {
|
||||||
stream << "plugin=" << plugins.at(i) << "\n";
|
stream << "content=" << plugins.at(i) << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -813,8 +813,7 @@ void MwIniImporter::importArchives(multistrmap &cfg, const multistrmap &ini) con
|
||||||
}
|
}
|
||||||
|
|
||||||
void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini) const {
|
void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini) const {
|
||||||
std::vector<std::string> esmFiles;
|
std::vector<std::string> contentFiles;
|
||||||
std::vector<std::string> espFiles;
|
|
||||||
std::string baseGameFile("Game Files:GameFile");
|
std::string baseGameFile("Game Files:GameFile");
|
||||||
std::string gameFile("");
|
std::string gameFile("");
|
||||||
|
|
||||||
|
@ -832,29 +831,19 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini) co
|
||||||
std::string filetype(entry->substr(entry->length()-3));
|
std::string filetype(entry->substr(entry->length()-3));
|
||||||
Misc::StringUtils::toLower(filetype);
|
Misc::StringUtils::toLower(filetype);
|
||||||
|
|
||||||
if(filetype.compare("esm") == 0) {
|
if(filetype.compare("esm") == 0 || filetype.compare("esp") == 0) {
|
||||||
esmFiles.push_back(*entry);
|
contentFiles.push_back(*entry);
|
||||||
}
|
|
||||||
else if(filetype.compare("esp") == 0) {
|
|
||||||
espFiles.push_back(*entry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gameFile = "";
|
gameFile = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.erase("master");
|
cfg.erase("content");
|
||||||
cfg.insert( std::make_pair<std::string, std::vector<std::string> > ("master", std::vector<std::string>() ) );
|
cfg.insert( std::make_pair("content", std::vector<std::string>() ) );
|
||||||
|
|
||||||
for(std::vector<std::string>::const_iterator it=esmFiles.begin(); it!=esmFiles.end(); ++it) {
|
for(std::vector<std::string>::const_iterator it=contentFiles.begin(); it!=contentFiles.end(); ++it) {
|
||||||
cfg["master"].push_back(*it);
|
cfg["content"].push_back(*it);
|
||||||
}
|
|
||||||
|
|
||||||
cfg.erase("plugin");
|
|
||||||
cfg.insert( std::make_pair<std::string, std::vector<std::string> > ("plugin", std::vector<std::string>() ) );
|
|
||||||
|
|
||||||
for(std::vector<std::string>::const_iterator it=espFiles.begin(); it!=espFiles.end(); ++it) {
|
|
||||||
cfg["plugin"].push_back(*it);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,11 @@ opencs_units (. editor)
|
||||||
set (CMAKE_BUILD_TYPE DEBUG)
|
set (CMAKE_BUILD_TYPE DEBUG)
|
||||||
|
|
||||||
opencs_units (model/doc
|
opencs_units (model/doc
|
||||||
document
|
document operation saving
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units_noqt (model/doc
|
opencs_units_noqt (model/doc
|
||||||
documentmanager
|
documentmanager stage savingstate savingstages
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_hdrs_noqt (model/doc
|
opencs_hdrs_noqt (model/doc
|
||||||
|
@ -33,11 +33,11 @@ opencs_hdrs_noqt (model/world
|
||||||
|
|
||||||
|
|
||||||
opencs_units (model/tools
|
opencs_units (model/tools
|
||||||
tools operation reportmodel
|
tools reportmodel
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units_noqt (model/tools
|
opencs_units_noqt (model/tools
|
||||||
stage verifier mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
|
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
|
||||||
birthsigncheck spellcheck
|
birthsigncheck spellcheck
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ opencs_units (view/world
|
||||||
opencs_units_noqt (view/world
|
opencs_units_noqt (view/world
|
||||||
dialoguesubview subviews
|
dialoguesubview subviews
|
||||||
enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
|
enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
|
||||||
scripthighlighter idvalidator
|
scripthighlighter idvalidator dialoguecreator
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,18 @@
|
||||||
|
|
||||||
#include "model/doc/document.hpp"
|
#include "model/doc/document.hpp"
|
||||||
#include "model/world/data.hpp"
|
#include "model/world/data.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
CS::Editor::Editor() : mViewManager (mDocumentManager)
|
CS::Editor::Editor()
|
||||||
|
: mDocumentManager (mCfgMgr), mViewManager (mDocumentManager)
|
||||||
{
|
{
|
||||||
mIpcServerName = "org.openmw.OpenCS";
|
mIpcServerName = "org.openmw.OpenCS";
|
||||||
|
|
||||||
setupDataFiles();
|
setupDataFiles();
|
||||||
|
|
||||||
mNewGame.setLocalData (mLocal);
|
mNewGame.setLocalData (mLocal);
|
||||||
|
mFileDialog.setLocalData (mLocal);
|
||||||
|
|
||||||
connect (&mViewManager, SIGNAL (newGameRequest ()), this, SLOT (createGame ()));
|
connect (&mViewManager, SIGNAL (newGameRequest ()), this, SLOT (createGame ()));
|
||||||
connect (&mViewManager, SIGNAL (newAddonRequest ()), this, SLOT (createAddon ()));
|
connect (&mViewManager, SIGNAL (newAddonRequest ()), this, SLOT (createAddon ()));
|
||||||
|
@ -29,7 +32,8 @@ CS::Editor::Editor() : mViewManager (mDocumentManager)
|
||||||
connect (&mStartup, SIGNAL (editConfig()), this, SLOT (showSettings ()));
|
connect (&mStartup, SIGNAL (editConfig()), this, SLOT (showSettings ()));
|
||||||
|
|
||||||
connect (&mFileDialog, SIGNAL(openFiles()), this, SLOT(openFiles()));
|
connect (&mFileDialog, SIGNAL(openFiles()), this, SLOT(openFiles()));
|
||||||
connect (&mFileDialog, SIGNAL(createNewFile()), this, SLOT(createNewFile()));
|
connect (&mFileDialog, SIGNAL(createNewFile (const boost::filesystem::path&)),
|
||||||
|
this, SLOT(createNewFile (const boost::filesystem::path&)));
|
||||||
|
|
||||||
connect (&mNewGame, SIGNAL (createRequest (const boost::filesystem::path&)),
|
connect (&mNewGame, SIGNAL (createRequest (const boost::filesystem::path&)),
|
||||||
this, SLOT (createNewGame (const boost::filesystem::path&)));
|
this, SLOT (createNewGame (const boost::filesystem::path&)));
|
||||||
|
@ -38,13 +42,14 @@ CS::Editor::Editor() : mViewManager (mDocumentManager)
|
||||||
void CS::Editor::setupDataFiles()
|
void CS::Editor::setupDataFiles()
|
||||||
{
|
{
|
||||||
boost::program_options::variables_map variables;
|
boost::program_options::variables_map variables;
|
||||||
boost::program_options::options_description desc;
|
boost::program_options::options_description desc("Syntax: opencs <options>\nAllowed options");
|
||||||
|
|
||||||
desc.add_options()
|
desc.add_options()
|
||||||
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken())
|
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken())
|
||||||
("data-local", boost::program_options::value<std::string>()->default_value(""))
|
("data-local", boost::program_options::value<std::string>()->default_value(""))
|
||||||
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
|
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
|
||||||
("encoding", boost::program_options::value<std::string>()->default_value("win1252"));
|
("encoding", boost::program_options::value<std::string>()->default_value("win1252"))
|
||||||
|
("resources", boost::program_options::value<std::string>()->default_value("resources"));
|
||||||
|
|
||||||
boost::program_options::notify(variables);
|
boost::program_options::notify(variables);
|
||||||
|
|
||||||
|
@ -84,6 +89,8 @@ void CS::Editor::setupDataFiles()
|
||||||
|
|
||||||
dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end());
|
dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end());
|
||||||
|
|
||||||
|
mDocumentManager.setResourceDir (variables["resources"].as<std::string>());
|
||||||
|
|
||||||
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
|
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
|
||||||
{
|
{
|
||||||
QString path = QString::fromStdString(iter->string());
|
QString path = QString::fromStdString(iter->string());
|
||||||
|
@ -134,7 +141,7 @@ void CS::Editor::openFiles()
|
||||||
mFileDialog.hide();
|
mFileDialog.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CS::Editor::createNewFile()
|
void CS::Editor::createNewFile (const boost::filesystem::path& savePath)
|
||||||
{
|
{
|
||||||
std::vector<boost::filesystem::path> files;
|
std::vector<boost::filesystem::path> files;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace CS
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
Files::ConfigurationManager mCfgMgr;
|
||||||
CSMSettings::UserSettings mUserSettings;
|
CSMSettings::UserSettings mUserSettings;
|
||||||
CSMDoc::DocumentManager mDocumentManager;
|
CSMDoc::DocumentManager mDocumentManager;
|
||||||
CSVDoc::ViewManager mViewManager;
|
CSVDoc::ViewManager mViewManager;
|
||||||
|
@ -34,7 +35,6 @@ namespace CS
|
||||||
CSVSettings::UserSettingsDialog mSettings;
|
CSVSettings::UserSettingsDialog mSettings;
|
||||||
CSVDoc::FileDialog mFileDialog;
|
CSVDoc::FileDialog mFileDialog;
|
||||||
|
|
||||||
Files::ConfigurationManager mCfgMgr;
|
|
||||||
boost::filesystem::path mLocal;
|
boost::filesystem::path mLocal;
|
||||||
|
|
||||||
void setupDataFiles();
|
void setupDataFiles();
|
||||||
|
@ -60,7 +60,7 @@ namespace CS
|
||||||
|
|
||||||
void loadDocument();
|
void loadDocument();
|
||||||
void openFiles();
|
void openFiles();
|
||||||
void createNewFile();
|
void createNewFile (const boost::filesystem::path& savePath);
|
||||||
void createNewGame (const boost::filesystem::path& file);
|
void createNewGame (const boost::filesystem::path& file);
|
||||||
|
|
||||||
void showStartup();
|
void showStartup();
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#ifndef Q_MOC_RUN
|
||||||
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
void CSMDoc::Document::load (const std::vector<boost::filesystem::path>::const_iterator& begin,
|
void CSMDoc::Document::load (const std::vector<boost::filesystem::path>::const_iterator& begin,
|
||||||
const std::vector<boost::filesystem::path>::const_iterator& end, bool lastAsModified)
|
const std::vector<boost::filesystem::path>::const_iterator& end, bool lastAsModified)
|
||||||
{
|
{
|
||||||
|
@ -12,10 +19,10 @@ void CSMDoc::Document::load (const std::vector<boost::filesystem::path>::const_i
|
||||||
--end2;
|
--end2;
|
||||||
|
|
||||||
for (std::vector<boost::filesystem::path>::const_iterator iter (begin); iter!=end2; ++iter)
|
for (std::vector<boost::filesystem::path>::const_iterator iter (begin); iter!=end2; ++iter)
|
||||||
getData().loadFile (*iter, true);
|
getData().loadFile (*iter, true, false);
|
||||||
|
|
||||||
if (lastAsModified)
|
if (lastAsModified)
|
||||||
getData().loadFile (*end2, false);
|
getData().loadFile (*end2, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::addGmsts()
|
void CSMDoc::Document::addGmsts()
|
||||||
|
@ -2058,9 +2065,9 @@ void CSMDoc::Document::addOptionalGlobals()
|
||||||
{
|
{
|
||||||
static const char *sGlobals[] =
|
static const char *sGlobals[] =
|
||||||
{
|
{
|
||||||
"dayspassed",
|
"DaysPassed",
|
||||||
"pcwerewolf",
|
"PCWerewolf",
|
||||||
"pcyear",
|
"PCYear",
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2137,11 +2144,86 @@ void CSMDoc::Document::createBase()
|
||||||
|
|
||||||
getData().getSkills().add (record);
|
getData().getSkills().add (record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *sVoice[] =
|
||||||
|
{
|
||||||
|
"Intruder",
|
||||||
|
"Attack",
|
||||||
|
"Hello",
|
||||||
|
"Thief",
|
||||||
|
"Alarm",
|
||||||
|
"Idle",
|
||||||
|
"Flee",
|
||||||
|
"Hit",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i=0; sVoice[i]; ++i)
|
||||||
|
{
|
||||||
|
ESM::Dialogue record;
|
||||||
|
record.mId = sVoice[i];
|
||||||
|
record.mType = ESM::Dialogue::Voice;
|
||||||
|
record.blank();
|
||||||
|
|
||||||
|
getData().getTopics().add (record);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *sGreetings[] =
|
||||||
|
{
|
||||||
|
"Greeting 0",
|
||||||
|
"Greeting 1",
|
||||||
|
"Greeting 2",
|
||||||
|
"Greeting 3",
|
||||||
|
"Greeting 4",
|
||||||
|
"Greeting 5",
|
||||||
|
"Greeting 6",
|
||||||
|
"Greeting 7",
|
||||||
|
"Greeting 8",
|
||||||
|
"Greeting 9",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i=0; sGreetings[i]; ++i)
|
||||||
|
{
|
||||||
|
ESM::Dialogue record;
|
||||||
|
record.mId = sGreetings[i];
|
||||||
|
record.mType = ESM::Dialogue::Greeting;
|
||||||
|
record.blank();
|
||||||
|
|
||||||
|
getData().getTopics().add (record);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *sPersuasion[] =
|
||||||
|
{
|
||||||
|
"Intimidate Success",
|
||||||
|
"Intimidate Fail",
|
||||||
|
"Service Refusal",
|
||||||
|
"Admire Success",
|
||||||
|
"Taunt Success",
|
||||||
|
"Bribe Success",
|
||||||
|
"Info Refusal",
|
||||||
|
"Admire Fail",
|
||||||
|
"Taunt Fail",
|
||||||
|
"Bribe Fail",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i=0; sPersuasion[i]; ++i)
|
||||||
|
{
|
||||||
|
ESM::Dialogue record;
|
||||||
|
record.mId = sPersuasion[i];
|
||||||
|
record.mType = ESM::Dialogue::Persuasion;
|
||||||
|
record.blank();
|
||||||
|
|
||||||
|
getData().getTopics().add (record);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files,
|
CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, bool new_)
|
||||||
const boost::filesystem::path& savePath, bool new_)
|
: mSavePath (savePath), mContentFiles (files), mTools (mData), mResDir(resDir),
|
||||||
: mSavePath (savePath), mTools (mData)
|
mProjectPath ((configuration.getUserPath() / "projects") /
|
||||||
|
(savePath.filename().string() + ".project")),
|
||||||
|
mSaving (*this, mProjectPath)
|
||||||
{
|
{
|
||||||
if (files.empty())
|
if (files.empty())
|
||||||
throw std::runtime_error ("Empty content file sequence");
|
throw std::runtime_error ("Empty content file sequence");
|
||||||
|
@ -2158,6 +2240,34 @@ CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files,
|
||||||
load (files.begin(), end, !new_);
|
load (files.begin(), end, !new_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (new_)
|
||||||
|
{
|
||||||
|
mData.setDescription ("");
|
||||||
|
mData.setAuthor ("");
|
||||||
|
}
|
||||||
|
/// \todo un-outcomment the else, once loading an existing content file works properly again.
|
||||||
|
// else
|
||||||
|
{
|
||||||
|
if (boost::filesystem::exists (mProjectPath))
|
||||||
|
{
|
||||||
|
getData().loadFile (mProjectPath, false, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
boost::filesystem::path locCustomFiltersPath (configuration.getUserPath());
|
||||||
|
locCustomFiltersPath /= "defaultfilters";
|
||||||
|
if (boost::filesystem::exists(locCustomFiltersPath))
|
||||||
|
{
|
||||||
|
boost::filesystem::copy_file (locCustomFiltersPath, mProjectPath);
|
||||||
|
} else {
|
||||||
|
boost::filesystem::path filters(mResDir);
|
||||||
|
filters /= "defaultfilters";
|
||||||
|
boost::filesystem::copy_file(filters, mProjectPath);
|
||||||
|
}
|
||||||
|
getData().loadFile (mProjectPath, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addOptionalGmsts();
|
addOptionalGmsts();
|
||||||
addOptionalGlobals();
|
addOptionalGlobals();
|
||||||
|
|
||||||
|
@ -2166,9 +2276,10 @@ CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files,
|
||||||
connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
||||||
connect (&mTools, SIGNAL (done (int)), this, SLOT (operationDone (int)));
|
connect (&mTools, SIGNAL (done (int)), this, SLOT (operationDone (int)));
|
||||||
|
|
||||||
// dummy implementation -> remove when proper save is implemented.
|
connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
||||||
mSaveCount = 0;
|
connect (&mSaving, SIGNAL (done (int)), this, SLOT (operationDone (int)));
|
||||||
connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving()));
|
connect (&mSaving, SIGNAL (reportMessage (const QString&, int)),
|
||||||
|
this, SLOT (reportMessage (const QString&, int)));
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMDoc::Document::~Document()
|
CSMDoc::Document::~Document()
|
||||||
|
@ -2187,7 +2298,7 @@ int CSMDoc::Document::getState() const
|
||||||
if (!mUndoStack.isClean())
|
if (!mUndoStack.isClean())
|
||||||
state |= State_Modified;
|
state |= State_Modified;
|
||||||
|
|
||||||
if (mSaveCount)
|
if (mSaving.isRunning())
|
||||||
state |= State_Locked | State_Saving | State_Operation;
|
state |= State_Locked | State_Saving | State_Operation;
|
||||||
|
|
||||||
if (int operations = mTools.getRunningOperations())
|
if (int operations = mTools.getRunningOperations())
|
||||||
|
@ -2201,12 +2312,20 @@ const boost::filesystem::path& CSMDoc::Document::getSavePath() const
|
||||||
return mSavePath;
|
return mSavePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<boost::filesystem::path>& CSMDoc::Document::getContentFiles() const
|
||||||
|
{
|
||||||
|
return mContentFiles;
|
||||||
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::save()
|
void CSMDoc::Document::save()
|
||||||
{
|
{
|
||||||
mSaveCount = 1;
|
if (mSaving.isRunning())
|
||||||
mSaveTimer.start (500);
|
throw std::logic_error (
|
||||||
|
"Failed to initiate save, because a save operation is already running.");
|
||||||
|
|
||||||
|
mSaving.start();
|
||||||
|
|
||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
emit progress (1, 16, State_Saving, 1, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::UniversalId CSMDoc::Document::verify()
|
CSMWorld::UniversalId CSMDoc::Document::verify()
|
||||||
|
@ -2218,46 +2337,28 @@ CSMWorld::UniversalId CSMDoc::Document::verify()
|
||||||
|
|
||||||
void CSMDoc::Document::abortOperation (int type)
|
void CSMDoc::Document::abortOperation (int type)
|
||||||
{
|
{
|
||||||
mTools.abortOperation (type);
|
|
||||||
|
|
||||||
if (type==State_Saving)
|
if (type==State_Saving)
|
||||||
{
|
mSaving.abort();
|
||||||
mSaveCount=0;
|
else
|
||||||
mSaveTimer.stop();
|
mTools.abortOperation (type);
|
||||||
emit stateChanged (getState(), this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CSMDoc::Document::modificationStateChanged (bool clean)
|
void CSMDoc::Document::modificationStateChanged (bool clean)
|
||||||
{
|
{
|
||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMDoc::Document::reportMessage (const QString& message, int type)
|
||||||
|
{
|
||||||
|
/// \todo find a better way to get these messages to the user.
|
||||||
|
std::cout << message.toUtf8().constData() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::operationDone (int type)
|
void CSMDoc::Document::operationDone (int type)
|
||||||
{
|
{
|
||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::saving()
|
|
||||||
{
|
|
||||||
++mSaveCount;
|
|
||||||
|
|
||||||
emit progress (mSaveCount, 16, State_Saving, 1, this);
|
|
||||||
|
|
||||||
if (mSaveCount>15)
|
|
||||||
{
|
|
||||||
//clear the stack before resetting the save state
|
|
||||||
//to avoid emitting incorrect states
|
|
||||||
mUndoStack.setClean();
|
|
||||||
|
|
||||||
mSaveCount = 0;
|
|
||||||
mSaveTimer.stop();
|
|
||||||
emit stateChanged (getState(), this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const CSMWorld::Data& CSMDoc::Document::getData() const
|
const CSMWorld::Data& CSMDoc::Document::getData() const
|
||||||
{
|
{
|
||||||
return mData;
|
return mData;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "../tools/tools.hpp"
|
#include "../tools/tools.hpp"
|
||||||
|
|
||||||
#include "state.hpp"
|
#include "state.hpp"
|
||||||
|
#include "saving.hpp"
|
||||||
|
|
||||||
class QAbstractItemModel;
|
class QAbstractItemModel;
|
||||||
|
|
||||||
|
@ -23,6 +24,11 @@ namespace ESM
|
||||||
struct Global;
|
struct Global;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Files
|
||||||
|
{
|
||||||
|
class ConfigurationManager;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CSMDoc
|
namespace CSMDoc
|
||||||
{
|
{
|
||||||
class Document : public QObject
|
class Document : public QObject
|
||||||
|
@ -32,16 +38,17 @@ namespace CSMDoc
|
||||||
private:
|
private:
|
||||||
|
|
||||||
boost::filesystem::path mSavePath;
|
boost::filesystem::path mSavePath;
|
||||||
|
std::vector<boost::filesystem::path> mContentFiles;
|
||||||
CSMWorld::Data mData;
|
CSMWorld::Data mData;
|
||||||
CSMTools::Tools mTools;
|
CSMTools::Tools mTools;
|
||||||
|
boost::filesystem::path mProjectPath;
|
||||||
|
Saving mSaving;
|
||||||
|
boost::filesystem::path mResDir;
|
||||||
|
|
||||||
// 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
|
// 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
|
||||||
// using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late.
|
// using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late.
|
||||||
QUndoStack mUndoStack;
|
QUndoStack mUndoStack;
|
||||||
|
|
||||||
int mSaveCount; ///< dummy implementation -> remove when proper save is implemented.
|
|
||||||
QTimer mSaveTimer; ///< dummy implementation -> remove when proper save is implemented.
|
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
Document (const Document&);
|
Document (const Document&);
|
||||||
Document& operator= (const Document&);
|
Document& operator= (const Document&);
|
||||||
|
@ -64,8 +71,7 @@ namespace CSMDoc
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Document (const std::vector<boost::filesystem::path>& files,
|
Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, bool new_);
|
||||||
const boost::filesystem::path& savePath, bool new_);
|
|
||||||
|
|
||||||
~Document();
|
~Document();
|
||||||
|
|
||||||
|
@ -75,6 +81,10 @@ namespace CSMDoc
|
||||||
|
|
||||||
const boost::filesystem::path& getSavePath() const;
|
const boost::filesystem::path& getSavePath() const;
|
||||||
|
|
||||||
|
const std::vector<boost::filesystem::path>& getContentFiles() const;
|
||||||
|
///< \attention The last element in this collection is the file that is being edited,
|
||||||
|
/// but with its original path instead of the save path.
|
||||||
|
|
||||||
void save();
|
void save();
|
||||||
|
|
||||||
CSMWorld::UniversalId verify();
|
CSMWorld::UniversalId verify();
|
||||||
|
@ -98,10 +108,9 @@ namespace CSMDoc
|
||||||
|
|
||||||
void modificationStateChanged (bool clean);
|
void modificationStateChanged (bool clean);
|
||||||
|
|
||||||
void operationDone (int type);
|
void reportMessage (const QString& message, int type);
|
||||||
|
|
||||||
void saving();
|
void operationDone (int type);
|
||||||
///< dummy implementation -> remove when proper save is implemented.
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
@ -110,3 +119,4 @@ namespace CSMDoc
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,22 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#ifndef Q_MOC_RUN
|
||||||
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
|
|
||||||
CSMDoc::DocumentManager::DocumentManager() {}
|
CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& configuration)
|
||||||
|
: mConfiguration (configuration)
|
||||||
|
{
|
||||||
|
boost::filesystem::path projectPath = configuration.getUserPath() / "projects";
|
||||||
|
|
||||||
|
if (!boost::filesystem::is_directory (projectPath))
|
||||||
|
boost::filesystem::create_directories (projectPath);
|
||||||
|
}
|
||||||
|
|
||||||
CSMDoc::DocumentManager::~DocumentManager()
|
CSMDoc::DocumentManager::~DocumentManager()
|
||||||
{
|
{
|
||||||
|
@ -17,7 +30,7 @@ CSMDoc::DocumentManager::~DocumentManager()
|
||||||
CSMDoc::Document *CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files, const boost::filesystem::path& savePath,
|
CSMDoc::Document *CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files, const boost::filesystem::path& savePath,
|
||||||
bool new_)
|
bool new_)
|
||||||
{
|
{
|
||||||
Document *document = new Document (files, savePath, new_);
|
Document *document = new Document (mConfiguration, files, savePath, mResDir, new_);
|
||||||
|
|
||||||
mDocuments.push_back (document);
|
mDocuments.push_back (document);
|
||||||
|
|
||||||
|
@ -36,3 +49,8 @@ bool CSMDoc::DocumentManager::removeDocument (Document *document)
|
||||||
|
|
||||||
return mDocuments.empty();
|
return mDocuments.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMDoc::DocumentManager::setResourceDir (const boost::filesystem::path& parResDir)
|
||||||
|
{
|
||||||
|
mResDir = boost::filesystem::system_complete(parResDir);
|
||||||
|
}
|
|
@ -6,6 +6,11 @@
|
||||||
|
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
namespace Files
|
||||||
|
{
|
||||||
|
class ConfigurationManager;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CSMDoc
|
namespace CSMDoc
|
||||||
{
|
{
|
||||||
class Document;
|
class Document;
|
||||||
|
@ -13,18 +18,18 @@ namespace CSMDoc
|
||||||
class DocumentManager
|
class DocumentManager
|
||||||
{
|
{
|
||||||
std::vector<Document *> mDocuments;
|
std::vector<Document *> mDocuments;
|
||||||
|
const Files::ConfigurationManager& mConfiguration;
|
||||||
|
|
||||||
DocumentManager (const DocumentManager&);
|
DocumentManager (const DocumentManager&);
|
||||||
DocumentManager& operator= (const DocumentManager&);
|
DocumentManager& operator= (const DocumentManager&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DocumentManager();
|
DocumentManager (const Files::ConfigurationManager& configuration);
|
||||||
|
|
||||||
~DocumentManager();
|
~DocumentManager();
|
||||||
|
|
||||||
Document *addDocument (const std::vector<boost::filesystem::path>& files,
|
Document *addDocument (const std::vector< boost::filesystem::path >& files, const boost::filesystem::path& savePath, bool new_);
|
||||||
const boost::filesystem::path& savePath, bool new_);
|
|
||||||
///< The ownership of the returned document is not transferred to the caller.
|
///< The ownership of the returned document is not transferred to the caller.
|
||||||
///
|
///
|
||||||
/// \param new_ Do not load the last content file in \a files and instead create in an
|
/// \param new_ Do not load the last content file in \a files and instead create in an
|
||||||
|
@ -32,6 +37,10 @@ namespace CSMDoc
|
||||||
|
|
||||||
bool removeDocument (Document *document);
|
bool removeDocument (Document *document);
|
||||||
///< \return last document removed?
|
///< \return last document removed?
|
||||||
|
void setResourceDir (const boost::filesystem::path& parResDir);
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::filesystem::path mResDir;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,16 +6,16 @@
|
||||||
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include "../doc/state.hpp"
|
#include "state.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "stage.hpp"
|
||||||
|
|
||||||
void CSMTools::Operation::prepareStages()
|
void CSMDoc::Operation::prepareStages()
|
||||||
{
|
{
|
||||||
mCurrentStage = mStages.begin();
|
mCurrentStage = mStages.begin();
|
||||||
mCurrentStep = 0;
|
mCurrentStep = 0;
|
||||||
mCurrentStepTotal = 0;
|
mCurrentStepTotal = 0;
|
||||||
mTotalSteps = 0;
|
mTotalSteps = 0;
|
||||||
|
mError = false;
|
||||||
|
|
||||||
for (std::vector<std::pair<Stage *, int> >::iterator iter (mStages.begin()); iter!=mStages.end(); ++iter)
|
for (std::vector<std::pair<Stage *, int> >::iterator iter (mStages.begin()); iter!=mStages.end(); ++iter)
|
||||||
{
|
{
|
||||||
|
@ -24,38 +24,61 @@ void CSMTools::Operation::prepareStages()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMTools::Operation::Operation (int type) : mType (type) {}
|
CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways)
|
||||||
|
: mType (type), mOrdered (ordered), mFinalAlways (finalAlways)
|
||||||
|
{
|
||||||
|
connect (this, SIGNAL (finished()), this, SLOT (operationDone()));
|
||||||
|
}
|
||||||
|
|
||||||
CSMTools::Operation::~Operation()
|
CSMDoc::Operation::~Operation()
|
||||||
{
|
{
|
||||||
for (std::vector<std::pair<Stage *, int> >::iterator iter (mStages.begin()); iter!=mStages.end(); ++iter)
|
for (std::vector<std::pair<Stage *, int> >::iterator iter (mStages.begin()); iter!=mStages.end(); ++iter)
|
||||||
delete iter->first;
|
delete iter->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::Operation::run()
|
void CSMDoc::Operation::run()
|
||||||
{
|
{
|
||||||
prepareStages();
|
prepareStages();
|
||||||
|
|
||||||
QTimer timer;
|
QTimer timer;
|
||||||
|
|
||||||
timer.connect (&timer, SIGNAL (timeout()), this, SLOT (verify()));
|
timer.connect (&timer, SIGNAL (timeout()), this, SLOT (executeStage()));
|
||||||
|
|
||||||
timer.start (0);
|
timer.start (0);
|
||||||
|
|
||||||
exec();
|
exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::Operation::appendStage (Stage *stage)
|
void CSMDoc::Operation::appendStage (Stage *stage)
|
||||||
{
|
{
|
||||||
mStages.push_back (std::make_pair (stage, 0));
|
mStages.push_back (std::make_pair (stage, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::Operation::abort()
|
bool CSMDoc::Operation::hasError() const
|
||||||
{
|
{
|
||||||
exit();
|
return mError;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::Operation::verify()
|
void CSMDoc::Operation::abort()
|
||||||
|
{
|
||||||
|
if (!isRunning())
|
||||||
|
return;
|
||||||
|
|
||||||
|
mError = true;
|
||||||
|
|
||||||
|
if (mFinalAlways)
|
||||||
|
{
|
||||||
|
if (mStages.begin()!=mStages.end() && mCurrentStage!=--mStages.end())
|
||||||
|
{
|
||||||
|
mCurrentStep = 0;
|
||||||
|
mCurrentStage = --mStages.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mCurrentStage = mStages.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::Operation::executeStage()
|
||||||
{
|
{
|
||||||
std::vector<std::string> messages;
|
std::vector<std::string> messages;
|
||||||
|
|
||||||
|
@ -67,8 +90,17 @@ void CSMTools::Operation::verify()
|
||||||
++mCurrentStage;
|
++mCurrentStage;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
mCurrentStage->first->perform (mCurrentStep++, messages);
|
mCurrentStage->first->perform (mCurrentStep++, messages);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
emit reportMessage (e.what(), mType);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
++mCurrentStepTotal;
|
++mCurrentStepTotal;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -82,3 +114,8 @@ void CSMTools::Operation::verify()
|
||||||
if (mCurrentStage==mStages.end())
|
if (mCurrentStage==mStages.end())
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMDoc::Operation::operationDone()
|
||||||
|
{
|
||||||
|
emit done (mType);
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
#ifndef CSM_TOOLS_OPERATION_H
|
#ifndef CSM_DOC_OPERATION_H
|
||||||
#define CSM_TOOLS_OPERATION_H
|
#define CSM_DOC_OPERATION_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMDoc
|
||||||
{
|
{
|
||||||
class Stage;
|
class Stage;
|
||||||
|
|
||||||
|
@ -19,12 +19,17 @@ namespace CSMTools
|
||||||
int mCurrentStep;
|
int mCurrentStep;
|
||||||
int mCurrentStepTotal;
|
int mCurrentStepTotal;
|
||||||
int mTotalSteps;
|
int mTotalSteps;
|
||||||
|
int mOrdered;
|
||||||
|
bool mFinalAlways;
|
||||||
|
bool mError;
|
||||||
|
|
||||||
void prepareStages();
|
void prepareStages();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Operation (int type);
|
Operation (int type, bool ordered, bool finalAlways = false);
|
||||||
|
///< \param ordered Stages must be executed in the given order.
|
||||||
|
/// \param finalAlways Execute last stage even if an error occurred during earlier stages.
|
||||||
|
|
||||||
virtual ~Operation();
|
virtual ~Operation();
|
||||||
|
|
||||||
|
@ -35,19 +40,25 @@ namespace CSMTools
|
||||||
///
|
///
|
||||||
/// \attention Do no call this function while this Operation is running.
|
/// \attention Do no call this function while this Operation is running.
|
||||||
|
|
||||||
|
bool hasError() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void progress (int current, int max, int type);
|
void progress (int current, int max, int type);
|
||||||
|
|
||||||
void reportMessage (const QString& message, int type);
|
void reportMessage (const QString& message, int type);
|
||||||
|
|
||||||
|
void done (int type);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void abort();
|
void abort();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void verify();
|
void executeStage();
|
||||||
|
|
||||||
|
void operationDone();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
74
apps/opencs/model/doc/saving.cpp
Normal file
74
apps/opencs/model/doc/saving.cpp
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
|
||||||
|
#include "saving.hpp"
|
||||||
|
|
||||||
|
#include "../world/data.hpp"
|
||||||
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
|
#include "state.hpp"
|
||||||
|
#include "savingstages.hpp"
|
||||||
|
#include "document.hpp"
|
||||||
|
|
||||||
|
CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& projectPath)
|
||||||
|
: Operation (State_Saving, true, true), mDocument (document), mState (*this, projectPath)
|
||||||
|
{
|
||||||
|
// save project file
|
||||||
|
appendStage (new OpenSaveStage (mDocument, mState, true));
|
||||||
|
|
||||||
|
appendStage (new WriteHeaderStage (mDocument, mState, true));
|
||||||
|
|
||||||
|
appendStage (new WriteFilterStage (mDocument, mState, CSMFilter::Filter::Scope_Project));
|
||||||
|
|
||||||
|
appendStage (new CloseSaveStage (mState));
|
||||||
|
|
||||||
|
// save content file
|
||||||
|
appendStage (new OpenSaveStage (mDocument, mState, false));
|
||||||
|
|
||||||
|
appendStage (new WriteHeaderStage (mDocument, mState, false));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Global> >
|
||||||
|
(mDocument.getData().getGlobals(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::GameSetting> >
|
||||||
|
(mDocument.getData().getGmsts(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Skill> >
|
||||||
|
(mDocument.getData().getSkills(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Class> >
|
||||||
|
(mDocument.getData().getClasses(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Faction> >
|
||||||
|
(mDocument.getData().getFactions(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Race> >
|
||||||
|
(mDocument.getData().getRaces(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Sound> >
|
||||||
|
(mDocument.getData().getSounds(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Script> >
|
||||||
|
(mDocument.getData().getScripts(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Region> >
|
||||||
|
(mDocument.getData().getRegions(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::BirthSign> >
|
||||||
|
(mDocument.getData().getBirthsigns(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Spell> >
|
||||||
|
(mDocument.getData().getSpells(), mState));
|
||||||
|
|
||||||
|
/// \todo deal with info records for topcis and journals
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Dialogue> >
|
||||||
|
(mDocument.getData().getTopics(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Dialogue> >
|
||||||
|
(mDocument.getData().getJournals(), mState));
|
||||||
|
|
||||||
|
appendStage (new WriteRefIdCollectionStage (mDocument, mState));
|
||||||
|
|
||||||
|
|
||||||
|
appendStage (new CloseSaveStage (mState));
|
||||||
|
|
||||||
|
appendStage (new FinalSavingStage (mDocument, mState));
|
||||||
|
}
|
27
apps/opencs/model/doc/saving.hpp
Normal file
27
apps/opencs/model/doc/saving.hpp
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef CSM_DOC_SAVING_H
|
||||||
|
#define CSM_DOC_SAVING_H
|
||||||
|
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
#include "operation.hpp"
|
||||||
|
#include "savingstate.hpp"
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
class Document;
|
||||||
|
|
||||||
|
class Saving : public Operation
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Document& mDocument;
|
||||||
|
SavingState mState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Saving (Document& document, const boost::filesystem::path& projectPath);
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
161
apps/opencs/model/doc/savingstages.cpp
Normal file
161
apps/opencs/model/doc/savingstages.cpp
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
|
||||||
|
#include "savingstages.hpp"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#include <QUndoStack>
|
||||||
|
|
||||||
|
#include "document.hpp"
|
||||||
|
#include "savingstate.hpp"
|
||||||
|
|
||||||
|
CSMDoc::OpenSaveStage::OpenSaveStage (Document& document, SavingState& state, bool projectFile)
|
||||||
|
: mDocument (document), mState (state), mProjectFile (projectFile)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMDoc::OpenSaveStage::setup()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::OpenSaveStage::perform (int stage, std::vector<std::string>& messages)
|
||||||
|
{
|
||||||
|
mState.start (mDocument, mProjectFile);
|
||||||
|
|
||||||
|
mState.getStream().open ((mProjectFile ? mState.getPath() : mState.getTmpPath()).string().c_str());
|
||||||
|
|
||||||
|
if (!mState.getStream().is_open())
|
||||||
|
throw std::runtime_error ("failed to open stream for saving");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMDoc::WriteHeaderStage::WriteHeaderStage (Document& document, SavingState& state, bool simple)
|
||||||
|
: mDocument (document), mState (state), mSimple (simple)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMDoc::WriteHeaderStage::setup()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::WriteHeaderStage::perform (int stage, std::vector<std::string>& messages)
|
||||||
|
{
|
||||||
|
mState.getWriter().setVersion();
|
||||||
|
|
||||||
|
mState.getWriter().clearMaster();
|
||||||
|
|
||||||
|
mState.getWriter().setFormat (0);
|
||||||
|
|
||||||
|
if (mSimple)
|
||||||
|
{
|
||||||
|
mState.getWriter().setAuthor ("");
|
||||||
|
mState.getWriter().setDescription ("");
|
||||||
|
mState.getWriter().setRecordCount (0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mState.getWriter().setAuthor (mDocument.getData().getAuthor());
|
||||||
|
mState.getWriter().setDescription (mDocument.getData().getDescription());
|
||||||
|
mState.getWriter().setRecordCount (
|
||||||
|
mDocument.getData().count (CSMWorld::RecordBase::State_Modified) +
|
||||||
|
mDocument.getData().count (CSMWorld::RecordBase::State_ModifiedOnly) +
|
||||||
|
mDocument.getData().count (CSMWorld::RecordBase::State_Deleted));
|
||||||
|
|
||||||
|
/// \todo refine dependency list (at least remove redundant dependencies)
|
||||||
|
std::vector<boost::filesystem::path> dependencies = mDocument.getContentFiles();
|
||||||
|
std::vector<boost::filesystem::path>::const_iterator end (--dependencies.end());
|
||||||
|
|
||||||
|
for (std::vector<boost::filesystem::path>::const_iterator iter (dependencies.begin());
|
||||||
|
iter!=end; ++iter)
|
||||||
|
{
|
||||||
|
std::string name = iter->filename().string();
|
||||||
|
uint64_t size = boost::filesystem::file_size (*iter);
|
||||||
|
|
||||||
|
mState.getWriter().addMaster (name, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mState.getWriter().save (mState.getStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMDoc::WriteRefIdCollectionStage::WriteRefIdCollectionStage (Document& document, SavingState& state)
|
||||||
|
: mDocument (document), mState (state)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMDoc::WriteRefIdCollectionStage::setup()
|
||||||
|
{
|
||||||
|
return mDocument.getData().getReferenceables().getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::WriteRefIdCollectionStage::perform (int stage, std::vector<std::string>& messages)
|
||||||
|
{
|
||||||
|
mDocument.getData().getReferenceables().save (stage, mState.getWriter());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMDoc::WriteFilterStage::WriteFilterStage (Document& document, SavingState& state,
|
||||||
|
CSMFilter::Filter::Scope scope)
|
||||||
|
: WriteCollectionStage<CSMWorld::IdCollection<CSMFilter::Filter> > (document.getData().getFilters(),
|
||||||
|
state),
|
||||||
|
mDocument (document), mScope (scope)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void CSMDoc::WriteFilterStage::perform (int stage, std::vector<std::string>& messages)
|
||||||
|
{
|
||||||
|
const CSMWorld::Record<CSMFilter::Filter>& record =
|
||||||
|
mDocument.getData().getFilters().getRecord (stage);
|
||||||
|
|
||||||
|
if (record.get().mScope==mScope)
|
||||||
|
WriteCollectionStage<CSMWorld::IdCollection<CSMFilter::Filter> >::perform (stage, messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMDoc::CloseSaveStage::CloseSaveStage (SavingState& state)
|
||||||
|
: mState (state)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMDoc::CloseSaveStage::setup()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::CloseSaveStage::perform (int stage, std::vector<std::string>& messages)
|
||||||
|
{
|
||||||
|
mState.getStream().close();
|
||||||
|
|
||||||
|
if (!mState.getStream())
|
||||||
|
throw std::runtime_error ("saving failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMDoc::FinalSavingStage::FinalSavingStage (Document& document, SavingState& state)
|
||||||
|
: mDocument (document), mState (state)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMDoc::FinalSavingStage::setup()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::FinalSavingStage::perform (int stage, std::vector<std::string>& messages)
|
||||||
|
{
|
||||||
|
if (mState.hasError())
|
||||||
|
{
|
||||||
|
mState.getWriter().close();
|
||||||
|
mState.getStream().close();
|
||||||
|
|
||||||
|
if (boost::filesystem::exists (mState.getTmpPath()))
|
||||||
|
boost::filesystem::remove (mState.getTmpPath());
|
||||||
|
}
|
||||||
|
else if (!mState.isProjectFile())
|
||||||
|
{
|
||||||
|
if (boost::filesystem::exists (mState.getPath()))
|
||||||
|
boost::filesystem::remove (mState.getPath());
|
||||||
|
|
||||||
|
boost::filesystem::rename (mState.getTmpPath(), mState.getPath());
|
||||||
|
|
||||||
|
mDocument.getUndoStack().setClean();
|
||||||
|
}
|
||||||
|
}
|
172
apps/opencs/model/doc/savingstages.hpp
Normal file
172
apps/opencs/model/doc/savingstages.hpp
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
#ifndef CSM_DOC_SAVINGSTAGES_H
|
||||||
|
#define CSM_DOC_SAVINGSTAGES_H
|
||||||
|
|
||||||
|
#include "stage.hpp"
|
||||||
|
|
||||||
|
#include "savingstate.hpp"
|
||||||
|
|
||||||
|
#include "../world/record.hpp"
|
||||||
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
|
#include "../filter/filter.hpp"
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
class Document;
|
||||||
|
class SavingState;
|
||||||
|
|
||||||
|
class OpenSaveStage : public Stage
|
||||||
|
{
|
||||||
|
Document& mDocument;
|
||||||
|
SavingState& mState;
|
||||||
|
bool mProjectFile;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
OpenSaveStage (Document& document, SavingState& state, bool projectFile);
|
||||||
|
///< \param projectFile Saving the project file instead of the content file.
|
||||||
|
|
||||||
|
virtual int setup();
|
||||||
|
///< \return number of steps
|
||||||
|
|
||||||
|
virtual void perform (int stage, std::vector<std::string>& messages);
|
||||||
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
|
};
|
||||||
|
|
||||||
|
class WriteHeaderStage : public Stage
|
||||||
|
{
|
||||||
|
Document& mDocument;
|
||||||
|
SavingState& mState;
|
||||||
|
bool mSimple;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
WriteHeaderStage (Document& document, SavingState& state, bool simple);
|
||||||
|
///< \param simple Simplified header (used for project files).
|
||||||
|
|
||||||
|
virtual int setup();
|
||||||
|
///< \return number of steps
|
||||||
|
|
||||||
|
virtual void perform (int stage, std::vector<std::string>& messages);
|
||||||
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<class CollectionT>
|
||||||
|
class WriteCollectionStage : public Stage
|
||||||
|
{
|
||||||
|
const CollectionT& mCollection;
|
||||||
|
SavingState& mState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
WriteCollectionStage (const CollectionT& collection, SavingState& state);
|
||||||
|
|
||||||
|
virtual int setup();
|
||||||
|
///< \return number of steps
|
||||||
|
|
||||||
|
virtual void perform (int stage, std::vector<std::string>& messages);
|
||||||
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class CollectionT>
|
||||||
|
WriteCollectionStage<CollectionT>::WriteCollectionStage (const CollectionT& collection,
|
||||||
|
SavingState& state)
|
||||||
|
: mCollection (collection), mState (state)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<class CollectionT>
|
||||||
|
int WriteCollectionStage<CollectionT>::setup()
|
||||||
|
{
|
||||||
|
return mCollection.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class CollectionT>
|
||||||
|
void WriteCollectionStage<CollectionT>::perform (int stage, std::vector<std::string>& messages)
|
||||||
|
{
|
||||||
|
CSMWorld::RecordBase::State state = mCollection.getRecord (stage).mState;
|
||||||
|
|
||||||
|
if (state==CSMWorld::RecordBase::State_Modified ||
|
||||||
|
state==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||||
|
{
|
||||||
|
std::string type;
|
||||||
|
for (int i=0; i<4; ++i)
|
||||||
|
/// \todo make endianess agnostic (change ESMWriter interface?)
|
||||||
|
type += reinterpret_cast<const char *> (&mCollection.getRecord (stage).mModified.sRecordId)[i];
|
||||||
|
|
||||||
|
mState.getWriter().startRecord (type);
|
||||||
|
mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage));
|
||||||
|
mCollection.getRecord (stage).mModified.save (mState.getWriter());
|
||||||
|
mState.getWriter().endRecord (type);
|
||||||
|
}
|
||||||
|
else if (state==CSMWorld::RecordBase::State_Deleted)
|
||||||
|
{
|
||||||
|
/// \todo write record with delete flag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class WriteRefIdCollectionStage : public Stage
|
||||||
|
{
|
||||||
|
Document& mDocument;
|
||||||
|
SavingState& mState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
WriteRefIdCollectionStage (Document& document, SavingState& state);
|
||||||
|
|
||||||
|
virtual int setup();
|
||||||
|
///< \return number of steps
|
||||||
|
|
||||||
|
virtual void perform (int stage, std::vector<std::string>& messages);
|
||||||
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class WriteFilterStage : public WriteCollectionStage<CSMWorld::IdCollection<CSMFilter::Filter> >
|
||||||
|
{
|
||||||
|
Document& mDocument;
|
||||||
|
CSMFilter::Filter::Scope mScope;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
WriteFilterStage (Document& document, SavingState& state, CSMFilter::Filter::Scope scope);
|
||||||
|
|
||||||
|
virtual void perform (int stage, std::vector<std::string>& messages);
|
||||||
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CloseSaveStage : public Stage
|
||||||
|
{
|
||||||
|
SavingState& mState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
CloseSaveStage (SavingState& state);
|
||||||
|
|
||||||
|
virtual int setup();
|
||||||
|
///< \return number of steps
|
||||||
|
|
||||||
|
virtual void perform (int stage, std::vector<std::string>& messages);
|
||||||
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
|
};
|
||||||
|
|
||||||
|
class FinalSavingStage : public Stage
|
||||||
|
{
|
||||||
|
Document& mDocument;
|
||||||
|
SavingState& mState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FinalSavingStage (Document& document, SavingState& state);
|
||||||
|
|
||||||
|
virtual int setup();
|
||||||
|
///< \return number of steps
|
||||||
|
|
||||||
|
virtual void perform (int stage, std::vector<std::string>& messages);
|
||||||
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
65
apps/opencs/model/doc/savingstate.cpp
Normal file
65
apps/opencs/model/doc/savingstate.cpp
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
|
||||||
|
#include "savingstate.hpp"
|
||||||
|
|
||||||
|
#include "operation.hpp"
|
||||||
|
#include "document.hpp"
|
||||||
|
|
||||||
|
CSMDoc::SavingState::SavingState (Operation& operation, const boost::filesystem::path& projectPath)
|
||||||
|
: mOperation (operation),
|
||||||
|
/// \todo set encoding properly, once config implementation has been fixed.
|
||||||
|
mEncoder (ToUTF8::calculateEncoding ("win1252")),
|
||||||
|
mProjectPath (projectPath), mProjectFile (false)
|
||||||
|
{
|
||||||
|
mWriter.setEncoder (&mEncoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMDoc::SavingState::hasError() const
|
||||||
|
{
|
||||||
|
return mOperation.hasError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::SavingState::start (Document& document, bool project)
|
||||||
|
{
|
||||||
|
mProjectFile = project;
|
||||||
|
|
||||||
|
if (mStream.is_open())
|
||||||
|
mStream.close();
|
||||||
|
|
||||||
|
mStream.clear();
|
||||||
|
|
||||||
|
if (project)
|
||||||
|
mPath = mProjectPath;
|
||||||
|
else
|
||||||
|
mPath = document.getSavePath();
|
||||||
|
|
||||||
|
boost::filesystem::path file (mPath.filename().string() + ".tmp");
|
||||||
|
|
||||||
|
mTmpPath = mPath.parent_path();
|
||||||
|
|
||||||
|
mTmpPath /= file;
|
||||||
|
}
|
||||||
|
|
||||||
|
const boost::filesystem::path& CSMDoc::SavingState::getPath() const
|
||||||
|
{
|
||||||
|
return mPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
const boost::filesystem::path& CSMDoc::SavingState::getTmpPath() const
|
||||||
|
{
|
||||||
|
return mTmpPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ofstream& CSMDoc::SavingState::getStream()
|
||||||
|
{
|
||||||
|
return mStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESM::ESMWriter& CSMDoc::SavingState::getWriter()
|
||||||
|
{
|
||||||
|
return mWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMDoc::SavingState::isProjectFile() const
|
||||||
|
{
|
||||||
|
return mProjectFile;
|
||||||
|
}
|
50
apps/opencs/model/doc/savingstate.hpp
Normal file
50
apps/opencs/model/doc/savingstate.hpp
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#ifndef CSM_DOC_SAVINGSTATE_H
|
||||||
|
#define CSM_DOC_SAVINGSTATE_H
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
class Operation;
|
||||||
|
class Document;
|
||||||
|
|
||||||
|
class SavingState
|
||||||
|
{
|
||||||
|
Operation& mOperation;
|
||||||
|
boost::filesystem::path mPath;
|
||||||
|
boost::filesystem::path mTmpPath;
|
||||||
|
ToUTF8::Utf8Encoder mEncoder;
|
||||||
|
std::ofstream mStream;
|
||||||
|
ESM::ESMWriter mWriter;
|
||||||
|
boost::filesystem::path mProjectPath;
|
||||||
|
bool mProjectFile;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
SavingState (Operation& operation, const boost::filesystem::path& projectPath);
|
||||||
|
|
||||||
|
bool hasError() const;
|
||||||
|
|
||||||
|
void start (Document& document, bool project);
|
||||||
|
///< \param project Save project file instead of content file.
|
||||||
|
|
||||||
|
const boost::filesystem::path& getPath() const;
|
||||||
|
|
||||||
|
const boost::filesystem::path& getTmpPath() const;
|
||||||
|
|
||||||
|
std::ofstream& getStream();
|
||||||
|
|
||||||
|
ESM::ESMWriter& getWriter();
|
||||||
|
|
||||||
|
bool isProjectFile() const;
|
||||||
|
///< Currently saving project file? (instead of content file)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
4
apps/opencs/model/doc/stage.cpp
Normal file
4
apps/opencs/model/doc/stage.cpp
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
#include "stage.hpp"
|
||||||
|
|
||||||
|
CSMDoc::Stage::~Stage() {}
|
|
@ -1,10 +1,10 @@
|
||||||
#ifndef CSM_TOOLS_STAGE_H
|
#ifndef CSM_DOC_STAGE_H
|
||||||
#define CSM_TOOLS_STAGE_H
|
#define CSM_DOC_STAGE_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMDoc
|
||||||
{
|
{
|
||||||
class Stage
|
class Stage
|
||||||
{
|
{
|
||||||
|
@ -16,7 +16,7 @@ namespace CSMTools
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages) = 0;
|
virtual void perform (int stage, std::vector<std::string>& messages) = 0;
|
||||||
///< Messages resulting from this tage will be appended to \a messages.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief VerifyStage: make sure that birthsign records are internally consistent
|
/// \brief VerifyStage: make sure that birthsign records are internally consistent
|
||||||
class BirthsignCheckStage : public Stage
|
class BirthsignCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::BirthSign>& mBirthsigns;
|
const CSMWorld::IdCollection<ESM::BirthSign>& mBirthsigns;
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief VerifyStage: make sure that class records are internally consistent
|
/// \brief VerifyStage: make sure that class records are internally consistent
|
||||||
class ClassCheckStage : public Stage
|
class ClassCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Class>& mClasses;
|
const CSMWorld::IdCollection<ESM::Class>& mClasses;
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief VerifyStage: make sure that faction records are internally consistent
|
/// \brief VerifyStage: make sure that faction records are internally consistent
|
||||||
class FactionCheckStage : public Stage
|
class FactionCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
|
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
|
@ -16,7 +16,7 @@ namespace CSMWorld
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief Verify stage: make sure that records with specific IDs exist.
|
/// \brief Verify stage: make sure that records with specific IDs exist.
|
||||||
class MandatoryIdStage : public Stage
|
class MandatoryIdStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::CollectionBase& mIdCollection;
|
const CSMWorld::CollectionBase& mIdCollection;
|
||||||
CSMWorld::UniversalId mCollectionId;
|
CSMWorld::UniversalId mCollectionId;
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief VerifyStage: make sure that race records are internally consistent
|
/// \brief VerifyStage: make sure that race records are internally consistent
|
||||||
class RaceCheckStage : public Stage
|
class RaceCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Race>& mRaces;
|
const CSMWorld::IdCollection<ESM::Race>& mRaces;
|
||||||
bool mPlayable;
|
bool mPlayable;
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief VerifyStage: make sure that region records are internally consistent
|
/// \brief VerifyStage: make sure that region records are internally consistent
|
||||||
class RegionCheckStage : public Stage
|
class RegionCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Region>& mRegions;
|
const CSMWorld::IdCollection<ESM::Region>& mRegions;
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief VerifyStage: make sure that skill records are internally consistent
|
/// \brief VerifyStage: make sure that skill records are internally consistent
|
||||||
class SkillCheckStage : public Stage
|
class SkillCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Skill>& mSkills;
|
const CSMWorld::IdCollection<ESM::Skill>& mSkills;
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief VerifyStage: make sure that sound records are internally consistent
|
/// \brief VerifyStage: make sure that sound records are internally consistent
|
||||||
class SoundCheckStage : public Stage
|
class SoundCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Sound>& mSounds;
|
const CSMWorld::IdCollection<ESM::Sound>& mSounds;
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
/// \brief VerifyStage: make sure that spell records are internally consistent
|
/// \brief VerifyStage: make sure that spell records are internally consistent
|
||||||
class SpellCheckStage : public Stage
|
class SpellCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
const CSMWorld::IdCollection<ESM::Spell>& mSpells;
|
const CSMWorld::IdCollection<ESM::Spell>& mSpells;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
|
|
||||||
#include "stage.hpp"
|
|
||||||
|
|
||||||
CSMTools::Stage::~Stage() {}
|
|
|
@ -3,9 +3,8 @@
|
||||||
|
|
||||||
#include <QThreadPool>
|
#include <QThreadPool>
|
||||||
|
|
||||||
#include "verifier.hpp"
|
|
||||||
|
|
||||||
#include "../doc/state.hpp"
|
#include "../doc/state.hpp"
|
||||||
|
#include "../doc/operation.hpp"
|
||||||
|
|
||||||
#include "../world/data.hpp"
|
#include "../world/data.hpp"
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
@ -21,7 +20,7 @@
|
||||||
#include "birthsigncheck.hpp"
|
#include "birthsigncheck.hpp"
|
||||||
#include "spellcheck.hpp"
|
#include "spellcheck.hpp"
|
||||||
|
|
||||||
CSMTools::Operation *CSMTools::Tools::get (int type)
|
CSMDoc::Operation *CSMTools::Tools::get (int type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
@ -31,19 +30,19 @@ CSMTools::Operation *CSMTools::Tools::get (int type)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CSMTools::Operation *CSMTools::Tools::get (int type) const
|
const CSMDoc::Operation *CSMTools::Tools::get (int type) const
|
||||||
{
|
{
|
||||||
return const_cast<Tools *> (this)->get (type);
|
return const_cast<Tools *> (this)->get (type);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMTools::Verifier *CSMTools::Tools::getVerifier()
|
CSMDoc::Operation *CSMTools::Tools::getVerifier()
|
||||||
{
|
{
|
||||||
if (!mVerifier)
|
if (!mVerifier)
|
||||||
{
|
{
|
||||||
mVerifier = new Verifier;
|
mVerifier = new CSMDoc::Operation (CSMDoc::State_Verifying, false);
|
||||||
|
|
||||||
connect (mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
|
connect (mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
|
||||||
connect (mVerifier, SIGNAL (finished()), this, SLOT (verifierDone()));
|
connect (mVerifier, SIGNAL (done (int)), this, SIGNAL (done (int)));
|
||||||
connect (mVerifier, SIGNAL (reportMessage (const QString&, int)),
|
connect (mVerifier, SIGNAL (reportMessage (const QString&, int)),
|
||||||
this, SLOT (verifierMessage (const QString&, int)));
|
this, SLOT (verifierMessage (const QString&, int)));
|
||||||
|
|
||||||
|
@ -103,7 +102,7 @@ CSMWorld::UniversalId CSMTools::Tools::runVerifier()
|
||||||
|
|
||||||
void CSMTools::Tools::abortOperation (int type)
|
void CSMTools::Tools::abortOperation (int type)
|
||||||
{
|
{
|
||||||
if (Operation *operation = get (type))
|
if (CSMDoc::Operation *operation = get (type))
|
||||||
operation->abort();
|
operation->abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +117,7 @@ int CSMTools::Tools::getRunningOperations() const
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
for (int i=0; sOperations[i]!=-1; ++i)
|
for (int i=0; sOperations[i]!=-1; ++i)
|
||||||
if (const Operation *operation = get (sOperations[i]))
|
if (const CSMDoc::Operation *operation = get (sOperations[i]))
|
||||||
if (operation->isRunning())
|
if (operation->isRunning())
|
||||||
result |= sOperations[i];
|
result |= sOperations[i];
|
||||||
|
|
||||||
|
@ -133,11 +132,6 @@ CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId&
|
||||||
return mReports.at (id.getIndex());
|
return mReports.at (id.getIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::Tools::verifierDone()
|
|
||||||
{
|
|
||||||
emit done (CSMDoc::State_Verifying);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSMTools::Tools::verifierMessage (const QString& message, int type)
|
void CSMTools::Tools::verifierMessage (const QString& message, int type)
|
||||||
{
|
{
|
||||||
std::map<int, int>::iterator iter = mActiveReports.find (type);
|
std::map<int, int>::iterator iter = mActiveReports.find (type);
|
||||||
|
|
|
@ -11,10 +11,13 @@ namespace CSMWorld
|
||||||
class UniversalId;
|
class UniversalId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
class Operation;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CSMTools
|
namespace CSMTools
|
||||||
{
|
{
|
||||||
class Verifier;
|
|
||||||
class Operation;
|
|
||||||
class ReportModel;
|
class ReportModel;
|
||||||
|
|
||||||
class Tools : public QObject
|
class Tools : public QObject
|
||||||
|
@ -22,7 +25,7 @@ namespace CSMTools
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
CSMWorld::Data& mData;
|
CSMWorld::Data& mData;
|
||||||
Verifier *mVerifier;
|
CSMDoc::Operation *mVerifier;
|
||||||
std::map<int, ReportModel *> mReports;
|
std::map<int, ReportModel *> mReports;
|
||||||
int mNextReportNumber;
|
int mNextReportNumber;
|
||||||
std::map<int, int> mActiveReports; // type, report number
|
std::map<int, int> mActiveReports; // type, report number
|
||||||
|
@ -31,12 +34,12 @@ namespace CSMTools
|
||||||
Tools (const Tools&);
|
Tools (const Tools&);
|
||||||
Tools& operator= (const Tools&);
|
Tools& operator= (const Tools&);
|
||||||
|
|
||||||
Verifier *getVerifier();
|
CSMDoc::Operation *getVerifier();
|
||||||
|
|
||||||
Operation *get (int type);
|
CSMDoc::Operation *get (int type);
|
||||||
///< Returns a 0-pointer, if operation hasn't been used yet.
|
///< Returns a 0-pointer, if operation hasn't been used yet.
|
||||||
|
|
||||||
const Operation *get (int type) const;
|
const CSMDoc::Operation *get (int type) const;
|
||||||
///< Returns a 0-pointer, if operation hasn't been used yet.
|
///< Returns a 0-pointer, if operation hasn't been used yet.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -58,8 +61,6 @@ namespace CSMTools
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void verifierDone();
|
|
||||||
|
|
||||||
void verifierMessage (const QString& message, int type);
|
void verifierMessage (const QString& message, int type);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
|
|
||||||
#include "verifier.hpp"
|
|
||||||
|
|
||||||
#include "../doc/state.hpp"
|
|
||||||
|
|
||||||
CSMTools::Verifier::Verifier() : Operation (CSMDoc::State_Verifying)
|
|
||||||
{}
|
|
|
@ -1,17 +0,0 @@
|
||||||
#ifndef CSM_TOOLS_VERIFIER_H
|
|
||||||
#define CSM_TOOLS_VERIFIER_H
|
|
||||||
|
|
||||||
#include "operation.hpp"
|
|
||||||
|
|
||||||
namespace CSMTools
|
|
||||||
{
|
|
||||||
class Verifier : public Operation
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
Verifier();
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,6 +1,31 @@
|
||||||
|
|
||||||
#include "collectionbase.hpp"
|
#include "collectionbase.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "columnbase.hpp"
|
||||||
|
|
||||||
CSMWorld::CollectionBase::CollectionBase() {}
|
CSMWorld::CollectionBase::CollectionBase() {}
|
||||||
|
|
||||||
CSMWorld::CollectionBase::~CollectionBase() {}
|
CSMWorld::CollectionBase::~CollectionBase() {}
|
||||||
|
|
||||||
|
int CSMWorld::CollectionBase::searchColumnIndex (Columns::ColumnId id) const
|
||||||
|
{
|
||||||
|
int columns = getColumns();
|
||||||
|
|
||||||
|
for (int i=0; i<columns; ++i)
|
||||||
|
if (getColumn (i).mColumnId==id)
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMWorld::CollectionBase::findColumnIndex (Columns::ColumnId id) const
|
||||||
|
{
|
||||||
|
int index = searchColumnIndex (id);
|
||||||
|
|
||||||
|
if (index==-1)
|
||||||
|
throw std::logic_error ("invalid column index");
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
|
@ -4,6 +4,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "universalid.hpp"
|
#include "universalid.hpp"
|
||||||
|
#include "columns.hpp"
|
||||||
|
|
||||||
class QVariant;
|
class QVariant;
|
||||||
|
|
||||||
|
@ -83,6 +84,13 @@ namespace CSMWorld
|
||||||
///< Return a sorted collection of all IDs
|
///< Return a sorted collection of all IDs
|
||||||
///
|
///
|
||||||
/// \param listDeleted include deleted record in the list
|
/// \param listDeleted include deleted record in the list
|
||||||
|
|
||||||
|
int searchColumnIndex (Columns::ColumnId id) const;
|
||||||
|
///< Return index of column with the given \a id. If no such column exists, -1 is returned.
|
||||||
|
|
||||||
|
int findColumnIndex (Columns::ColumnId id) const;
|
||||||
|
///< Return index of column with the given \a id. If no such column exists, an exception is
|
||||||
|
/// thrown.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,8 @@ namespace CSMWorld
|
||||||
Display_CreatureType,
|
Display_CreatureType,
|
||||||
Display_WeaponType,
|
Display_WeaponType,
|
||||||
Display_RecordState,
|
Display_RecordState,
|
||||||
Display_RefRecordType
|
Display_RefRecordType,
|
||||||
|
Display_DialogueType
|
||||||
};
|
};
|
||||||
|
|
||||||
int mColumnId;
|
int mColumnId;
|
||||||
|
|
|
@ -1217,6 +1217,37 @@ namespace CSMWorld
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
struct ScopeColumn : public Column<ESXRecordT>
|
||||||
|
{
|
||||||
|
ScopeColumn()
|
||||||
|
: Column<ESXRecordT> (Columns::ColumnId_Scope, ColumnBase::Display_Integer, 0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return static_cast<int> (record.get().mScope);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
ESXRecordT record2 = record.get();
|
||||||
|
record2.mScope = static_cast<CSMFilter::Filter::Scope> (data.toInt());
|
||||||
|
record.setModified (record2);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isUserEditable() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template<typename ESXRecordT>
|
template<typename ESXRecordT>
|
||||||
struct PosColumn : public Column<ESXRecordT>
|
struct PosColumn : public Column<ESXRecordT>
|
||||||
{
|
{
|
||||||
|
@ -1284,6 +1315,39 @@ namespace CSMWorld
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
struct DialogueTypeColumn : public Column<ESXRecordT>
|
||||||
|
{
|
||||||
|
DialogueTypeColumn (bool hidden = false)
|
||||||
|
: Column<ESXRecordT> (Columns::ColumnId_DialogueType, ColumnBase::Display_DialogueType,
|
||||||
|
hidden ? 0 : ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return static_cast<int> (record.get().mType);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
ESXRecordT record2 = record.get();
|
||||||
|
|
||||||
|
record2.mType = data.toInt();
|
||||||
|
|
||||||
|
record.setModified (record2);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isUserEditable() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -159,6 +159,8 @@ namespace CSMWorld
|
||||||
{ ColumnId_DoorPositionXRot, "Teleport Rot X" },
|
{ ColumnId_DoorPositionXRot, "Teleport Rot X" },
|
||||||
{ ColumnId_DoorPositionYRot, "Teleport Rot Y" },
|
{ ColumnId_DoorPositionYRot, "Teleport Rot Y" },
|
||||||
{ ColumnId_DoorPositionZRot, "Teleport Rot Z" },
|
{ ColumnId_DoorPositionZRot, "Teleport Rot Z" },
|
||||||
|
{ ColumnId_DialogueType, "Dialogue Type" },
|
||||||
|
{ ColumnId_Scope, "Scope", },
|
||||||
|
|
||||||
{ ColumnId_UseValue1, "Use value 1" },
|
{ ColumnId_UseValue1, "Use value 1" },
|
||||||
{ ColumnId_UseValue2, "Use value 2" },
|
{ ColumnId_UseValue2, "Use value 2" },
|
||||||
|
@ -269,6 +271,11 @@ namespace
|
||||||
"unknown", "none", "short", "integer", "long", "float", "string", 0
|
"unknown", "none", "short", "integer", "long", "float", "string", 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char *sDialogueTypeEnums[] =
|
||||||
|
{
|
||||||
|
"Topic", "Voice", "Greeting", "Persuasion", 0
|
||||||
|
};
|
||||||
|
|
||||||
const char **getEnumNames (CSMWorld::Columns::ColumnId column)
|
const char **getEnumNames (CSMWorld::Columns::ColumnId column)
|
||||||
{
|
{
|
||||||
switch (column)
|
switch (column)
|
||||||
|
@ -283,6 +290,7 @@ namespace
|
||||||
case CSMWorld::Columns::ColumnId_WeaponType: return sWeaponTypes;
|
case CSMWorld::Columns::ColumnId_WeaponType: return sWeaponTypes;
|
||||||
case CSMWorld::Columns::ColumnId_Modification: return sModificationEnums;
|
case CSMWorld::Columns::ColumnId_Modification: return sModificationEnums;
|
||||||
case CSMWorld::Columns::ColumnId_ValueType: return sVarTypeEnums;
|
case CSMWorld::Columns::ColumnId_ValueType: return sVarTypeEnums;
|
||||||
|
case CSMWorld::Columns::ColumnId_DialogueType: return sDialogueTypeEnums;
|
||||||
|
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,6 +152,8 @@ namespace CSMWorld
|
||||||
ColumnId_DoorPositionXRot = 139,
|
ColumnId_DoorPositionXRot = 139,
|
||||||
ColumnId_DoorPositionYRot = 140,
|
ColumnId_DoorPositionYRot = 140,
|
||||||
ColumnId_DoorPositionZRot = 141,
|
ColumnId_DoorPositionZRot = 141,
|
||||||
|
ColumnId_DialogueType = 142,
|
||||||
|
ColumnId_Scope = 143,
|
||||||
|
|
||||||
// Allocated to a separate value range, so we don't get a collision should we ever need
|
// Allocated to a separate value range, so we don't get a collision should we ever need
|
||||||
// to extend the number of use values.
|
// to extend the number of use values.
|
||||||
|
|
|
@ -44,6 +44,17 @@ void CSMWorld::Data::appendIds (std::vector<std::string>& ids, const CollectionB
|
||||||
ids.insert (ids.end(), ids2.begin(), ids2.end());
|
ids.insert (ids.end(), ids2.begin(), ids2.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CSMWorld::Data::count (RecordBase::State state, const CollectionBase& collection)
|
||||||
|
{
|
||||||
|
int number = 0;
|
||||||
|
|
||||||
|
for (int i=0; i<collection.getSize(); ++i)
|
||||||
|
if (collection.getRecord (i).mState==state)
|
||||||
|
++number;
|
||||||
|
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
CSMWorld::Data::Data() : mRefs (mCells)
|
CSMWorld::Data::Data() : mRefs (mCells)
|
||||||
{
|
{
|
||||||
mGlobals.addColumn (new StringIdColumn<ESM::Global>);
|
mGlobals.addColumn (new StringIdColumn<ESM::Global>);
|
||||||
|
@ -141,6 +152,14 @@ CSMWorld::Data::Data() : mRefs (mCells)
|
||||||
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_StarterSpell, 0x2));
|
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_StarterSpell, 0x2));
|
||||||
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_AlwaysSucceeds, 0x4));
|
mSpells.addColumn (new FlagColumn<ESM::Spell> (Columns::ColumnId_AlwaysSucceeds, 0x4));
|
||||||
|
|
||||||
|
mTopics.addColumn (new StringIdColumn<ESM::Dialogue>);
|
||||||
|
mTopics.addColumn (new RecordStateColumn<ESM::Dialogue>);
|
||||||
|
mTopics.addColumn (new DialogueTypeColumn<ESM::Dialogue>);
|
||||||
|
|
||||||
|
mJournals.addColumn (new StringIdColumn<ESM::Dialogue>);
|
||||||
|
mJournals.addColumn (new RecordStateColumn<ESM::Dialogue>);
|
||||||
|
mJournals.addColumn (new DialogueTypeColumn<ESM::Dialogue> (true));
|
||||||
|
|
||||||
mCells.addColumn (new StringIdColumn<Cell>);
|
mCells.addColumn (new StringIdColumn<Cell>);
|
||||||
mCells.addColumn (new RecordStateColumn<Cell>);
|
mCells.addColumn (new RecordStateColumn<Cell>);
|
||||||
mCells.addColumn (new FixedRecordTypeColumn<Cell> (UniversalId::Type_Cell));
|
mCells.addColumn (new FixedRecordTypeColumn<Cell> (UniversalId::Type_Cell));
|
||||||
|
@ -184,6 +203,7 @@ CSMWorld::Data::Data() : mRefs (mCells)
|
||||||
mFilters.addColumn (new RecordStateColumn<CSMFilter::Filter>);
|
mFilters.addColumn (new RecordStateColumn<CSMFilter::Filter>);
|
||||||
mFilters.addColumn (new FilterColumn<CSMFilter::Filter>);
|
mFilters.addColumn (new FilterColumn<CSMFilter::Filter>);
|
||||||
mFilters.addColumn (new DescriptionColumn<CSMFilter::Filter>);
|
mFilters.addColumn (new DescriptionColumn<CSMFilter::Filter>);
|
||||||
|
mFilters.addColumn (new ScopeColumn<CSMFilter::Filter>);
|
||||||
|
|
||||||
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
|
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
|
||||||
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
|
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
|
||||||
|
@ -196,6 +216,8 @@ CSMWorld::Data::Data() : mRefs (mCells)
|
||||||
addModel (new IdTable (&mRegions), UniversalId::Type_Regions, UniversalId::Type_Region);
|
addModel (new IdTable (&mRegions), UniversalId::Type_Regions, UniversalId::Type_Region);
|
||||||
addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsigns, UniversalId::Type_Birthsign);
|
addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsigns, UniversalId::Type_Birthsign);
|
||||||
addModel (new IdTable (&mSpells), UniversalId::Type_Spells, UniversalId::Type_Spell);
|
addModel (new IdTable (&mSpells), UniversalId::Type_Spells, UniversalId::Type_Spell);
|
||||||
|
addModel (new IdTable (&mTopics), UniversalId::Type_Topics, UniversalId::Type_Topic);
|
||||||
|
addModel (new IdTable (&mJournals), UniversalId::Type_Journals, UniversalId::Type_Journal);
|
||||||
addModel (new IdTable (&mCells), UniversalId::Type_Cells, UniversalId::Type_Cell);
|
addModel (new IdTable (&mCells), UniversalId::Type_Cells, UniversalId::Type_Cell);
|
||||||
addModel (new IdTable (&mReferenceables), UniversalId::Type_Referenceables,
|
addModel (new IdTable (&mReferenceables), UniversalId::Type_Referenceables,
|
||||||
UniversalId::Type_Referenceable);
|
UniversalId::Type_Referenceable);
|
||||||
|
@ -319,6 +341,28 @@ CSMWorld::IdCollection<ESM::Spell>& CSMWorld::Data::getSpells()
|
||||||
return mSpells;
|
return mSpells;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const CSMWorld::IdCollection<ESM::Dialogue>& CSMWorld::Data::getTopics() const
|
||||||
|
{
|
||||||
|
return mTopics;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::IdCollection<ESM::Dialogue>& CSMWorld::Data::getTopics()
|
||||||
|
{
|
||||||
|
return mTopics;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CSMWorld::IdCollection<ESM::Dialogue>& CSMWorld::Data::getJournals() const
|
||||||
|
{
|
||||||
|
return mJournals;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::IdCollection<ESM::Dialogue>& CSMWorld::Data::getJournals()
|
||||||
|
{
|
||||||
|
return mJournals;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const CSMWorld::IdCollection<CSMWorld::Cell>& CSMWorld::Data::getCells() const
|
const CSMWorld::IdCollection<CSMWorld::Cell>& CSMWorld::Data::getCells() const
|
||||||
{
|
{
|
||||||
return mCells;
|
return mCells;
|
||||||
|
@ -387,7 +431,7 @@ void CSMWorld::Data::merge()
|
||||||
mGlobals.merge();
|
mGlobals.merge();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
|
void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base, bool project)
|
||||||
{
|
{
|
||||||
ESM::ESMReader reader;
|
ESM::ESMReader reader;
|
||||||
|
|
||||||
|
@ -397,6 +441,9 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
|
||||||
|
|
||||||
reader.open (path.string());
|
reader.open (path.string());
|
||||||
|
|
||||||
|
mAuthor = reader.getAuthor();
|
||||||
|
mDescription = reader.getDesc();
|
||||||
|
|
||||||
// Note: We do not need to send update signals here, because at this point the model is not connected
|
// Note: We do not need to send update signals here, because at this point the model is not connected
|
||||||
// to any view.
|
// to any view.
|
||||||
while (reader.hasMoreRecs())
|
while (reader.hasMoreRecs())
|
||||||
|
@ -447,6 +494,54 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
|
||||||
case ESM::REC_STAT: mReferenceables.load (reader, base, UniversalId::Type_Static); break;
|
case ESM::REC_STAT: mReferenceables.load (reader, base, UniversalId::Type_Static); break;
|
||||||
case ESM::REC_WEAP: mReferenceables.load (reader, base, UniversalId::Type_Weapon); break;
|
case ESM::REC_WEAP: mReferenceables.load (reader, base, UniversalId::Type_Weapon); break;
|
||||||
|
|
||||||
|
case ESM::REC_DIAL:
|
||||||
|
{
|
||||||
|
std::string id = reader.getHNOString ("NAME");
|
||||||
|
|
||||||
|
ESM::Dialogue record;
|
||||||
|
record.mId = id;
|
||||||
|
record.load (reader);
|
||||||
|
|
||||||
|
if (record.mType==ESM::Dialogue::Journal)
|
||||||
|
{
|
||||||
|
mJournals.load (record, base);
|
||||||
|
}
|
||||||
|
else if (record.mType==ESM::Dialogue::Deleted)
|
||||||
|
{
|
||||||
|
if (mJournals.tryDelete (id))
|
||||||
|
{
|
||||||
|
/// \todo handle info records
|
||||||
|
}
|
||||||
|
else if (mTopics.tryDelete (id))
|
||||||
|
{
|
||||||
|
/// \todo handle info records
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/// \todo report deletion of non-existing record
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mTopics.load (record, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ESM::REC_FILT:
|
||||||
|
|
||||||
|
if (project)
|
||||||
|
{
|
||||||
|
mFilters.load (reader, base);
|
||||||
|
mFilters.setData (mFilters.getSize()-1,
|
||||||
|
mFilters.findColumnIndex (CSMWorld::Columns::ColumnId_Scope),
|
||||||
|
static_cast<int> (CSMFilter::Filter::Scope_Project));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fall through (filter record in a content file is an error with format 0)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
/// \todo throw an exception instead, once all records are implemented
|
/// \todo throw an exception instead, once all records are implemented
|
||||||
|
@ -469,10 +564,50 @@ bool CSMWorld::Data::hasId (const std::string& id) const
|
||||||
getRegions().searchId (id)!=-1 ||
|
getRegions().searchId (id)!=-1 ||
|
||||||
getBirthsigns().searchId (id)!=-1 ||
|
getBirthsigns().searchId (id)!=-1 ||
|
||||||
getSpells().searchId (id)!=-1 ||
|
getSpells().searchId (id)!=-1 ||
|
||||||
|
getTopics().searchId (id)!=-1 ||
|
||||||
|
getJournals().searchId (id)!=-1 ||
|
||||||
getCells().searchId (id)!=-1 ||
|
getCells().searchId (id)!=-1 ||
|
||||||
getReferenceables().searchId (id)!=-1;
|
getReferenceables().searchId (id)!=-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CSMWorld::Data::count (RecordBase::State state) const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
count (state, mGlobals) +
|
||||||
|
count (state, mGmsts) +
|
||||||
|
count (state, mSkills) +
|
||||||
|
count (state, mClasses) +
|
||||||
|
count (state, mFactions) +
|
||||||
|
count (state, mRaces) +
|
||||||
|
count (state, mSounds) +
|
||||||
|
count (state, mScripts) +
|
||||||
|
count (state, mRegions) +
|
||||||
|
count (state, mBirthsigns) +
|
||||||
|
count (state, mSpells) +
|
||||||
|
count (state, mCells) +
|
||||||
|
count (state, mReferenceables);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::Data::setDescription (const std::string& description)
|
||||||
|
{
|
||||||
|
mDescription = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CSMWorld::Data::getDescription() const
|
||||||
|
{
|
||||||
|
return mDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::Data::setAuthor (const std::string& author)
|
||||||
|
{
|
||||||
|
mAuthor = author;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CSMWorld::Data::getAuthor() const
|
||||||
|
{
|
||||||
|
return mAuthor;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::string> CSMWorld::Data::getIds (bool listDeleted) const
|
std::vector<std::string> CSMWorld::Data::getIds (bool listDeleted) const
|
||||||
{
|
{
|
||||||
std::vector<std::string> ids;
|
std::vector<std::string> ids;
|
||||||
|
@ -487,6 +622,8 @@ std::vector<std::string> CSMWorld::Data::getIds (bool listDeleted) const
|
||||||
appendIds (ids, mRegions, listDeleted);
|
appendIds (ids, mRegions, listDeleted);
|
||||||
appendIds (ids, mBirthsigns, listDeleted);
|
appendIds (ids, mBirthsigns, listDeleted);
|
||||||
appendIds (ids, mSpells, listDeleted);
|
appendIds (ids, mSpells, listDeleted);
|
||||||
|
appendIds (ids, mTopics, listDeleted);
|
||||||
|
appendIds (ids, mJournals, listDeleted);
|
||||||
appendIds (ids, mCells, listDeleted);
|
appendIds (ids, mCells, listDeleted);
|
||||||
appendIds (ids, mReferenceables, listDeleted);
|
appendIds (ids, mReferenceables, listDeleted);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <components/esm/loadregn.hpp>
|
#include <components/esm/loadregn.hpp>
|
||||||
#include <components/esm/loadbsgn.hpp>
|
#include <components/esm/loadbsgn.hpp>
|
||||||
#include <components/esm/loadspel.hpp>
|
#include <components/esm/loadspel.hpp>
|
||||||
|
#include <components/esm/loaddial.hpp>
|
||||||
|
|
||||||
#include "../filter/filter.hpp"
|
#include "../filter/filter.hpp"
|
||||||
|
|
||||||
|
@ -48,12 +49,16 @@ namespace CSMWorld
|
||||||
IdCollection<ESM::Region> mRegions;
|
IdCollection<ESM::Region> mRegions;
|
||||||
IdCollection<ESM::BirthSign> mBirthsigns;
|
IdCollection<ESM::BirthSign> mBirthsigns;
|
||||||
IdCollection<ESM::Spell> mSpells;
|
IdCollection<ESM::Spell> mSpells;
|
||||||
|
IdCollection<ESM::Dialogue> mTopics;
|
||||||
|
IdCollection<ESM::Dialogue> mJournals;
|
||||||
IdCollection<Cell> mCells;
|
IdCollection<Cell> mCells;
|
||||||
RefIdCollection mReferenceables;
|
RefIdCollection mReferenceables;
|
||||||
RefCollection mRefs;
|
RefCollection mRefs;
|
||||||
IdCollection<CSMFilter::Filter> mFilters;
|
IdCollection<CSMFilter::Filter> mFilters;
|
||||||
std::vector<QAbstractItemModel *> mModels;
|
std::vector<QAbstractItemModel *> mModels;
|
||||||
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
||||||
|
std::string mAuthor;
|
||||||
|
std::string mDescription;
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
Data (const Data&);
|
Data (const Data&);
|
||||||
|
@ -66,6 +71,8 @@ namespace CSMWorld
|
||||||
bool listDeleted);
|
bool listDeleted);
|
||||||
///< Append all IDs from collection to \a ids.
|
///< Append all IDs from collection to \a ids.
|
||||||
|
|
||||||
|
static int count (RecordBase::State state, const CollectionBase& collection);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Data();
|
Data();
|
||||||
|
@ -116,6 +123,14 @@ namespace CSMWorld
|
||||||
|
|
||||||
IdCollection<ESM::Spell>& getSpells();
|
IdCollection<ESM::Spell>& getSpells();
|
||||||
|
|
||||||
|
const IdCollection<ESM::Dialogue>& getTopics() const;
|
||||||
|
|
||||||
|
IdCollection<ESM::Dialogue>& getTopics();
|
||||||
|
|
||||||
|
const IdCollection<ESM::Dialogue>& getJournals() const;
|
||||||
|
|
||||||
|
IdCollection<ESM::Dialogue>& getJournals();
|
||||||
|
|
||||||
const IdCollection<Cell>& getCells() const;
|
const IdCollection<Cell>& getCells() const;
|
||||||
|
|
||||||
IdCollection<Cell>& getCells();
|
IdCollection<Cell>& getCells();
|
||||||
|
@ -141,8 +156,10 @@ namespace CSMWorld
|
||||||
void merge();
|
void merge();
|
||||||
///< Merge modified into base.
|
///< Merge modified into base.
|
||||||
|
|
||||||
void loadFile (const boost::filesystem::path& path, bool base);
|
void loadFile (const boost::filesystem::path& path, bool base, bool project);
|
||||||
///< Merging content of a file into base or modified.
|
///< Merging content of a file into base or modified.
|
||||||
|
///
|
||||||
|
/// \param project load project file instead of content file
|
||||||
|
|
||||||
bool hasId (const std::string& id) const;
|
bool hasId (const std::string& id) const;
|
||||||
|
|
||||||
|
@ -151,6 +168,17 @@ namespace CSMWorld
|
||||||
///
|
///
|
||||||
/// \param listDeleted include deleted record in the list
|
/// \param listDeleted include deleted record in the list
|
||||||
|
|
||||||
|
int count (RecordBase::State state) const;
|
||||||
|
///< Return number of top-level records with the given \a state.
|
||||||
|
|
||||||
|
void setDescription (const std::string& description);
|
||||||
|
|
||||||
|
std::string getDescription() const;
|
||||||
|
|
||||||
|
void setAuthor (const std::string& author);
|
||||||
|
|
||||||
|
std::string getAuthor() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void idListChanged();
|
void idListChanged();
|
||||||
|
|
|
@ -7,21 +7,24 @@
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
|
|
||||||
/// \brief Single type collection of top level records
|
/// \brief Single type collection of top level records
|
||||||
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
|
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
|
||||||
class IdCollection : public Collection<ESXRecordT, IdAccessorT>
|
class IdCollection : public Collection<ESXRecordT, IdAccessorT>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void load (ESM::ESMReader& reader, bool base,
|
void load (ESM::ESMReader& reader, bool base);
|
||||||
UniversalId::Type type = UniversalId::Type_None);
|
|
||||||
///< \param type Will be ignored, unless the collection supports multiple record types
|
void load (const ESXRecordT& record, bool base);
|
||||||
|
|
||||||
|
bool tryDelete (const std::string& id);
|
||||||
|
///< Try deleting \a id. If the id does not exist or can't be deleted the call is ignored.
|
||||||
|
///
|
||||||
|
/// \return Has the ID been deleted?
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ESXRecordT, typename IdAccessorT>
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
void IdCollection<ESXRecordT, IdAccessorT>::load (ESM::ESMReader& reader, bool base,
|
void IdCollection<ESXRecordT, IdAccessorT>::load (ESM::ESMReader& reader, bool base)
|
||||||
UniversalId::Type type)
|
|
||||||
{
|
{
|
||||||
std::string id = reader.getHNOString ("NAME");
|
std::string id = reader.getHNOString ("NAME");
|
||||||
|
|
||||||
|
@ -56,6 +59,13 @@ namespace CSMWorld
|
||||||
IdAccessorT().getId (record) = id;
|
IdAccessorT().getId (record) = id;
|
||||||
record.load (reader);
|
record.load (reader);
|
||||||
|
|
||||||
|
load (record, base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
void IdCollection<ESXRecordT, IdAccessorT>::load (const ESXRecordT& record, bool base)
|
||||||
|
{
|
||||||
int index = this->searchId (IdAccessorT().getId (record));
|
int index = this->searchId (IdAccessorT().getId (record));
|
||||||
|
|
||||||
if (index==-1)
|
if (index==-1)
|
||||||
|
@ -80,6 +90,31 @@ namespace CSMWorld
|
||||||
this->setRecord (index, record2);
|
this->setRecord (index, record2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
bool IdCollection<ESXRecordT, IdAccessorT>::tryDelete (const std::string& id)
|
||||||
|
{
|
||||||
|
int index = this->searchId (id);
|
||||||
|
|
||||||
|
if (index==-1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Record<ESXRecordT> record = Collection<ESXRecordT, IdAccessorT>::getRecord (index);
|
||||||
|
|
||||||
|
if (record.isDeleted())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (record.mState==RecordBase::State_ModifiedOnly)
|
||||||
|
{
|
||||||
|
Collection<ESXRecordT, IdAccessorT>::removeRows (index, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
record.mState = RecordBase::State_Deleted;
|
||||||
|
setRecord (index, record);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,21 +161,10 @@ const CSMWorld::RecordBase& CSMWorld::IdTable::getRecord (const std::string& id)
|
||||||
|
|
||||||
int CSMWorld::IdTable::searchColumnIndex (Columns::ColumnId id) const
|
int CSMWorld::IdTable::searchColumnIndex (Columns::ColumnId id) const
|
||||||
{
|
{
|
||||||
int columns = mIdCollection->getColumns();
|
return mIdCollection->searchColumnIndex (id);
|
||||||
|
|
||||||
for (int i=0; i<columns; ++i)
|
|
||||||
if (mIdCollection->getColumn (i).mColumnId==id)
|
|
||||||
return i;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CSMWorld::IdTable::findColumnIndex (Columns::ColumnId id) const
|
int CSMWorld::IdTable::findColumnIndex (Columns::ColumnId id) const
|
||||||
{
|
{
|
||||||
int index = searchColumnIndex (id);
|
return mIdCollection->findColumnIndex (id);
|
||||||
|
|
||||||
if (index==-1)
|
|
||||||
throw std::logic_error ("invalid column index");
|
|
||||||
|
|
||||||
return index;
|
|
||||||
}
|
}
|
|
@ -539,3 +539,8 @@ std::vector<std::string> CSMWorld::RefIdCollection::getIds (bool listDeleted) co
|
||||||
{
|
{
|
||||||
return mData.getIds (listDeleted);
|
return mData.getIds (listDeleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMWorld::RefIdCollection::save (int index, ESM::ESMWriter& writer) const
|
||||||
|
{
|
||||||
|
mData.save (index, writer);
|
||||||
|
}
|
|
@ -9,6 +9,11 @@
|
||||||
#include "collectionbase.hpp"
|
#include "collectionbase.hpp"
|
||||||
#include "refiddata.hpp"
|
#include "refiddata.hpp"
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
class ESMWriter;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
class RefIdAdapter;
|
class RefIdAdapter;
|
||||||
|
@ -94,6 +99,8 @@ namespace CSMWorld
|
||||||
///< Return a sorted collection of all IDs
|
///< Return a sorted collection of all IDs
|
||||||
///
|
///
|
||||||
/// \param listDeleted include deleted record in the list
|
/// \param listDeleted include deleted record in the list
|
||||||
|
|
||||||
|
void save (int index, ESM::ESMWriter& writer) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -218,3 +218,16 @@ std::vector<std::string> CSMWorld::RefIdData::getIds (bool listDeleted) const
|
||||||
|
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMWorld::RefIdData::save (int index, ESM::ESMWriter& writer) const
|
||||||
|
{
|
||||||
|
LocalIndex localIndex = globalToLocalIndex (index);
|
||||||
|
|
||||||
|
std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator iter =
|
||||||
|
mRecordContainers.find (localIndex.second);
|
||||||
|
|
||||||
|
if (iter==mRecordContainers.end())
|
||||||
|
throw std::logic_error ("invalid local index type");
|
||||||
|
|
||||||
|
iter->second->save (localIndex.first, writer);
|
||||||
|
}
|
|
@ -23,6 +23,7 @@
|
||||||
#include <components/esm/loadweap.hpp>
|
#include <components/esm/loadweap.hpp>
|
||||||
#include <components/esm/loadnpc.hpp>
|
#include <components/esm/loadnpc.hpp>
|
||||||
#include <components/esm/loadmisc.hpp>
|
#include <components/esm/loadmisc.hpp>
|
||||||
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
|
||||||
#include "record.hpp"
|
#include "record.hpp"
|
||||||
#include "universalid.hpp"
|
#include "universalid.hpp"
|
||||||
|
@ -51,6 +52,8 @@ namespace CSMWorld
|
||||||
virtual void erase (int index, int count) = 0;
|
virtual void erase (int index, int count) = 0;
|
||||||
|
|
||||||
virtual std::string getId (int index) const = 0;
|
virtual std::string getId (int index) const = 0;
|
||||||
|
|
||||||
|
virtual void save (int index, ESM::ESMWriter& writer) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename RecordT>
|
template<typename RecordT>
|
||||||
|
@ -71,6 +74,8 @@ namespace CSMWorld
|
||||||
virtual void erase (int index, int count);
|
virtual void erase (int index, int count);
|
||||||
|
|
||||||
virtual std::string getId (int index) const;
|
virtual std::string getId (int index) const;
|
||||||
|
|
||||||
|
virtual void save (int index, ESM::ESMWriter& writer) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename RecordT>
|
template<typename RecordT>
|
||||||
|
@ -123,6 +128,31 @@ namespace CSMWorld
|
||||||
return mContainer.at (index).get().mId;
|
return mContainer.at (index).get().mId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename RecordT>
|
||||||
|
void RefIdDataContainer<RecordT>::save (int index, ESM::ESMWriter& writer) const
|
||||||
|
{
|
||||||
|
CSMWorld::RecordBase::State state = mContainer.at (index).mState;
|
||||||
|
|
||||||
|
if (state==CSMWorld::RecordBase::State_Modified ||
|
||||||
|
state==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||||
|
{
|
||||||
|
std::string type;
|
||||||
|
for (int i=0; i<4; ++i)
|
||||||
|
/// \todo make endianess agnostic (change ESMWriter interface?)
|
||||||
|
type += reinterpret_cast<const char *> (&mContainer.at (index).mModified.sRecordId)[i];
|
||||||
|
|
||||||
|
writer.startRecord (type);
|
||||||
|
writer.writeHNCString ("NAME", getId (index));
|
||||||
|
mContainer.at (index).mModified.save (writer);
|
||||||
|
writer.endRecord (type);
|
||||||
|
}
|
||||||
|
else if (state==CSMWorld::RecordBase::State_Deleted)
|
||||||
|
{
|
||||||
|
/// \todo write record with delete flag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class RefIdData
|
class RefIdData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -187,6 +217,8 @@ namespace CSMWorld
|
||||||
///< Return a sorted collection of all IDs
|
///< Return a sorted collection of all IDs
|
||||||
///
|
///
|
||||||
/// \param listDeleted include deleted record in the list
|
/// \param listDeleted include deleted record in the list
|
||||||
|
|
||||||
|
void save (int index, ESM::ESMWriter& writer) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,8 @@ namespace
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", 0 },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", 0 },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", 0 },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Topics, "Topics", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Journals, "Journals", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", 0 },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables,
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables,
|
||||||
"Referenceables", 0 },
|
"Referenceables", 0 },
|
||||||
|
@ -54,6 +56,8 @@ namespace
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", ":./land.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", ":./land.png" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", ":./birthsign.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", ":./birthsign.png" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" },
|
||||||
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Topic, "Topic", 0 },
|
||||||
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" },
|
||||||
|
|
|
@ -87,6 +87,10 @@ namespace CSMWorld
|
||||||
Type_RegionMap,
|
Type_RegionMap,
|
||||||
Type_Filter,
|
Type_Filter,
|
||||||
Type_Filters,
|
Type_Filters,
|
||||||
|
Type_Topics,
|
||||||
|
Type_Topic,
|
||||||
|
Type_Journals,
|
||||||
|
Type_Journal,
|
||||||
Type_Scene
|
Type_Scene
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -128,3 +128,8 @@ void CSVDoc::FileDialog::slotRejected()
|
||||||
emit rejected();
|
emit rejected();
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVDoc::FileDialog::createNewFile()
|
||||||
|
{
|
||||||
|
emit createNewFile (mAdjusterWidget->getPath());
|
||||||
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ namespace CSVDoc
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void openFiles();
|
void openFiles();
|
||||||
void createNewFile();
|
void createNewFile (const boost::filesystem::path& savePath);
|
||||||
|
|
||||||
void signalUpdateCreateButton (bool, int);
|
void signalUpdateCreateButton (bool, int);
|
||||||
void signalUpdateCreateButtonFlags(int);
|
void signalUpdateCreateButtonFlags(int);
|
||||||
|
|
|
@ -6,7 +6,10 @@
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
|
|
||||||
|
#ifndef CS_QT_BOOST_FILESYSTEM_PATH_DECLARED
|
||||||
|
#define CS_QT_BOOST_FILESYSTEM_PATH_DECLARED
|
||||||
Q_DECLARE_METATYPE (boost::filesystem::path)
|
Q_DECLARE_METATYPE (boost::filesystem::path)
|
||||||
|
#endif
|
||||||
|
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,17 @@ CSVDoc::StartupDialogue::StartupDialogue() : mWidth (0), mColumn (2)
|
||||||
layout->addWidget (createButtons());
|
layout->addWidget (createButtons());
|
||||||
layout->addWidget (createTools());
|
layout->addWidget (createTools());
|
||||||
|
|
||||||
|
/// \todo remove this label once loading and saving are fully implemented
|
||||||
|
QLabel *warning = new QLabel ("<font color=Red>WARNING:<p>OpenCS is in alpha stage.<br>The code for loading and saving is incomplete.<br>This version of OpenCS is only a preview.<br>Do NOT use it for real editing!<br>You will lose records both on loading and on saving.<p>Please note:<br>If you lose data and come to the OpenMW forum to complain,<br>we will mock you.</font color>");
|
||||||
|
|
||||||
|
QFont font;
|
||||||
|
font.setPointSize (12);
|
||||||
|
font.setBold (true);
|
||||||
|
|
||||||
|
warning->setFont (font);
|
||||||
|
|
||||||
|
layout->addWidget (warning, 1);
|
||||||
|
|
||||||
setLayout (layout);
|
setLayout (layout);
|
||||||
|
|
||||||
QRect scr = QApplication::desktop()->screenGeometry();
|
QRect scr = QApplication::desktop()->screenGeometry();
|
||||||
|
|
|
@ -163,6 +163,14 @@ void CSVDoc::View::setupMechanicsMenu()
|
||||||
QAction *spells = new QAction (tr ("Spells"), this);
|
QAction *spells = new QAction (tr ("Spells"), this);
|
||||||
connect (spells, SIGNAL (triggered()), this, SLOT (addSpellsSubView()));
|
connect (spells, SIGNAL (triggered()), this, SLOT (addSpellsSubView()));
|
||||||
mechanics->addAction (spells);
|
mechanics->addAction (spells);
|
||||||
|
|
||||||
|
QAction *topics = new QAction (tr ("Topics"), this);
|
||||||
|
connect (topics, SIGNAL (triggered()), this, SLOT (addTopicsSubView()));
|
||||||
|
mechanics->addAction (topics);
|
||||||
|
|
||||||
|
QAction *journals = new QAction (tr ("Journals"), this);
|
||||||
|
connect (journals, SIGNAL (triggered()), this, SLOT (addJournalsSubView()));
|
||||||
|
mechanics->addAction (journals);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::View::setupAssetsMenu()
|
void CSVDoc::View::setupAssetsMenu()
|
||||||
|
@ -412,6 +420,16 @@ void CSVDoc::View::addSceneSubView()
|
||||||
addSubView (CSMWorld::UniversalId::Type_Scene);
|
addSubView (CSMWorld::UniversalId::Type_Scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVDoc::View::addTopicsSubView()
|
||||||
|
{
|
||||||
|
addSubView (CSMWorld::UniversalId::Type_Topics);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::View::addJournalsSubView()
|
||||||
|
{
|
||||||
|
addSubView (CSMWorld::UniversalId::Type_Journals);
|
||||||
|
}
|
||||||
|
|
||||||
void CSVDoc::View::abortOperation (int type)
|
void CSVDoc::View::abortOperation (int type)
|
||||||
{
|
{
|
||||||
mDocument->abortOperation (type);
|
mDocument->abortOperation (type);
|
||||||
|
|
|
@ -166,6 +166,10 @@ namespace CSVDoc
|
||||||
|
|
||||||
void addSceneSubView();
|
void addSceneSubView();
|
||||||
|
|
||||||
|
void addTopicsSubView();
|
||||||
|
|
||||||
|
void addJournalsSubView();
|
||||||
|
|
||||||
void toggleShowStatusBar (bool show);
|
void toggleShowStatusBar (bool show);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,8 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
|
||||||
{ CSMWorld::ColumnBase::Display_ArmorType, CSMWorld::Columns::ColumnId_ArmorType, false },
|
{ CSMWorld::ColumnBase::Display_ArmorType, CSMWorld::Columns::ColumnId_ArmorType, false },
|
||||||
{ CSMWorld::ColumnBase::Display_ClothingType, CSMWorld::Columns::ColumnId_ClothingType, false },
|
{ CSMWorld::ColumnBase::Display_ClothingType, CSMWorld::Columns::ColumnId_ClothingType, false },
|
||||||
{ CSMWorld::ColumnBase::Display_CreatureType, CSMWorld::Columns::ColumnId_CreatureType, false },
|
{ CSMWorld::ColumnBase::Display_CreatureType, CSMWorld::Columns::ColumnId_CreatureType, false },
|
||||||
{ CSMWorld::ColumnBase::Display_WeaponType, CSMWorld::Columns::ColumnId_WeaponType, false }
|
{ CSMWorld::ColumnBase::Display_WeaponType, CSMWorld::Columns::ColumnId_WeaponType, false },
|
||||||
|
{ CSMWorld::ColumnBase::Display_DialogueType, CSMWorld::Columns::ColumnId_DialogueType, false }
|
||||||
};
|
};
|
||||||
|
|
||||||
for (std::size_t i=0; i<sizeof (sMapping)/sizeof (Mapping); ++i)
|
for (std::size_t i=0; i<sizeof (sMapping)/sizeof (Mapping); ++i)
|
||||||
|
|
|
@ -6,6 +6,11 @@
|
||||||
|
|
||||||
#include "../../model/filter/filter.hpp"
|
#include "../../model/filter/filter.hpp"
|
||||||
|
|
||||||
|
#include "../../model/world/data.hpp"
|
||||||
|
#include "../../model/world/commands.hpp"
|
||||||
|
#include "../../model/world/columns.hpp"
|
||||||
|
#include "../../model/world/idtable.hpp"
|
||||||
|
|
||||||
std::string CSVFilter::FilterCreator::getNamespace() const
|
std::string CSVFilter::FilterCreator::getNamespace() const
|
||||||
{
|
{
|
||||||
switch (mScope->currentIndex())
|
switch (mScope->currentIndex())
|
||||||
|
@ -28,6 +33,15 @@ std::string CSVFilter::FilterCreator::getId() const
|
||||||
return getNamespace() + GenericCreator::getId();
|
return getNamespace() + GenericCreator::getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVFilter::FilterCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const
|
||||||
|
{
|
||||||
|
int index =
|
||||||
|
dynamic_cast<CSMWorld::IdTable&> (*getData().getTableModel (getCollectionId())).
|
||||||
|
findColumnIndex (CSMWorld::Columns::ColumnId_Scope);
|
||||||
|
|
||||||
|
command.addValue (index, mScope->currentIndex());
|
||||||
|
}
|
||||||
|
|
||||||
CSVFilter::FilterCreator::FilterCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
CSVFilter::FilterCreator::FilterCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||||
const CSMWorld::UniversalId& id)
|
const CSMWorld::UniversalId& id)
|
||||||
: GenericCreator (data, undoStack, id)
|
: GenericCreator (data, undoStack, id)
|
||||||
|
@ -39,7 +53,7 @@ CSVFilter::FilterCreator::FilterCreator (CSMWorld::Data& data, QUndoStack& undoS
|
||||||
|
|
||||||
mScope->addItem ("Project");
|
mScope->addItem ("Project");
|
||||||
mScope->addItem ("Session");
|
mScope->addItem ("Session");
|
||||||
/// \ŧodo re-enable for OpenMW 1.1
|
/// \todo re-enable for OpenMW 1.1
|
||||||
// mScope->addItem ("Content");
|
// mScope->addItem ("Content");
|
||||||
|
|
||||||
connect (mScope, SIGNAL (currentIndexChanged (int)), this, SLOT (setScope (int)));
|
connect (mScope, SIGNAL (currentIndexChanged (int)), this, SLOT (setScope (int)));
|
||||||
|
|
|
@ -25,6 +25,8 @@ namespace CSVFilter
|
||||||
|
|
||||||
virtual std::string getId() const;
|
virtual std::string getId() const;
|
||||||
|
|
||||||
|
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FilterCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
FilterCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||||
|
|
35
apps/opencs/view/world/dialoguecreator.cpp
Normal file
35
apps/opencs/view/world/dialoguecreator.cpp
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
#include "dialoguecreator.hpp"
|
||||||
|
|
||||||
|
#include <components/esm/loaddial.hpp>
|
||||||
|
|
||||||
|
#include "../../model/world/data.hpp"
|
||||||
|
#include "../../model/world/commands.hpp"
|
||||||
|
#include "../../model/world/columns.hpp"
|
||||||
|
#include "../../model/world/idtable.hpp"
|
||||||
|
|
||||||
|
void CSVWorld::DialogueCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const
|
||||||
|
{
|
||||||
|
int index =
|
||||||
|
dynamic_cast<CSMWorld::IdTable&> (*getData().getTableModel (getCollectionId())).
|
||||||
|
findColumnIndex (CSMWorld::Columns::ColumnId_DialogueType);
|
||||||
|
|
||||||
|
command.addValue (index, mType);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVWorld::DialogueCreator::DialogueCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||||
|
const CSMWorld::UniversalId& id, int type)
|
||||||
|
: GenericCreator (data, undoStack, id), mType (type)
|
||||||
|
{}
|
||||||
|
|
||||||
|
CSVWorld::Creator *CSVWorld::TopicCreatorFactory::makeCreator (CSMWorld::Data& data,
|
||||||
|
QUndoStack& undoStack, const CSMWorld::UniversalId& id) const
|
||||||
|
{
|
||||||
|
return new DialogueCreator (data, undoStack, id, ESM::Dialogue::Topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVWorld::Creator *CSVWorld::JournalCreatorFactory::makeCreator (CSMWorld::Data& data,
|
||||||
|
QUndoStack& undoStack, const CSMWorld::UniversalId& id) const
|
||||||
|
{
|
||||||
|
return new DialogueCreator (data, undoStack, id, ESM::Dialogue::Journal);
|
||||||
|
}
|
41
apps/opencs/view/world/dialoguecreator.hpp
Normal file
41
apps/opencs/view/world/dialoguecreator.hpp
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef CSV_WORLD_DIALOGUECREATOR_H
|
||||||
|
#define CSV_WORLD_DIALOGUECREATOR_H
|
||||||
|
|
||||||
|
#include "genericcreator.hpp"
|
||||||
|
|
||||||
|
namespace CSVWorld
|
||||||
|
{
|
||||||
|
class DialogueCreator : public GenericCreator
|
||||||
|
{
|
||||||
|
int mType;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DialogueCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||||
|
const CSMWorld::UniversalId& id, int type);
|
||||||
|
};
|
||||||
|
|
||||||
|
class TopicCreatorFactory : public CreatorFactoryBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||||
|
const CSMWorld::UniversalId& id) const;
|
||||||
|
///< The ownership of the returned Creator is transferred to the caller.
|
||||||
|
};
|
||||||
|
|
||||||
|
class JournalCreatorFactory : public CreatorFactoryBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||||
|
const CSMWorld::UniversalId& id) const;
|
||||||
|
///< The ownership of the returned Creator is transferred to the caller.
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -14,6 +14,7 @@
|
||||||
#include "referenceablecreator.hpp"
|
#include "referenceablecreator.hpp"
|
||||||
#include "referencecreator.hpp"
|
#include "referencecreator.hpp"
|
||||||
#include "scenesubview.hpp"
|
#include "scenesubview.hpp"
|
||||||
|
#include "dialoguecreator.hpp"
|
||||||
|
|
||||||
void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
||||||
{
|
{
|
||||||
|
@ -53,6 +54,12 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
||||||
manager.add (CSMWorld::UniversalId::Type_References,
|
manager.add (CSMWorld::UniversalId::Type_References,
|
||||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<ReferenceCreator> >);
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<ReferenceCreator> >);
|
||||||
|
|
||||||
|
manager.add (CSMWorld::UniversalId::Type_Topics,
|
||||||
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, TopicCreatorFactory>);
|
||||||
|
|
||||||
|
manager.add (CSMWorld::UniversalId::Type_Journal,
|
||||||
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, JournalCreatorFactory>);
|
||||||
|
|
||||||
// Subviews for editing/viewing individual records
|
// Subviews for editing/viewing individual records
|
||||||
manager.add (CSMWorld::UniversalId::Type_Script, new CSVDoc::SubViewFactory<ScriptSubView>);
|
manager.add (CSMWorld::UniversalId::Type_Script, new CSVDoc::SubViewFactory<ScriptSubView>);
|
||||||
|
|
||||||
|
|
|
@ -87,12 +87,27 @@ std::vector<std::string> CSVWorld::Table::listDeletableSelectedIds() const
|
||||||
{
|
{
|
||||||
QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0));
|
QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0));
|
||||||
|
|
||||||
|
// check record state
|
||||||
CSMWorld::RecordBase::State state =
|
CSMWorld::RecordBase::State state =
|
||||||
static_cast<CSMWorld::RecordBase::State> (
|
static_cast<CSMWorld::RecordBase::State> (
|
||||||
mModel->data (mModel->index (index.row(), 1)).toInt());
|
mModel->data (mModel->index (index.row(), 1)).toInt());
|
||||||
|
|
||||||
if (state!=CSMWorld::RecordBase::State_Deleted)
|
if (state==CSMWorld::RecordBase::State_Deleted)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// check other columns (only relevant for a subset of the tables)
|
||||||
|
int dialogueTypeIndex =
|
||||||
|
mModel->searchColumnIndex (CSMWorld::Columns::ColumnId_DialogueType);
|
||||||
|
|
||||||
|
if (dialogueTypeIndex!=-1)
|
||||||
{
|
{
|
||||||
|
int type = mModel->data (mModel->index (index.row(), dialogueTypeIndex)).toInt();
|
||||||
|
|
||||||
|
if (type!=ESM::Dialogue::Topic && type!=ESM::Dialogue::Journal)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the id to the collection
|
||||||
int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
|
int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
|
||||||
|
|
||||||
std::string id = mModel->data (mModel->index (index.row(), columnIndex)).
|
std::string id = mModel->data (mModel->index (index.row(), columnIndex)).
|
||||||
|
@ -101,7 +116,6 @@ std::vector<std::string> CSVWorld::Table::listDeletableSelectedIds() const
|
||||||
deletableIds.push_back (id);
|
deletableIds.push_back (id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return deletableIds;
|
return deletableIds;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,7 @@ add_openmw_dir (mwworld
|
||||||
cells localscripts customdata weather inventorystore ptr actionopen actionread
|
cells localscripts customdata weather inventorystore ptr actionopen actionread
|
||||||
actionequip timestamp actionalchemy cellstore actionapply actioneat
|
actionequip timestamp actionalchemy cellstore actionapply actioneat
|
||||||
esmstore store recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
|
esmstore store recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
|
||||||
|
contentloader esmloader omwloader
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwclass
|
add_openmw_dir (mwclass
|
||||||
|
|
|
@ -261,34 +261,14 @@ void OMW::Engine::setCell (const std::string& cellName)
|
||||||
mCellName = cellName;
|
mCellName = cellName;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set master file (esm)
|
void OMW::Engine::addContentFile(const std::string& file)
|
||||||
// - If the given name does not have an extension, ".esm" is added automatically
|
|
||||||
|
|
||||||
void OMW::Engine::addMaster (const std::string& master)
|
|
||||||
{
|
{
|
||||||
mMaster.push_back(master);
|
if (file.find_last_of(".") == std::string::npos)
|
||||||
std::string &str = mMaster.back();
|
|
||||||
|
|
||||||
// Append .esm if not already there
|
|
||||||
std::string::size_type sep = str.find_last_of (".");
|
|
||||||
if (sep == std::string::npos)
|
|
||||||
{
|
{
|
||||||
str += ".esm";
|
throw std::runtime_error("Missing extension in content file!");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Add plugin file (esp)
|
mContentFiles.push_back(file);
|
||||||
void OMW::Engine::addPlugin (const std::string& plugin)
|
|
||||||
{
|
|
||||||
mPlugins.push_back(plugin);
|
|
||||||
std::string &str = mPlugins.back();
|
|
||||||
|
|
||||||
// Append .esp if not already there
|
|
||||||
std::string::size_type sep = str.find_last_of (".");
|
|
||||||
if (sep == std::string::npos)
|
|
||||||
{
|
|
||||||
str += ".esp";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OMW::Engine::setScriptsVerbosity(bool scriptsVerbosity)
|
void OMW::Engine::setScriptsVerbosity(bool scriptsVerbosity)
|
||||||
|
@ -401,7 +381,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
mEnvironment.setWindowManager (window);
|
mEnvironment.setWindowManager (window);
|
||||||
|
|
||||||
// Create the world
|
// Create the world
|
||||||
mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mMaster, mPlugins,
|
mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mContentFiles,
|
||||||
mResDir, mCfgMgr.getCachePath(), mEncoder, mFallbackMap,
|
mResDir, mCfgMgr.getCachePath(), mEncoder, mFallbackMap,
|
||||||
mActivationDistanceOverride));
|
mActivationDistanceOverride));
|
||||||
MWBase::Environment::get().getWorld()->setupPlayer();
|
MWBase::Environment::get().getWorld()->setupPlayer();
|
||||||
|
@ -416,8 +396,8 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
|
|
||||||
//Load translation data
|
//Load translation data
|
||||||
mTranslationDataStorage.setEncoder(mEncoder);
|
mTranslationDataStorage.setEncoder(mEncoder);
|
||||||
for (size_t i = 0; i < mMaster.size(); i++)
|
for (size_t i = 0; i < mContentFiles.size(); i++)
|
||||||
mTranslationDataStorage.loadTranslationData(mFileCollections, mMaster[i]);
|
mTranslationDataStorage.loadTranslationData(mFileCollections, mContentFiles[i]);
|
||||||
|
|
||||||
Compiler::registerExtensions (mExtensions);
|
Compiler::registerExtensions (mExtensions);
|
||||||
|
|
||||||
|
@ -482,7 +462,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||||
void OMW::Engine::go()
|
void OMW::Engine::go()
|
||||||
{
|
{
|
||||||
assert (!mCellName.empty());
|
assert (!mCellName.empty());
|
||||||
assert (!mMaster.empty());
|
assert (!mContentFiles.empty());
|
||||||
assert (!mOgre);
|
assert (!mOgre);
|
||||||
|
|
||||||
Settings::Manager settings;
|
Settings::Manager settings;
|
||||||
|
|
|
@ -68,8 +68,7 @@ namespace OMW
|
||||||
boost::filesystem::path mResDir;
|
boost::filesystem::path mResDir;
|
||||||
OEngine::Render::OgreRenderer *mOgre;
|
OEngine::Render::OgreRenderer *mOgre;
|
||||||
std::string mCellName;
|
std::string mCellName;
|
||||||
std::vector<std::string> mMaster;
|
std::vector<std::string> mContentFiles;
|
||||||
std::vector<std::string> mPlugins;
|
|
||||||
int mFpsLevel;
|
int mFpsLevel;
|
||||||
bool mVerboseScripts;
|
bool mVerboseScripts;
|
||||||
bool mNewGame;
|
bool mNewGame;
|
||||||
|
@ -135,13 +134,11 @@ namespace OMW
|
||||||
/// Set start cell name (only interiors for now)
|
/// Set start cell name (only interiors for now)
|
||||||
void setCell(const std::string& cellName);
|
void setCell(const std::string& cellName);
|
||||||
|
|
||||||
/// Set master file (esm)
|
/**
|
||||||
/// - If the given name does not have an extension, ".esm" is added automatically
|
* @brief addContentFile - Adds content file (ie. esm/esp, or omwgame/omwaddon) to the content files container.
|
||||||
void addMaster(const std::string& master);
|
* @param file - filename (extension is required)
|
||||||
|
*/
|
||||||
/// Same as "addMaster", but for plugin files (esp)
|
void addContentFile(const std::string& file);
|
||||||
/// - If the given name does not have an extension, ".esp" is added automatically
|
|
||||||
void addPlugin(const std::string& plugin);
|
|
||||||
|
|
||||||
/// Enable fps counter
|
/// Enable fps counter
|
||||||
void showFPS(int level);
|
void showFPS(int level);
|
||||||
|
|
|
@ -110,11 +110,8 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
||||||
("start", bpo::value<std::string>()->default_value("Beshara"),
|
("start", bpo::value<std::string>()->default_value("Beshara"),
|
||||||
"set initial cell")
|
"set initial cell")
|
||||||
|
|
||||||
("master", bpo::value<StringsVector>()->default_value(StringsVector(), "")
|
("content", bpo::value<StringsVector>()->default_value(StringsVector(), "")
|
||||||
->multitoken(), "master file(s)")
|
->multitoken(), "content file(s): esm/esp, or omwgame/omwaddon")
|
||||||
|
|
||||||
("plugin", bpo::value<StringsVector>()->default_value(StringsVector(), "")
|
|
||||||
->multitoken(), "plugin file(s)")
|
|
||||||
|
|
||||||
("anim-verbose", bpo::value<bool>()->implicit_value(true)
|
("anim-verbose", bpo::value<bool>()->implicit_value(true)
|
||||||
->default_value(false), "output animation indices files")
|
->default_value(false), "output animation indices files")
|
||||||
|
@ -152,8 +149,6 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
||||||
|
|
||||||
("activate-dist", bpo::value <int> ()->default_value (-1), "activation distance override");
|
("activate-dist", bpo::value <int> ()->default_value (-1), "activation distance override");
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv)
|
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv)
|
||||||
.options(desc).allow_unregistered().run();
|
.options(desc).allow_unregistered().run();
|
||||||
|
|
||||||
|
@ -211,29 +206,18 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
||||||
|
|
||||||
engine.setResourceDir(variables["resources"].as<std::string>());
|
engine.setResourceDir(variables["resources"].as<std::string>());
|
||||||
|
|
||||||
// master and plugin
|
StringsVector content = variables["content"].as<StringsVector>();
|
||||||
StringsVector master = variables["master"].as<StringsVector>();
|
if (content.empty())
|
||||||
if (master.empty())
|
|
||||||
{
|
{
|
||||||
std::cout << "No master file given. Aborting...\n";
|
std::cout << "No content file given (esm/esp, nor omwgame/omwaddon). Aborting..." << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringsVector plugin = variables["plugin"].as<StringsVector>();
|
StringsVector::const_iterator it(content.begin());
|
||||||
// Removed check for 255 files, which would be the hard-coded limit in Morrowind.
|
StringsVector::const_iterator end(content.end());
|
||||||
// I'll keep the following variable in, maybe we can use it for something different.
|
for (; it != end; ++it)
|
||||||
// Say, a feedback like "loading file x/cnt".
|
|
||||||
// Commenting this out for now to silence compiler warning.
|
|
||||||
//int cnt = master.size() + plugin.size();
|
|
||||||
|
|
||||||
// Prepare loading master/plugin files (i.e. send filenames to engine)
|
|
||||||
for (std::vector<std::string>::size_type i = 0; i < master.size(); i++)
|
|
||||||
{
|
{
|
||||||
engine.addMaster(master[i]);
|
engine.addContentFile(*it);
|
||||||
}
|
|
||||||
for (std::vector<std::string>::size_type i = 0; i < plugin.size(); i++)
|
|
||||||
{
|
|
||||||
engine.addPlugin(plugin[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// startup-settings
|
// startup-settings
|
||||||
|
|
35
apps/openmw/mwworld/contentloader.hpp
Normal file
35
apps/openmw/mwworld/contentloader.hpp
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef CONTENTLOADER_HPP
|
||||||
|
#define CONTENTLOADER_HPP
|
||||||
|
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
#include "components/loadinglistener/loadinglistener.hpp"
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
|
||||||
|
struct ContentLoader
|
||||||
|
{
|
||||||
|
ContentLoader(Loading::Listener& listener)
|
||||||
|
: mListener(listener)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~ContentLoader()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void load(const boost::filesystem::path& filepath, int& index)
|
||||||
|
{
|
||||||
|
std::cout << "Loading content file " << filepath.string() << std::endl;
|
||||||
|
mListener.setLabel(filepath.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Loading::Listener& mListener;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace MWWorld */
|
||||||
|
|
||||||
|
#endif /* CONTENTLOADER_HPP */
|
31
apps/openmw/mwworld/esmloader.cpp
Normal file
31
apps/openmw/mwworld/esmloader.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include "esmloader.hpp"
|
||||||
|
#include "esmstore.hpp"
|
||||||
|
|
||||||
|
#include "components/to_utf8/to_utf8.hpp"
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
|
||||||
|
EsmLoader::EsmLoader(MWWorld::ESMStore& store, std::vector<ESM::ESMReader>& readers,
|
||||||
|
ToUTF8::Utf8Encoder* encoder, Loading::Listener& listener)
|
||||||
|
: ContentLoader(listener)
|
||||||
|
, mStore(store)
|
||||||
|
, mEsm(readers)
|
||||||
|
, mEncoder(encoder)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void EsmLoader::load(const boost::filesystem::path& filepath, int& index)
|
||||||
|
{
|
||||||
|
ContentLoader::load(filepath.filename(), index);
|
||||||
|
|
||||||
|
ESM::ESMReader lEsm;
|
||||||
|
lEsm.setEncoder(mEncoder);
|
||||||
|
lEsm.setIndex(index);
|
||||||
|
lEsm.setGlobalReaderList(&mEsm);
|
||||||
|
lEsm.open(filepath.string());
|
||||||
|
mEsm[index] = lEsm;
|
||||||
|
mStore.load(mEsm[index], &mListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace MWWorld */
|
34
apps/openmw/mwworld/esmloader.hpp
Normal file
34
apps/openmw/mwworld/esmloader.hpp
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef ESMLOADER_HPP
|
||||||
|
#define ESMLOADER_HPP
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "contentloader.hpp"
|
||||||
|
#include "components/esm/esmreader.hpp"
|
||||||
|
|
||||||
|
namespace ToUTF8
|
||||||
|
{
|
||||||
|
class Utf8Encoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
|
||||||
|
class ESMStore;
|
||||||
|
|
||||||
|
struct EsmLoader : public ContentLoader
|
||||||
|
{
|
||||||
|
EsmLoader(MWWorld::ESMStore& store, std::vector<ESM::ESMReader>& readers,
|
||||||
|
ToUTF8::Utf8Encoder* encoder, Loading::Listener& listener);
|
||||||
|
|
||||||
|
void load(const boost::filesystem::path& filepath, int& index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<ESM::ESMReader>& mEsm;
|
||||||
|
MWWorld::ESMStore& mStore;
|
||||||
|
ToUTF8::Utf8Encoder* mEncoder;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace MWWorld */
|
||||||
|
|
||||||
|
#endif // ESMLOADER_HPP
|
17
apps/openmw/mwworld/omwloader.cpp
Normal file
17
apps/openmw/mwworld/omwloader.cpp
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#include "omwloader.hpp"
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
|
||||||
|
OmwLoader::OmwLoader(Loading::Listener& listener)
|
||||||
|
: ContentLoader(listener)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void OmwLoader::load(const boost::filesystem::path& filepath, int& index)
|
||||||
|
{
|
||||||
|
ContentLoader::load(filepath.filename(), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace MWWorld */
|
||||||
|
|
21
apps/openmw/mwworld/omwloader.hpp
Normal file
21
apps/openmw/mwworld/omwloader.hpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef OMWLOADER_HPP
|
||||||
|
#define OMWLOADER_HPP
|
||||||
|
|
||||||
|
#include "contentloader.hpp"
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Placeholder for real OpenMW content loader
|
||||||
|
*/
|
||||||
|
struct OmwLoader : public ContentLoader
|
||||||
|
{
|
||||||
|
OmwLoader(Loading::Listener& listener);
|
||||||
|
|
||||||
|
void load(const boost::filesystem::path& filepath, int& index);
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace MWWorld */
|
||||||
|
|
||||||
|
#endif /* OMWLOADER_HPP */
|
|
@ -1,4 +1,11 @@
|
||||||
#include "worldimp.hpp"
|
#include "worldimp.hpp"
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <boost/tr1/tr1/unordered_map>
|
||||||
|
#elif defined HAVE_UNORDERED_MAP
|
||||||
|
#include <unordered_map>
|
||||||
|
#else
|
||||||
|
#include <tr1/unordered_map>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <OgreSceneNode.h>
|
#include <OgreSceneNode.h>
|
||||||
|
|
||||||
|
@ -31,6 +38,10 @@
|
||||||
#include "containerstore.hpp"
|
#include "containerstore.hpp"
|
||||||
#include "inventorystore.hpp"
|
#include "inventorystore.hpp"
|
||||||
|
|
||||||
|
#include "contentloader.hpp"
|
||||||
|
#include "esmloader.hpp"
|
||||||
|
#include "omwloader.hpp"
|
||||||
|
|
||||||
using namespace Ogre;
|
using namespace Ogre;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
@ -80,6 +91,38 @@ namespace
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
|
struct GameContentLoader : public ContentLoader
|
||||||
|
{
|
||||||
|
GameContentLoader(Loading::Listener& listener)
|
||||||
|
: ContentLoader(listener)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool addLoader(const std::string& extension, ContentLoader* loader)
|
||||||
|
{
|
||||||
|
return mLoaders.insert(std::make_pair(extension, loader)).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load(const boost::filesystem::path& filepath, int& index)
|
||||||
|
{
|
||||||
|
LoadersContainer::iterator it(mLoaders.find(filepath.extension().string()));
|
||||||
|
if (it != mLoaders.end())
|
||||||
|
{
|
||||||
|
it->second->load(filepath, index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string msg("Cannot load file: ");
|
||||||
|
msg += filepath.string();
|
||||||
|
throw std::runtime_error(msg.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::tr1::unordered_map<std::string, ContentLoader*> LoadersContainer;
|
||||||
|
LoadersContainer mLoaders;
|
||||||
|
};
|
||||||
|
|
||||||
Ptr World::getPtrViaHandle (const std::string& handle, Ptr::CellStore& cell)
|
Ptr World::getPtrViaHandle (const std::string& handle, Ptr::CellStore& cell)
|
||||||
{
|
{
|
||||||
if (MWWorld::LiveCellRef<ESM::Activator> *ref =
|
if (MWWorld::LiveCellRef<ESM::Activator> *ref =
|
||||||
|
@ -163,7 +206,7 @@ namespace MWWorld
|
||||||
|
|
||||||
World::World (OEngine::Render::OgreRenderer& renderer,
|
World::World (OEngine::Render::OgreRenderer& renderer,
|
||||||
const Files::Collections& fileCollections,
|
const Files::Collections& fileCollections,
|
||||||
const std::vector<std::string>& master, const std::vector<std::string>& plugins,
|
const std::vector<std::string>& contentFiles,
|
||||||
const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir,
|
const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir,
|
||||||
ToUTF8::Utf8Encoder* encoder, const std::map<std::string,std::string>& fallbackMap, int mActivationDistanceOverride)
|
ToUTF8::Utf8Encoder* encoder, const std::map<std::string,std::string>& fallbackMap, int mActivationDistanceOverride)
|
||||||
: mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0),
|
: mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0),
|
||||||
|
@ -181,44 +224,22 @@ namespace MWWorld
|
||||||
|
|
||||||
mWeatherManager = new MWWorld::WeatherManager(mRendering,&mFallback);
|
mWeatherManager = new MWWorld::WeatherManager(mRendering,&mFallback);
|
||||||
|
|
||||||
int idx = 0;
|
|
||||||
// NOTE: We might need to reserve one more for the running game / save.
|
// NOTE: We might need to reserve one more for the running game / save.
|
||||||
mEsm.resize(master.size() + plugins.size());
|
mEsm.resize(contentFiles.size());
|
||||||
Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
||||||
listener->loadingOn();
|
listener->loadingOn();
|
||||||
for (std::vector<std::string>::size_type i = 0; i < master.size(); i++, idx++)
|
|
||||||
{
|
|
||||||
boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master[i]));
|
|
||||||
|
|
||||||
std::cout << "Loading ESM " << masterPath.string() << "\n";
|
GameContentLoader gameContentLoader(*listener);
|
||||||
listener->setLabel(masterPath.filename().string());
|
EsmLoader esmLoader(mStore, mEsm, encoder, *listener);
|
||||||
|
OmwLoader omwLoader(*listener);
|
||||||
|
|
||||||
// This parses the ESM file
|
gameContentLoader.addLoader(".esm", &esmLoader);
|
||||||
ESM::ESMReader lEsm;
|
gameContentLoader.addLoader(".esp", &esmLoader);
|
||||||
lEsm.setEncoder(encoder);
|
gameContentLoader.addLoader(".omwgame", &omwLoader);
|
||||||
lEsm.setIndex(idx);
|
gameContentLoader.addLoader(".omwaddon", &omwLoader);
|
||||||
lEsm.setGlobalReaderList(&mEsm);
|
|
||||||
lEsm.open (masterPath.string());
|
|
||||||
mEsm[idx] = lEsm;
|
|
||||||
mStore.load (mEsm[idx], listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (std::vector<std::string>::size_type i = 0; i < plugins.size(); i++, idx++)
|
loadContentFiles(fileCollections, contentFiles, gameContentLoader);
|
||||||
{
|
|
||||||
boost::filesystem::path pluginPath (fileCollections.getCollection (".esp").getPath (plugins[i]));
|
|
||||||
|
|
||||||
std::cout << "Loading ESP " << pluginPath.string() << "\n";
|
|
||||||
listener->setLabel(pluginPath.filename().string());
|
|
||||||
|
|
||||||
// This parses the ESP file
|
|
||||||
ESM::ESMReader lEsm;
|
|
||||||
lEsm.setEncoder(encoder);
|
|
||||||
lEsm.setIndex(idx);
|
|
||||||
lEsm.setGlobalReaderList(&mEsm);
|
|
||||||
lEsm.open (pluginPath.string());
|
|
||||||
mEsm[idx] = lEsm;
|
|
||||||
mStore.load (mEsm[idx], listener);
|
|
||||||
}
|
|
||||||
listener->loadingOff();
|
listener->loadingOff();
|
||||||
|
|
||||||
// insert records that may not be present in all versions of MW
|
// insert records that may not be present in all versions of MW
|
||||||
|
@ -1983,4 +2004,19 @@ namespace MWWorld
|
||||||
return mGodMode;
|
return mGodMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::loadContentFiles(const Files::Collections& fileCollections,
|
||||||
|
const std::vector<std::string>& content, ContentLoader& contentLoader)
|
||||||
|
{
|
||||||
|
std::vector<std::string>::const_iterator it(content.begin());
|
||||||
|
std::vector<std::string>::const_iterator end(content.end());
|
||||||
|
for (int idx = 0; it != end; ++it, ++idx)
|
||||||
|
{
|
||||||
|
boost::filesystem::path filename(*it);
|
||||||
|
const Files::MultiDirCollection& col = fileCollections.getCollection(filename.extension().string());
|
||||||
|
if (col.doesExist(*it))
|
||||||
|
{
|
||||||
|
contentLoader.load(col.getPath(*it), idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
#include "contentloader.hpp"
|
||||||
|
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
class Vector3;
|
class Vector3;
|
||||||
|
@ -41,6 +43,8 @@ namespace MWRender
|
||||||
class Animation;
|
class Animation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ContentLoader;
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
class WeatherManager;
|
class WeatherManager;
|
||||||
|
@ -113,6 +117,15 @@ namespace MWWorld
|
||||||
|
|
||||||
void ensureNeededRecords();
|
void ensureNeededRecords();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief loadContentFiles - Loads content files (esm,esp,omwgame,omwaddon)
|
||||||
|
* @param fileCollections- Container which holds content file names and their paths
|
||||||
|
* @param content - Container which holds content file names
|
||||||
|
* @param contentLoader -
|
||||||
|
*/
|
||||||
|
void loadContentFiles(const Files::Collections& fileCollections,
|
||||||
|
const std::vector<std::string>& content, ContentLoader& contentLoader);
|
||||||
|
|
||||||
int mPlayIntro;
|
int mPlayIntro;
|
||||||
|
|
||||||
bool mTeleportEnabled;
|
bool mTeleportEnabled;
|
||||||
|
@ -122,7 +135,7 @@ namespace MWWorld
|
||||||
|
|
||||||
World (OEngine::Render::OgreRenderer& renderer,
|
World (OEngine::Render::OgreRenderer& renderer,
|
||||||
const Files::Collections& fileCollections,
|
const Files::Collections& fileCollections,
|
||||||
const std::vector<std::string>& master, const std::vector<std::string>& plugins,
|
const std::vector<std::string>& contentFiles,
|
||||||
const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir,
|
const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir,
|
||||||
ToUTF8::Utf8Encoder* encoder, const std::map<std::string,std::string>& fallbackMap, int mActivationDistanceOverride);
|
ToUTF8::Utf8Encoder* encoder, const std::map<std::string,std::string>& fallbackMap, int mActivationDistanceOverride);
|
||||||
|
|
||||||
|
|
|
@ -44,9 +44,9 @@ namespace ESM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AIPackageList::save(ESMWriter &esm)
|
void AIPackageList::save(ESMWriter &esm) const
|
||||||
{
|
{
|
||||||
typedef std::vector<AIPackage>::iterator PackageIter;
|
typedef std::vector<AIPackage>::const_iterator PackageIter;
|
||||||
for (PackageIter it = mList.begin(); it != mList.end(); ++it) {
|
for (PackageIter it = mList.begin(); it != mList.end(); ++it) {
|
||||||
switch (it->mType) {
|
switch (it->mType) {
|
||||||
case AI_Wander:
|
case AI_Wander:
|
||||||
|
|
|
@ -93,7 +93,7 @@ namespace ESM
|
||||||
/// it needs to use retSubName() if needed. But, hey, there
|
/// it needs to use retSubName() if needed. But, hey, there
|
||||||
/// is only one field left (XSCL) and only two records uses AI
|
/// is only one field left (XSCL) and only two records uses AI
|
||||||
void load(ESMReader &esm);
|
void load(ESMReader &esm);
|
||||||
void save(ESMWriter &esm);
|
void save(ESMWriter &esm) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include "esmwriter.hpp"
|
#include "esmwriter.hpp"
|
||||||
|
|
||||||
void ESM::CellRef::save(ESMWriter &esm)
|
void ESM::CellRef::save(ESMWriter &esm) const
|
||||||
{
|
{
|
||||||
esm.writeHNT("FRMR", mRefnum);
|
esm.writeHNT("FRMR", mRefnum);
|
||||||
esm.writeHNCString("NAME", mRefID);
|
esm.writeHNCString("NAME", mRefID);
|
||||||
|
|
|
@ -83,7 +83,7 @@ namespace ESM
|
||||||
// Position and rotation of this object within the cell
|
// Position and rotation of this object within the cell
|
||||||
Position mPos;
|
Position mPos;
|
||||||
|
|
||||||
void save(ESMWriter &esm);
|
void save(ESMWriter &esm) const;
|
||||||
|
|
||||||
void blank();
|
void blank();
|
||||||
};
|
};
|
||||||
|
|
|
@ -36,6 +36,7 @@ struct Position
|
||||||
|
|
||||||
enum RecNameInts
|
enum RecNameInts
|
||||||
{
|
{
|
||||||
|
// format 0 / legacy
|
||||||
REC_ACTI = 0x49544341,
|
REC_ACTI = 0x49544341,
|
||||||
REC_ALCH = 0x48434c41,
|
REC_ALCH = 0x48434c41,
|
||||||
REC_APPA = 0x41505041,
|
REC_APPA = 0x41505041,
|
||||||
|
@ -80,7 +81,10 @@ enum RecNameInts
|
||||||
REC_SPEL = 0x4c455053,
|
REC_SPEL = 0x4c455053,
|
||||||
REC_SSCR = 0x52435353,
|
REC_SSCR = 0x52435353,
|
||||||
REC_STAT = 0x54415453,
|
REC_STAT = 0x54415453,
|
||||||
REC_WEAP = 0x50414557
|
REC_WEAP = 0x50414557,
|
||||||
|
|
||||||
|
// format 1
|
||||||
|
REC_FILT = 0x544C4946
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,9 @@ void EffectList::load(ESMReader &esm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectList::save(ESMWriter &esm)
|
void EffectList::save(ESMWriter &esm) const
|
||||||
{
|
{
|
||||||
for (std::vector<ENAMstruct>::iterator it = mList.begin(); it != mList.end(); ++it) {
|
for (std::vector<ENAMstruct>::const_iterator it = mList.begin(); it != mList.end(); ++it) {
|
||||||
esm.writeHNT<ENAMstruct>("ENAM", *it, 24);
|
esm.writeHNT<ENAMstruct>("ENAM", *it, 24);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ namespace ESM
|
||||||
std::vector<ENAMstruct> mList;
|
std::vector<ENAMstruct> mList;
|
||||||
|
|
||||||
void load(ESMReader &esm);
|
void load(ESMReader &esm);
|
||||||
void save(ESMWriter &esm);
|
void save(ESMWriter &esm) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,132 +2,136 @@
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <stdexcept>
|
||||||
|
|
||||||
bool count = true;
|
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
ESMWriter::ESMWriter() : mRecordCount (0), mCounting (true) {}
|
||||||
|
|
||||||
int ESMWriter::getVersion()
|
unsigned int ESMWriter::getVersion() const
|
||||||
{
|
{
|
||||||
return mHeader.mData.version;
|
return mHeader.mData.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::setVersion(int ver)
|
void ESMWriter::setVersion(unsigned int ver)
|
||||||
{
|
{
|
||||||
mHeader.mData.version = ver;
|
mHeader.mData.version = ver;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::setAuthor(const std::string& auth)
|
void ESMWriter::setAuthor(const std::string& auth)
|
||||||
{
|
{
|
||||||
mHeader.mData.author.assign (auth);
|
mHeader.mData.author.assign (auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::setDescription(const std::string& desc)
|
void ESMWriter::setDescription(const std::string& desc)
|
||||||
{
|
{
|
||||||
mHeader.mData.desc.assign (desc);
|
mHeader.mData.desc.assign (desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::setRecordCount (int count)
|
void ESMWriter::setRecordCount (int count)
|
||||||
{
|
{
|
||||||
mHeader.mData.records = count;
|
mHeader.mData.records = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::setFormat (int format)
|
void ESMWriter::setFormat (int format)
|
||||||
{
|
{
|
||||||
mHeader.mFormat = format;
|
mHeader.mFormat = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::addMaster(const std::string& name, uint64_t size)
|
void ESMWriter::clearMaster()
|
||||||
{
|
{
|
||||||
|
mHeader.mMaster.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESMWriter::addMaster(const std::string& name, uint64_t size)
|
||||||
|
{
|
||||||
Header::MasterData d;
|
Header::MasterData d;
|
||||||
d.name = name;
|
d.name = name;
|
||||||
d.size = size;
|
d.size = size;
|
||||||
mHeader.mMaster.push_back(d);
|
mHeader.mMaster.push_back(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::save(const std::string& file)
|
void ESMWriter::save(const std::string& file)
|
||||||
{
|
{
|
||||||
std::ofstream fs(file.c_str(), std::ios_base::out | std::ios_base::trunc);
|
std::ofstream fs(file.c_str(), std::ios_base::out | std::ios_base::trunc);
|
||||||
save(fs);
|
save(fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::save(std::ostream& file)
|
void ESMWriter::save(std::ostream& file)
|
||||||
{
|
{
|
||||||
m_recordCount = 0;
|
mRecordCount = 0;
|
||||||
m_stream = &file;
|
mRecords.clear();
|
||||||
|
mCounting = true;
|
||||||
|
mStream = &file;
|
||||||
|
|
||||||
startRecord("TES3", 0);
|
startRecord("TES3", 0);
|
||||||
|
|
||||||
mHeader.save (*this);
|
mHeader.save (*this);
|
||||||
|
|
||||||
endRecord("TES3");
|
endRecord("TES3");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::close()
|
void ESMWriter::close()
|
||||||
{
|
{
|
||||||
m_stream->flush();
|
if (!mRecords.empty())
|
||||||
|
throw std::runtime_error ("Unclosed record remaining");
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_records.empty())
|
void ESMWriter::startRecord(const std::string& name, uint32_t flags)
|
||||||
throw "Unclosed record remaining";
|
{
|
||||||
}
|
mRecordCount++;
|
||||||
|
|
||||||
void ESMWriter::startRecord(const std::string& name, uint32_t flags)
|
|
||||||
{
|
|
||||||
m_recordCount++;
|
|
||||||
|
|
||||||
writeName(name);
|
writeName(name);
|
||||||
RecordData rec;
|
RecordData rec;
|
||||||
rec.name = name;
|
rec.name = name;
|
||||||
rec.position = m_stream->tellp();
|
rec.position = mStream->tellp();
|
||||||
rec.size = 0;
|
rec.size = 0;
|
||||||
writeT<int>(0); // Size goes here
|
writeT<int>(0); // Size goes here
|
||||||
writeT<int>(0); // Unused header?
|
writeT<int>(0); // Unused header?
|
||||||
writeT(flags);
|
writeT(flags);
|
||||||
m_records.push_back(rec);
|
mRecords.push_back(rec);
|
||||||
|
|
||||||
assert(m_records.back().size == 0);
|
assert(mRecords.back().size == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::startSubRecord(const std::string& name)
|
void ESMWriter::startSubRecord(const std::string& name)
|
||||||
{
|
{
|
||||||
writeName(name);
|
writeName(name);
|
||||||
RecordData rec;
|
RecordData rec;
|
||||||
rec.name = name;
|
rec.name = name;
|
||||||
rec.position = m_stream->tellp();
|
rec.position = mStream->tellp();
|
||||||
rec.size = 0;
|
rec.size = 0;
|
||||||
writeT<int>(0); // Size goes here
|
writeT<int>(0); // Size goes here
|
||||||
m_records.push_back(rec);
|
mRecords.push_back(rec);
|
||||||
|
|
||||||
assert(m_records.back().size == 0);
|
assert(mRecords.back().size == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::endRecord(const std::string& name)
|
void ESMWriter::endRecord(const std::string& name)
|
||||||
{
|
{
|
||||||
RecordData rec = m_records.back();
|
RecordData rec = mRecords.back();
|
||||||
assert(rec.name == name);
|
assert(rec.name == name);
|
||||||
m_records.pop_back();
|
mRecords.pop_back();
|
||||||
|
|
||||||
m_stream->seekp(rec.position);
|
mStream->seekp(rec.position);
|
||||||
|
|
||||||
count = false;
|
mCounting = false;
|
||||||
write((char*)&rec.size, sizeof(int));
|
write (reinterpret_cast<const char*> (&rec.size), sizeof(int));
|
||||||
count = true;
|
mCounting = true;
|
||||||
|
|
||||||
m_stream->seekp(0, std::ios::end);
|
mStream->seekp(0, std::ios::end);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::writeHNString(const std::string& name, const std::string& data)
|
void ESMWriter::writeHNString(const std::string& name, const std::string& data)
|
||||||
{
|
{
|
||||||
startSubRecord(name);
|
startSubRecord(name);
|
||||||
writeHString(data);
|
writeHString(data);
|
||||||
endRecord(name);
|
endRecord(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::writeHNString(const std::string& name, const std::string& data, size_t size)
|
void ESMWriter::writeHNString(const std::string& name, const std::string& data, size_t size)
|
||||||
{
|
{
|
||||||
assert(data.size() <= size);
|
assert(data.size() <= size);
|
||||||
startSubRecord(name);
|
startSubRecord(name);
|
||||||
writeHString(data);
|
writeHString(data);
|
||||||
|
@ -139,48 +143,47 @@ void ESMWriter::writeHNString(const std::string& name, const std::string& data,
|
||||||
}
|
}
|
||||||
|
|
||||||
endRecord(name);
|
endRecord(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::writeHString(const std::string& data)
|
void ESMWriter::writeHString(const std::string& data)
|
||||||
{
|
{
|
||||||
if (data.size() == 0)
|
if (data.size() == 0)
|
||||||
write("\0", 1);
|
write("\0", 1);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Convert to UTF8 and return
|
// Convert to UTF8 and return
|
||||||
std::string ascii = m_encoder->getLegacyEnc(data);
|
std::string ascii = mEncoder->getLegacyEnc(data);
|
||||||
|
|
||||||
write(ascii.c_str(), ascii.size());
|
write(ascii.c_str(), ascii.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::writeHCString(const std::string& data)
|
void ESMWriter::writeHCString(const std::string& data)
|
||||||
{
|
{
|
||||||
writeHString(data);
|
writeHString(data);
|
||||||
if (data.size() > 0 && data[data.size()-1] != '\0')
|
if (data.size() > 0 && data[data.size()-1] != '\0')
|
||||||
write("\0", 1);
|
write("\0", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::writeName(const std::string& name)
|
void ESMWriter::writeName(const std::string& name)
|
||||||
{
|
{
|
||||||
assert((name.size() == 4 && name[3] != '\0'));
|
assert((name.size() == 4 && name[3] != '\0'));
|
||||||
write(name.c_str(), name.size());
|
write(name.c_str(), name.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::write(const char* data, size_t size)
|
void ESMWriter::write(const char* data, size_t size)
|
||||||
{
|
|
||||||
if (count && !m_records.empty())
|
|
||||||
{
|
{
|
||||||
for (std::list<RecordData>::iterator it = m_records.begin(); it != m_records.end(); ++it)
|
if (mCounting && !mRecords.empty())
|
||||||
|
{
|
||||||
|
for (std::list<RecordData>::iterator it = mRecords.begin(); it != mRecords.end(); ++it)
|
||||||
it->size += size;
|
it->size += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_stream->write(data, size);
|
mStream->write(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::setEncoder(ToUTF8::Utf8Encoder* encoder)
|
|
||||||
{
|
|
||||||
m_encoder = encoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
void ESMWriter::setEncoder(ToUTF8::Utf8Encoder* encoder)
|
||||||
|
{
|
||||||
|
mEncoder = encoder;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,20 +20,30 @@ class ESMWriter
|
||||||
size_t size;
|
size_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int getVersion();
|
|
||||||
void setVersion(int ver);
|
ESMWriter();
|
||||||
void setEncoder(ToUTF8::Utf8Encoder *encoding); // Write strings as UTF-8?
|
|
||||||
|
unsigned int getVersion() const;
|
||||||
|
void setVersion(unsigned int ver = 0x3fa66666);
|
||||||
|
void setEncoder(ToUTF8::Utf8Encoder *encoding);
|
||||||
void setAuthor(const std::string& author);
|
void setAuthor(const std::string& author);
|
||||||
void setDescription(const std::string& desc);
|
void setDescription(const std::string& desc);
|
||||||
void setRecordCount (int count);
|
void setRecordCount (int count);
|
||||||
void setFormat (int format);
|
void setFormat (int format);
|
||||||
|
|
||||||
|
void clearMaster();
|
||||||
|
|
||||||
void addMaster(const std::string& name, uint64_t size);
|
void addMaster(const std::string& name, uint64_t size);
|
||||||
|
|
||||||
void save(const std::string& file);
|
void save(const std::string& file);
|
||||||
|
///< Start saving a file by writing the TES3 header.
|
||||||
|
|
||||||
void save(std::ostream& file);
|
void save(std::ostream& file);
|
||||||
|
///< Start saving a file by writing the TES3 header.
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
|
///< \note Does not close the stream.
|
||||||
|
|
||||||
void writeHNString(const std::string& name, const std::string& data);
|
void writeHNString(const std::string& name, const std::string& data);
|
||||||
void writeHNString(const std::string& name, const std::string& data, size_t size);
|
void writeHNString(const std::string& name, const std::string& data, size_t size);
|
||||||
|
@ -82,7 +92,7 @@ public:
|
||||||
write((char*)&data, size);
|
write((char*)&data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void startRecord(const std::string& name, uint32_t flags);
|
void startRecord(const std::string& name, uint32_t flags = 0);
|
||||||
void startSubRecord(const std::string& name);
|
void startSubRecord(const std::string& name);
|
||||||
void endRecord(const std::string& name);
|
void endRecord(const std::string& name);
|
||||||
void writeHString(const std::string& data);
|
void writeHString(const std::string& data);
|
||||||
|
@ -90,15 +100,16 @@ public:
|
||||||
void writeName(const std::string& data);
|
void writeName(const std::string& data);
|
||||||
void write(const char* data, size_t size);
|
void write(const char* data, size_t size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::list<RecordData> m_records;
|
std::list<RecordData> mRecords;
|
||||||
std::ostream* m_stream;
|
std::ostream* mStream;
|
||||||
std::streampos m_headerPos;
|
std::streampos mHeaderPos;
|
||||||
ToUTF8::Utf8Encoder* m_encoder;
|
ToUTF8::Utf8Encoder* mEncoder;
|
||||||
int m_recordCount;
|
int mRecordCount;
|
||||||
|
bool mCounting;
|
||||||
|
|
||||||
Header mHeader;
|
Header mHeader;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
#include "esmreader.hpp"
|
#include "esmreader.hpp"
|
||||||
#include "esmwriter.hpp"
|
#include "esmwriter.hpp"
|
||||||
|
#include "defs.hpp"
|
||||||
|
|
||||||
|
unsigned int ESM::Filter::sRecordId = REC_FILT;
|
||||||
|
|
||||||
void ESM::Filter::load (ESMReader& esm)
|
void ESM::Filter::load (ESMReader& esm)
|
||||||
{
|
{
|
||||||
|
@ -10,7 +13,7 @@ void ESM::Filter::load (ESMReader& esm)
|
||||||
mDescription = esm.getHNString ("DESC");
|
mDescription = esm.getHNString ("DESC");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESM::Filter::save (ESMWriter& esm)
|
void ESM::Filter::save (ESMWriter& esm) const
|
||||||
{
|
{
|
||||||
esm.writeHNCString ("FILT", mFilter);
|
esm.writeHNCString ("FILT", mFilter);
|
||||||
esm.writeHNCString ("DESC", mDescription);
|
esm.writeHNCString ("DESC", mDescription);
|
||||||
|
|
|
@ -10,6 +10,8 @@ namespace ESM
|
||||||
|
|
||||||
struct Filter
|
struct Filter
|
||||||
{
|
{
|
||||||
|
static unsigned int sRecordId;
|
||||||
|
|
||||||
std::string mId;
|
std::string mId;
|
||||||
|
|
||||||
std::string mDescription;
|
std::string mDescription;
|
||||||
|
@ -17,7 +19,7 @@ namespace ESM
|
||||||
std::string mFilter;
|
std::string mFilter;
|
||||||
|
|
||||||
void load (ESMReader& esm);
|
void load (ESMReader& esm);
|
||||||
void save (ESMWriter& esm);
|
void save (ESMWriter& esm) const;
|
||||||
|
|
||||||
void blank();
|
void blank();
|
||||||
///< Set record to default state (does not touch the ID).
|
///< Set record to default state (does not touch the ID).
|
||||||
|
|
|
@ -2,16 +2,19 @@
|
||||||
|
|
||||||
#include "esmreader.hpp"
|
#include "esmreader.hpp"
|
||||||
#include "esmwriter.hpp"
|
#include "esmwriter.hpp"
|
||||||
|
#include "defs.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
unsigned int Activator::sRecordId = REC_ACTI;
|
||||||
|
|
||||||
void Activator::load(ESMReader &esm)
|
void Activator::load(ESMReader &esm)
|
||||||
{
|
{
|
||||||
mModel = esm.getHNString("MODL");
|
mModel = esm.getHNString("MODL");
|
||||||
mName = esm.getHNString("FNAM");
|
mName = esm.getHNString("FNAM");
|
||||||
mScript = esm.getHNOString("SCRI");
|
mScript = esm.getHNOString("SCRI");
|
||||||
}
|
}
|
||||||
void Activator::save(ESMWriter &esm)
|
void Activator::save(ESMWriter &esm) const
|
||||||
{
|
{
|
||||||
esm.writeHNCString("MODL", mModel);
|
esm.writeHNCString("MODL", mModel);
|
||||||
esm.writeHNCString("FNAM", mName);
|
esm.writeHNCString("FNAM", mName);
|
||||||
|
|
|
@ -11,10 +11,12 @@ class ESMWriter;
|
||||||
|
|
||||||
struct Activator
|
struct Activator
|
||||||
{
|
{
|
||||||
|
static unsigned int sRecordId;
|
||||||
|
|
||||||
std::string mId, mName, mScript, mModel;
|
std::string mId, mName, mScript, mModel;
|
||||||
|
|
||||||
void load(ESMReader &esm);
|
void load(ESMReader &esm);
|
||||||
void save(ESMWriter &esm);
|
void save(ESMWriter &esm) const;
|
||||||
|
|
||||||
void blank();
|
void blank();
|
||||||
///< Set record to default state (does not touch the ID).
|
///< Set record to default state (does not touch the ID).
|
||||||
|
|
|
@ -2,9 +2,12 @@
|
||||||
|
|
||||||
#include "esmreader.hpp"
|
#include "esmreader.hpp"
|
||||||
#include "esmwriter.hpp"
|
#include "esmwriter.hpp"
|
||||||
|
#include "defs.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
unsigned int Potion::sRecordId = REC_ALCH;
|
||||||
|
|
||||||
void Potion::load(ESMReader &esm)
|
void Potion::load(ESMReader &esm)
|
||||||
{
|
{
|
||||||
mModel = esm.getHNString("MODL");
|
mModel = esm.getHNString("MODL");
|
||||||
|
@ -14,7 +17,7 @@ void Potion::load(ESMReader &esm)
|
||||||
esm.getHNT(mData, "ALDT", 12);
|
esm.getHNT(mData, "ALDT", 12);
|
||||||
mEffects.load(esm);
|
mEffects.load(esm);
|
||||||
}
|
}
|
||||||
void Potion::save(ESMWriter &esm)
|
void Potion::save(ESMWriter &esm) const
|
||||||
{
|
{
|
||||||
esm.writeHNCString("MODL", mModel);
|
esm.writeHNCString("MODL", mModel);
|
||||||
esm.writeHNOCString("TEXT", mIcon);
|
esm.writeHNOCString("TEXT", mIcon);
|
||||||
|
|
|
@ -17,6 +17,8 @@ class ESMWriter;
|
||||||
|
|
||||||
struct Potion
|
struct Potion
|
||||||
{
|
{
|
||||||
|
static unsigned int sRecordId;
|
||||||
|
|
||||||
struct ALDTstruct
|
struct ALDTstruct
|
||||||
{
|
{
|
||||||
float mWeight;
|
float mWeight;
|
||||||
|
@ -29,7 +31,7 @@ struct Potion
|
||||||
EffectList mEffects;
|
EffectList mEffects;
|
||||||
|
|
||||||
void load(ESMReader &esm);
|
void load(ESMReader &esm);
|
||||||
void save(ESMWriter &esm);
|
void save(ESMWriter &esm) const;
|
||||||
|
|
||||||
void blank();
|
void blank();
|
||||||
///< Set record to default state (does not touch the ID).
|
///< Set record to default state (does not touch the ID).
|
||||||
|
|
|
@ -2,9 +2,12 @@
|
||||||
|
|
||||||
#include "esmreader.hpp"
|
#include "esmreader.hpp"
|
||||||
#include "esmwriter.hpp"
|
#include "esmwriter.hpp"
|
||||||
|
#include "defs.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
unsigned int Apparatus::sRecordId = REC_APPA;
|
||||||
|
|
||||||
void Apparatus::load(ESMReader &esm)
|
void Apparatus::load(ESMReader &esm)
|
||||||
{
|
{
|
||||||
// we will not treat duplicated subrecords as errors here
|
// we will not treat duplicated subrecords as errors here
|
||||||
|
@ -28,7 +31,7 @@ void Apparatus::load(ESMReader &esm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Apparatus::save(ESMWriter &esm)
|
void Apparatus::save(ESMWriter &esm) const
|
||||||
{
|
{
|
||||||
esm.writeHNCString("MODL", mModel);
|
esm.writeHNCString("MODL", mModel);
|
||||||
esm.writeHNCString("FNAM", mName);
|
esm.writeHNCString("FNAM", mName);
|
||||||
|
|
|
@ -15,6 +15,8 @@ class ESMWriter;
|
||||||
|
|
||||||
struct Apparatus
|
struct Apparatus
|
||||||
{
|
{
|
||||||
|
static unsigned int sRecordId;
|
||||||
|
|
||||||
enum AppaType
|
enum AppaType
|
||||||
{
|
{
|
||||||
MortarPestle = 0,
|
MortarPestle = 0,
|
||||||
|
@ -35,7 +37,7 @@ struct Apparatus
|
||||||
std::string mId, mModel, mIcon, mScript, mName;
|
std::string mId, mModel, mIcon, mScript, mName;
|
||||||
|
|
||||||
void load(ESMReader &esm);
|
void load(ESMReader &esm);
|
||||||
void save(ESMWriter &esm);
|
void save(ESMWriter &esm) const;
|
||||||
|
|
||||||
void blank();
|
void blank();
|
||||||
///< Set record to default state (does not touch the ID).
|
///< Set record to default state (does not touch the ID).
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "esmreader.hpp"
|
#include "esmreader.hpp"
|
||||||
#include "esmwriter.hpp"
|
#include "esmwriter.hpp"
|
||||||
|
#include "defs.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
@ -18,9 +19,9 @@ void PartReferenceList::load(ESMReader &esm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PartReferenceList::save(ESMWriter &esm)
|
void PartReferenceList::save(ESMWriter &esm) const
|
||||||
{
|
{
|
||||||
for (std::vector<PartReference>::iterator it = mParts.begin(); it != mParts.end(); ++it)
|
for (std::vector<PartReference>::const_iterator it = mParts.begin(); it != mParts.end(); ++it)
|
||||||
{
|
{
|
||||||
esm.writeHNT("INDX", it->mPart);
|
esm.writeHNT("INDX", it->mPart);
|
||||||
esm.writeHNOString("BNAM", it->mMale);
|
esm.writeHNOString("BNAM", it->mMale);
|
||||||
|
@ -28,6 +29,8 @@ void PartReferenceList::save(ESMWriter &esm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int Armor::sRecordId = REC_ARMO;
|
||||||
|
|
||||||
void Armor::load(ESMReader &esm)
|
void Armor::load(ESMReader &esm)
|
||||||
{
|
{
|
||||||
mModel = esm.getHNString("MODL");
|
mModel = esm.getHNString("MODL");
|
||||||
|
@ -39,7 +42,7 @@ void Armor::load(ESMReader &esm)
|
||||||
mEnchant = esm.getHNOString("ENAM");
|
mEnchant = esm.getHNOString("ENAM");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Armor::save(ESMWriter &esm)
|
void Armor::save(ESMWriter &esm) const
|
||||||
{
|
{
|
||||||
esm.writeHNCString("MODL", mModel);
|
esm.writeHNCString("MODL", mModel);
|
||||||
esm.writeHNCString("FNAM", mName);
|
esm.writeHNCString("FNAM", mName);
|
||||||
|
|
|
@ -56,11 +56,13 @@ struct PartReferenceList
|
||||||
std::vector<PartReference> mParts;
|
std::vector<PartReference> mParts;
|
||||||
|
|
||||||
void load(ESMReader &esm);
|
void load(ESMReader &esm);
|
||||||
void save(ESMWriter &esm);
|
void save(ESMWriter &esm) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Armor
|
struct Armor
|
||||||
{
|
{
|
||||||
|
static unsigned int sRecordId;
|
||||||
|
|
||||||
enum Type
|
enum Type
|
||||||
{
|
{
|
||||||
Helmet = 0,
|
Helmet = 0,
|
||||||
|
@ -89,7 +91,7 @@ struct Armor
|
||||||
std::string mId, mName, mModel, mIcon, mScript, mEnchant;
|
std::string mId, mName, mModel, mIcon, mScript, mEnchant;
|
||||||
|
|
||||||
void load(ESMReader &esm);
|
void load(ESMReader &esm);
|
||||||
void save(ESMWriter &esm);
|
void save(ESMWriter &esm) const;
|
||||||
|
|
||||||
void blank();
|
void blank();
|
||||||
///< Set record to default state (does not touch the ID).
|
///< Set record to default state (does not touch the ID).
|
||||||
|
|
|
@ -2,9 +2,12 @@
|
||||||
|
|
||||||
#include "esmreader.hpp"
|
#include "esmreader.hpp"
|
||||||
#include "esmwriter.hpp"
|
#include "esmwriter.hpp"
|
||||||
|
#include "defs.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
unsigned int BodyPart::sRecordId = REC_BODY;
|
||||||
|
|
||||||
|
|
||||||
void BodyPart::load(ESMReader &esm)
|
void BodyPart::load(ESMReader &esm)
|
||||||
{
|
{
|
||||||
|
@ -12,7 +15,7 @@ void BodyPart::load(ESMReader &esm)
|
||||||
mRace = esm.getHNString("FNAM");
|
mRace = esm.getHNString("FNAM");
|
||||||
esm.getHNT(mData, "BYDT", 4);
|
esm.getHNT(mData, "BYDT", 4);
|
||||||
}
|
}
|
||||||
void BodyPart::save(ESMWriter &esm)
|
void BodyPart::save(ESMWriter &esm) const
|
||||||
{
|
{
|
||||||
esm.writeHNCString("MODL", mModel);
|
esm.writeHNCString("MODL", mModel);
|
||||||
esm.writeHNCString("FNAM", mRace);
|
esm.writeHNCString("FNAM", mRace);
|
||||||
|
|
|
@ -11,6 +11,8 @@ class ESMWriter;
|
||||||
|
|
||||||
struct BodyPart
|
struct BodyPart
|
||||||
{
|
{
|
||||||
|
static unsigned int sRecordId;
|
||||||
|
|
||||||
enum MeshPart
|
enum MeshPart
|
||||||
{
|
{
|
||||||
MP_Head = 0,
|
MP_Head = 0,
|
||||||
|
@ -57,7 +59,7 @@ struct BodyPart
|
||||||
std::string mId, mModel, mRace;
|
std::string mId, mModel, mRace;
|
||||||
|
|
||||||
void load(ESMReader &esm);
|
void load(ESMReader &esm);
|
||||||
void save(ESMWriter &esm);
|
void save(ESMWriter &esm) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
|
|
||||||
#include "esmreader.hpp"
|
#include "esmreader.hpp"
|
||||||
#include "esmwriter.hpp"
|
#include "esmwriter.hpp"
|
||||||
|
#include "defs.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
unsigned int Book::sRecordId = REC_BOOK;
|
||||||
|
|
||||||
void Book::load(ESMReader &esm)
|
void Book::load(ESMReader &esm)
|
||||||
{
|
{
|
||||||
|
@ -16,7 +18,7 @@ void Book::load(ESMReader &esm)
|
||||||
mText = esm.getHNOString("TEXT");
|
mText = esm.getHNOString("TEXT");
|
||||||
mEnchant = esm.getHNOString("ENAM");
|
mEnchant = esm.getHNOString("ENAM");
|
||||||
}
|
}
|
||||||
void Book::save(ESMWriter &esm)
|
void Book::save(ESMWriter &esm) const
|
||||||
{
|
{
|
||||||
esm.writeHNCString("MODL", mModel);
|
esm.writeHNCString("MODL", mModel);
|
||||||
esm.writeHNOCString("FNAM", mName);
|
esm.writeHNOCString("FNAM", mName);
|
||||||
|
|
|
@ -14,6 +14,8 @@ class ESMWriter;
|
||||||
|
|
||||||
struct Book
|
struct Book
|
||||||
{
|
{
|
||||||
|
static unsigned int sRecordId;
|
||||||
|
|
||||||
struct BKDTstruct
|
struct BKDTstruct
|
||||||
{
|
{
|
||||||
float mWeight;
|
float mWeight;
|
||||||
|
@ -25,7 +27,7 @@ struct Book
|
||||||
std::string mId;
|
std::string mId;
|
||||||
|
|
||||||
void load(ESMReader &esm);
|
void load(ESMReader &esm);
|
||||||
void save(ESMWriter &esm);
|
void save(ESMWriter &esm) const;
|
||||||
|
|
||||||
void blank();
|
void blank();
|
||||||
///< Set record to default state (does not touch the ID).
|
///< Set record to default state (does not touch the ID).
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
|
|
||||||
#include "esmreader.hpp"
|
#include "esmreader.hpp"
|
||||||
#include "esmwriter.hpp"
|
#include "esmwriter.hpp"
|
||||||
|
#include "defs.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
unsigned int BirthSign::sRecordId = REC_BSGN;
|
||||||
|
|
||||||
void BirthSign::load(ESMReader &esm)
|
void BirthSign::load(ESMReader &esm)
|
||||||
{
|
{
|
||||||
|
@ -15,7 +17,7 @@ void BirthSign::load(ESMReader &esm)
|
||||||
mPowers.load(esm);
|
mPowers.load(esm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BirthSign::save(ESMWriter &esm)
|
void BirthSign::save(ESMWriter &esm) const
|
||||||
{
|
{
|
||||||
esm.writeHNCString("FNAM", mName);
|
esm.writeHNCString("FNAM", mName);
|
||||||
esm.writeHNOCString("TNAM", mTexture);
|
esm.writeHNOCString("TNAM", mTexture);
|
||||||
|
|
|
@ -13,13 +13,15 @@ class ESMWriter;
|
||||||
|
|
||||||
struct BirthSign
|
struct BirthSign
|
||||||
{
|
{
|
||||||
|
static unsigned int sRecordId;
|
||||||
|
|
||||||
std::string mId, mName, mDescription, mTexture;
|
std::string mId, mName, mDescription, mTexture;
|
||||||
|
|
||||||
// List of powers and abilities that come with this birth sign.
|
// List of powers and abilities that come with this birth sign.
|
||||||
SpellList mPowers;
|
SpellList mPowers;
|
||||||
|
|
||||||
void load(ESMReader &esm);
|
void load(ESMReader &esm);
|
||||||
void save(ESMWriter &esm);
|
void save(ESMWriter &esm) const;
|
||||||
|
|
||||||
void blank();
|
void blank();
|
||||||
///< Set record to default state (does not touch the ID/index).
|
///< Set record to default state (does not touch the ID/index).
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue