Add clothing/armor part reference table to dialogue subview.

This commit is contained in:
cc9cii 2015-04-13 21:08:23 +10:00
parent 526b53fce0
commit 513c3a47cb
6 changed files with 222 additions and 33 deletions

View file

@ -250,7 +250,7 @@ namespace CSMWorld
{ ColumnId_AiPackageList, "Ai Packages"},
{ ColumnId_AiPackage, "Package"},
{ ColumnId_AiWanderDist, "Wander Dist"},
{ ColumnId_AiWanderDuration, "Wander Duration"},
{ ColumnId_AiDuration, "Duration"},
{ ColumnId_AiWanderToD, "Wander ToD"},
{ ColumnId_AiWanderIdle, "Wander Idle"},
{ ColumnId_AiWanderRepeat, "Wander Repeat"},
@ -258,6 +258,11 @@ namespace CSMWorld
{ ColumnId_AiTargetId, "Target ID"},
{ ColumnId_AiTargetCell, "Target Cell"},
{ ColumnId_PartRefList, "Part Reference"},
{ ColumnId_PartRefType, "Type"},
{ ColumnId_PartRefMale, "Male"},
{ ColumnId_PartRefFemale, "Female"},
{ ColumnId_UseValue1, "Use value 1" },
{ ColumnId_UseValue2, "Use value 2" },
{ ColumnId_UseValue3, "Use value 3" },

View file

@ -239,7 +239,7 @@ namespace CSMWorld
ColumnId_AiPackageList = 219,
ColumnId_AiPackage = 220,
ColumnId_AiWanderDist = 221,
ColumnId_AiWanderDuration = 222,
ColumnId_AiDuration = 222,
ColumnId_AiWanderToD = 223,
ColumnId_AiWanderIdle = 224,
ColumnId_AiWanderRepeat = 225,
@ -248,6 +248,11 @@ namespace CSMWorld
ColumnId_AiTargetId = 227,
ColumnId_AiTargetCell = 228,
ColumnId_PartRefList = 229,
ColumnId_PartRefType = 230,
ColumnId_PartRefMale = 231,
ColumnId_PartRefFemale = 232,
// Allocated to a separate value range, so we don't get a collision should we ever need
// to extend the number of use values.
ColumnId_UseValue1 = 0x10000,

View file

@ -81,9 +81,10 @@ void CSMWorld::ApparatusRefIdAdapter::setData (const RefIdColumn *column, RefIdD
CSMWorld::ArmorRefIdAdapter::ArmorRefIdAdapter (const EnchantableColumns& columns,
const RefIdColumn *type, const RefIdColumn *health, const RefIdColumn *armor)
const RefIdColumn *type, const RefIdColumn *health, const RefIdColumn *armor,
const RefIdColumn *partRef)
: EnchantableRefIdAdapter<ESM::Armor> (UniversalId::Type_Armor, columns),
mType (type), mHealth (health), mArmor (armor)
mType (type), mHealth (health), mArmor (armor), mPartRef(partRef)
{}
QVariant CSMWorld::ArmorRefIdAdapter::getData (const RefIdColumn *column,
@ -101,6 +102,9 @@ QVariant CSMWorld::ArmorRefIdAdapter::getData (const RefIdColumn *column,
if (column==mArmor)
return record.get().mData.mArmor;
if (column==mPartRef)
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
return EnchantableRefIdAdapter<ESM::Armor>::getData (column, data, index);
}
@ -156,8 +160,9 @@ void CSMWorld::BookRefIdAdapter::setData (const RefIdColumn *column, RefIdData&
}
CSMWorld::ClothingRefIdAdapter::ClothingRefIdAdapter (const EnchantableColumns& columns,
const RefIdColumn *type)
: EnchantableRefIdAdapter<ESM::Clothing> (UniversalId::Type_Clothing, columns), mType (type)
const RefIdColumn *type, const RefIdColumn *partRef)
: EnchantableRefIdAdapter<ESM::Clothing> (UniversalId::Type_Clothing, columns), mType (type),
mPartRef(partRef)
{}
QVariant CSMWorld::ClothingRefIdAdapter::getData (const RefIdColumn *column,
@ -169,6 +174,9 @@ QVariant CSMWorld::ClothingRefIdAdapter::getData (const RefIdColumn *column,
if (column==mType)
return record.get().mData.mType;
if (column==mPartRef)
return true; // to show nested tables in dialogue subview, see IdTree::hasChildren()
return EnchantableRefIdAdapter<ESM::Clothing>::getData (column, data, index);
}

View file

@ -622,11 +622,12 @@ namespace CSMWorld
const RefIdColumn *mType;
const RefIdColumn *mHealth;
const RefIdColumn *mArmor;
const RefIdColumn *mPartRef;
public:
ArmorRefIdAdapter (const EnchantableColumns& columns, const RefIdColumn *type,
const RefIdColumn *health, const RefIdColumn *armor);
const RefIdColumn *health, const RefIdColumn *armor, const RefIdColumn *partRef);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
@ -657,10 +658,12 @@ namespace CSMWorld
class ClothingRefIdAdapter : public EnchantableRefIdAdapter<ESM::Clothing>
{
const RefIdColumn *mType;
const RefIdColumn *mPartRef;
public:
ClothingRefIdAdapter (const EnchantableColumns& columns, const RefIdColumn *type);
ClothingRefIdAdapter (const EnchantableColumns& columns,
const RefIdColumn *type, const RefIdColumn *partRef);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
@ -1290,27 +1293,13 @@ namespace CSMWorld
switch (subColIndex)
{
case 0:
return QString::fromUtf8(content.mCellName.c_str());
case 1:
return content.mPos.pos[0];
case 2:
return content.mPos.pos[1];
case 3:
return content.mPos.pos[2];
case 4:
return content.mPos.rot[0];
case 5:
return content.mPos.rot[1];
case 6:
return content.mPos.rot[2];
case 0: return QString::fromUtf8(content.mCellName.c_str());
case 1: return content.mPos.pos[0];
case 2: return content.mPos.pos[1];
case 3: return content.mPos.pos[2];
case 4: return content.mPos.rot[0];
case 5: return content.mPos.rot[1];
case 6: return content.mPos.rot[2];
default:
throw std::runtime_error("Trying to access non-existing column in the nested table!");
}
@ -1675,6 +1664,170 @@ namespace CSMWorld
return static_cast<int>(record.get().mAiPackage.mList.size());
}
};
static const char *sPartRefs[ESM::PRT_Count] =
{
"Head", "Hair", "Neck", "Cuirass", "Groin",
"Skirt", "Right Hand", "Left Hand", "Right Wrist", "Left Wrist",
"Shield", "Right Forearm", "Left Forearm", "Right Upperarm", "Left Upperarm",
"Right Foot", "Left Foot", "Right Ankle", "Left Ankle", "Right Knee",
"Left Knee", "Right Leg", "Left Leg", "Right Pauldron", "Left Pauldron",
"Weapon", "Tail"
};
template <typename ESXRecordT>
class BodyPartRefIdAdapter : public NestedRefIdAdapterBase
{
UniversalId::Type mType;
// not implemented
BodyPartRefIdAdapter (const BodyPartRefIdAdapter&);
BodyPartRefIdAdapter& operator= (const BodyPartRefIdAdapter&);
public:
BodyPartRefIdAdapter(UniversalId::Type type) :mType(type) {}
virtual ~BodyPartRefIdAdapter() {}
virtual void addNestedRow (const RefIdColumn *column,
RefIdData& data, int index, int position) const
{
Record<ESXRecordT>& record =
static_cast<Record<ESXRecordT>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
ESXRecordT apparel = record.get();
std::vector<ESM::PartReference>& list = apparel.mParts.mParts;
ESM::PartReference newPart;
newPart.mPart = 0; // 0 == head
newPart.mMale = "";
newPart.mFemale = "";
if (position >= (int)list.size())
list.push_back(newPart);
else
list.insert(list.begin()+position, newPart);
record.setModified (apparel);
}
virtual void removeNestedRow (const RefIdColumn *column,
RefIdData& data, int index, int rowToRemove) const
{
Record<ESXRecordT>& record =
static_cast<Record<ESXRecordT>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
ESXRecordT apparel = record.get();
std::vector<ESM::PartReference>& list = apparel.mParts.mParts;
if (rowToRemove < 0 || rowToRemove >= static_cast<int> (list.size()))
throw std::runtime_error ("index out of range");
list.erase (list.begin () + rowToRemove);
record.setModified (apparel);
}
virtual void setNestedTable (const RefIdColumn* column,
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const
{
Record<ESXRecordT>& record =
static_cast<Record<ESXRecordT>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
ESXRecordT apparel = record.get();
apparel.mParts.mParts =
static_cast<const NestedTableWrapper<std::vector<typename ESM::PartReference> >&>(nestedTable).mNestedTable;
record.setModified (apparel);
}
virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column,
const RefIdData& data, int index) const
{
const Record<ESXRecordT>& record =
static_cast<const Record<ESXRecordT>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
// deleted by dtor of NestedTableStoring
return new NestedTableWrapper<std::vector<typename ESM::PartReference> >(record.get().mParts.mParts);
}
virtual QVariant getNestedData (const RefIdColumn *column,
const RefIdData& data, int index, int subRowIndex, int subColIndex) const
{
const Record<ESXRecordT>& record =
static_cast<const Record<ESXRecordT>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
const std::vector<ESM::PartReference>& list = record.get().mParts.mParts;
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (list.size()))
throw std::runtime_error ("index out of range");
const ESM::PartReference& content = list.at(subRowIndex);
switch (subColIndex)
{
case 0: return QString(sPartRefs[content.mPart]);
case 1: return QString(content.mMale.c_str());
case 2: return QString(content.mFemale.c_str());
default:
throw std::runtime_error("Trying to access non-existing column in the nested table!");
}
}
virtual void setNestedData (const RefIdColumn *column,
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const
{
Record<ESXRecordT>& record =
static_cast<Record<ESXRecordT>&> (data.getRecord (RefIdData::LocalIndex (row, mType)));
ESXRecordT apparel = record.get();
std::vector<ESM::PartReference>& list = apparel.mParts.mParts;
if (subRowIndex < 0 || subRowIndex >= static_cast<int> (list.size()))
throw std::runtime_error ("index out of range");
switch(subColIndex)
{
case 0:
{
std::string part = value.toString().toStdString();
bool found = false;
for (unsigned int i = 0; i < ESM::PRT_Count; ++i)
{
if (part == sPartRefs[i])
{
list.at(subRowIndex).mPart = static_cast<unsigned char>(i);
found = true;
break;
}
}
if (!found)
return; // return without saving
else
break;
}
case 1: list.at(subRowIndex).mMale = value.toString().toStdString(); break;
case 2: list.at(subRowIndex).mFemale = value.toString().toStdString(); break;
default:
throw std::runtime_error("Trying to access non-existing column in the nested table!");
}
record.setModified (apparel);
}
virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
{
return 3;
}
virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
{
const Record<ESXRecordT>& record =
static_cast<const Record<ESXRecordT>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
return static_cast<int>(record.get().mParts.mParts.size());
}
};
}
#endif

View file

@ -196,7 +196,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_AiWanderDist, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_AiWanderDuration, CSMWorld::ColumnBase::Display_Integer));
new RefIdColumn (Columns::ColumnId_AiDuration, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_AiWanderToD, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
@ -475,6 +475,24 @@ CSMWorld::RefIdCollection::RefIdCollection()
weaponColumns.mFlags.insert (std::make_pair (&mColumns.back(), sWeaponFlagTable[i].mFlag));
}
// Nested table
mColumns.push_back(RefIdColumn (Columns::ColumnId_PartRefList, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue));
const RefIdColumn *partRef = &mColumns.back();
std::map<UniversalId::Type, NestedRefIdAdapterBase*> partMap;
partMap.insert(
std::make_pair(UniversalId::Type_Armor, new BodyPartRefIdAdapter<ESM::Armor> (UniversalId::Type_Armor)));
partMap.insert(
std::make_pair(UniversalId::Type_Clothing, new BodyPartRefIdAdapter<ESM::Clothing> (UniversalId::Type_Clothing)));
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), partMap));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_PartRefType, CSMWorld::ColumnBase::Display_String));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_PartRefMale, CSMWorld::ColumnBase::Display_String));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_PartRefFemale, CSMWorld::ColumnBase::Display_String));
mAdapters.insert (std::make_pair (UniversalId::Type_Activator,
new NameRefIdAdapter<ESM::Activator> (UniversalId::Type_Activator, nameColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Potion,
@ -482,11 +500,11 @@ CSMWorld::RefIdCollection::RefIdCollection()
mAdapters.insert (std::make_pair (UniversalId::Type_Apparatus,
new ApparatusRefIdAdapter (inventoryColumns, apparatusType, toolsColumns.mQuality)));
mAdapters.insert (std::make_pair (UniversalId::Type_Armor,
new ArmorRefIdAdapter (enchantableColumns, armorType, health, armor)));
new ArmorRefIdAdapter (enchantableColumns, armorType, health, armor, partRef)));
mAdapters.insert (std::make_pair (UniversalId::Type_Book,
new BookRefIdAdapter (enchantableColumns, scroll, attribute)));
mAdapters.insert (std::make_pair (UniversalId::Type_Clothing,
new ClothingRefIdAdapter (enchantableColumns, clothingType)));
new ClothingRefIdAdapter (enchantableColumns, clothingType, partRef)));
mAdapters.insert (std::make_pair (UniversalId::Type_Container,
new ContainerRefIdAdapter (nameColumns, weightCapacity, organic, respawn, content)));
mAdapters.insert (std::make_pair (UniversalId::Type_Creature,