diff --git a/apps/opencs/model/doc/saving.cpp b/apps/opencs/model/doc/saving.cpp index ef753bb4b..95631eea9 100644 --- a/apps/opencs/model/doc/saving.cpp +++ b/apps/opencs/model/doc/saving.cpp @@ -62,6 +62,9 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje appendStage (new WriteCollectionStage > (mDocument.getData().getEnchantments(), mState)); + appendStage (new WriteCollectionStage > + (mDocument.getData().getBodyParts(), mState)); + appendStage (new WriteDialogueCollectionStage (mDocument, mState, false)); appendStage (new WriteDialogueCollectionStage (mDocument, mState, true)); diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index d31d7cf29..5844e97a7 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -463,14 +463,21 @@ namespace CSMWorld struct FlagColumn : public Column { int mMask; + bool mInverted; - FlagColumn (int columnId, int mask) - : Column (columnId, ColumnBase::Display_Boolean), mMask (mask) + FlagColumn (int columnId, int mask, bool inverted = false) + : Column (columnId, ColumnBase::Display_Boolean), mMask (mask), + mInverted (inverted) {} virtual QVariant get (const Record& record) const { - return (record.get().mData.mFlags & mMask)!=0; + bool flag = (record.get().mData.mFlags & mMask)!=0; + + if (mInverted) + flag = !flag; + + return flag; } virtual void set (Record& record, const QVariant& data) @@ -479,7 +486,7 @@ namespace CSMWorld int flags = record2.mData.mFlags & ~mMask; - if (data.toInt()) + if ((data.toInt()!=0)!=mInverted) flags |= mMask; record2.mData.mFlags = flags; @@ -1758,6 +1765,58 @@ namespace CSMWorld return true; } }; + + template + struct ModelColumn : public Column + { + ModelColumn() : Column (Columns::ColumnId_Model, ColumnBase::Display_String) {} + + virtual QVariant get (const Record& record) const + { + return QString::fromUtf8 (record.get().mModel.c_str()); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mModel = data.toString().toUtf8().constData(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; + + template + struct VampireColumn : public Column + { + VampireColumn() : Column (Columns::ColumnId_Vampire, ColumnBase::Display_Boolean) + {} + + virtual QVariant get (const Record& record) const + { + return record.get().mData.mVampire!=0; + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mData.mVampire = data.toInt(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; + } #endif diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 4f88e7b1b..3d363aac4 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -178,7 +178,7 @@ namespace CSMWorld { ColumnId_MagicState, "Magic" }, { ColumnId_StealthState, "Stealth" }, { ColumnId_EnchantmentType, "Enchantment Type" }, - { ColumnId_AutoCalc, "Auto Calc" }, + { ColumnId_Vampire, "Vampire" }, { ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue2, "Use value 2" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 0b65b2932..bb6c0e453 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -171,6 +171,7 @@ namespace CSMWorld ColumnId_MagicState = 158, ColumnId_StealthState = 159, ColumnId_EnchantmentType = 160, + ColumnId_Vampire = 161, // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 12de19a82..0353d2142 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -206,6 +206,18 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding) mEnchantments.addColumn (new ChargesColumn2); mEnchantments.addColumn (new AutoCalcColumn); + mBodyParts.addColumn (new StringIdColumn); + mBodyParts.addColumn (new RecordStateColumn); + mBodyParts.addColumn (new FixedRecordTypeColumn (UniversalId::Type_BodyPart)); + + mBodyParts.addColumn (new VampireColumn); + mBodyParts.addColumn (new FlagColumn (Columns::ColumnId_Female, ESM::BodyPart::BPF_Female)); + mBodyParts.addColumn (new FlagColumn (Columns::ColumnId_Playable, ESM::BodyPart::BPF_NotPlayable, true)); + + mBodyParts.addColumn (new ModelColumn); + mBodyParts.addColumn (new RaceColumn); + + mRefs.addColumn (new StringIdColumn (true)); mRefs.addColumn (new RecordStateColumn); mRefs.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Reference)); @@ -261,6 +273,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding) addModel (new IdTable (&mJournalInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_JournalInfo); addModel (new IdTable (&mCells, IdTable::Feature_ViewId), UniversalId::Type_Cell); addModel (new IdTable (&mEnchantments), UniversalId::Type_Enchantment); + addModel (new IdTable (&mBodyParts), UniversalId::Type_BodyPart); addModel (new IdTable (&mReferenceables, IdTable::Feature_Preview), UniversalId::Type_Referenceable); addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference); @@ -476,6 +489,16 @@ CSMWorld::IdCollection& CSMWorld::Data::getEnchantments() return mEnchantments; } +const CSMWorld::IdCollection& CSMWorld::Data::getBodyParts() const +{ + return mBodyParts; +} + +CSMWorld::IdCollection& CSMWorld::Data::getBodyParts() +{ + return mBodyParts; +} + QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); @@ -554,6 +577,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages) case ESM::REC_BSGN: mBirthsigns.load (*mReader, mBase); break; case ESM::REC_SPEL: mSpells.load (*mReader, mBase); break; case ESM::REC_ENCH: mEnchantments.load (*mReader, mBase); break; + case ESM::REC_BODY: mBodyParts.load (*mReader, mBase); break; case ESM::REC_CELL: { diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 758354450..9bdb449e0 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -65,6 +66,7 @@ namespace CSMWorld IdCollection mTopics; IdCollection mJournals; IdCollection mEnchantments; + IdCollection mBodyParts; InfoCollection mTopicInfos; InfoCollection mJournalInfos; IdCollection mCells; @@ -180,6 +182,10 @@ namespace CSMWorld IdCollection& getEnchantments(); + const IdCollection& getBodyParts() const; + + IdCollection& getBodyParts(); + QAbstractItemModel *getTableModel (const UniversalId& id); ///< If no table model is available for \a id, an exception is thrown. /// diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 79273a831..3a5f3f043 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -36,6 +36,7 @@ namespace { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_JournalInfos, "Journal Infos", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Enchantments, "Enchantments", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_BodyParts, "Body Parts", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables, "Referenceables", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_References, @@ -95,6 +96,7 @@ namespace { CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", 0 }, { CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Enchantment, "Enchantment", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_BodyPart, "Body Part", 0 }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index f92ad0bcb..c7514336f 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -102,10 +102,12 @@ namespace CSMWorld Type_Preview, Type_LoadErrorLog, Type_Enchantments, - Type_Enchantment + Type_Enchantment, + Type_BodyParts, + Type_BodyPart }; - enum { NumberOfTypes = Type_Enchantment+1 }; + enum { NumberOfTypes = Type_BodyPart+1 }; private: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index a356721f6..6a807f086 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -191,6 +191,10 @@ void CSVDoc::View::setupCharacterMenu() QAction *journalInfos = new QAction (tr ("Journal Infos"), this); connect (journalInfos, SIGNAL (triggered()), this, SLOT (addJournalInfosSubView())); characters->addAction (journalInfos); + + QAction *bodyParts = new QAction (tr ("Body Parts"), this); + connect (bodyParts, SIGNAL (triggered()), this, SLOT (addBodyPartsSubView())); + characters->addAction (bodyParts); } void CSVDoc::View::setupAssetsMenu() @@ -478,6 +482,11 @@ void CSVDoc::View::addEnchantmentsSubView() addSubView (CSMWorld::UniversalId::Type_Enchantments); } +void CSVDoc::View::addBodyPartsSubView() +{ + addSubView (CSMWorld::UniversalId::Type_BodyParts); +} + void CSVDoc::View::abortOperation (int type) { mDocument->abortOperation (type); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 1ba73c56d..a227997c2 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -180,6 +180,8 @@ namespace CSVDoc void addEnchantmentsSubView(); + void addBodyPartsSubView(); + void toggleShowStatusBar (bool show); void loadErrorLog(); diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index c1b5393d3..8c666c1fe 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -40,6 +40,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CSMWorld::UniversalId::Type_Birthsigns, CSMWorld::UniversalId::Type_Spells, CSMWorld::UniversalId::Type_Enchantments, + CSMWorld::UniversalId::Type_BodyParts, CSMWorld::UniversalId::Type_None // end marker }; @@ -94,6 +95,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CSMWorld::UniversalId::Type_Sound, CSMWorld::UniversalId::Type_Faction, CSMWorld::UniversalId::Type_Enchantment, + CSMWorld::UniversalId::Type_BodyPart, CSMWorld::UniversalId::Type_None // end marker }; diff --git a/components/esm/loadbody.cpp b/components/esm/loadbody.cpp index c45f8d252..9a1164d04 100644 --- a/components/esm/loadbody.cpp +++ b/components/esm/loadbody.cpp @@ -22,4 +22,14 @@ void BodyPart::save(ESMWriter &esm) const esm.writeHNT("BYDT", mData, 4); } + void BodyPart::blank() + { + mData.mPart = 0; + mData.mVampire = 0; + mData.mFlags = 0; + mData.mType = 0; + + mModel.clear(); + mRace.clear(); + } } diff --git a/components/esm/loadbody.hpp b/components/esm/loadbody.hpp index 9623caa31..286e3f96e 100644 --- a/components/esm/loadbody.hpp +++ b/components/esm/loadbody.hpp @@ -60,6 +60,9 @@ struct BodyPart void load(ESMReader &esm); void save(ESMWriter &esm) const; + + void blank(); + ///< Set record to default state (does not touch the ID). }; } #endif