1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-03-30 21:06:43 +00:00

Merge pull request #9 from cc9cii/master-cherry-pick-2

Master cherry pick 2
This commit is contained in:
cc9cii 2015-09-08 07:55:29 +10:00
commit 904f9871cc
252 changed files with 579 additions and 357 deletions

View file

@ -364,6 +364,8 @@ configure_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb.txt
if (NOT WIN32 AND NOT APPLE)
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
"${OpenMW_BINARY_DIR}/openmw.desktop")
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.appdata.xml
"${OpenMW_BINARY_DIR}/openmw.appdata.xml")
configure_file(${OpenMW_SOURCE_DIR}/files/openmw-cs.desktop
"${OpenMW_BINARY_DIR}/openmw-cs.desktop")
endif()
@ -450,6 +452,7 @@ IF(NOT WIN32 AND NOT APPLE)
# Install icon and desktop file
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.appdata.xml" DESTINATION "${DATAROOTDIR}/appdata" COMPONENT "openmw")
IF(BUILD_OPENCS)
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw-cs.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "opencs")
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/openmw-cs.png" DESTINATION "${ICONDIR}" COMPONENT "opencs")

View file

@ -1,28 +0,0 @@
#!/bin/bash
#Script to test all nif files (both loose, and in BSA archives) in data files directory
#The user input as an absolute path
DATAFILESDIR="`readlink -m "$1"`"
#Program used to test
TEST_PROG="`pwd`/niftest"
#Make sure our files don't bother anyone
NIFTEST_TMP_DIR="/tmp/niftest_$RANDOM/"
mkdir "$NIFTEST_TMP_DIR"
cd "$NIFTEST_TMP_DIR"
find "$DATAFILESDIR" -iname *bsa > nifs.txt
find "$DATAFILESDIR" -iname *nif >> nifs.txt
sed -e 's/.*/\"&\"/' nifs.txt > quoted_nifs.txt
xargs --arg-file=quoted_nifs.txt "$TEST_PROG" 2>&1 | tee nif_out.txt
# xargs --arg-file=quoted_nifs.txt "$TEST_PROG" 2> nif_out.txt >/dev/null
echo "List of bad NIF Files:"
cat nif_out.txt|grep File:|cut -d ' ' -f 2-
rm nifs.txt
rm quoted_nifs.txt
rm nif_out.txt
rmdir "$NIFTEST_TMP_DIR"

View file

@ -2,12 +2,20 @@
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <components/nif/niffile.hpp>
#include <components/files/constrainedfilestream.hpp>
#include <components/vfs/manager.hpp>
#include <components/vfs/bsaarchive.hpp>
#include <components/vfs/filesystemarchive.hpp>
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
// Create local aliases for brevity
namespace bpo = boost::program_options;
namespace bfs = boost::filesystem;
///See if the file has the named extension
bool hasExtension(std::string filename, std::string extensionToFind)
@ -35,32 +43,97 @@ bool isBSA(std::string filename)
return hasExtension(filename,"bsa");
}
///Check all the nif files in the given BSA archive
void readBSA(std::string filename)
/// Check all the nif files in a given VFS::Archive
/// \note Takes ownership!
/// \note Can not read a bsa file inside of a bsa file.
void readVFS(VFS::Archive* anArchive,std::string archivePath = "")
{
VFS::Manager myManager(false);
myManager.addArchive(new VFS::BsaArchive(filename));
VFS::Manager myManager(true);
myManager.addArchive(anArchive);
myManager.buildIndex();
std::map<std::string, VFS::File*> files=myManager.getIndex();
for(std::map<std::string, VFS::File*>::const_iterator it=files.begin(); it!=files.end(); ++it)
{
std::string name = it->first;
if(isNIF(name))
{
// std::cout << "Decoding: " << name << std::endl;
Nif::NIFFile temp_nif(myManager.get(name),name);
}
std::string name = it->first;
try{
if(isNIF(name))
{
// std::cout << "Decoding: " << name << std::endl;
Nif::NIFFile temp_nif(myManager.get(name),archivePath+name);
}
else if(isBSA(name))
{
if(!archivePath.empty() && !isBSA(archivePath))
{
// std::cout << "Reading BSA File: " << name << std::endl;
readVFS(new VFS::BsaArchive(archivePath+name),archivePath+name+"/");
// std::cout << "Done with BSA File: " << name << std::endl;
}
}
}
catch (std::exception& e)
{
std::cerr << "ERROR, an exception has occurred: " << e.what() << std::endl;
}
}
}
std::vector<std::string> parseOptions (int argc, char** argv)
{
bpo::options_description desc("Ensure that OpenMW can use the provided NIF and BSA files\n\n"
"Usages:\n"
" niftool <nif files, BSA files, or directories>\n"
" Scan the file or directories for nif errors.\n\n"
"Allowed options");
desc.add_options()
("help,h", "print help message.")
("input-file", bpo::value< std::vector<std::string> >(), "input file")
;
//Default option if none provided
bpo::positional_options_description p;
p.add("input-file", -1);
bpo::variables_map variables;
try
{
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv).
options(desc).positional(p).run();
bpo::store(valid_opts, variables);
}
catch(std::exception &e)
{
std::cout << "ERROR parsing arguments: " << e.what() << "\n\n"
<< desc << std::endl;
exit(1);
}
bpo::notify(variables);
if (variables.count ("help"))
{
std::cout << desc << std::endl;
exit(1);
}
if (variables.count("input-file"))
{
return variables["input-file"].as< std::vector<std::string> >();
}
std::cout << "No input files or directories specified!" << std::endl;
std::cout << desc << std::endl;
exit(1);
}
int main(int argc, char **argv)
{
std::vector<std::string> files = parseOptions (argc, argv);
std::cout << "Reading Files" << std::endl;
for(int i = 1; i<argc;i++)
{
std::string name = argv[i];
// std::cout << "Reading Files" << std::endl;
for(std::vector<std::string>::const_iterator it=files.begin(); it!=files.end(); ++it)
{
std::string name = *it;
try{
if(isNIF(name))
@ -70,12 +143,17 @@ int main(int argc, char **argv)
}
else if(isBSA(name))
{
std::cout << "Reading BSA File: " << name << std::endl;
readBSA(name);
// std::cout << "Reading BSA File: " << name << std::endl;
readVFS(new VFS::BsaArchive(name));
}
else if(bfs::is_directory(bfs::path(name)))
{
// std::cout << "Reading All Files in: " << name << std::endl;
readVFS(new VFS::FileSystemArchive(name),name);
}
else
{
std::cerr << "ERROR: \"" << name << "\" is not a nif or bsa file!" << std::endl;
std::cerr << "ERROR: \"" << name << "\" is not a nif file, bsa file, or directory!" << std::endl;
}
}
catch (std::exception& e)

View file

@ -23,7 +23,7 @@ opencs_units (model/world
opencs_units_noqt (model/world
universalid record commands columnbase scriptcontext cell refidcollection
universalid record commands columnbase columnimp scriptcontext cell refidcollection
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope
pathgrid landtexture land nestedtablewrapper nestedcollection nestedcoladapterimp nestedinfocollection
idcompletionmanager npcstats metadata
@ -41,7 +41,7 @@ opencs_units (model/tools
opencs_units_noqt (model/tools
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck
startscriptcheck search searchoperation searchstage pathgridcheck soundgencheck
startscriptcheck search searchoperation searchstage pathgridcheck soundgencheck magiceffectcheck
)

View file

@ -1,4 +1,3 @@
#include "editor.hpp"
#include <openengine/bullet/BulletShapeLoader.h>

View file

@ -1,4 +1,3 @@
#include "editor.hpp"
#include <exception>

View file

@ -1,4 +1,3 @@
#include "blacklist.hpp"
#include <algorithm>

View file

@ -1,4 +1,3 @@
#include "documentmanager.hpp"
#include <algorithm>

View file

@ -1,4 +1,3 @@
#include "loader.hpp"
#include <QTimer>

View file

@ -1,4 +1,3 @@
#include "messages.hpp"
CSMDoc::Message::Message() {}

View file

@ -1,4 +1,3 @@
#include "operation.hpp"
#include <string>

View file

@ -1,4 +1,3 @@
#include "operationholder.hpp"
#include "../settings/usersettings.hpp"

View file

@ -1,4 +1,3 @@
#include "runner.hpp"
#include <QApplication>

View file

@ -1,4 +1,3 @@
#include "saving.hpp"
#include "../world/data.hpp"
@ -81,22 +80,25 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::StartScript> >
(mDocument.getData().getStartScripts(), mState));
appendStage (new WriteDialogueCollectionStage (mDocument, mState, false));
appendStage (new WriteDialogueCollectionStage (mDocument, mState, true));
appendStage (new WriteRefIdCollectionStage (mDocument, mState));
appendStage (new CollectionReferencesStage (mDocument, mState));
appendStage (new WriteCellCollectionStage (mDocument, mState));
// Dialogue can reference objects and cells so must be written after these records for vanilla-compatible files
appendStage (new WriteDialogueCollectionStage (mDocument, mState, false));
appendStage (new WriteDialogueCollectionStage (mDocument, mState, true));
appendStage (new WritePathgridCollectionStage (mDocument, mState));
appendStage (new WriteLandCollectionStage (mDocument, mState));
appendStage (new WriteLandTextureCollectionStage (mDocument, mState));
// references Land Textures
appendStage (new WriteLandCollectionStage (mDocument, mState));
// close file and clean up
appendStage (new CloseSaveStage (mState));

View file

@ -1,4 +1,3 @@
#include "savingstages.hpp"
#include <fstream>
@ -455,6 +454,8 @@ void CSMDoc::WriteLandTextureCollectionStage::perform (int stage, Messages& mess
mState.getWriter().startRecord (record.sRecordId);
mState.getWriter().writeHNString("NAME", record.mId);
record.save (mState.getWriter());
mState.getWriter().endRecord (record.sRecordId);

View file

@ -1,4 +1,3 @@
#include "savingstate.hpp"
#include "operation.hpp"

View file

@ -1,4 +1,3 @@
#include "stage.hpp"
CSMDoc::Stage::~Stage() {}

View file

@ -1,4 +1,3 @@
#include "andnode.hpp"
#include <sstream>

View file

@ -1,4 +1,3 @@
#include "booleannode.hpp"
CSMFilter::BooleanNode::BooleanNode (bool true_) : mTrue (true_) {}

View file

@ -1,4 +1,3 @@
#include "leafnode.hpp"
std::vector<int> CSMFilter::LeafNode::getReferencedColumns() const

View file

@ -1,4 +1,3 @@
#include "narynode.hpp"
#include <sstream>

View file

@ -1,4 +1,3 @@
#include "node.hpp"
CSMFilter::Node::Node() {}

View file

@ -1,4 +1,3 @@
#include "notnode.hpp"
CSMFilter::NotNode::NotNode (boost::shared_ptr<Node> child) : UnaryNode (child, "not") {}

View file

@ -1,4 +1,3 @@
#include "ornode.hpp"
#include <sstream>

View file

@ -1,4 +1,3 @@
#include "parser.hpp"
#include <cctype>

View file

@ -1,4 +1,3 @@
#include "textnode.hpp"
#include <sstream>

View file

@ -1,4 +1,3 @@
#include "unarynode.hpp"
CSMFilter::UnaryNode::UnaryNode (boost::shared_ptr<Node> child, const std::string& name)

View file

@ -1,4 +1,3 @@
#include "valuenode.hpp"
#include <sstream>

View file

@ -1,4 +1,3 @@
#include "birthsigncheck.hpp"
#include <sstream>

View file

@ -1,4 +1,3 @@
#include "classcheck.hpp"
#include <sstream>

View file

@ -1,4 +1,3 @@
#include "factioncheck.hpp"
#include <sstream>

View file

@ -0,0 +1,133 @@
#include "magiceffectcheck.hpp"
#include <components/misc/resourcehelpers.hpp>
#include "../world/resources.hpp"
#include "../world/data.hpp"
namespace
{
void addMessageIfNotEmpty(CSMDoc::Messages &messages, const CSMWorld::UniversalId &id, const std::string text)
{
if (!text.empty())
{
messages.push_back(std::make_pair(id, text));
}
}
}
bool CSMTools::MagicEffectCheckStage::isTextureExists(const std::string &texture, bool isIcon) const
{
const CSMWorld::Resources &textures = isIcon ? mIcons : mTextures;
bool exists = false;
if (textures.searchId(texture) != -1)
{
exists = true;
}
else
{
std::string ddsTexture = texture;
if (Misc::ResourceHelpers::changeExtensionToDds(ddsTexture) && textures.searchId(ddsTexture) != -1)
{
exists = true;
}
}
return exists;
}
std::string CSMTools::MagicEffectCheckStage::checkReferenceable(const std::string &id,
const CSMWorld::UniversalId &type,
const std::string &column) const
{
std::string error;
if (!id.empty())
{
CSMWorld::RefIdData::LocalIndex index = mReferenceables.getDataSet().searchId(id);
if (index.first == -1)
{
error = "No such " + column + " '" + id + "'";
}
else if (index.second != type.getType())
{
error = column + " is not of type " + type.getTypeName();
}
}
return error;
}
std::string CSMTools::MagicEffectCheckStage::checkSound(const std::string &id, const std::string &column) const
{
std::string error;
if (!id.empty() && mSounds.searchId(id) == -1)
{
error = "No such " + column + " '" + id + "'";
}
return error;
}
CSMTools::MagicEffectCheckStage::MagicEffectCheckStage(const CSMWorld::IdCollection<ESM::MagicEffect> &effects,
const CSMWorld::IdCollection<ESM::Sound> &sounds,
const CSMWorld::RefIdCollection &referenceables,
const CSMWorld::Resources &icons,
const CSMWorld::Resources &textures)
: mMagicEffects(effects),
mSounds(sounds),
mReferenceables(referenceables),
mIcons(icons),
mTextures(textures)
{}
int CSMTools::MagicEffectCheckStage::setup()
{
return mMagicEffects.getSize();
}
void CSMTools::MagicEffectCheckStage::perform(int stage, CSMDoc::Messages &messages)
{
ESM::MagicEffect effect = mMagicEffects.getRecord(stage).get();
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_MagicEffect, effect.mId);
if (effect.mData.mBaseCost < 0.0f)
{
messages.push_back(std::make_pair(id, "Base Cost is negative"));
}
if (effect.mIcon.empty())
{
messages.push_back(std::make_pair(id, "Icon is not specified"));
}
else if (!isTextureExists(effect.mIcon, true))
{
messages.push_back(std::make_pair(id, "No such Icon '" + effect.mIcon + "'"));
}
if (!effect.mParticle.empty() && !isTextureExists(effect.mParticle, false))
{
messages.push_back(std::make_pair(id, "No such Particle '" + effect.mParticle + "'"));
}
addMessageIfNotEmpty(messages,
id,
checkReferenceable(effect.mCasting, CSMWorld::UniversalId::Type_Static, "Casting Object"));
addMessageIfNotEmpty(messages,
id,
checkReferenceable(effect.mHit, CSMWorld::UniversalId::Type_Static, "Hit Object"));
addMessageIfNotEmpty(messages,
id,
checkReferenceable(effect.mArea, CSMWorld::UniversalId::Type_Static, "Area Object"));
addMessageIfNotEmpty(messages,
id,
checkReferenceable(effect.mBolt, CSMWorld::UniversalId::Type_Weapon, "Bolt Object"));
addMessageIfNotEmpty(messages, id, checkSound(effect.mCastSound, "Casting Sound"));
addMessageIfNotEmpty(messages, id, checkSound(effect.mHitSound, "Hit Sound"));
addMessageIfNotEmpty(messages, id, checkSound(effect.mAreaSound, "Area Sound"));
addMessageIfNotEmpty(messages, id, checkSound(effect.mBoltSound, "Bolt Sound"));
if (effect.mDescription.empty())
{
messages.push_back(std::make_pair(id, "Description is empty"));
}
}

View file

@ -0,0 +1,50 @@
#ifndef CSM_TOOLS_MAGICEFFECTCHECK_HPP
#define CSM_TOOLS_MAGICEFFECTCHECK_HPP
#include <components/esm/loadmgef.hpp>
#include <components/esm/loadsoun.hpp>
#include "../world/idcollection.hpp"
#include "../world/refidcollection.hpp"
#include "../doc/stage.hpp"
namespace CSMWorld
{
class Resources;
}
namespace CSMTools
{
/// \brief VerifyStage: make sure that magic effect records are internally consistent
class MagicEffectCheckStage : public CSMDoc::Stage
{
const CSMWorld::IdCollection<ESM::MagicEffect> &mMagicEffects;
const CSMWorld::IdCollection<ESM::Sound> &mSounds;
const CSMWorld::RefIdCollection &mReferenceables;
const CSMWorld::Resources &mIcons;
const CSMWorld::Resources &mTextures;
private:
bool isTextureExists(const std::string &texture, bool isIcon) const;
std::string checkReferenceable(const std::string &id,
const CSMWorld::UniversalId &type,
const std::string &column) const;
std::string checkSound(const std::string &id, const std::string &column) const;
public:
MagicEffectCheckStage(const CSMWorld::IdCollection<ESM::MagicEffect> &effects,
const CSMWorld::IdCollection<ESM::Sound> &sounds,
const CSMWorld::RefIdCollection &referenceables,
const CSMWorld::Resources &icons,
const CSMWorld::Resources &textures);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, CSMDoc::Messages &messages);
///< Messages resulting from this tage will be appended to \a messages.
};
}
#endif

View file

@ -1,4 +1,3 @@
#include "mandatoryid.hpp"
#include "../world/collectionbase.hpp"

View file

@ -1,4 +1,3 @@
#include "racecheck.hpp"
#include <sstream>

View file

@ -1,4 +1,3 @@
#include "regioncheck.hpp"
#include <sstream>

View file

@ -1,4 +1,3 @@
#include "reportmodel.hpp"
#include <stdexcept>

View file

@ -1,4 +1,3 @@
#include "scriptcheck.hpp"
#include <components/compiler/tokenloc.hpp>

View file

@ -1,4 +1,3 @@
#include "search.hpp"
#include <stdexcept>

View file

@ -1,4 +1,3 @@
#include "searchoperation.hpp"
#include "../doc/state.hpp"

View file

@ -1,4 +1,3 @@
#include "searchstage.hpp"
#include "../world/idtablebase.hpp"

View file

@ -1,4 +1,3 @@
#include "skillcheck.hpp"
#include <sstream>

View file

@ -1,4 +1,3 @@
#include "soundcheck.hpp"
#include <sstream>

View file

@ -1,4 +1,3 @@
#include "spellcheck.hpp"
#include <sstream>

View file

@ -1,4 +1,3 @@
#include "startscriptcheck.hpp"
#include <components/misc/stringops.hpp>

View file

@ -1,4 +1,3 @@
#include "tools.hpp"
#include <QThreadPool>
@ -28,6 +27,7 @@
#include "searchoperation.hpp"
#include "pathgridcheck.hpp"
#include "soundgencheck.hpp"
#include "magiceffectcheck.hpp"
CSMDoc::OperationHolder *CSMTools::Tools::get (int type)
{
@ -108,6 +108,12 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier()
mData.getSounds(),
mData.getReferenceables()));
mVerifierOperation->appendStage (new MagicEffectCheckStage (mData.getMagicEffects(),
mData.getSounds(),
mData.getReferenceables(),
mData.getResources (CSMWorld::UniversalId::Type_Icons),
mData.getResources (CSMWorld::UniversalId::Type_Textures)));
mVerifier.setOperation (mVerifierOperation);
}

View file

@ -1,4 +1,3 @@
#include "cell.hpp"
#include <sstream>

View file

@ -1,4 +1,3 @@
#include "cellcoordinates.hpp"
#include <ostream>

View file

@ -1,4 +1,3 @@
#include "cellselection.hpp"
#include <cmath>

View file

@ -1,4 +1,3 @@
#include "collectionbase.hpp"
#include <stdexcept>

View file

@ -82,7 +82,6 @@ bool CSMWorld::ColumnBase::isId (Display display)
Display_EffectId,
Display_PartRefType,
Display_AiPackageType,
Display_YesNo,
Display_InfoCondFunc,
Display_InfoCondVar,
Display_InfoCondComp,

View file

@ -118,7 +118,6 @@ namespace CSMWorld
Display_EffectId,
Display_PartRefType,
Display_AiPackageType,
Display_YesNo,
Display_InfoCondFunc,
Display_InfoCondVar,
Display_InfoCondComp,
@ -192,6 +191,12 @@ namespace CSMWorld
ColumnBase::Display_NestedHeader, flags)
{}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
// There is nothing to do here.
// This prevents exceptions from parent's implementation
}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return true; // required by IdTree::hasChildren()

View file

@ -0,0 +1,28 @@
#include "columnimp.hpp"
CSMWorld::BodyPartRaceColumn::BodyPartRaceColumn(const MeshTypeColumn<ESM::BodyPart> *meshType)
: mMeshType(meshType)
{}
QVariant CSMWorld::BodyPartRaceColumn::get(const Record<ESM::BodyPart> &record) const
{
if (mMeshType != NULL && mMeshType->get(record) == ESM::BodyPart::MT_Skin)
{
return QString::fromUtf8(record.get().mRace.c_str());
}
return QVariant(QVariant::UserType);
}
void CSMWorld::BodyPartRaceColumn::set(Record<ESM::BodyPart> &record, const QVariant &data)
{
ESM::BodyPart record2 = record.get();
record2.mRace = data.toString().toUtf8().constData();
record.setModified(record2);
}
bool CSMWorld::BodyPartRaceColumn::isEditable() const
{
return true;
}

View file

@ -9,6 +9,10 @@
#include <QColor>
#include <components/esm/loadbody.hpp>
#include <components/esm/loadskil.hpp>
#include <components/esm/loadrace.hpp>
#include "columnbase.hpp"
#include "columns.hpp"
#include "info.hpp"
@ -1911,8 +1915,8 @@ namespace CSMWorld
template<typename ESXRecordT>
struct MeshTypeColumn : public Column<ESXRecordT>
{
MeshTypeColumn()
: Column<ESXRecordT> (Columns::ColumnId_MeshType, ColumnBase::Display_MeshType)
MeshTypeColumn(int flags = ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue)
: Column<ESXRecordT> (Columns::ColumnId_MeshType, ColumnBase::Display_MeshType, flags)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
@ -2379,7 +2383,18 @@ namespace CSMWorld
{
return true;
}
};
};
struct BodyPartRaceColumn : public RaceColumn<ESM::BodyPart>
{
const MeshTypeColumn<ESM::BodyPart> *mMeshType;
BodyPartRaceColumn(const MeshTypeColumn<ESM::BodyPart> *meshType);
virtual QVariant get(const Record<ESM::BodyPart> &record) const;
virtual void set(Record<ESM::BodyPart> &record, const QVariant &data);
virtual bool isEditable() const;
};
}
#endif

View file

@ -1,4 +1,3 @@
#include "columns.hpp"
#include <components/misc/stringops.hpp>
@ -35,6 +34,8 @@ namespace CSMWorld
{ ColumnId_Volume, "Volume" },
{ ColumnId_MinRange, "Min Range" },
{ ColumnId_MaxRange, "Max Range" },
{ ColumnId_MinMagnitude, "Min Magnitude" },
{ ColumnId_MaxMagnitude, "Max Magnitude" },
{ ColumnId_SoundFile, "Sound File" },
{ ColumnId_MapColour, "Map Colour" },
{ ColumnId_SleepEncounter, "Sleep Encounter" },
@ -107,7 +108,6 @@ namespace CSMWorld
{ ColumnId_OriginalCreature, "Original Creature" },
{ ColumnId_Biped, "Biped" },
{ ColumnId_HasWeapon, "Has Weapon" },
{ ColumnId_NoMovement, "No Movement" },
{ ColumnId_Swims, "Swims" },
{ ColumnId_Flies, "Flies" },
{ ColumnId_Walks, "Walks" },
@ -540,11 +540,6 @@ namespace
"AI Wander", "AI Travel", "AI Follow", "AI Escort", "AI Activate", 0
};
static const char *sAiWanderRepeat[] =
{
"No", "Yes", 0
};
static const char *sInfoCondFunc[] =
{
" ", "Function", "Global", "Local", "Journal",
@ -584,7 +579,6 @@ namespace
case CSMWorld::Columns::ColumnId_EffectId: return sEffectId;
case CSMWorld::Columns::ColumnId_PartRefType: return sPartRefType;
case CSMWorld::Columns::ColumnId_AiPackageType: return sAiPackageType;
case CSMWorld::Columns::ColumnId_AiWanderRepeat: return sAiWanderRepeat;
case CSMWorld::Columns::ColumnId_InfoCondFunc: return sInfoCondFunc;
// FIXME: don't have dynamic value enum delegate, use Display_String for now
//case CSMWorld::Columns::ColumnId_InfoCond: return sInfoCond;

View file

@ -102,7 +102,7 @@ namespace CSMWorld
ColumnId_OriginalCreature = 87,
ColumnId_Biped = 88,
ColumnId_HasWeapon = 89,
ColumnId_NoMovement = 90,
// unused
ColumnId_Swims = 91,
ColumnId_Flies = 92,
ColumnId_Walks = 93,
@ -306,9 +306,12 @@ namespace CSMWorld
ColumnId_FileDescription = 276,
ColumnId_Author = 277,
ColumnId_SpellSrc = 278,
ColumnId_SpellCost = 279,
ColumnId_SpellChance = 280,
ColumnId_MinMagnitude = 278,
ColumnId_MaxMagnitude = 279,
ColumnId_SpellSrc = 280,
ColumnId_SpellCost = 281,
ColumnId_SpellChance = 282,
// Allocated to a separate value range, so we don't get a collision should we ever need
// to extend the number of use values.

View file

@ -1,4 +1,3 @@
#include "commanddispatcher.hpp"
#include <algorithm>

View file

@ -21,19 +21,31 @@ CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelI
// Replace proxy with actual model
mIndex = proxy->mapToSource (index);
mModel = proxy->sourceModel();
}
if (mIndex.parent().isValid())
{
setText ("Modify " + dynamic_cast<CSMWorld::IdTree*>(mModel)->nestedHeaderData (
mIndex.parent().column(), mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString());
}
else
{
setText ("Modify " + mModel->headerData (mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString());
}
// Remember record state before the modification
if (CSMWorld::IdTable *table = dynamic_cast<IdTable *>(mModel))
{
mHasRecordState = true;
int stateColumnIndex = table->findColumnIndex(Columns::ColumnId_Modification);
mRecordStateIndex = table->index(mIndex.row(), stateColumnIndex);
int rowIndex = mIndex.row();
if (mIndex.parent().isValid())
{
rowIndex = mIndex.parent().row();
}
mRecordStateIndex = table->index(rowIndex, stateColumnIndex);
mOldRecordState = static_cast<CSMWorld::RecordBase::State>(table->data(mRecordStateIndex).toInt());
}
}
@ -282,21 +294,24 @@ CSMWorld::DeleteNestedCommand::DeleteNestedCommand (IdTree& model,
std::string title =
model.headerData(parentColumn, Qt::Horizontal, Qt::DisplayRole).toString().toUtf8().constData();
setText (("Delete row in " + title + " sub-table of " + mId).c_str());
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
mModifyParentCommand = new ModifyCommand(mModel, parentIndex, parentIndex.data(Qt::EditRole), this);
}
void CSMWorld::DeleteNestedCommand::redo()
{
const QModelIndex& parentIndex = mModel.getModelIndex(mId, mParentColumn);
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
mModel.removeRows (mNestedRow, 1, parentIndex);
mModifyParentCommand->redo();
}
void CSMWorld::DeleteNestedCommand::undo()
{
const QModelIndex& parentIndex = mModel.getModelIndex(mId, mParentColumn);
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
mModel.setNestedTable(parentIndex, getOld());
mModifyParentCommand->undo();
}
CSMWorld::AddNestedCommand::AddNestedCommand(IdTree& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent)
@ -310,20 +325,23 @@ CSMWorld::AddNestedCommand::AddNestedCommand(IdTree& model, const std::string& i
std::string title =
model.headerData(parentColumn, Qt::Horizontal, Qt::DisplayRole).toString().toUtf8().constData();
setText (("Add row in " + title + " sub-table of " + mId).c_str());
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
mModifyParentCommand = new ModifyCommand(mModel, parentIndex, parentIndex.data(Qt::EditRole), this);
}
void CSMWorld::AddNestedCommand::redo()
{
const QModelIndex& parentIndex = mModel.getModelIndex(mId, mParentColumn);
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
mModel.addNestedRow (parentIndex, mNewRow);
mModifyParentCommand->redo();
}
void CSMWorld::AddNestedCommand::undo()
{
const QModelIndex& parentIndex = mModel.getModelIndex(mId, mParentColumn);
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
mModel.setNestedTable(parentIndex, getOld());
mModifyParentCommand->undo();
}
CSMWorld::NestedTableStoring::NestedTableStoring(const IdTree& model, const std::string& id, int parentColumn)

View file

@ -200,6 +200,9 @@ namespace CSMWorld
int mNestedRow;
// The command to redo/undo the Modified status of a record
ModifyCommand *mModifyParentCommand;
public:
DeleteNestedCommand (IdTree& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent = 0);
@ -219,6 +222,9 @@ namespace CSMWorld
int mParentColumn;
// The command to redo/undo the Modified status of a record
ModifyCommand *mModifyParentCommand;
public:
AddNestedCommand(IdTree& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent = 0);

View file

@ -1,4 +1,3 @@
#include "data.hpp"
#include <stdexcept>
@ -293,9 +292,9 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mSpells.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_Duration, ColumnBase::Display_Integer)); // reuse from light
mSpells.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_MinRange, ColumnBase::Display_Integer)); // reuse from sound
new NestedChildColumn (Columns::ColumnId_MinMagnitude, ColumnBase::Display_Integer));
mSpells.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_MaxRange, ColumnBase::Display_Integer)); // reuse from sound
new NestedChildColumn (Columns::ColumnId_MaxMagnitude, ColumnBase::Display_Integer));
mTopics.addColumn (new StringIdColumn<ESM::Dialogue>);
mTopics.addColumn (new RecordStateColumn<ESM::Dialogue>);
@ -409,9 +408,9 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mEnchantments.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_Duration, ColumnBase::Display_Integer)); // reuse from light
mEnchantments.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_MinRange, ColumnBase::Display_Integer)); // reuse from sound
new NestedChildColumn (Columns::ColumnId_MinMagnitude, ColumnBase::Display_Integer));
mEnchantments.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_MaxRange, ColumnBase::Display_Integer)); // reuse from sound
new NestedChildColumn (Columns::ColumnId_MaxMagnitude, ColumnBase::Display_Integer));
mBodyParts.addColumn (new StringIdColumn<ESM::BodyPart>);
mBodyParts.addColumn (new RecordStateColumn<ESM::BodyPart>);
@ -421,9 +420,12 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mBodyParts.addColumn (new FlagColumn<ESM::BodyPart> (Columns::ColumnId_Female, ESM::BodyPart::BPF_Female));
mBodyParts.addColumn (new FlagColumn<ESM::BodyPart> (Columns::ColumnId_Playable,
ESM::BodyPart::BPF_NotPlayable, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, true));
mBodyParts.addColumn (new MeshTypeColumn<ESM::BodyPart>);
int meshTypeFlags = ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh;
MeshTypeColumn<ESM::BodyPart> *meshTypeColumn = new MeshTypeColumn<ESM::BodyPart>(meshTypeFlags);
mBodyParts.addColumn (meshTypeColumn);
mBodyParts.addColumn (new ModelColumn<ESM::BodyPart>);
mBodyParts.addColumn (new RaceColumn<ESM::BodyPart>);
mBodyParts.addColumn (new BodyPartRaceColumn(meshTypeColumn));
mSoundGens.addColumn (new StringIdColumn<ESM::SoundGenerator>);
mSoundGens.addColumn (new RecordStateColumn<ESM::SoundGenerator>);

View file

@ -76,8 +76,15 @@ bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value
if (mIdCollection->getColumn (index.column()).isEditable() && role==Qt::EditRole)
{
mIdCollection->setData (index.row(), index.column(), value);
emit dataChanged(index, index);
emit dataChanged (index, index);
// Modifying a value can also change the Modified status of a record.
int stateColumn = searchColumnIndex(Columns::ColumnId_Modification);
if (stateColumn != -1)
{
QModelIndex stateIndex = this->index(index.row(), stateColumn);
emit dataChanged(stateIndex, stateIndex);
}
return true;
}

View file

@ -1,4 +1,3 @@
#include "idtablebase.hpp"
CSMWorld::IdTableBase::IdTableBase (unsigned int features) : mFeatures (features) {}

View file

@ -1,10 +1,21 @@
#include "idtableproxymodel.hpp"
#include <vector>
#include "idtablebase.hpp"
namespace
{
std::string getEnumValue(const std::vector<std::string> &values, int index)
{
if (index < 0 || index >= static_cast<int>(values.size()))
{
return "";
}
return values[index];
}
}
void CSMWorld::IdTableProxyModel::updateColumnMap()
{
Q_ASSERT(mSourceModel != NULL);
@ -93,7 +104,9 @@ bool CSMWorld::IdTableProxyModel::lessThan(const QModelIndex &left, const QModel
if (valuesIt != mEnumColumnCache.end())
{
return valuesIt->second[left.data().toInt()] < valuesIt->second[right.data().toInt()];
std::string first = getEnumValue(valuesIt->second, left.data().toInt());
std::string second = getEnumValue(valuesIt->second, right.data().toInt());
return first < second;
}
return QSortFilterProxyModel::lessThan(left, right);
}

View file

@ -95,8 +95,15 @@ bool CSMWorld::IdTree::setData (const QModelIndex &index, const QVariant &value,
const std::pair<int, int>& parentAddress(unfoldIndexAddress(index.internalId()));
mNestedCollection->setNestedData(parentAddress.first, parentAddress.second, value, index.row(), index.column());
emit dataChanged(index, index);
emit dataChanged (index, index);
// Modifying a value can also change the Modified status of a record.
int stateColumn = searchColumnIndex(Columns::ColumnId_Modification);
if (stateColumn != -1)
{
QModelIndex stateIndex = this->index(index.parent().row(), stateColumn);
emit dataChanged(stateIndex, stateIndex);
}
return true;
}

View file

@ -1,4 +1,3 @@
#include "infocollection.hpp"
#include <stdexcept>

View file

@ -9,13 +9,7 @@ namespace CSMWorld
{
ESM::LandTexture::load(esm);
int plugin = esm.getIndex();
std::ostringstream stream;
stream << mIndex << "_" << plugin;
mId = stream.str();
mPluginIndex = esm.getIndex();
}
}

View file

@ -7,13 +7,10 @@
namespace CSMWorld
{
/// \brief Wrapper for LandTexture record. Encodes mIndex and the plugin index (obtained from ESMReader)
/// in the ID.
///
/// \attention The mId field of the ESM::LandTexture struct is not used.
/// \brief Wrapper for LandTexture record, providing info which plugin the LandTexture was loaded from.
struct LandTexture : public ESM::LandTexture
{
std::string mId;
int mPluginIndex;
void load (ESM::ESMReader &esm);
};

View file

@ -1,4 +1,3 @@
#include "metadata.hpp"
#include <components/esm/loadtes3.hpp>

View file

@ -1,4 +1,3 @@
#include "record.hpp"
CSMWorld::RecordBase::~RecordBase() {}

View file

@ -1,4 +1,3 @@
#include "ref.hpp"
#include <cmath>

View file

@ -1,4 +1,3 @@
#include "refcollection.hpp"
#include <sstream>

View file

@ -1466,7 +1466,7 @@ namespace CSMWorld
return QVariant();
case 5: // wander repeat
if (content.mType == ESM::AI_Wander)
return content.mWander.mShouldRepeat;
return content.mWander.mShouldRepeat != 0;
else
return QVariant();
case 6: // activate name

View file

@ -94,9 +94,9 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data)
mColumns.back().addColumn(
new NestedChildColumn (Columns::ColumnId_Duration, ColumnBase::Display_Integer)); // reuse from light
mColumns.back().addColumn(
new NestedChildColumn (Columns::ColumnId_MinRange, ColumnBase::Display_Integer)); // reuse from sound
new NestedChildColumn (Columns::ColumnId_MinMagnitude, ColumnBase::Display_Integer));
mColumns.back().addColumn(
new NestedChildColumn (Columns::ColumnId_MaxRange, ColumnBase::Display_Integer)); // reuse from sound
new NestedChildColumn (Columns::ColumnId_MaxMagnitude, ColumnBase::Display_Integer));
EnchantableColumns enchantableColumns (inventoryColumns);
@ -156,7 +156,7 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data)
new RefIdColumn (Columns::ColumnId_SpellType, CSMWorld::ColumnBase::Display_SpellType, false/*editable*/, false/*user editable*/));
// creatures do not have below columns
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_SpellSrc, CSMWorld::ColumnBase::Display_YesNo, false, false)); // from race
new RefIdColumn (Columns::ColumnId_SpellSrc, CSMWorld::ColumnBase::Display_Boolean, false, false)); // from race
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_SpellCost, CSMWorld::ColumnBase::Display_Integer, false, false));
mColumns.back().addColumn(
@ -208,7 +208,7 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data)
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_AiWanderIdle, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_AiWanderRepeat, CSMWorld::ColumnBase::Display_YesNo));
new RefIdColumn (Columns::ColumnId_AiWanderRepeat, CSMWorld::ColumnBase::Display_Boolean));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_AiActivateName, CSMWorld::ColumnBase::Display_String));
mColumns.back().addColumn(
@ -331,7 +331,6 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data)
{
{ Columns::ColumnId_Biped, ESM::Creature::Bipedal },
{ Columns::ColumnId_HasWeapon, ESM::Creature::Weapon },
{ Columns::ColumnId_NoMovement, ESM::Creature::None },
{ Columns::ColumnId_Swims, ESM::Creature::Swims },
{ Columns::ColumnId_Flies, ESM::Creature::Flies },
{ Columns::ColumnId_Walks, ESM::Creature::Walks },
@ -391,7 +390,7 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data)
{ Columns::ColumnId_Portable, ESM::Light::Carry },
{ Columns::ColumnId_NegativeLight, ESM::Light::Negative },
{ Columns::ColumnId_Flickering, ESM::Light::Flicker },
{ Columns::ColumnId_SlowFlickering, ESM::Light::Flicker },
{ Columns::ColumnId_SlowFlickering, ESM::Light::FlickerSlow },
{ Columns::ColumnId_Pulsing, ESM::Light::Pulse },
{ Columns::ColumnId_SlowPulsing, ESM::Light::PulseSlow },
{ Columns::ColumnId_Fire, ESM::Light::Fire },

View file

@ -1,4 +1,3 @@
#include "refiddata.hpp"
#include <cassert>

View file

@ -1,4 +1,3 @@
#include "regionmap.hpp"
#include <cmath>

View file

@ -1,4 +1,3 @@
#include "resources.hpp"
#include <sstream>

View file

@ -1,4 +1,3 @@
#include "resourcesmanager.hpp"
#include <stdexcept>

View file

@ -1,4 +1,3 @@
#include "resourcetable.hpp"
#include <stdexcept>

View file

@ -1,4 +1,3 @@
#include "scope.hpp"
#include <stdexcept>

View file

@ -1,4 +1,3 @@
#include "scriptcontext.hpp"
#include <algorithm>

View file

@ -1,4 +1,3 @@
#ifndef TABLEMIMEDATA_H
#define TABLEMIMEDATA_H

View file

@ -1,4 +1,3 @@
#include "universalid.hpp"
#include <ostream>

View file

@ -1,4 +1,3 @@
#include "adjusterwidget.hpp"
#include <stdexcept>

View file

@ -1,4 +1,3 @@
#include "filewidget.hpp"
#include <QHBoxLayout>

View file

@ -1,4 +1,3 @@
#include "globaldebugprofilemenu.hpp"
#include <vector>

View file

@ -1,4 +1,3 @@
#include "loader.hpp"
#include <QVBoxLayout>

View file

@ -1,4 +1,3 @@
#include "newgame.hpp"
#include <QApplication>

View file

@ -1,4 +1,3 @@
#include "runlogsubview.hpp"
#include <QTextEdit>

View file

@ -1,4 +1,3 @@
#include "startup.hpp"
#include <QApplication>

View file

@ -1,4 +1,3 @@
#include "subviewfactory.hpp"
#include <cassert>

View file

@ -1,4 +1,3 @@
#include "viewmanager.hpp"
#include <vector>
@ -97,13 +96,12 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
{ CSMWorld::ColumnBase::Display_MeshType, CSMWorld::Columns::ColumnId_MeshType, false },
{ CSMWorld::ColumnBase::Display_Gender, CSMWorld::Columns::ColumnId_Gender, true },
{ CSMWorld::ColumnBase::Display_SoundGeneratorType, CSMWorld::Columns::ColumnId_SoundGeneratorType, false },
{ CSMWorld::ColumnBase::Display_School, CSMWorld::Columns::ColumnId_School, true },
{ CSMWorld::ColumnBase::Display_School, CSMWorld::Columns::ColumnId_School, false },
{ CSMWorld::ColumnBase::Display_SkillImpact, CSMWorld::Columns::ColumnId_SkillImpact, true },
{ CSMWorld::ColumnBase::Display_EffectRange, CSMWorld::Columns::ColumnId_EffectRange, false },
{ CSMWorld::ColumnBase::Display_EffectId, CSMWorld::Columns::ColumnId_EffectId, false },
{ CSMWorld::ColumnBase::Display_PartRefType, CSMWorld::Columns::ColumnId_PartRefType, false },
{ CSMWorld::ColumnBase::Display_AiPackageType, CSMWorld::Columns::ColumnId_AiPackageType, false },
{ CSMWorld::ColumnBase::Display_YesNo, CSMWorld::Columns::ColumnId_AiWanderRepeat, false },
{ CSMWorld::ColumnBase::Display_InfoCondFunc, CSMWorld::Columns::ColumnId_InfoCondFunc, false },
{ CSMWorld::ColumnBase::Display_InfoCondComp, CSMWorld::Columns::ColumnId_InfoCondComp, false },
{ CSMWorld::ColumnBase::Display_RaceSkill, CSMWorld::Columns::ColumnId_RaceSkill, true },

View file

@ -1,4 +1,3 @@
#include "editwidget.hpp"
#include <QAbstractItemModel>

View file

@ -1,4 +1,3 @@
#include "filterbox.hpp"
#include <QHBoxLayout>

View file

@ -1,4 +1,3 @@
#include "recordfilterbox.hpp"
#include <QHBoxLayout>

View file

@ -1,4 +1,3 @@
#include "cell.hpp"
#include <OgreSceneManager.h>

View file

@ -1,4 +1,3 @@
#include "editmode.hpp"
#include "worldspacewidget.hpp"

View file

@ -1,4 +1,3 @@
#include "lightingbright.hpp"
#include <OgreSceneManager.h>

View file

@ -1,4 +1,3 @@
#include "pagedworldspacewidget.hpp"
#include <sstream>

View file

@ -1,4 +1,3 @@
#include "previewwidget.hpp"
#include <OgreSceneManager.h>

View file

@ -28,10 +28,18 @@ namespace CSVRender
const ESM::LandTexture* TerrainStorage::getLandTexture(int index, short plugin)
{
std::ostringstream stream;
stream << index << "_" << plugin;
int numRecords = mData.getLandTextures().getSize();
return &mData.getLandTextures().getRecord(stream.str()).get();
for (int i=0; i<numRecords; ++i)
{
const CSMWorld::LandTexture* ltex = &mData.getLandTextures().getRecord(i).get();
if (ltex->mIndex == index && ltex->mPluginIndex == plugin)
return ltex;
}
std::stringstream error;
error << "Can't find LandTexture " << index << " from plugin " << plugin;
throw std::runtime_error(error.str());
}
void TerrainStorage::getBounds(float &minX, float &maxX, float &minY, float &maxY)

Some files were not shown because too many files have changed in this diff Show more