Support for undoing property changes + tons of tweaks and fixes
This commit is contained in:
parent
c7d448225c
commit
cc054cf571
|
@ -33,6 +33,18 @@ public:
|
|||
void SetResource(CResource *pRes);
|
||||
void SetNodeIndex(u32 Index);
|
||||
void SetUnknown(u32 Index, u32 Value);
|
||||
|
||||
// Operators
|
||||
inline bool operator==(const CAnimationParameters& rkOther) const
|
||||
{
|
||||
return ( (mGame == rkOther.mGame) &&
|
||||
(mpCharSet == rkOther.mpCharSet) &&
|
||||
(mNodeIndex == rkOther.mNodeIndex) &&
|
||||
(mUnknown1 == rkOther.mUnknown1) &&
|
||||
(mUnknown2 == rkOther.mUnknown2) &&
|
||||
(mUnknown3 == rkOther.mUnknown3) &&
|
||||
(mUnknown4 == rkOther.mUnknown4) );
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CANIMATIONPARAMETERS_H
|
||||
|
|
|
@ -196,6 +196,7 @@ CResource* CResCache::GetResource(const TString& ResPath)
|
|||
else if (type == "CHAR") Res = CAnimSetLoader::LoadCHAR(file);
|
||||
else if (type == "MREA") Res = CAreaLoader::LoadMREA(file);
|
||||
else if (type == "MLVL") Res = CWorldLoader::LoadMLVL(file);
|
||||
else if (type == "STRG") Res = CStringLoader::LoadSTRG(file);
|
||||
else if (type == "FONT") Res = CFontLoader::LoadFONT(file);
|
||||
else if (type == "SCAN") Res = CScanLoader::LoadSCAN(file);
|
||||
else if (type == "DCLN") Res = CCollisionLoader::LoadDCLN(file);
|
||||
|
|
|
@ -31,11 +31,19 @@ public:
|
|||
|
||||
inline CUniqueID ID() const
|
||||
{
|
||||
TString FileName = mPath.GetFileName();
|
||||
|
||||
if (!mIsPath)
|
||||
return CUniqueID::FromString(mPath.GetFileName());
|
||||
return CUniqueID::FromString(FileName);
|
||||
|
||||
else
|
||||
{
|
||||
if (FileName.IsHexString() && (FileName.Size() == 8 || FileName.Size() == 16))
|
||||
return CUniqueID::FromString(FileName);
|
||||
else
|
||||
return CUniqueID::skInvalidID64;
|
||||
}
|
||||
}
|
||||
|
||||
inline CFourCC Type() const
|
||||
{
|
||||
|
@ -64,6 +72,16 @@ public:
|
|||
else
|
||||
return mIsValidPath;
|
||||
}
|
||||
|
||||
inline bool operator==(const CResourceInfo& rkOther) const
|
||||
{
|
||||
return (mPath.GetFileName() == rkOther.mPath.GetFileName());
|
||||
}
|
||||
|
||||
inline bool operator!=(const CResourceInfo& rkOther) const
|
||||
{
|
||||
return (!(*this == rkOther));
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CRESOURCEINFO
|
||||
|
|
|
@ -99,7 +99,7 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& SCLY)
|
|||
CUniqueID ResID = (mVersion < eCorruptionProto ? SCLY.ReadLong() : SCLY.ReadLongLong());
|
||||
const TStringList& rkExtensions = static_cast<CFileTemplate*>(pTemp)->Extensions();
|
||||
|
||||
CResourceInfo Info(ResID, "UNKN");
|
||||
CResourceInfo Info(ResID, CFourCC(!rkExtensions.empty() ? rkExtensions.front() : "UNKN"));
|
||||
|
||||
if (ResID.IsValid())
|
||||
{
|
||||
|
|
|
@ -40,6 +40,7 @@ public:
|
|||
virtual ~IProperty() {}
|
||||
virtual EPropertyType Type() const = 0;
|
||||
virtual TString ToString() const { return ""; }
|
||||
virtual IPropertyValue* RawValue() { return nullptr; }
|
||||
|
||||
inline CPropertyStruct* Parent() const { return mpParent; }
|
||||
|
||||
|
@ -68,6 +69,7 @@ public:
|
|||
~TTypedProperty() {}
|
||||
virtual EPropertyType Type() const { return TypeEnum; }
|
||||
virtual TString ToString() const { return mValue.ToString(); }
|
||||
virtual IPropertyValue* RawValue() { return &mValue; }
|
||||
|
||||
inline PropType Get() const { return mValue.Get(); }
|
||||
inline void Set(PropType v) { mValue.Set(v); }
|
||||
|
@ -77,7 +79,7 @@ typedef TTypedProperty<char, eByteProperty, CByteValue>
|
|||
typedef TTypedProperty<short, eShortProperty, CShortValue> TShortProperty;
|
||||
typedef TTypedProperty<long, eLongProperty, CLongValue> TLongProperty;
|
||||
typedef TTypedProperty<long, eEnumProperty, CLongValue> TEnumProperty;
|
||||
typedef TTypedProperty<long, eBitfieldProperty, CLongValue> TBitfieldProperty;
|
||||
typedef TTypedProperty<long, eBitfieldProperty, CHexLongValue> TBitfieldProperty;
|
||||
typedef TTypedProperty<float, eFloatProperty, CFloatValue> TFloatProperty;
|
||||
typedef TTypedProperty<TString, eStringProperty, CStringValue> TStringProperty;
|
||||
typedef TTypedProperty<CVector3f, eVector3Property, CVector3Value> TVector3Property;
|
||||
|
|
|
@ -338,13 +338,11 @@ public:
|
|||
CEnumTemplate(u32 ID, CStructTemplate *pParent = 0)
|
||||
: TLongTemplate(ID, pParent)
|
||||
{
|
||||
mDefaultValue.SetHexStringOutput(true);
|
||||
}
|
||||
|
||||
CEnumTemplate(u32 ID, const TString& rkName, ECookPreference CookPreference, CStructTemplate *pParent = 0)
|
||||
: TLongTemplate(ID, rkName, CookPreference, pParent)
|
||||
{
|
||||
mDefaultValue.SetHexStringOutput(true);
|
||||
}
|
||||
|
||||
virtual EPropertyType Type() const { return eEnumProperty; }
|
||||
|
@ -393,7 +391,7 @@ public:
|
|||
|
||||
// CBitfieldTemplate - Property template for bitfields, which can have multiple
|
||||
// distinct boolean parameters packed into one property.
|
||||
class CBitfieldTemplate : public TLongTemplate
|
||||
class CBitfieldTemplate : public TTypedPropertyTemplate<u32, eBitfieldProperty, CHexLongValue>
|
||||
{
|
||||
friend class CTemplateLoader;
|
||||
friend class CTemplateWriter;
|
||||
|
@ -411,15 +409,13 @@ class CBitfieldTemplate : public TLongTemplate
|
|||
|
||||
public:
|
||||
CBitfieldTemplate(u32 ID, CStructTemplate *pParent = 0)
|
||||
: TLongTemplate(ID, pParent)
|
||||
: TTypedPropertyTemplate(ID, pParent)
|
||||
{
|
||||
mDefaultValue.SetHexStringOutput(true);
|
||||
}
|
||||
|
||||
CBitfieldTemplate(u32 ID, const TString& rkName, ECookPreference CookPreference, CStructTemplate *pParent = 0)
|
||||
: TLongTemplate(ID, rkName, CookPreference, pParent)
|
||||
: TTypedPropertyTemplate(ID, rkName, CookPreference, pParent)
|
||||
{
|
||||
mDefaultValue.SetHexStringOutput(true);
|
||||
}
|
||||
|
||||
virtual EPropertyType Type() const { return eBitfieldProperty; }
|
||||
|
|
|
@ -17,6 +17,9 @@ class IPropertyValue
|
|||
public:
|
||||
virtual TString ToString() const = 0;
|
||||
virtual void FromString(const TString& rkString) = 0;
|
||||
virtual IPropertyValue* Clone() const = 0;
|
||||
virtual void Copy(IPropertyValue *pValue) = 0;
|
||||
virtual bool Matches(IPropertyValue *pValue) const = 0;
|
||||
};
|
||||
|
||||
template<typename PropType>
|
||||
|
@ -28,8 +31,20 @@ protected:
|
|||
public:
|
||||
TTypedPropertyValue() {}
|
||||
|
||||
TTypedPropertyValue(PropType Val)
|
||||
: mValue(Val) {}
|
||||
TTypedPropertyValue(PropType rkVal)
|
||||
: mValue(rkVal) {}
|
||||
|
||||
virtual void Copy(IPropertyValue *pValue)
|
||||
{
|
||||
TTypedPropertyValue *pOther = static_cast<TTypedPropertyValue*>(pValue);
|
||||
mValue = pOther->mValue;
|
||||
}
|
||||
|
||||
virtual bool Matches(IPropertyValue *pValue) const
|
||||
{
|
||||
TTypedPropertyValue *pOther = static_cast<TTypedPropertyValue*>(pValue);
|
||||
return (mValue == pOther->mValue);
|
||||
}
|
||||
|
||||
PropType Get() const
|
||||
{
|
||||
|
@ -69,6 +84,11 @@ public:
|
|||
{
|
||||
mValue = (rkString == "true");
|
||||
}
|
||||
|
||||
IPropertyValue* Clone() const
|
||||
{
|
||||
return new CBoolValue(mValue);
|
||||
}
|
||||
};
|
||||
|
||||
class CByteValue : public TTypedPropertyValue<s8>
|
||||
|
@ -87,6 +107,11 @@ public:
|
|||
u32 base = (rkString.StartsWith("0x") ? 16 : 10);
|
||||
mValue = (s8) rkString.ToInt32(base);
|
||||
}
|
||||
|
||||
IPropertyValue* Clone() const
|
||||
{
|
||||
return new CByteValue(mValue);
|
||||
}
|
||||
};
|
||||
|
||||
class CShortValue : public TTypedPropertyValue<s16>
|
||||
|
@ -105,27 +130,21 @@ public:
|
|||
u32 base = (rkString.StartsWith("0x") ? 16 : 10);
|
||||
mValue = (s16) rkString.ToInt32(base);
|
||||
}
|
||||
|
||||
IPropertyValue* Clone() const
|
||||
{
|
||||
return new CShortValue(mValue);
|
||||
}
|
||||
};
|
||||
|
||||
class CLongValue : public TTypedPropertyValue<s32>
|
||||
{
|
||||
protected:
|
||||
bool mShouldOutputHex;
|
||||
|
||||
public:
|
||||
CLongValue() { mShouldOutputHex = false; mValue = 0; }
|
||||
CLongValue(s32 Val) { mShouldOutputHex = false; mValue = Val; }
|
||||
|
||||
void SetHexStringOutput(bool enable)
|
||||
{
|
||||
mShouldOutputHex = enable;
|
||||
}
|
||||
CLongValue() { mValue = 0; }
|
||||
CLongValue(s32 Val) { mValue = Val; }
|
||||
|
||||
TString ToString() const
|
||||
{
|
||||
if (mShouldOutputHex)
|
||||
return TString::HexString((u32) mValue, true, true, 8);
|
||||
else
|
||||
return TString::FromInt32(mValue, 0, 10);
|
||||
}
|
||||
|
||||
|
@ -134,6 +153,34 @@ public:
|
|||
u32 base = (rkString.StartsWith("0x") ? 16 : 10);
|
||||
mValue = (s32) rkString.ToInt32(base);
|
||||
}
|
||||
|
||||
IPropertyValue* Clone() const
|
||||
{
|
||||
return new CLongValue(mValue);
|
||||
}
|
||||
};
|
||||
|
||||
class CHexLongValue : public TTypedPropertyValue<u32>
|
||||
{
|
||||
public:
|
||||
CHexLongValue() { mValue = 0; }
|
||||
CHexLongValue(u32 Val) { mValue = Val; }
|
||||
|
||||
TString ToString() const
|
||||
{
|
||||
return TString::HexString(mValue, true, true, 8);
|
||||
}
|
||||
|
||||
void FromString(const TString& rkString)
|
||||
{
|
||||
u32 base = (rkString.StartsWith("0x") ? 16 : 10);
|
||||
mValue = (s32) rkString.ToInt32(base);
|
||||
}
|
||||
|
||||
IPropertyValue* Clone() const
|
||||
{
|
||||
return new CHexLongValue(mValue);
|
||||
}
|
||||
};
|
||||
|
||||
class CFloatValue : public TTypedPropertyValue<float>
|
||||
|
@ -151,6 +198,11 @@ public:
|
|||
{
|
||||
mValue = rkString.ToFloat();
|
||||
}
|
||||
|
||||
IPropertyValue* Clone() const
|
||||
{
|
||||
return new CFloatValue(mValue);
|
||||
}
|
||||
};
|
||||
|
||||
class CStringValue : public TTypedPropertyValue<TString>
|
||||
|
@ -169,6 +221,11 @@ public:
|
|||
{
|
||||
mValue = rkString;
|
||||
}
|
||||
|
||||
IPropertyValue* Clone() const
|
||||
{
|
||||
return new CStringValue(mValue);
|
||||
}
|
||||
};
|
||||
|
||||
class CColorValue : public TTypedPropertyValue<CColor>
|
||||
|
@ -207,6 +264,11 @@ public:
|
|||
pPtr++;
|
||||
}
|
||||
}
|
||||
|
||||
IPropertyValue* Clone() const
|
||||
{
|
||||
return new CColorValue(mValue);
|
||||
}
|
||||
};
|
||||
|
||||
class CVector3Value : public TTypedPropertyValue<CVector3f>
|
||||
|
@ -243,15 +305,26 @@ public:
|
|||
pPtr++;
|
||||
}
|
||||
}
|
||||
|
||||
IPropertyValue* Clone() const
|
||||
{
|
||||
return new CVector3Value(mValue);
|
||||
}
|
||||
};
|
||||
|
||||
class CCharacterValue : public TTypedPropertyValue<CAnimationParameters>
|
||||
{
|
||||
public:
|
||||
CCharacterValue() {}
|
||||
CCharacterValue(const CAnimationParameters& rkParams) { mValue = rkParams; }
|
||||
|
||||
TString ToString() const { return ""; }
|
||||
void FromString(const TString&) { }
|
||||
|
||||
IPropertyValue* Clone() const
|
||||
{
|
||||
return new CCharacterValue(mValue);
|
||||
}
|
||||
};
|
||||
|
||||
class CFileValue : public TTypedPropertyValue<CResourceInfo>
|
||||
|
@ -262,15 +335,26 @@ public:
|
|||
|
||||
TString ToString() const { return ""; }
|
||||
void FromString(const TString&) { }
|
||||
|
||||
IPropertyValue* Clone() const
|
||||
{
|
||||
return new CFileValue(mValue);
|
||||
}
|
||||
};
|
||||
|
||||
class CUnknownValue : public TTypedPropertyValue<std::vector<u8>>
|
||||
{
|
||||
public:
|
||||
CUnknownValue();
|
||||
CUnknownValue(const std::vector<u8>& rkVec) { mValue = rkVec; }
|
||||
|
||||
TString ToString() const { return ""; }
|
||||
void FromString(const TString&) {}
|
||||
|
||||
IPropertyValue* Clone() const
|
||||
{
|
||||
return new CUnknownValue(mValue);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // IPROPERTYVALUE_H
|
||||
|
|
|
@ -133,7 +133,8 @@ HEADERS += \
|
|||
PropertyEdit/CPropertyView.h \
|
||||
PropertyEdit/CPropertyRelay.h \
|
||||
WorldEditor/CInstancesProxyModel.h \
|
||||
WorldEditor/CInstancesModel.h
|
||||
WorldEditor/CInstancesModel.h \
|
||||
Undo/CEditScriptPropertyCommand.h
|
||||
|
||||
# Source Files
|
||||
SOURCES += \
|
||||
|
@ -184,7 +185,8 @@ SOURCES += \
|
|||
PropertyEdit/CPropertyModel.cpp \
|
||||
PropertyEdit/CPropertyDelegate.cpp \
|
||||
PropertyEdit/CPropertyView.cpp \
|
||||
WorldEditor/CInstancesModel.cpp
|
||||
WorldEditor/CInstancesModel.cpp \
|
||||
Undo/CEditScriptPropertyCommand.cpp
|
||||
|
||||
# UI Files
|
||||
FORMS += \
|
||||
|
|
|
@ -233,6 +233,7 @@ void INodeEditor::ExitPickMode()
|
|||
|
||||
void INodeEditor::NotifySelectionModified()
|
||||
{
|
||||
RecalculateSelectionBounds();
|
||||
UpdateSelectionUI();
|
||||
emit SelectionModified();
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "CPropertyRelay.h"
|
||||
|
||||
#include "Editor/UICommon.h"
|
||||
#include "Editor/Undo/CEditScriptPropertyCommand.h"
|
||||
#include "Editor/Widgets/WColorPicker.h"
|
||||
#include "Editor/Widgets/WDraggableSpinBox.h"
|
||||
#include "Editor/Widgets/WIntegralSpinBox.h"
|
||||
|
@ -23,16 +24,24 @@
|
|||
|
||||
CPropertyDelegate::CPropertyDelegate(QObject *pParent /*= 0*/)
|
||||
: QStyledItemDelegate(pParent)
|
||||
, mpEditor(nullptr)
|
||||
, mpModel(nullptr)
|
||||
, mInRelayWidgetEdit(false)
|
||||
, mEditInProgress(false)
|
||||
, mRelaysBlocked(false)
|
||||
{
|
||||
}
|
||||
|
||||
void CPropertyDelegate::SetModel(CPropertyModel *pModel)
|
||||
void CPropertyDelegate::SetPropertyModel(CPropertyModel *pModel)
|
||||
{
|
||||
mpModel = pModel;
|
||||
}
|
||||
|
||||
void CPropertyDelegate::SetEditor(CWorldEditor *pEditor)
|
||||
{
|
||||
mpEditor = pEditor;
|
||||
}
|
||||
|
||||
QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionViewItem& /*rkOption*/, const QModelIndex& rkIndex) const
|
||||
{
|
||||
if (!mpModel) return nullptr;
|
||||
|
@ -116,6 +125,7 @@ QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionVie
|
|||
WResourceSelector *pSelector = new WResourceSelector(pParent);
|
||||
CFileTemplate *pTemp = static_cast<CFileTemplate*>(pProp->Template());
|
||||
pSelector->SetAllowedExtensions(pTemp->Extensions());
|
||||
pSelector->setFont(qobject_cast<QWidget*>(parent())->font()); // bit of a hack to stop the resource selector font from changing
|
||||
|
||||
CONNECT_RELAY(pSelector, rkIndex, ResourceChanged(QString))
|
||||
pOut = pSelector;
|
||||
|
@ -190,6 +200,8 @@ void CPropertyDelegate::setEditorData(QWidget *pEditor, const QModelIndex &rkInd
|
|||
IProperty *pProp = mpModel->PropertyForIndex(rkIndex, false);
|
||||
|
||||
if (pProp)
|
||||
{
|
||||
if (!mEditInProgress)
|
||||
{
|
||||
switch (pProp->Type())
|
||||
{
|
||||
|
@ -210,7 +222,6 @@ void CPropertyDelegate::setEditorData(QWidget *pEditor, const QModelIndex &rkInd
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
case eLongProperty:
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
|
||||
|
@ -277,6 +288,7 @@ void CPropertyDelegate::setEditorData(QWidget *pEditor, const QModelIndex &rkInd
|
|||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set editor data for character/bitfield/vector/color sub-property
|
||||
else if (rkIndex.internalId() & 0x1)
|
||||
|
@ -335,9 +347,12 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
|
|||
if (!pEditor) return;
|
||||
|
||||
IProperty *pProp = mpModel->PropertyForIndex(rkIndex, false);
|
||||
IPropertyValue *pOldValue = nullptr;
|
||||
|
||||
if (pProp)
|
||||
{
|
||||
pOldValue = pProp->RawValue()->Clone();
|
||||
|
||||
switch (pProp->Type())
|
||||
{
|
||||
|
||||
|
@ -385,9 +400,6 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
|
|||
Color.b = SrcColor.blue() / 255.f;
|
||||
Color.a = SrcColor.alpha() / 255.f;
|
||||
pColor->Set(Color);
|
||||
|
||||
// Make sure sub-properties update with the new color
|
||||
mpModel->UpdateSubProperties(rkIndex);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -430,6 +442,7 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
|
|||
else if (rkIndex.internalId() & 0x1)
|
||||
{
|
||||
pProp = mpModel->PropertyForIndex(rkIndex, true);
|
||||
pOldValue = pProp->RawValue()->Clone();
|
||||
|
||||
if (pProp->Type() == eCharacterProperty)
|
||||
SetCharacterModelData(pEditor, rkIndex);
|
||||
|
@ -474,13 +487,33 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
|
|||
|
||||
pColor->Set(Value);
|
||||
}
|
||||
|
||||
QModelIndex ParentWidgetIndex = mpModel->index(rkIndex.parent().row(), 1, rkIndex.parent().parent());
|
||||
mpModel->dataChanged(ParentWidgetIndex, ParentWidgetIndex);
|
||||
}
|
||||
}
|
||||
|
||||
emit PropertyEdited(rkIndex, true);
|
||||
if (pProp)
|
||||
{
|
||||
// Check for edit in progress
|
||||
bool Matches = pOldValue->Matches(pProp->RawValue());
|
||||
|
||||
if (!Matches && mInRelayWidgetEdit && pEditor->hasFocus())
|
||||
mEditInProgress = true;
|
||||
|
||||
bool EditInProgress = mEditInProgress;
|
||||
|
||||
// Check for edit finished
|
||||
if (!mInRelayWidgetEdit || !pEditor->hasFocus())
|
||||
mEditInProgress = false;
|
||||
|
||||
// Create undo command
|
||||
if (!Matches || EditInProgress)
|
||||
{
|
||||
CEditScriptPropertyCommand *pCommand = new CEditScriptPropertyCommand(mpModel, rkIndex, pOldValue, !mEditInProgress);
|
||||
mpEditor->UndoStack()->push(pCommand);
|
||||
}
|
||||
|
||||
else
|
||||
delete pOldValue;
|
||||
}
|
||||
}
|
||||
|
||||
bool CPropertyDelegate::eventFilter(QObject *pObject, QEvent *pEvent)
|
||||
|
@ -513,6 +546,7 @@ QWidget* CPropertyDelegate::CreateCharacterEditor(QWidget *pParent, const QModel
|
|||
if (Type == eFileProperty)
|
||||
{
|
||||
WResourceSelector *pSelector = new WResourceSelector(pParent);
|
||||
pSelector->setFont(qobject_cast<QWidget*>(parent())->font()); // hack to keep the selector font from changing
|
||||
|
||||
if (Params.Version() <= eEchoes)
|
||||
pSelector->SetAllowedExtensions("ANCS");
|
||||
|
@ -636,6 +670,10 @@ void CPropertyDelegate::WidgetEdited(QWidget *pWidget, const QModelIndex& rkInde
|
|||
{
|
||||
// This slot is used to update property values as they're being updated so changes can be
|
||||
// reflected in realtime in other parts of the application.
|
||||
mInRelayWidgetEdit = true;
|
||||
|
||||
if (!mRelaysBlocked)
|
||||
setModelData(pWidget, mpModel, rkIndex);
|
||||
|
||||
mInRelayWidgetEdit = false;
|
||||
}
|
||||
|
|
|
@ -1,19 +1,25 @@
|
|||
#ifndef CPROPERTYDELEGATE_H
|
||||
#define CPROPERTYDELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
#include "CPropertyModel.h"
|
||||
#include "Editor/WorldEditor/CWorldEditor.h"
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
class CPropertyDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
CWorldEditor *mpEditor;
|
||||
CPropertyModel *mpModel;
|
||||
bool mInRelayWidgetEdit;
|
||||
mutable bool mEditInProgress;
|
||||
mutable bool mRelaysBlocked;
|
||||
|
||||
public:
|
||||
CPropertyDelegate(QObject *pParent = 0);
|
||||
void SetModel(CPropertyModel *pModel);
|
||||
void SetPropertyModel(CPropertyModel *pModel);
|
||||
void SetEditor(CWorldEditor *pEditor);
|
||||
|
||||
virtual QWidget* createEditor(QWidget *pParent, const QStyleOptionViewItem& rkOption, const QModelIndex &rkIndex) const;
|
||||
virtual void setEditorData(QWidget *pEditor, const QModelIndex &rkIndex) const;
|
||||
virtual void setModelData(QWidget *pEditor, QAbstractItemModel *pModel, const QModelIndex &rkIndex) const;
|
||||
|
@ -29,9 +35,6 @@ public slots:
|
|||
|
||||
protected:
|
||||
void BlockRelays(bool Block) const { mRelaysBlocked = Block; }
|
||||
|
||||
signals:
|
||||
void PropertyEdited(const QModelIndex& rkIndex, bool IsDone) const;
|
||||
};
|
||||
|
||||
#endif // CPROPERTYDELEGATE_H
|
||||
|
|
|
@ -292,7 +292,7 @@ QVariant CPropertyModel::data(const QModelIndex& rkIndex, int Role) const
|
|||
// Add uncooked notification
|
||||
if (pProp->Template()->CookPreference() == eNeverCook)
|
||||
{
|
||||
Text += "<br/><b>This is an uncooked property.</b>";
|
||||
Text.prepend("<i>[uncooked]</i>");
|
||||
}
|
||||
|
||||
// Add description
|
||||
|
@ -393,19 +393,20 @@ Qt::ItemFlags CPropertyModel::flags(const QModelIndex& rkIndex) const
|
|||
else return (Qt::ItemIsEnabled | Qt::ItemIsEditable);
|
||||
}
|
||||
|
||||
void CPropertyModel::UpdateSubProperties(const QModelIndex& rkIndex)
|
||||
void CPropertyModel::NotifyPropertyModified(const QModelIndex& rkIndex)
|
||||
{
|
||||
IProperty *pProp = PropertyForIndex(rkIndex, false);
|
||||
if (rowCount(rkIndex) != 0)
|
||||
emit dataChanged( index(0, 1, rkIndex), index(rowCount(rkIndex) - 1, 1, rkIndex));
|
||||
|
||||
if (pProp)
|
||||
if (rkIndex.internalId() & 0x1)
|
||||
{
|
||||
QVector<int> Roles(Qt::DisplayRole);
|
||||
|
||||
if (pProp->Type() == eVector3Property)
|
||||
emit dataChanged( index(0, 1, rkIndex), index(2, 1, rkIndex), Roles);
|
||||
else if (pProp->Type() == eColorProperty)
|
||||
emit dataChanged( index(0, 1, rkIndex), index(3, 1, rkIndex), Roles);
|
||||
QModelIndex Parent = rkIndex.parent();
|
||||
Parent = Parent.sibling(Parent.row(), 1);
|
||||
emit dataChanged(Parent, Parent);
|
||||
}
|
||||
|
||||
emit dataChanged(rkIndex, rkIndex);
|
||||
emit PropertyModified(rkIndex);
|
||||
}
|
||||
|
||||
void CPropertyModel::ResizeArray(const QModelIndex& rkIndex, u32 NewSize)
|
||||
|
|
|
@ -22,8 +22,12 @@ public:
|
|||
QModelIndex index(int Row, int Column, const QModelIndex& rkParent) const;
|
||||
QModelIndex parent(const QModelIndex& rkChild) const;
|
||||
Qt::ItemFlags flags(const QModelIndex& rkIndex) const;
|
||||
void UpdateSubProperties(const QModelIndex& rkIndex);
|
||||
|
||||
void NotifyPropertyModified(const QModelIndex& rkIndex);
|
||||
void ResizeArray(const QModelIndex& rkIndex, u32 NewSize);
|
||||
|
||||
signals:
|
||||
void PropertyModified(const QModelIndex& rkIndex);
|
||||
};
|
||||
|
||||
#endif // CPROPERTYMODEL_H
|
||||
|
|
|
@ -14,16 +14,16 @@ CPropertyView::CPropertyView(QWidget *pParent)
|
|||
setEditTriggers(AllEditTriggers);
|
||||
setModel(mpModel);
|
||||
|
||||
connect(mpModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(SetPersistentEditors(QModelIndex)));
|
||||
connect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(SetPersistentEditors(QModelIndex)));
|
||||
connect(mpDelegate, SIGNAL(PropertyEdited(QModelIndex,bool)), this, SLOT(OnPropertyModified(QModelIndex,bool)));
|
||||
connect(mpModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(SetPersistentEditors(QModelIndex)));
|
||||
connect(mpModel, SIGNAL(PropertyModified(QModelIndex)), this, SLOT(OnPropertyModified(QModelIndex)));
|
||||
}
|
||||
|
||||
void CPropertyView::setModel(QAbstractItemModel *pModel)
|
||||
{
|
||||
CPropertyModel *pPropModel = qobject_cast<CPropertyModel*>(pModel);
|
||||
mpModel = pPropModel;
|
||||
mpDelegate->SetModel(pPropModel);
|
||||
mpDelegate->SetPropertyModel(pPropModel);
|
||||
QTreeView::setModel(pPropModel);
|
||||
|
||||
if (pPropModel)
|
||||
|
@ -61,7 +61,13 @@ bool CPropertyView::event(QEvent *pEvent)
|
|||
else return QTreeView::event(pEvent);
|
||||
}
|
||||
|
||||
void CPropertyView::SetObject(CScriptObject *pObj)
|
||||
void CPropertyView::SetEditor(CWorldEditor *pEditor)
|
||||
{
|
||||
mpEditor = pEditor;
|
||||
mpDelegate->SetEditor(pEditor);
|
||||
}
|
||||
|
||||
void CPropertyView::SetInstance(CScriptObject *pObj)
|
||||
{
|
||||
mpObject = pObj;
|
||||
mpModel->SetBaseStruct(pObj ? pObj->Properties() : nullptr);
|
||||
|
@ -168,23 +174,21 @@ void CPropertyView::ClosePersistentEditors(const QModelIndex& rkIndex)
|
|||
}
|
||||
}
|
||||
|
||||
void CPropertyView::OnPropertyModified(const QModelIndex &rkIndex, bool IsDone)
|
||||
void CPropertyView::OnPropertyModified(const QModelIndex& rkIndex)
|
||||
{
|
||||
// Check for a resource being changed on a character property. If that's the case we need to remake the persistent editors.
|
||||
if (rkIndex.internalId() & 0x1)
|
||||
// Check for a character resource being changed. If that's the case we need to remake the persistent editors.
|
||||
IProperty *pProp = mpModel->PropertyForIndex(rkIndex, true);
|
||||
|
||||
if (pProp->Type() == eCharacterProperty && rkIndex.internalId() & 0x1)
|
||||
{
|
||||
if (mpModel->PropertyForIndex(rkIndex, true)->Type() == eCharacterProperty)
|
||||
{
|
||||
EGame Game = static_cast<TCharacterProperty*>(mpModel->PropertyForIndex(rkIndex, true))->Get().Version();
|
||||
EGame Game = static_cast<TCharacterProperty*>(pProp)->Get().Version();
|
||||
|
||||
if (mpDelegate->DetermineCharacterPropType(Game, rkIndex) == eFileProperty)
|
||||
{
|
||||
QModelIndex Parent = rkIndex.parent();
|
||||
ClosePersistentEditors(Parent);
|
||||
SetPersistentEditors(Parent);
|
||||
}
|
||||
ClosePersistentEditors(rkIndex.parent());
|
||||
SetPersistentEditors(rkIndex.parent());
|
||||
}
|
||||
}
|
||||
|
||||
emit PropertyModified(rkIndex, IsDone);
|
||||
emit PropertyModified(pProp);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ class CPropertyView : public QTreeView
|
|||
{
|
||||
Q_OBJECT
|
||||
|
||||
CWorldEditor *mpEditor;
|
||||
CPropertyModel *mpModel;
|
||||
CPropertyDelegate *mpDelegate;
|
||||
CScriptObject *mpObject;
|
||||
|
@ -18,7 +19,8 @@ public:
|
|||
CPropertyView(QWidget *pParent = 0);
|
||||
void setModel(QAbstractItemModel *pModel);
|
||||
bool event(QEvent *pEvent);
|
||||
void SetObject(CScriptObject *pObj);
|
||||
void SetEditor(CWorldEditor *pEditor);
|
||||
void SetInstance(CScriptObject *pObj);
|
||||
void UpdateEditorProperties(const QModelIndex& rkParent);
|
||||
|
||||
inline CPropertyModel* PropertyModel() const { return mpModel; }
|
||||
|
@ -26,10 +28,10 @@ public:
|
|||
public slots:
|
||||
void SetPersistentEditors(const QModelIndex& rkIndex);
|
||||
void ClosePersistentEditors(const QModelIndex& rkIndex);
|
||||
void OnPropertyModified(const QModelIndex& rkIndex, bool IsDone);
|
||||
void OnPropertyModified(const QModelIndex& rkIndex);
|
||||
|
||||
signals:
|
||||
void PropertyModified(const QModelIndex &rkIndex, bool IsDone);
|
||||
void PropertyModified(IProperty *pProperty);
|
||||
};
|
||||
|
||||
#endif // CPROPERTYVIEW_H
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
#include "CEditScriptPropertyCommand.h"
|
||||
#include "EUndoCommand.h"
|
||||
|
||||
CEditScriptPropertyCommand::CEditScriptPropertyCommand(CPropertyModel *pModel, const QModelIndex& rkIndex, IPropertyValue *pOldValue, bool IsDone)
|
||||
: QUndoCommand("Edit Property")
|
||||
, mpModel(pModel)
|
||||
, mIndex(rkIndex)
|
||||
, mCommandEnded(IsDone)
|
||||
{
|
||||
mpProperty = pModel->PropertyForIndex(rkIndex, true);
|
||||
mpOldValue = pOldValue;
|
||||
mpNewValue = mpProperty->RawValue()->Clone();
|
||||
}
|
||||
|
||||
CEditScriptPropertyCommand::~CEditScriptPropertyCommand()
|
||||
{
|
||||
delete mpOldValue;
|
||||
delete mpNewValue;
|
||||
}
|
||||
|
||||
int CEditScriptPropertyCommand::id() const
|
||||
{
|
||||
return eEditScriptPropertyCmd;
|
||||
}
|
||||
|
||||
bool CEditScriptPropertyCommand::mergeWith(const QUndoCommand *pkOther)
|
||||
{
|
||||
if (!mCommandEnded && pkOther->id() == eEditScriptPropertyCmd)
|
||||
{
|
||||
const CEditScriptPropertyCommand *pkCmd = static_cast<const CEditScriptPropertyCommand*>(pkOther);
|
||||
|
||||
if (pkCmd->mpProperty == mpProperty)
|
||||
{
|
||||
mpNewValue->Copy(pkCmd->mpNewValue);
|
||||
mCommandEnded = pkCmd->mCommandEnded;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CEditScriptPropertyCommand::undo()
|
||||
{
|
||||
mpProperty->RawValue()->Copy(mpOldValue);
|
||||
mpModel->NotifyPropertyModified(mIndex);
|
||||
}
|
||||
|
||||
void CEditScriptPropertyCommand::redo()
|
||||
{
|
||||
mpProperty->RawValue()->Copy(mpNewValue);
|
||||
mpModel->NotifyPropertyModified(mIndex);
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef CEDITSCRIPTPROPERTYCOMMAND_H
|
||||
#define CEDITSCRIPTPROPERTYCOMMAND_H
|
||||
|
||||
#include "Editor/PropertyEdit/CPropertyDelegate.h"
|
||||
#include <QUndoCommand>
|
||||
|
||||
class CEditScriptPropertyCommand : public QUndoCommand
|
||||
{
|
||||
CPropertyModel *mpModel;
|
||||
IProperty *mpProperty;
|
||||
QModelIndex mIndex;
|
||||
|
||||
IPropertyValue *mpOldValue;
|
||||
IPropertyValue *mpNewValue;
|
||||
bool mCommandEnded;
|
||||
|
||||
public:
|
||||
CEditScriptPropertyCommand(CPropertyModel *pModel, const QModelIndex& rkIndex, IPropertyValue *pOldValue, bool IsDone);
|
||||
~CEditScriptPropertyCommand();
|
||||
int id() const;
|
||||
bool mergeWith(const QUndoCommand *pkOther);
|
||||
void undo();
|
||||
void redo();
|
||||
};
|
||||
|
||||
#endif // CEDITSCRIPTPROPERTYCOMMAND_H
|
|
@ -5,7 +5,8 @@ enum EUndoCommand
|
|||
{
|
||||
eTranslateNodeCmd,
|
||||
eRotateNodeCmd,
|
||||
eScaleNodeCmd
|
||||
eScaleNodeCmd,
|
||||
eEditScriptPropertyCmd
|
||||
};
|
||||
|
||||
#endif // EUNDOCOMMAND
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "CClearSelectionCommand.h"
|
||||
#include "CSelectAllCommand.h"
|
||||
#include "CInvertSelectionCommand.h"
|
||||
#include "CEditScriptPropertyCommand.h"
|
||||
#include "EUndoCommand.h"
|
||||
|
||||
#endif // UNDOCOMMANDS
|
||||
|
|
|
@ -106,6 +106,22 @@ bool WResourceSelector::HasSupportedExtension(const CResourceInfo& rkRes)
|
|||
return IsSupportedExtension(TO_QSTRING(rkRes.Type().ToString()));
|
||||
}
|
||||
|
||||
void WResourceSelector::UpdateFrameColor()
|
||||
{
|
||||
bool RedFrame = false;
|
||||
|
||||
// Red frame should only display if an incorrect resource path is entered. It shouldn't display on Invalid Asset ID.
|
||||
if (!mResourceValid)
|
||||
{
|
||||
TString Name = mResource.ToString().GetFileName(false);
|
||||
|
||||
if (!Name.IsHexString() || (Name.Size() != 8 && Name.Size() != 16) || mResource.ID().IsValid())
|
||||
RedFrame = true;
|
||||
}
|
||||
mUI.LineEdit->setStyleSheet(RedFrame ? "border: 1px solid red" : "");
|
||||
mUI.LineEdit->setFont(font());
|
||||
}
|
||||
|
||||
// ************ GETTERS ************
|
||||
CResourceInfo WResourceSelector::GetResourceInfo()
|
||||
{
|
||||
|
@ -147,24 +163,38 @@ void WResourceSelector::SetResource(CResource *pRes)
|
|||
SetResource(CResourceInfo());
|
||||
}
|
||||
|
||||
void WResourceSelector::SetResource(const QString& rkRes)
|
||||
{
|
||||
TString Res = TO_TSTRING(rkRes);
|
||||
TString Name = Res.GetFileName(false);
|
||||
TString Dir = Res.GetFileDirectory();
|
||||
TString Ext = Res.GetFileExtension();
|
||||
|
||||
if (Dir.IsEmpty() && Name.IsHexString() && (Name.Size() == 8 || Name.Size() == 16) && Ext.Size() == 4)
|
||||
SetResource(CResourceInfo(Name.Size() == 8 ? Name.ToInt32() : Name.ToInt64(), Ext));
|
||||
else
|
||||
SetResource(CResourceInfo(Res));
|
||||
}
|
||||
|
||||
void WResourceSelector::SetResource(const CResourceInfo& rkRes)
|
||||
{
|
||||
if (mResource != rkRes)
|
||||
{
|
||||
mResource = rkRes;
|
||||
|
||||
if (mResource.IsValid())
|
||||
{
|
||||
mResourceValid = HasSupportedExtension(rkRes);
|
||||
mUI.LineEdit->setText(TO_QSTRING(mResource.ToString()));
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
mResourceValid = false;
|
||||
mUI.LineEdit->clear();
|
||||
}
|
||||
|
||||
mUI.LineEdit->setText(TO_QSTRING(mResource.ToString()));
|
||||
|
||||
UpdateFrameColor();
|
||||
CreatePreviewPanel();
|
||||
SetButtonsBasedOnResType();
|
||||
Q_ASSERT(!mUI.LineEdit->text().isEmpty());
|
||||
emit ResourceChanged(TO_QSTRING(mResource.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
void WResourceSelector::SetAllowedExtensions(const QString& extension)
|
||||
|
@ -183,7 +213,7 @@ void WResourceSelector::SetAllowedExtensions(const TStringList& extensions)
|
|||
void WResourceSelector::SetText(const QString& ResPath)
|
||||
{
|
||||
mUI.LineEdit->setText(ResPath);
|
||||
LoadResource(ResPath);
|
||||
SetResource(ResPath);
|
||||
}
|
||||
|
||||
void WResourceSelector::SetEditButtonEnabled(bool Enabled)
|
||||
|
@ -214,7 +244,7 @@ void WResourceSelector::AdjustPreviewToParent(bool adjust)
|
|||
// ************ SLOTS ************
|
||||
void WResourceSelector::OnLineEditTextEdited()
|
||||
{
|
||||
LoadResource(mUI.LineEdit->text());
|
||||
SetResource(mUI.LineEdit->text());
|
||||
}
|
||||
|
||||
void WResourceSelector::OnBrowseButtonClicked()
|
||||
|
@ -246,7 +276,7 @@ void WResourceSelector::OnBrowseButtonClicked()
|
|||
if (!NewRes.isEmpty())
|
||||
{
|
||||
mUI.LineEdit->setText(NewRes);
|
||||
LoadResource(NewRes);
|
||||
SetResource(NewRes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,27 +303,6 @@ void WResourceSelector::Export()
|
|||
emit ExportResource(mResource);
|
||||
}
|
||||
|
||||
void WResourceSelector::LoadResource(const QString& ResPath)
|
||||
{
|
||||
mResource = CResourceInfo();
|
||||
|
||||
TString PathStr = ResPath.toStdString();
|
||||
TString Ext = PathStr.GetFileExtension();
|
||||
|
||||
if (IsSupportedExtension(TO_QSTRING(Ext)))
|
||||
{
|
||||
mResource = CResourceInfo(TO_TSTRING(ResPath));
|
||||
mResourceValid = mResource.IsValid();
|
||||
|
||||
if (mPreviewPanelValid) mpPreviewPanel->SetResource(mResource.Load());
|
||||
}
|
||||
else mResourceValid = false;
|
||||
|
||||
SetButtonsBasedOnResType();
|
||||
CreatePreviewPanel();
|
||||
emit ResourceChanged(ResPath);
|
||||
}
|
||||
|
||||
void WResourceSelector::CreatePreviewPanel()
|
||||
{
|
||||
delete mpPreviewPanel;
|
||||
|
|
|
@ -54,6 +54,7 @@ public:
|
|||
bool eventFilter(QObject *, QEvent *);
|
||||
bool IsSupportedExtension(const QString& extension);
|
||||
bool HasSupportedExtension(const CResourceInfo& rkRes);
|
||||
void UpdateFrameColor();
|
||||
|
||||
// Getters
|
||||
CResourceInfo GetResourceInfo();
|
||||
|
@ -65,6 +66,7 @@ public:
|
|||
|
||||
// Setters
|
||||
void SetResource(CResource *pRes);
|
||||
void SetResource(const QString& rkRes);
|
||||
void SetResource(const CResourceInfo& rkRes);
|
||||
void SetAllowedExtensions(const QString& extension);
|
||||
void SetAllowedExtensions(const QStringList& extensions);
|
||||
|
@ -85,7 +87,6 @@ public slots:
|
|||
private:
|
||||
void Edit();
|
||||
void Export();
|
||||
void LoadResource(const QString& ResPath);
|
||||
void CreatePreviewPanel();
|
||||
void ShowPreviewPanel();
|
||||
void HidePreviewPanel();
|
||||
|
|
|
@ -108,6 +108,7 @@ void WVectorEditor::SetX(double x)
|
|||
mpSpinBoxX->setValue((double) x);
|
||||
mpSpinBoxX->blockSignals(false);
|
||||
|
||||
mEditing = true;
|
||||
emit ValueChanged(mValue);
|
||||
}
|
||||
|
||||
|
@ -119,6 +120,7 @@ void WVectorEditor::SetY(double y)
|
|||
mpSpinBoxY->setValue((double) y);
|
||||
mpSpinBoxY->blockSignals(false);
|
||||
|
||||
mEditing = true;
|
||||
emit ValueChanged(mValue);
|
||||
}
|
||||
|
||||
|
@ -130,6 +132,7 @@ void WVectorEditor::SetZ(double z)
|
|||
mpSpinBoxZ->setValue((double) z);
|
||||
mpSpinBoxZ->blockSignals(false);
|
||||
|
||||
mEditing = true;
|
||||
emit ValueChanged(mValue);
|
||||
}
|
||||
|
||||
|
@ -181,5 +184,6 @@ void WVectorEditor::SetupUI()
|
|||
// ************ PRIVATE SLOTS ************
|
||||
void WVectorEditor::OnSpinBoxEditingDone()
|
||||
{
|
||||
emit EditingDone(mValue);
|
||||
if (mEditing) emit EditingDone(mValue);
|
||||
mEditing = false;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ class WVectorEditor : public QWidget
|
|||
Q_OBJECT
|
||||
|
||||
CVector3f mValue;
|
||||
bool mEditing;
|
||||
|
||||
Qt::Orientation mOrientation;
|
||||
QLayout *mpLayout;
|
||||
|
|
|
@ -16,7 +16,7 @@ WModifyTab::WModifyTab(QWidget *pParent) :
|
|||
ui->PropertyView->header()->resizeSection(0, PropViewWidth * 0.3);
|
||||
ui->PropertyView->header()->resizeSection(1, PropViewWidth * 0.3);
|
||||
ui->PropertyView->header()->setSectionResizeMode(1, QHeaderView::Fixed);
|
||||
connect(ui->PropertyView, SIGNAL(PropertyModified(QModelIndex,bool)), this, SLOT(OnPropertyModified(QModelIndex,bool)));
|
||||
connect(ui->PropertyView, SIGNAL(PropertyModified(IProperty*)), this, SLOT(OnPropertyModified(IProperty*)));
|
||||
|
||||
mpInLinkModel = new CLinkModel(this);
|
||||
mpInLinkModel->SetConnectionType(CLinkModel::eIncoming);
|
||||
|
@ -41,6 +41,7 @@ WModifyTab::~WModifyTab()
|
|||
void WModifyTab::SetEditor(CWorldEditor *pEditor)
|
||||
{
|
||||
mpWorldEditor = pEditor;
|
||||
ui->PropertyView->SetEditor(mpWorldEditor);
|
||||
connect(mpWorldEditor, SIGNAL(SelectionTransformed()), this, SLOT(OnWorldSelectionTransformed()));
|
||||
}
|
||||
|
||||
|
@ -60,7 +61,7 @@ void WModifyTab::GenerateUI(QList<CSceneNode*>& Selection)
|
|||
CScriptObject *pObj = pScriptNode->Object();
|
||||
|
||||
// Set up UI
|
||||
ui->PropertyView->SetObject(pObj);
|
||||
ui->PropertyView->SetInstance(pObj);
|
||||
mpInLinkModel->SetObject(pObj);
|
||||
mpOutLinkModel->SetObject(pObj);
|
||||
ui->LightGroupBox->hide();
|
||||
|
@ -75,7 +76,7 @@ void WModifyTab::GenerateUI(QList<CSceneNode*>& Selection)
|
|||
void WModifyTab::ClearUI()
|
||||
{
|
||||
ui->ObjectsTabWidget->hide();
|
||||
ui->PropertyView->SetObject(nullptr);
|
||||
ui->PropertyView->SetInstance(nullptr);
|
||||
ui->LightGroupBox->hide();
|
||||
mpSelectedNode = nullptr;
|
||||
}
|
||||
|
@ -85,17 +86,27 @@ void WModifyTab::OnWorldSelectionTransformed()
|
|||
ui->PropertyView->UpdateEditorProperties(QModelIndex());
|
||||
}
|
||||
|
||||
void WModifyTab::OnPropertyModified(const QModelIndex& rkIndex, bool /*IsDone*/)
|
||||
void WModifyTab::OnPropertyModified(IProperty *pProp)
|
||||
{
|
||||
if (mpSelectedNode->NodeType() == eScriptNode)
|
||||
{
|
||||
CScriptNode *pNode = static_cast<CScriptNode*>(mpSelectedNode);
|
||||
IProperty *pProperty = ui->PropertyView->PropertyModel()->PropertyForIndex(rkIndex, true);
|
||||
pNode->PropertyModified(pProperty);
|
||||
pNode->PropertyModified(pProp);
|
||||
|
||||
// If this is the instance name property, then other parts of the UI need to be updated to reflect the new name.
|
||||
if (pNode->Object()->IsEditorProperty(pProperty) && pProperty->Type() == eStringProperty)
|
||||
if (pNode->Object()->IsEditorProperty(pProp) && pProp->Type() == eStringProperty)
|
||||
mpWorldEditor->UpdateSelectionUI();
|
||||
|
||||
// If this is a model/character, then we'll treat it as a modified selection. This is to make sure the selection bounds updates.
|
||||
if (pProp->Type() == eFileProperty)
|
||||
{
|
||||
CFileTemplate *pFile = static_cast<CFileTemplate*>(pProp->Template());
|
||||
|
||||
if (pFile->AcceptsExtension("CMDL") || pFile->AcceptsExtension("ANCS") || pFile->AcceptsExtension("CHAR"))
|
||||
mpWorldEditor->NotifySelectionModified();
|
||||
}
|
||||
else if (pProp->Type() == eCharacterProperty)
|
||||
mpWorldEditor->NotifySelectionModified();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ public:
|
|||
|
||||
public slots:
|
||||
void OnWorldSelectionTransformed();
|
||||
void OnPropertyModified(const QModelIndex& rkIndex, bool IsDone);
|
||||
void OnPropertyModified(IProperty *pProp);
|
||||
|
||||
private:
|
||||
Ui::WModifyTab *ui;
|
||||
|
|
Loading…
Reference in New Issue