Added interface for editing array properties in the property view
This commit is contained in:
parent
3b41415581
commit
9a24a34bc6
|
@ -130,9 +130,9 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& SCLY)
|
|||
for (u32 iElem = 0; iElem < Size; iElem++)
|
||||
{
|
||||
if (mVersion < eEchoesDemo)
|
||||
LoadStructMP1(SCLY, pArrayCast->ElementByIndex(iElem), pArrayCast->SubStructTemplate());
|
||||
LoadStructMP1(SCLY, static_cast<CPropertyStruct*>(pArrayCast->PropertyByIndex(iElem)), pArrayCast->SubStructTemplate());
|
||||
else
|
||||
LoadStructMP2(SCLY, pArrayCast->ElementByIndex(iElem), pArrayCast->SubStructTemplate());
|
||||
LoadStructMP2(SCLY, static_cast<CPropertyStruct*>(pArrayCast->PropertyByIndex(iElem)), pArrayCast->SubStructTemplate());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -23,12 +23,6 @@ TIDString IProperty::IDString(bool FullPath) const
|
|||
}
|
||||
|
||||
// ************ CPropertyStruct ************
|
||||
CPropertyStruct::~CPropertyStruct()
|
||||
{
|
||||
for (auto it = mProperties.begin(); it != mProperties.end(); it++)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
IProperty* CPropertyStruct::PropertyByIndex(u32 index) const
|
||||
{
|
||||
return mProperties[index];
|
||||
|
@ -106,21 +100,21 @@ CPropertyStruct* CPropertyStruct::StructByIDString(const TIDString& rkStr) const
|
|||
// ************ CArrayProperty ************
|
||||
void CArrayProperty::Resize(u32 Size)
|
||||
{
|
||||
u32 OldSize = mSubStructs.size();
|
||||
u32 OldSize = mProperties.size();
|
||||
if (OldSize == Size) return;
|
||||
|
||||
if (Size < OldSize)
|
||||
{
|
||||
for (u32 i = mSubStructs.size() - 1; i >= Size; i--)
|
||||
delete mSubStructs[i];
|
||||
for (u32 i = mProperties.size() - 1; i >= Size; i--)
|
||||
delete mProperties[i];
|
||||
}
|
||||
|
||||
mSubStructs.resize(Size);
|
||||
mProperties.resize(Size);
|
||||
|
||||
if (Size > OldSize)
|
||||
{
|
||||
for (u32 i = OldSize; i < Size; i++)
|
||||
mSubStructs[i] = static_cast<CArrayTemplate*>(mpTemplate)->CreateSubStruct();
|
||||
mProperties[i] = static_cast<CArrayTemplate*>(mpTemplate)->CreateSubStruct(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,3 +123,8 @@ CStructTemplate* CArrayProperty::SubStructTemplate() const
|
|||
// CArrayTemplate inherits from CStructTemplate. The template defines the substruct structure.
|
||||
return static_cast<CStructTemplate*>(Template());
|
||||
}
|
||||
|
||||
TString CArrayProperty::ElementName() const
|
||||
{
|
||||
return static_cast<CArrayTemplate*>(Template())->ElementName();
|
||||
}
|
||||
|
|
|
@ -92,12 +92,16 @@ typedef TTypedProperty<std::vector<u8>, eUnknownProperty, CUnknownValue>
|
|||
class CPropertyStruct : public IProperty
|
||||
{
|
||||
friend class CScriptLoader;
|
||||
protected:
|
||||
std::vector<IProperty*> mProperties;
|
||||
public:
|
||||
CPropertyStruct(IPropertyTemplate *pTemp, CPropertyStruct *pParent)
|
||||
: IProperty(pTemp, pParent) {}
|
||||
|
||||
~CPropertyStruct();
|
||||
~CPropertyStruct() {
|
||||
for (auto it = mProperties.begin(); it != mProperties.end(); it++)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
EPropertyType Type() const { return eStructProperty; }
|
||||
|
||||
|
@ -118,31 +122,23 @@ public:
|
|||
/*
|
||||
* CArrayProperty stores a repeated property struct.
|
||||
*/
|
||||
class CArrayProperty : public IProperty
|
||||
class CArrayProperty : public CPropertyStruct
|
||||
{
|
||||
friend class CScriptLoader;
|
||||
std::vector<CPropertyStruct*> mSubStructs;
|
||||
|
||||
public:
|
||||
CArrayProperty(IPropertyTemplate *pTemp, CPropertyStruct *pParent)
|
||||
: IProperty(pTemp, pParent) {}
|
||||
|
||||
~CArrayProperty() {
|
||||
for (u32 iSub = 0; iSub < mSubStructs.size(); iSub++)
|
||||
delete mSubStructs[iSub];
|
||||
}
|
||||
: CPropertyStruct(pTemp, pParent) {}
|
||||
|
||||
EPropertyType Type() const { return eArrayProperty; }
|
||||
|
||||
// Inline
|
||||
inline u32 Count() const { return mSubStructs.size(); }
|
||||
inline void Reserve(u32 amount) { mSubStructs.reserve(amount); }
|
||||
inline CPropertyStruct* ElementByIndex(u32 index) { return mSubStructs[index]; }
|
||||
inline CPropertyStruct* operator[](u32 index) { return ElementByIndex(index); }
|
||||
inline void Reserve(u32 amount) { mProperties.reserve(amount); }
|
||||
|
||||
// Functions
|
||||
void Resize(u32 Size);
|
||||
CStructTemplate* SubStructTemplate() const;
|
||||
TString ElementName() const;
|
||||
};
|
||||
|
||||
#endif // IPROPERTY
|
||||
|
|
|
@ -502,6 +502,7 @@ class CArrayTemplate : public CStructTemplate
|
|||
{
|
||||
friend class CTemplateLoader;
|
||||
friend class CTemplateWriter;
|
||||
TString mElementName;
|
||||
|
||||
public:
|
||||
CArrayTemplate(u32 ID, CStructTemplate *pParent = 0)
|
||||
|
@ -518,14 +519,25 @@ public:
|
|||
|
||||
EPropertyType Type() const { return eArrayProperty; }
|
||||
|
||||
void SetParam(const TString& rkParamName, const TString& rkValue)
|
||||
{
|
||||
if (rkParamName == "element_name")
|
||||
mElementName = rkValue;
|
||||
else
|
||||
CStructTemplate::SetParam(rkParamName, rkValue);
|
||||
}
|
||||
|
||||
IProperty* InstantiateProperty(CPropertyStruct *pParent)
|
||||
{
|
||||
return new CArrayProperty(this, pParent);
|
||||
}
|
||||
|
||||
CPropertyStruct* CreateSubStruct()
|
||||
TString ElementName() const { return mElementName; }
|
||||
void SetElementName(const TString& rkName) { mElementName = rkName; }
|
||||
|
||||
CPropertyStruct* CreateSubStruct(CArrayProperty *pArray)
|
||||
{
|
||||
return (CPropertyStruct*) CStructTemplate::InstantiateProperty(nullptr);
|
||||
return (CPropertyStruct*) CStructTemplate::InstantiateProperty(pArray);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -47,9 +47,22 @@ QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionVie
|
|||
break;
|
||||
|
||||
case eShortProperty:
|
||||
case eLongProperty:
|
||||
pOut = new WIntegralSpinBox(pParent);
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = new WIntegralSpinBox(pParent);
|
||||
pSpinBox->setMinimum(INT16_MIN);
|
||||
pSpinBox->setMaximum(INT16_MAX);
|
||||
pOut = pSpinBox;
|
||||
break;
|
||||
}
|
||||
|
||||
case eLongProperty:
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = new WIntegralSpinBox(pParent);
|
||||
pSpinBox->setMinimum(INT32_MIN);
|
||||
pSpinBox->setMaximum(INT32_MAX);
|
||||
pOut = pSpinBox;
|
||||
break;
|
||||
}
|
||||
|
||||
case eFloatProperty:
|
||||
{
|
||||
|
@ -93,6 +106,15 @@ QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionVie
|
|||
break;
|
||||
}
|
||||
|
||||
case eArrayProperty:
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = new WIntegralSpinBox(pParent);
|
||||
pSpinBox->setMinimum(0);
|
||||
pSpinBox->setMaximum(999);
|
||||
pOut = pSpinBox;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,6 +244,14 @@ void CPropertyDelegate::setEditorData(QWidget *pEditor, const QModelIndex &rkInd
|
|||
break;
|
||||
}
|
||||
|
||||
case eArrayProperty:
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
|
||||
CArrayProperty *pArray = static_cast<CArrayProperty*>(pProp);
|
||||
pSpinBox->setValue(pArray->Count());
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -352,6 +382,14 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
|
|||
break;
|
||||
}
|
||||
|
||||
case eArrayProperty:
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
|
||||
u32 NewCount = pSpinBox->value();
|
||||
mpModel->ResizeArray(rkIndex, NewCount);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,13 +43,16 @@ int CPropertyModel::columnCount(const QModelIndex& /*rkParent*/) const
|
|||
int CPropertyModel::rowCount(const QModelIndex& rkParent) const
|
||||
{
|
||||
if (!mpBaseStruct) return 0;
|
||||
if (!rkParent.isValid()) return mpBaseStruct->Count();
|
||||
if (rkParent.column() != 0) return 0;
|
||||
if (rkParent.internalId() & 0x1) return 0;
|
||||
|
||||
IProperty *pProp = PropertyForIndex(rkParent, false);
|
||||
if (pProp == mpBaseStruct) return mpBaseStruct->Count();
|
||||
|
||||
switch (pProp->Type())
|
||||
{
|
||||
case eStructProperty:
|
||||
case eArrayProperty:
|
||||
return static_cast<CPropertyStruct*>(pProp)->Count();
|
||||
|
||||
case eBitfieldProperty:
|
||||
|
@ -208,7 +211,30 @@ QVariant CPropertyModel::data(const QModelIndex& rkIndex, int Role) const
|
|||
IProperty *pProp = PropertyForIndex(rkIndex, false);
|
||||
|
||||
if (rkIndex.column() == 0)
|
||||
{
|
||||
// Check for arrays
|
||||
IProperty *pParent = pProp->Parent();
|
||||
|
||||
if (pParent)
|
||||
{
|
||||
// For direct array sub-properties, display the element name instead of the property name (the property name is the array name)
|
||||
if (pProp->Type() == eStructProperty && pParent->Type() == eArrayProperty)
|
||||
{
|
||||
TString ElementName = static_cast<CArrayProperty*>(pParent)->ElementName();
|
||||
return QString("%1 %2").arg(TO_QSTRING(ElementName)).arg(rkIndex.row() + 1);
|
||||
}
|
||||
|
||||
// Check whether the parent struct is an array element with one sub-property
|
||||
if (pParent->Type() == eStructProperty && pParent->Parent() && pParent->Parent()->Type() == eArrayProperty)
|
||||
{
|
||||
if (static_cast<CPropertyStruct*>(pParent)->Count() == 1)
|
||||
return QString("%1 %2").arg(TO_QSTRING(pProp->Name())).arg(rkIndex.row() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Display property name for everything else
|
||||
return TO_QSTRING(pProp->Name());
|
||||
}
|
||||
|
||||
if (rkIndex.column() == 1)
|
||||
{
|
||||
|
@ -232,6 +258,13 @@ QVariant CPropertyModel::data(const QModelIndex& rkIndex, int Role) const
|
|||
}
|
||||
else return "";
|
||||
|
||||
// Display the element count for arrays
|
||||
case eArrayProperty:
|
||||
{
|
||||
u32 Count = static_cast<CArrayProperty*>(pProp)->Count();
|
||||
return QString("%1 element%2").arg(Count).arg(Count != 1 ? "s" : "");
|
||||
}
|
||||
|
||||
// No display text on properties with persistent editors
|
||||
case eBoolProperty:
|
||||
case eFileProperty:
|
||||
|
@ -273,12 +306,8 @@ QModelIndex CPropertyModel::index(int Row, int Column, const QModelIndex& rkPare
|
|||
if (!hasIndex(Row, Column, rkParent))
|
||||
return QModelIndex();
|
||||
|
||||
// Root index
|
||||
if (!rkParent.isValid())
|
||||
return createIndex(Row, Column, mpBaseStruct->PropertyByIndex(Row));
|
||||
|
||||
// Check property for children
|
||||
IProperty *pParent = PropertyForIndex(rkParent, false);
|
||||
IProperty *pParent = (rkParent.isValid() ? PropertyForIndex(rkParent, false) : mpBaseStruct);
|
||||
|
||||
// Struct
|
||||
if (pParent->Type() == eStructProperty)
|
||||
|
@ -287,9 +316,22 @@ QModelIndex CPropertyModel::index(int Row, int Column, const QModelIndex& rkPare
|
|||
return createIndex(Row, Column, pProp);
|
||||
}
|
||||
|
||||
// Array
|
||||
if (pParent->Type() == eArrayProperty)
|
||||
{
|
||||
IProperty *pProp = static_cast<CArrayProperty*>(pParent)->PropertyByIndex(Row);
|
||||
|
||||
// If this array element only has one sub-property then let's just skip the redundant tree node and show the sub-property directly.
|
||||
CPropertyStruct *pStruct = static_cast<CPropertyStruct*>(pProp);
|
||||
if (pStruct->Count() == 1)
|
||||
pProp = pStruct->PropertyByIndex(0);
|
||||
|
||||
return createIndex(Row, Column, pProp);
|
||||
}
|
||||
|
||||
// Other property
|
||||
if (pParent->Type() == eColorProperty || pParent->Type() == eVector3Property || pParent->Type() == eBitfieldProperty || pParent->Type() == eCharacterProperty)
|
||||
return createIndex(Row, Column, rkParent.internalId() | 0x1);
|
||||
return createIndex(Row, Column, u32(pParent) | 0x1);
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
@ -314,10 +356,22 @@ QModelIndex CPropertyModel::parent(const QModelIndex& rkChild) const
|
|||
// Iterate over grandfather properties until we find the row
|
||||
CPropertyStruct *pGrandparent = pParent->Parent();
|
||||
|
||||
// Check for array with one sub-property
|
||||
if (pGrandparent->Type() == eArrayProperty)
|
||||
{
|
||||
CPropertyStruct *pStruct = static_cast<CPropertyStruct*>(pParent);
|
||||
|
||||
if (pStruct->Count() == 1)
|
||||
{
|
||||
pParent = pGrandparent;
|
||||
pGrandparent = pGrandparent->Parent();
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 iProp = 0; iProp < pGrandparent->Count(); iProp++)
|
||||
{
|
||||
if (pGrandparent->PropertyByIndex(iProp) == pParent)
|
||||
return createIndex(iProp, rkChild.column(), pParent);
|
||||
return createIndex(iProp, 0, pParent);
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
|
@ -343,3 +397,30 @@ void CPropertyModel::UpdateSubProperties(const QModelIndex& rkIndex)
|
|||
emit dataChanged( index(0, 1, rkIndex), index(3, 1, rkIndex), Roles);
|
||||
}
|
||||
}
|
||||
|
||||
void CPropertyModel::ResizeArray(const QModelIndex& rkIndex, u32 NewSize)
|
||||
{
|
||||
QModelIndex Index = index(rkIndex.row(), 0, rkIndex.parent());
|
||||
CArrayProperty *pArray = static_cast<CArrayProperty*>(PropertyForIndex(rkIndex, false));
|
||||
|
||||
if (pArray && pArray->Type() == eArrayProperty)
|
||||
{
|
||||
u32 OldSize = pArray->Count();
|
||||
|
||||
if (OldSize != NewSize)
|
||||
{
|
||||
if (OldSize < NewSize)
|
||||
{
|
||||
beginInsertRows(Index, OldSize, NewSize - 1);
|
||||
pArray->Resize(NewSize);
|
||||
endInsertRows();
|
||||
}
|
||||
else
|
||||
{
|
||||
beginRemoveRows(Index, NewSize, OldSize - 1);
|
||||
pArray->Resize(NewSize);
|
||||
endRemoveRows();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ public:
|
|||
QModelIndex parent(const QModelIndex& rkChild) const;
|
||||
Qt::ItemFlags flags(const QModelIndex& rkIndex) const;
|
||||
void UpdateSubProperties(const QModelIndex& rkIndex);
|
||||
void ResizeArray(const QModelIndex& rkIndex, u32 NewSize);
|
||||
};
|
||||
|
||||
#endif // CPROPERTYMODEL_H
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "CPropertyView.h"
|
||||
#include "CPropertyDelegate.h"
|
||||
#include <Core/Resource/Script/IPropertyTemplate.h>
|
||||
|
||||
#include <QEvent>
|
||||
#include <QToolTip>
|
||||
|
||||
|
@ -12,6 +13,9 @@ CPropertyView::CPropertyView(QWidget *pParent)
|
|||
setItemDelegateForColumn(1, mpDelegate);
|
||||
setEditTriggers(AllEditTriggers);
|
||||
setModel(mpModel);
|
||||
|
||||
connect(mpModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(SetPersistentEditors(QModelIndex)));
|
||||
connect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(SetPersistentEditors(QModelIndex)));
|
||||
}
|
||||
|
||||
void CPropertyView::setModel(QAbstractItemModel *pModel)
|
||||
|
@ -104,7 +108,8 @@ void CPropertyView::SetPersistentEditors(const QModelIndex& rkParent)
|
|||
break;
|
||||
}
|
||||
|
||||
SetPersistentEditors(ChildIndex);
|
||||
if (isExpanded(ChildIndex))
|
||||
SetPersistentEditors(ChildIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,9 @@ public:
|
|||
void setModel(QAbstractItemModel *pModel);
|
||||
bool event(QEvent *pEvent);
|
||||
void SetBaseStruct(CPropertyStruct *pStruct);
|
||||
void SetPersistentEditors(const QModelIndex& rkParent);
|
||||
|
||||
public slots:
|
||||
void SetPersistentEditors(const QModelIndex& rkIndex);
|
||||
};
|
||||
|
||||
#endif // CPROPERTYVIEW_H
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<struct name="AnimationParameters" type="single">
|
||||
<property ID="0x00" name="AnimSet" type="file" extensions="ANCS"/>
|
||||
<property ID="0x01" name="Node" type="long"/>
|
||||
<property ID="0x02" name="ANCS int 2" type="long"/>
|
||||
</struct>
|
|
@ -6893,7 +6893,7 @@
|
|||
<property ID="0xEF5671D6" name="Unknown"/>
|
||||
<property ID="0xEF582BD6" name="Unknown"/>
|
||||
<property ID="0xEF5AA575" name="Unknown"/>
|
||||
<property ID="0xEF5C94E9" name="Unknown"/>
|
||||
<property ID="0xEF5C94E9" name="Sequence Connections"/>
|
||||
<property ID="0xEF6D8C96" name="Unknown"/>
|
||||
<property ID="0xEF6D8F65" name="Unknown"/>
|
||||
<property ID="0xEF7A8E16" name="Unknown"/>
|
||||
|
|
|
@ -5,7 +5,16 @@
|
|||
<struct ID="0x255A4580" template="Structs/EditorProperties.xml"/>
|
||||
<array ID="0xEF5C94E9">
|
||||
<default>0</default>
|
||||
<properties/>
|
||||
<element_name>Connection</element_name>
|
||||
<properties>
|
||||
<property ID="0x00" name="Connection Index" type="short" />
|
||||
<array ID="0x01" name="Activation Times">
|
||||
<properties>
|
||||
<property ID="0x00" name="Time" type="float" />
|
||||
</properties>
|
||||
</array>
|
||||
<property ID="0x02" name="Unknown" type="bool" />
|
||||
</properties>
|
||||
</array>
|
||||
<property ID="0xB8BD2175" type="float">
|
||||
<default>0.0</default>
|
||||
|
|
Loading…
Reference in New Issue