diff --git a/src/Core/Resource/Factory/CScriptLoader.cpp b/src/Core/Resource/Factory/CScriptLoader.cpp index 1f47d000..f0e9bf27 100644 --- a/src/Core/Resource/Factory/CScriptLoader.cpp +++ b/src/Core/Resource/Factory/CScriptLoader.cpp @@ -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(pArrayCast->PropertyByIndex(iElem)), pArrayCast->SubStructTemplate()); else - LoadStructMP2(SCLY, pArrayCast->ElementByIndex(iElem), pArrayCast->SubStructTemplate()); + LoadStructMP2(SCLY, static_cast(pArrayCast->PropertyByIndex(iElem)), pArrayCast->SubStructTemplate()); } break; } diff --git a/src/Core/Resource/Script/IProperty.cpp b/src/Core/Resource/Script/IProperty.cpp index 2d6e9b7a..ec335575 100644 --- a/src/Core/Resource/Script/IProperty.cpp +++ b/src/Core/Resource/Script/IProperty.cpp @@ -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(mpTemplate)->CreateSubStruct(); + mProperties[i] = static_cast(mpTemplate)->CreateSubStruct(this); } } @@ -129,3 +123,8 @@ CStructTemplate* CArrayProperty::SubStructTemplate() const // CArrayTemplate inherits from CStructTemplate. The template defines the substruct structure. return static_cast(Template()); } + +TString CArrayProperty::ElementName() const +{ + return static_cast(Template())->ElementName(); +} diff --git a/src/Core/Resource/Script/IProperty.h b/src/Core/Resource/Script/IProperty.h index d290e27a..0ed11a74 100644 --- a/src/Core/Resource/Script/IProperty.h +++ b/src/Core/Resource/Script/IProperty.h @@ -92,12 +92,16 @@ typedef TTypedProperty, eUnknownProperty, CUnknownValue> class CPropertyStruct : public IProperty { friend class CScriptLoader; +protected: std::vector 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 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 diff --git a/src/Core/Resource/Script/IPropertyTemplate.h b/src/Core/Resource/Script/IPropertyTemplate.h index 4c4c7031..864a0cda 100644 --- a/src/Core/Resource/Script/IPropertyTemplate.h +++ b/src/Core/Resource/Script/IPropertyTemplate.h @@ -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); } }; diff --git a/src/Editor/PropertyEdit/CPropertyDelegate.cpp b/src/Editor/PropertyEdit/CPropertyDelegate.cpp index 96bde034..661ccfea 100644 --- a/src/Editor/PropertyEdit/CPropertyDelegate.cpp +++ b/src/Editor/PropertyEdit/CPropertyDelegate.cpp @@ -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(pEditor); + CArrayProperty *pArray = static_cast(pProp); + pSpinBox->setValue(pArray->Count()); + break; + } + } } @@ -352,6 +382,14 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo break; } + case eArrayProperty: + { + WIntegralSpinBox *pSpinBox = static_cast(pEditor); + u32 NewCount = pSpinBox->value(); + mpModel->ResizeArray(rkIndex, NewCount); + break; + } + } } diff --git a/src/Editor/PropertyEdit/CPropertyModel.cpp b/src/Editor/PropertyEdit/CPropertyModel.cpp index e26a833f..860589fa 100644 --- a/src/Editor/PropertyEdit/CPropertyModel.cpp +++ b/src/Editor/PropertyEdit/CPropertyModel.cpp @@ -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(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(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(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(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(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(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(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(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(); + } + } + } +} diff --git a/src/Editor/PropertyEdit/CPropertyModel.h b/src/Editor/PropertyEdit/CPropertyModel.h index 9714e3f8..f6da0147 100644 --- a/src/Editor/PropertyEdit/CPropertyModel.h +++ b/src/Editor/PropertyEdit/CPropertyModel.h @@ -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 diff --git a/src/Editor/PropertyEdit/CPropertyView.cpp b/src/Editor/PropertyEdit/CPropertyView.cpp index 3225e204..2ec52a87 100644 --- a/src/Editor/PropertyEdit/CPropertyView.cpp +++ b/src/Editor/PropertyEdit/CPropertyView.cpp @@ -1,6 +1,7 @@ #include "CPropertyView.h" #include "CPropertyDelegate.h" #include + #include #include @@ -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); } } diff --git a/src/Editor/PropertyEdit/CPropertyView.h b/src/Editor/PropertyEdit/CPropertyView.h index 6af5e081..e48c3c37 100644 --- a/src/Editor/PropertyEdit/CPropertyView.h +++ b/src/Editor/PropertyEdit/CPropertyView.h @@ -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 diff --git a/templates/mp1/Structs/AnimationParameters.xml b/templates/mp1/Structs/AnimationParameters.xml deleted file mode 100644 index 945ed680..00000000 --- a/templates/mp1/Structs/AnimationParameters.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/templates/mp2/Properties.xml b/templates/mp2/Properties.xml index 95edeadb..62c66fee 100644 --- a/templates/mp2/Properties.xml +++ b/templates/mp2/Properties.xml @@ -6893,7 +6893,7 @@ - + diff --git a/templates/mp2/Script/SequenceTimer.xml b/templates/mp2/Script/SequenceTimer.xml index 9d6ad5fa..a07db9c9 100644 --- a/templates/mp2/Script/SequenceTimer.xml +++ b/templates/mp2/Script/SequenceTimer.xml @@ -5,7 +5,16 @@ 0 - + Connection + + + + + + + + + 0.0