Support for undoing property changes + tons of tweaks and fixes

This commit is contained in:
parax0 2016-01-31 01:11:32 -07:00
parent c7d448225c
commit cc054cf571
25 changed files with 467 additions and 192 deletions

View File

@ -33,6 +33,18 @@ public:
void SetResource(CResource *pRes); void SetResource(CResource *pRes);
void SetNodeIndex(u32 Index); void SetNodeIndex(u32 Index);
void SetUnknown(u32 Index, u32 Value); 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 #endif // CANIMATIONPARAMETERS_H

View File

@ -196,6 +196,7 @@ CResource* CResCache::GetResource(const TString& ResPath)
else if (type == "CHAR") Res = CAnimSetLoader::LoadCHAR(file); else if (type == "CHAR") Res = CAnimSetLoader::LoadCHAR(file);
else if (type == "MREA") Res = CAreaLoader::LoadMREA(file); else if (type == "MREA") Res = CAreaLoader::LoadMREA(file);
else if (type == "MLVL") Res = CWorldLoader::LoadMLVL(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 == "FONT") Res = CFontLoader::LoadFONT(file);
else if (type == "SCAN") Res = CScanLoader::LoadSCAN(file); else if (type == "SCAN") Res = CScanLoader::LoadSCAN(file);
else if (type == "DCLN") Res = CCollisionLoader::LoadDCLN(file); else if (type == "DCLN") Res = CCollisionLoader::LoadDCLN(file);

View File

@ -31,10 +31,18 @@ public:
inline CUniqueID ID() const inline CUniqueID ID() const
{ {
TString FileName = mPath.GetFileName();
if (!mIsPath) if (!mIsPath)
return CUniqueID::FromString(mPath.GetFileName()); return CUniqueID::FromString(FileName);
else else
return CUniqueID::skInvalidID64; {
if (FileName.IsHexString() && (FileName.Size() == 8 || FileName.Size() == 16))
return CUniqueID::FromString(FileName);
else
return CUniqueID::skInvalidID64;
}
} }
inline CFourCC Type() const inline CFourCC Type() const
@ -64,6 +72,16 @@ public:
else else
return mIsValidPath; 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 #endif // CRESOURCEINFO

View File

@ -99,7 +99,7 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& SCLY)
CUniqueID ResID = (mVersion < eCorruptionProto ? SCLY.ReadLong() : SCLY.ReadLongLong()); CUniqueID ResID = (mVersion < eCorruptionProto ? SCLY.ReadLong() : SCLY.ReadLongLong());
const TStringList& rkExtensions = static_cast<CFileTemplate*>(pTemp)->Extensions(); const TStringList& rkExtensions = static_cast<CFileTemplate*>(pTemp)->Extensions();
CResourceInfo Info(ResID, "UNKN"); CResourceInfo Info(ResID, CFourCC(!rkExtensions.empty() ? rkExtensions.front() : "UNKN"));
if (ResID.IsValid()) if (ResID.IsValid())
{ {

View File

@ -40,6 +40,7 @@ public:
virtual ~IProperty() {} virtual ~IProperty() {}
virtual EPropertyType Type() const = 0; virtual EPropertyType Type() const = 0;
virtual TString ToString() const { return ""; } virtual TString ToString() const { return ""; }
virtual IPropertyValue* RawValue() { return nullptr; }
inline CPropertyStruct* Parent() const { return mpParent; } inline CPropertyStruct* Parent() const { return mpParent; }
@ -68,6 +69,7 @@ public:
~TTypedProperty() {} ~TTypedProperty() {}
virtual EPropertyType Type() const { return TypeEnum; } virtual EPropertyType Type() const { return TypeEnum; }
virtual TString ToString() const { return mValue.ToString(); } virtual TString ToString() const { return mValue.ToString(); }
virtual IPropertyValue* RawValue() { return &mValue; }
inline PropType Get() const { return mValue.Get(); } inline PropType Get() const { return mValue.Get(); }
inline void Set(PropType v) { mValue.Set(v); } 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<short, eShortProperty, CShortValue> TShortProperty;
typedef TTypedProperty<long, eLongProperty, CLongValue> TLongProperty; typedef TTypedProperty<long, eLongProperty, CLongValue> TLongProperty;
typedef TTypedProperty<long, eEnumProperty, CLongValue> TEnumProperty; 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<float, eFloatProperty, CFloatValue> TFloatProperty;
typedef TTypedProperty<TString, eStringProperty, CStringValue> TStringProperty; typedef TTypedProperty<TString, eStringProperty, CStringValue> TStringProperty;
typedef TTypedProperty<CVector3f, eVector3Property, CVector3Value> TVector3Property; typedef TTypedProperty<CVector3f, eVector3Property, CVector3Value> TVector3Property;

View File

@ -338,13 +338,11 @@ public:
CEnumTemplate(u32 ID, CStructTemplate *pParent = 0) CEnumTemplate(u32 ID, CStructTemplate *pParent = 0)
: TLongTemplate(ID, pParent) : TLongTemplate(ID, pParent)
{ {
mDefaultValue.SetHexStringOutput(true);
} }
CEnumTemplate(u32 ID, const TString& rkName, ECookPreference CookPreference, CStructTemplate *pParent = 0) CEnumTemplate(u32 ID, const TString& rkName, ECookPreference CookPreference, CStructTemplate *pParent = 0)
: TLongTemplate(ID, rkName, CookPreference, pParent) : TLongTemplate(ID, rkName, CookPreference, pParent)
{ {
mDefaultValue.SetHexStringOutput(true);
} }
virtual EPropertyType Type() const { return eEnumProperty; } virtual EPropertyType Type() const { return eEnumProperty; }
@ -393,7 +391,7 @@ public:
// CBitfieldTemplate - Property template for bitfields, which can have multiple // CBitfieldTemplate - Property template for bitfields, which can have multiple
// distinct boolean parameters packed into one property. // distinct boolean parameters packed into one property.
class CBitfieldTemplate : public TLongTemplate class CBitfieldTemplate : public TTypedPropertyTemplate<u32, eBitfieldProperty, CHexLongValue>
{ {
friend class CTemplateLoader; friend class CTemplateLoader;
friend class CTemplateWriter; friend class CTemplateWriter;
@ -411,15 +409,13 @@ class CBitfieldTemplate : public TLongTemplate
public: public:
CBitfieldTemplate(u32 ID, CStructTemplate *pParent = 0) 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) 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; } virtual EPropertyType Type() const { return eBitfieldProperty; }

View File

@ -17,6 +17,9 @@ class IPropertyValue
public: public:
virtual TString ToString() const = 0; virtual TString ToString() const = 0;
virtual void FromString(const TString& rkString) = 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> template<typename PropType>
@ -28,8 +31,20 @@ protected:
public: public:
TTypedPropertyValue() {} TTypedPropertyValue() {}
TTypedPropertyValue(PropType Val) TTypedPropertyValue(PropType rkVal)
: mValue(Val) {} : 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 PropType Get() const
{ {
@ -69,6 +84,11 @@ public:
{ {
mValue = (rkString == "true"); mValue = (rkString == "true");
} }
IPropertyValue* Clone() const
{
return new CBoolValue(mValue);
}
}; };
class CByteValue : public TTypedPropertyValue<s8> class CByteValue : public TTypedPropertyValue<s8>
@ -87,6 +107,11 @@ public:
u32 base = (rkString.StartsWith("0x") ? 16 : 10); u32 base = (rkString.StartsWith("0x") ? 16 : 10);
mValue = (s8) rkString.ToInt32(base); mValue = (s8) rkString.ToInt32(base);
} }
IPropertyValue* Clone() const
{
return new CByteValue(mValue);
}
}; };
class CShortValue : public TTypedPropertyValue<s16> class CShortValue : public TTypedPropertyValue<s16>
@ -105,28 +130,22 @@ public:
u32 base = (rkString.StartsWith("0x") ? 16 : 10); u32 base = (rkString.StartsWith("0x") ? 16 : 10);
mValue = (s16) rkString.ToInt32(base); mValue = (s16) rkString.ToInt32(base);
} }
IPropertyValue* Clone() const
{
return new CShortValue(mValue);
}
}; };
class CLongValue : public TTypedPropertyValue<s32> class CLongValue : public TTypedPropertyValue<s32>
{ {
protected:
bool mShouldOutputHex;
public: public:
CLongValue() { mShouldOutputHex = false; mValue = 0; } CLongValue() { mValue = 0; }
CLongValue(s32 Val) { mShouldOutputHex = false; mValue = Val; } CLongValue(s32 Val) { mValue = Val; }
void SetHexStringOutput(bool enable)
{
mShouldOutputHex = enable;
}
TString ToString() const TString ToString() const
{ {
if (mShouldOutputHex) return TString::FromInt32(mValue, 0, 10);
return TString::HexString((u32) mValue, true, true, 8);
else
return TString::FromInt32(mValue, 0, 10);
} }
void FromString(const TString& rkString) void FromString(const TString& rkString)
@ -134,6 +153,34 @@ public:
u32 base = (rkString.StartsWith("0x") ? 16 : 10); u32 base = (rkString.StartsWith("0x") ? 16 : 10);
mValue = (s32) rkString.ToInt32(base); 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> class CFloatValue : public TTypedPropertyValue<float>
@ -151,6 +198,11 @@ public:
{ {
mValue = rkString.ToFloat(); mValue = rkString.ToFloat();
} }
IPropertyValue* Clone() const
{
return new CFloatValue(mValue);
}
}; };
class CStringValue : public TTypedPropertyValue<TString> class CStringValue : public TTypedPropertyValue<TString>
@ -169,6 +221,11 @@ public:
{ {
mValue = rkString; mValue = rkString;
} }
IPropertyValue* Clone() const
{
return new CStringValue(mValue);
}
}; };
class CColorValue : public TTypedPropertyValue<CColor> class CColorValue : public TTypedPropertyValue<CColor>
@ -207,6 +264,11 @@ public:
pPtr++; pPtr++;
} }
} }
IPropertyValue* Clone() const
{
return new CColorValue(mValue);
}
}; };
class CVector3Value : public TTypedPropertyValue<CVector3f> class CVector3Value : public TTypedPropertyValue<CVector3f>
@ -243,15 +305,26 @@ public:
pPtr++; pPtr++;
} }
} }
IPropertyValue* Clone() const
{
return new CVector3Value(mValue);
}
}; };
class CCharacterValue : public TTypedPropertyValue<CAnimationParameters> class CCharacterValue : public TTypedPropertyValue<CAnimationParameters>
{ {
public: public:
CCharacterValue() {} CCharacterValue() {}
CCharacterValue(const CAnimationParameters& rkParams) { mValue = rkParams; }
TString ToString() const { return ""; } TString ToString() const { return ""; }
void FromString(const TString&) { } void FromString(const TString&) { }
IPropertyValue* Clone() const
{
return new CCharacterValue(mValue);
}
}; };
class CFileValue : public TTypedPropertyValue<CResourceInfo> class CFileValue : public TTypedPropertyValue<CResourceInfo>
@ -262,15 +335,26 @@ public:
TString ToString() const { return ""; } TString ToString() const { return ""; }
void FromString(const TString&) { } void FromString(const TString&) { }
IPropertyValue* Clone() const
{
return new CFileValue(mValue);
}
}; };
class CUnknownValue : public TTypedPropertyValue<std::vector<u8>> class CUnknownValue : public TTypedPropertyValue<std::vector<u8>>
{ {
public: public:
CUnknownValue(); CUnknownValue();
CUnknownValue(const std::vector<u8>& rkVec) { mValue = rkVec; }
TString ToString() const { return ""; } TString ToString() const { return ""; }
void FromString(const TString&) {} void FromString(const TString&) {}
IPropertyValue* Clone() const
{
return new CUnknownValue(mValue);
}
}; };
#endif // IPROPERTYVALUE_H #endif // IPROPERTYVALUE_H

View File

@ -133,7 +133,8 @@ HEADERS += \
PropertyEdit/CPropertyView.h \ PropertyEdit/CPropertyView.h \
PropertyEdit/CPropertyRelay.h \ PropertyEdit/CPropertyRelay.h \
WorldEditor/CInstancesProxyModel.h \ WorldEditor/CInstancesProxyModel.h \
WorldEditor/CInstancesModel.h WorldEditor/CInstancesModel.h \
Undo/CEditScriptPropertyCommand.h
# Source Files # Source Files
SOURCES += \ SOURCES += \
@ -184,7 +185,8 @@ SOURCES += \
PropertyEdit/CPropertyModel.cpp \ PropertyEdit/CPropertyModel.cpp \
PropertyEdit/CPropertyDelegate.cpp \ PropertyEdit/CPropertyDelegate.cpp \
PropertyEdit/CPropertyView.cpp \ PropertyEdit/CPropertyView.cpp \
WorldEditor/CInstancesModel.cpp WorldEditor/CInstancesModel.cpp \
Undo/CEditScriptPropertyCommand.cpp
# UI Files # UI Files
FORMS += \ FORMS += \

View File

@ -233,6 +233,7 @@ void INodeEditor::ExitPickMode()
void INodeEditor::NotifySelectionModified() void INodeEditor::NotifySelectionModified()
{ {
RecalculateSelectionBounds();
UpdateSelectionUI(); UpdateSelectionUI();
emit SelectionModified(); emit SelectionModified();
} }

View File

@ -2,6 +2,7 @@
#include "CPropertyRelay.h" #include "CPropertyRelay.h"
#include "Editor/UICommon.h" #include "Editor/UICommon.h"
#include "Editor/Undo/CEditScriptPropertyCommand.h"
#include "Editor/Widgets/WColorPicker.h" #include "Editor/Widgets/WColorPicker.h"
#include "Editor/Widgets/WDraggableSpinBox.h" #include "Editor/Widgets/WDraggableSpinBox.h"
#include "Editor/Widgets/WIntegralSpinBox.h" #include "Editor/Widgets/WIntegralSpinBox.h"
@ -23,16 +24,24 @@
CPropertyDelegate::CPropertyDelegate(QObject *pParent /*= 0*/) CPropertyDelegate::CPropertyDelegate(QObject *pParent /*= 0*/)
: QStyledItemDelegate(pParent) : QStyledItemDelegate(pParent)
, mpEditor(nullptr)
, mpModel(nullptr) , mpModel(nullptr)
, mInRelayWidgetEdit(false)
, mEditInProgress(false)
, mRelaysBlocked(false) , mRelaysBlocked(false)
{ {
} }
void CPropertyDelegate::SetModel(CPropertyModel *pModel) void CPropertyDelegate::SetPropertyModel(CPropertyModel *pModel)
{ {
mpModel = pModel; mpModel = pModel;
} }
void CPropertyDelegate::SetEditor(CWorldEditor *pEditor)
{
mpEditor = pEditor;
}
QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionViewItem& /*rkOption*/, const QModelIndex& rkIndex) const QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionViewItem& /*rkOption*/, const QModelIndex& rkIndex) const
{ {
if (!mpModel) return nullptr; if (!mpModel) return nullptr;
@ -116,6 +125,7 @@ QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionVie
WResourceSelector *pSelector = new WResourceSelector(pParent); WResourceSelector *pSelector = new WResourceSelector(pParent);
CFileTemplate *pTemp = static_cast<CFileTemplate*>(pProp->Template()); CFileTemplate *pTemp = static_cast<CFileTemplate*>(pProp->Template());
pSelector->SetAllowedExtensions(pTemp->Extensions()); 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)) CONNECT_RELAY(pSelector, rkIndex, ResourceChanged(QString))
pOut = pSelector; pOut = pSelector;
@ -191,90 +201,92 @@ void CPropertyDelegate::setEditorData(QWidget *pEditor, const QModelIndex &rkInd
if (pProp) if (pProp)
{ {
switch (pProp->Type()) if (!mEditInProgress)
{ {
switch (pProp->Type())
{
case eBoolProperty: case eBoolProperty:
{ {
QCheckBox *pCheckBox = static_cast<QCheckBox*>(pEditor); QCheckBox *pCheckBox = static_cast<QCheckBox*>(pEditor);
TBoolProperty *pBool = static_cast<TBoolProperty*>(pProp); TBoolProperty *pBool = static_cast<TBoolProperty*>(pProp);
pCheckBox->setChecked(pBool->Get()); pCheckBox->setChecked(pBool->Get());
break; break;
} }
case eShortProperty: case eShortProperty:
{ {
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor); WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
TShortProperty *pShort = static_cast<TShortProperty*>(pProp); TShortProperty *pShort = static_cast<TShortProperty*>(pProp);
pSpinBox->setValue(pShort->Get()); pSpinBox->setValue(pShort->Get());
break; break;
} }
case eLongProperty:
{
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
TLongProperty *pLong = static_cast<TLongProperty*>(pProp);
pSpinBox->setValue(pLong->Get());
break;
}
case eLongProperty: case eFloatProperty:
{ {
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor); WDraggableSpinBox *pSpinBox = static_cast<WDraggableSpinBox*>(pEditor);
TLongProperty *pLong = static_cast<TLongProperty*>(pProp); TFloatProperty *pFloat = static_cast<TFloatProperty*>(pProp);
pSpinBox->setValue(pLong->Get()); pSpinBox->setValue(pFloat->Get());
break; break;
} }
case eFloatProperty: case eColorProperty:
{ {
WDraggableSpinBox *pSpinBox = static_cast<WDraggableSpinBox*>(pEditor); WColorPicker *pColorPicker = static_cast<WColorPicker*>(pEditor);
TFloatProperty *pFloat = static_cast<TFloatProperty*>(pProp); TColorProperty *pColor = static_cast<TColorProperty*>(pProp);
pSpinBox->setValue(pFloat->Get());
break;
}
case eColorProperty: CColor SrcColor = pColor->Get();
{ QColor Color;
WColorPicker *pColorPicker = static_cast<WColorPicker*>(pEditor); Color.setRed(SrcColor.r * 255);
TColorProperty *pColor = static_cast<TColorProperty*>(pProp); Color.setGreen(SrcColor.g * 255);
Color.setBlue(SrcColor.b * 255);
Color.setAlpha(SrcColor.a * 255);
CColor SrcColor = pColor->Get(); pColorPicker->setColor(Color);
QColor Color; break;
Color.setRed(SrcColor.r * 255); }
Color.setGreen(SrcColor.g * 255);
Color.setBlue(SrcColor.b * 255);
Color.setAlpha(SrcColor.a * 255);
pColorPicker->setColor(Color); case eStringProperty:
break; {
} QLineEdit *pLineEdit = static_cast<QLineEdit*>(pEditor);
TStringProperty *pString = static_cast<TStringProperty*>(pProp);
pLineEdit->setText(TO_QSTRING(pString->Get()));
break;
}
case eStringProperty: case eEnumProperty:
{ {
QLineEdit *pLineEdit = static_cast<QLineEdit*>(pEditor); QComboBox *pComboBox = static_cast<QComboBox*>(pEditor);
TStringProperty *pString = static_cast<TStringProperty*>(pProp); TEnumProperty *pEnum = static_cast<TEnumProperty*>(pProp);
pLineEdit->setText(TO_QSTRING(pString->Get())); pComboBox->setCurrentIndex(pEnum->Get());
break; break;
} }
case eEnumProperty: case eFileProperty:
{ {
QComboBox *pComboBox = static_cast<QComboBox*>(pEditor); WResourceSelector *pSelector = static_cast<WResourceSelector*>(pEditor);
TEnumProperty *pEnum = static_cast<TEnumProperty*>(pProp); TFileProperty *pFile = static_cast<TFileProperty*>(pProp);
pComboBox->setCurrentIndex(pEnum->Get()); pSelector->SetResource(pFile->Get());
break; break;
} }
case eFileProperty: case eArrayProperty:
{ {
WResourceSelector *pSelector = static_cast<WResourceSelector*>(pEditor); WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
TFileProperty *pFile = static_cast<TFileProperty*>(pProp); CArrayProperty *pArray = static_cast<CArrayProperty*>(pProp);
pSelector->SetResource(pFile->Get()); pSpinBox->setValue(pArray->Count());
break; break;
} }
case eArrayProperty:
{
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
CArrayProperty *pArray = static_cast<CArrayProperty*>(pProp);
pSpinBox->setValue(pArray->Count());
break;
}
}
} }
} }
@ -335,9 +347,12 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
if (!pEditor) return; if (!pEditor) return;
IProperty *pProp = mpModel->PropertyForIndex(rkIndex, false); IProperty *pProp = mpModel->PropertyForIndex(rkIndex, false);
IPropertyValue *pOldValue = nullptr;
if (pProp) if (pProp)
{ {
pOldValue = pProp->RawValue()->Clone();
switch (pProp->Type()) switch (pProp->Type())
{ {
@ -385,9 +400,6 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
Color.b = SrcColor.blue() / 255.f; Color.b = SrcColor.blue() / 255.f;
Color.a = SrcColor.alpha() / 255.f; Color.a = SrcColor.alpha() / 255.f;
pColor->Set(Color); pColor->Set(Color);
// Make sure sub-properties update with the new color
mpModel->UpdateSubProperties(rkIndex);
break; break;
} }
@ -430,6 +442,7 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
else if (rkIndex.internalId() & 0x1) else if (rkIndex.internalId() & 0x1)
{ {
pProp = mpModel->PropertyForIndex(rkIndex, true); pProp = mpModel->PropertyForIndex(rkIndex, true);
pOldValue = pProp->RawValue()->Clone();
if (pProp->Type() == eCharacterProperty) if (pProp->Type() == eCharacterProperty)
SetCharacterModelData(pEditor, rkIndex); SetCharacterModelData(pEditor, rkIndex);
@ -474,13 +487,33 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
pColor->Set(Value); 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) bool CPropertyDelegate::eventFilter(QObject *pObject, QEvent *pEvent)
@ -513,6 +546,7 @@ QWidget* CPropertyDelegate::CreateCharacterEditor(QWidget *pParent, const QModel
if (Type == eFileProperty) if (Type == eFileProperty)
{ {
WResourceSelector *pSelector = new WResourceSelector(pParent); WResourceSelector *pSelector = new WResourceSelector(pParent);
pSelector->setFont(qobject_cast<QWidget*>(parent())->font()); // hack to keep the selector font from changing
if (Params.Version() <= eEchoes) if (Params.Version() <= eEchoes)
pSelector->SetAllowedExtensions("ANCS"); 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 // 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. // reflected in realtime in other parts of the application.
mInRelayWidgetEdit = true;
if (!mRelaysBlocked) if (!mRelaysBlocked)
setModelData(pWidget, mpModel, rkIndex); setModelData(pWidget, mpModel, rkIndex);
mInRelayWidgetEdit = false;
} }

View File

@ -1,19 +1,25 @@
#ifndef CPROPERTYDELEGATE_H #ifndef CPROPERTYDELEGATE_H
#define CPROPERTYDELEGATE_H #define CPROPERTYDELEGATE_H
#include <QStyledItemDelegate>
#include "CPropertyModel.h" #include "CPropertyModel.h"
#include "Editor/WorldEditor/CWorldEditor.h"
#include <QStyledItemDelegate>
class CPropertyDelegate : public QStyledItemDelegate class CPropertyDelegate : public QStyledItemDelegate
{ {
Q_OBJECT Q_OBJECT
CWorldEditor *mpEditor;
CPropertyModel *mpModel; CPropertyModel *mpModel;
bool mInRelayWidgetEdit;
mutable bool mEditInProgress;
mutable bool mRelaysBlocked; mutable bool mRelaysBlocked;
public: public:
CPropertyDelegate(QObject *pParent = 0); 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 QWidget* createEditor(QWidget *pParent, const QStyleOptionViewItem& rkOption, const QModelIndex &rkIndex) const;
virtual void setEditorData(QWidget *pEditor, const QModelIndex &rkIndex) const; virtual void setEditorData(QWidget *pEditor, const QModelIndex &rkIndex) const;
virtual void setModelData(QWidget *pEditor, QAbstractItemModel *pModel, const QModelIndex &rkIndex) const; virtual void setModelData(QWidget *pEditor, QAbstractItemModel *pModel, const QModelIndex &rkIndex) const;
@ -29,9 +35,6 @@ public slots:
protected: protected:
void BlockRelays(bool Block) const { mRelaysBlocked = Block; } void BlockRelays(bool Block) const { mRelaysBlocked = Block; }
signals:
void PropertyEdited(const QModelIndex& rkIndex, bool IsDone) const;
}; };
#endif // CPROPERTYDELEGATE_H #endif // CPROPERTYDELEGATE_H

View File

@ -292,7 +292,7 @@ QVariant CPropertyModel::data(const QModelIndex& rkIndex, int Role) const
// Add uncooked notification // Add uncooked notification
if (pProp->Template()->CookPreference() == eNeverCook) if (pProp->Template()->CookPreference() == eNeverCook)
{ {
Text += "<br/><b>This is an uncooked property.</b>"; Text.prepend("<i>[uncooked]</i>");
} }
// Add description // Add description
@ -393,19 +393,20 @@ Qt::ItemFlags CPropertyModel::flags(const QModelIndex& rkIndex) const
else return (Qt::ItemIsEnabled | Qt::ItemIsEditable); 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); QModelIndex Parent = rkIndex.parent();
Parent = Parent.sibling(Parent.row(), 1);
if (pProp->Type() == eVector3Property) emit dataChanged(Parent, Parent);
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);
} }
emit dataChanged(rkIndex, rkIndex);
emit PropertyModified(rkIndex);
} }
void CPropertyModel::ResizeArray(const QModelIndex& rkIndex, u32 NewSize) void CPropertyModel::ResizeArray(const QModelIndex& rkIndex, u32 NewSize)

View File

@ -22,8 +22,12 @@ public:
QModelIndex index(int Row, int Column, const QModelIndex& rkParent) const; QModelIndex index(int Row, int Column, const QModelIndex& rkParent) const;
QModelIndex parent(const QModelIndex& rkChild) const; QModelIndex parent(const QModelIndex& rkChild) const;
Qt::ItemFlags flags(const QModelIndex& rkIndex) 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); void ResizeArray(const QModelIndex& rkIndex, u32 NewSize);
signals:
void PropertyModified(const QModelIndex& rkIndex);
}; };
#endif // CPROPERTYMODEL_H #endif // CPROPERTYMODEL_H

View File

@ -14,16 +14,16 @@ CPropertyView::CPropertyView(QWidget *pParent)
setEditTriggers(AllEditTriggers); setEditTriggers(AllEditTriggers);
setModel(mpModel); setModel(mpModel);
connect(mpModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(SetPersistentEditors(QModelIndex)));
connect(this, SIGNAL(expanded(QModelIndex)), 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) void CPropertyView::setModel(QAbstractItemModel *pModel)
{ {
CPropertyModel *pPropModel = qobject_cast<CPropertyModel*>(pModel); CPropertyModel *pPropModel = qobject_cast<CPropertyModel*>(pModel);
mpModel = pPropModel; mpModel = pPropModel;
mpDelegate->SetModel(pPropModel); mpDelegate->SetPropertyModel(pPropModel);
QTreeView::setModel(pPropModel); QTreeView::setModel(pPropModel);
if (pPropModel) if (pPropModel)
@ -61,7 +61,13 @@ bool CPropertyView::event(QEvent *pEvent)
else return QTreeView::event(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; mpObject = pObj;
mpModel->SetBaseStruct(pObj ? pObj->Properties() : nullptr); 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. // Check for a character resource being changed. If that's the case we need to remake the persistent editors.
if (rkIndex.internalId() & 0x1) IProperty *pProp = mpModel->PropertyForIndex(rkIndex, true);
{
if (mpModel->PropertyForIndex(rkIndex, true)->Type() == eCharacterProperty)
{
EGame Game = static_cast<TCharacterProperty*>(mpModel->PropertyForIndex(rkIndex, true))->Get().Version();
if (mpDelegate->DetermineCharacterPropType(Game, rkIndex) == eFileProperty) if (pProp->Type() == eCharacterProperty && rkIndex.internalId() & 0x1)
{ {
QModelIndex Parent = rkIndex.parent(); EGame Game = static_cast<TCharacterProperty*>(pProp)->Get().Version();
ClosePersistentEditors(Parent);
SetPersistentEditors(Parent); if (mpDelegate->DetermineCharacterPropType(Game, rkIndex) == eFileProperty)
} {
ClosePersistentEditors(rkIndex.parent());
SetPersistentEditors(rkIndex.parent());
} }
} }
emit PropertyModified(rkIndex, IsDone); emit PropertyModified(pProp);
} }

View File

@ -10,6 +10,7 @@ class CPropertyView : public QTreeView
{ {
Q_OBJECT Q_OBJECT
CWorldEditor *mpEditor;
CPropertyModel *mpModel; CPropertyModel *mpModel;
CPropertyDelegate *mpDelegate; CPropertyDelegate *mpDelegate;
CScriptObject *mpObject; CScriptObject *mpObject;
@ -18,7 +19,8 @@ public:
CPropertyView(QWidget *pParent = 0); CPropertyView(QWidget *pParent = 0);
void setModel(QAbstractItemModel *pModel); void setModel(QAbstractItemModel *pModel);
bool event(QEvent *pEvent); bool event(QEvent *pEvent);
void SetObject(CScriptObject *pObj); void SetEditor(CWorldEditor *pEditor);
void SetInstance(CScriptObject *pObj);
void UpdateEditorProperties(const QModelIndex& rkParent); void UpdateEditorProperties(const QModelIndex& rkParent);
inline CPropertyModel* PropertyModel() const { return mpModel; } inline CPropertyModel* PropertyModel() const { return mpModel; }
@ -26,10 +28,10 @@ public:
public slots: public slots:
void SetPersistentEditors(const QModelIndex& rkIndex); void SetPersistentEditors(const QModelIndex& rkIndex);
void ClosePersistentEditors(const QModelIndex& rkIndex); void ClosePersistentEditors(const QModelIndex& rkIndex);
void OnPropertyModified(const QModelIndex& rkIndex, bool IsDone); void OnPropertyModified(const QModelIndex& rkIndex);
signals: signals:
void PropertyModified(const QModelIndex &rkIndex, bool IsDone); void PropertyModified(IProperty *pProperty);
}; };
#endif // CPROPERTYVIEW_H #endif // CPROPERTYVIEW_H

View File

@ -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);
}

View File

@ -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

View File

@ -5,7 +5,8 @@ enum EUndoCommand
{ {
eTranslateNodeCmd, eTranslateNodeCmd,
eRotateNodeCmd, eRotateNodeCmd,
eScaleNodeCmd eScaleNodeCmd,
eEditScriptPropertyCmd
}; };
#endif // EUNDOCOMMAND #endif // EUNDOCOMMAND

View File

@ -9,6 +9,7 @@
#include "CClearSelectionCommand.h" #include "CClearSelectionCommand.h"
#include "CSelectAllCommand.h" #include "CSelectAllCommand.h"
#include "CInvertSelectionCommand.h" #include "CInvertSelectionCommand.h"
#include "CEditScriptPropertyCommand.h"
#include "EUndoCommand.h" #include "EUndoCommand.h"
#endif // UNDOCOMMANDS #endif // UNDOCOMMANDS

View File

@ -106,6 +106,22 @@ bool WResourceSelector::HasSupportedExtension(const CResourceInfo& rkRes)
return IsSupportedExtension(TO_QSTRING(rkRes.Type().ToString())); 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 ************ // ************ GETTERS ************
CResourceInfo WResourceSelector::GetResourceInfo() CResourceInfo WResourceSelector::GetResourceInfo()
{ {
@ -147,24 +163,38 @@ void WResourceSelector::SetResource(CResource *pRes)
SetResource(CResourceInfo()); 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) void WResourceSelector::SetResource(const CResourceInfo& rkRes)
{ {
mResource = rkRes; if (mResource != rkRes)
if (mResource.IsValid())
{ {
mResourceValid = HasSupportedExtension(rkRes); mResource = rkRes;
if (mResource.IsValid())
mResourceValid = HasSupportedExtension(rkRes);
else
mResourceValid = false;
mUI.LineEdit->setText(TO_QSTRING(mResource.ToString())); mUI.LineEdit->setText(TO_QSTRING(mResource.ToString()));
}
else UpdateFrameColor();
{ CreatePreviewPanel();
mResourceValid = false; SetButtonsBasedOnResType();
mUI.LineEdit->clear(); Q_ASSERT(!mUI.LineEdit->text().isEmpty());
emit ResourceChanged(TO_QSTRING(mResource.ToString()));
} }
CreatePreviewPanel();
SetButtonsBasedOnResType();
} }
void WResourceSelector::SetAllowedExtensions(const QString& extension) void WResourceSelector::SetAllowedExtensions(const QString& extension)
@ -183,7 +213,7 @@ void WResourceSelector::SetAllowedExtensions(const TStringList& extensions)
void WResourceSelector::SetText(const QString& ResPath) void WResourceSelector::SetText(const QString& ResPath)
{ {
mUI.LineEdit->setText(ResPath); mUI.LineEdit->setText(ResPath);
LoadResource(ResPath); SetResource(ResPath);
} }
void WResourceSelector::SetEditButtonEnabled(bool Enabled) void WResourceSelector::SetEditButtonEnabled(bool Enabled)
@ -214,7 +244,7 @@ void WResourceSelector::AdjustPreviewToParent(bool adjust)
// ************ SLOTS ************ // ************ SLOTS ************
void WResourceSelector::OnLineEditTextEdited() void WResourceSelector::OnLineEditTextEdited()
{ {
LoadResource(mUI.LineEdit->text()); SetResource(mUI.LineEdit->text());
} }
void WResourceSelector::OnBrowseButtonClicked() void WResourceSelector::OnBrowseButtonClicked()
@ -246,7 +276,7 @@ void WResourceSelector::OnBrowseButtonClicked()
if (!NewRes.isEmpty()) if (!NewRes.isEmpty())
{ {
mUI.LineEdit->setText(NewRes); mUI.LineEdit->setText(NewRes);
LoadResource(NewRes); SetResource(NewRes);
} }
} }
@ -273,27 +303,6 @@ void WResourceSelector::Export()
emit ExportResource(mResource); 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() void WResourceSelector::CreatePreviewPanel()
{ {
delete mpPreviewPanel; delete mpPreviewPanel;

View File

@ -54,6 +54,7 @@ public:
bool eventFilter(QObject *, QEvent *); bool eventFilter(QObject *, QEvent *);
bool IsSupportedExtension(const QString& extension); bool IsSupportedExtension(const QString& extension);
bool HasSupportedExtension(const CResourceInfo& rkRes); bool HasSupportedExtension(const CResourceInfo& rkRes);
void UpdateFrameColor();
// Getters // Getters
CResourceInfo GetResourceInfo(); CResourceInfo GetResourceInfo();
@ -65,6 +66,7 @@ public:
// Setters // Setters
void SetResource(CResource *pRes); void SetResource(CResource *pRes);
void SetResource(const QString& rkRes);
void SetResource(const CResourceInfo& rkRes); void SetResource(const CResourceInfo& rkRes);
void SetAllowedExtensions(const QString& extension); void SetAllowedExtensions(const QString& extension);
void SetAllowedExtensions(const QStringList& extensions); void SetAllowedExtensions(const QStringList& extensions);
@ -85,7 +87,6 @@ public slots:
private: private:
void Edit(); void Edit();
void Export(); void Export();
void LoadResource(const QString& ResPath);
void CreatePreviewPanel(); void CreatePreviewPanel();
void ShowPreviewPanel(); void ShowPreviewPanel();
void HidePreviewPanel(); void HidePreviewPanel();

View File

@ -108,6 +108,7 @@ void WVectorEditor::SetX(double x)
mpSpinBoxX->setValue((double) x); mpSpinBoxX->setValue((double) x);
mpSpinBoxX->blockSignals(false); mpSpinBoxX->blockSignals(false);
mEditing = true;
emit ValueChanged(mValue); emit ValueChanged(mValue);
} }
@ -119,6 +120,7 @@ void WVectorEditor::SetY(double y)
mpSpinBoxY->setValue((double) y); mpSpinBoxY->setValue((double) y);
mpSpinBoxY->blockSignals(false); mpSpinBoxY->blockSignals(false);
mEditing = true;
emit ValueChanged(mValue); emit ValueChanged(mValue);
} }
@ -130,6 +132,7 @@ void WVectorEditor::SetZ(double z)
mpSpinBoxZ->setValue((double) z); mpSpinBoxZ->setValue((double) z);
mpSpinBoxZ->blockSignals(false); mpSpinBoxZ->blockSignals(false);
mEditing = true;
emit ValueChanged(mValue); emit ValueChanged(mValue);
} }
@ -181,5 +184,6 @@ void WVectorEditor::SetupUI()
// ************ PRIVATE SLOTS ************ // ************ PRIVATE SLOTS ************
void WVectorEditor::OnSpinBoxEditingDone() void WVectorEditor::OnSpinBoxEditingDone()
{ {
emit EditingDone(mValue); if (mEditing) emit EditingDone(mValue);
mEditing = false;
} }

View File

@ -15,6 +15,7 @@ class WVectorEditor : public QWidget
Q_OBJECT Q_OBJECT
CVector3f mValue; CVector3f mValue;
bool mEditing;
Qt::Orientation mOrientation; Qt::Orientation mOrientation;
QLayout *mpLayout; QLayout *mpLayout;

View File

@ -16,7 +16,7 @@ WModifyTab::WModifyTab(QWidget *pParent) :
ui->PropertyView->header()->resizeSection(0, PropViewWidth * 0.3); ui->PropertyView->header()->resizeSection(0, PropViewWidth * 0.3);
ui->PropertyView->header()->resizeSection(1, PropViewWidth * 0.3); ui->PropertyView->header()->resizeSection(1, PropViewWidth * 0.3);
ui->PropertyView->header()->setSectionResizeMode(1, QHeaderView::Fixed); 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 = new CLinkModel(this);
mpInLinkModel->SetConnectionType(CLinkModel::eIncoming); mpInLinkModel->SetConnectionType(CLinkModel::eIncoming);
@ -41,6 +41,7 @@ WModifyTab::~WModifyTab()
void WModifyTab::SetEditor(CWorldEditor *pEditor) void WModifyTab::SetEditor(CWorldEditor *pEditor)
{ {
mpWorldEditor = pEditor; mpWorldEditor = pEditor;
ui->PropertyView->SetEditor(mpWorldEditor);
connect(mpWorldEditor, SIGNAL(SelectionTransformed()), this, SLOT(OnWorldSelectionTransformed())); connect(mpWorldEditor, SIGNAL(SelectionTransformed()), this, SLOT(OnWorldSelectionTransformed()));
} }
@ -60,7 +61,7 @@ void WModifyTab::GenerateUI(QList<CSceneNode*>& Selection)
CScriptObject *pObj = pScriptNode->Object(); CScriptObject *pObj = pScriptNode->Object();
// Set up UI // Set up UI
ui->PropertyView->SetObject(pObj); ui->PropertyView->SetInstance(pObj);
mpInLinkModel->SetObject(pObj); mpInLinkModel->SetObject(pObj);
mpOutLinkModel->SetObject(pObj); mpOutLinkModel->SetObject(pObj);
ui->LightGroupBox->hide(); ui->LightGroupBox->hide();
@ -75,7 +76,7 @@ void WModifyTab::GenerateUI(QList<CSceneNode*>& Selection)
void WModifyTab::ClearUI() void WModifyTab::ClearUI()
{ {
ui->ObjectsTabWidget->hide(); ui->ObjectsTabWidget->hide();
ui->PropertyView->SetObject(nullptr); ui->PropertyView->SetInstance(nullptr);
ui->LightGroupBox->hide(); ui->LightGroupBox->hide();
mpSelectedNode = nullptr; mpSelectedNode = nullptr;
} }
@ -85,17 +86,27 @@ void WModifyTab::OnWorldSelectionTransformed()
ui->PropertyView->UpdateEditorProperties(QModelIndex()); ui->PropertyView->UpdateEditorProperties(QModelIndex());
} }
void WModifyTab::OnPropertyModified(const QModelIndex& rkIndex, bool /*IsDone*/) void WModifyTab::OnPropertyModified(IProperty *pProp)
{ {
if (mpSelectedNode->NodeType() == eScriptNode) if (mpSelectedNode->NodeType() == eScriptNode)
{ {
CScriptNode *pNode = static_cast<CScriptNode*>(mpSelectedNode); CScriptNode *pNode = static_cast<CScriptNode*>(mpSelectedNode);
IProperty *pProperty = ui->PropertyView->PropertyModel()->PropertyForIndex(rkIndex, true); pNode->PropertyModified(pProp);
pNode->PropertyModified(pProperty);
// If this is the instance name property, then other parts of the UI need to be updated to reflect the new name. // 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(); 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();
} }
} }

View File

@ -36,7 +36,7 @@ public:
public slots: public slots:
void OnWorldSelectionTransformed(); void OnWorldSelectionTransformed();
void OnPropertyModified(const QModelIndex& rkIndex, bool IsDone); void OnPropertyModified(IProperty *pProp);
private: private:
Ui::WModifyTab *ui; Ui::WModifyTab *ui;