From 38942988d52edab2c188175fc7ca311ec4572d7c Mon Sep 17 00:00:00 2001 From: parax0 Date: Fri, 22 Jan 2016 13:53:57 -0700 Subject: [PATCH] Implemented new property editor, CPropertyView --- src/Common/TString.h | 2 +- src/Core/Resource/CAnimationParameters.cpp | 67 +- src/Core/Resource/CAnimationParameters.h | 17 +- src/Core/Resource/Factory/CScriptLoader.cpp | 2 +- src/Core/Resource/Factory/CTemplateLoader.cpp | 2 +- src/Core/Resource/Script/CScriptObject.cpp | 2 +- src/Core/Resource/Script/CScriptTemplate.cpp | 4 +- src/Core/Resource/Script/IProperty.cpp | 27 +- src/Core/Resource/Script/IProperty.h | 78 ++- src/Core/Resource/Script/IPropertyTemplate.h | 40 +- src/Core/ScriptExtra/CDoorExtra.cpp | 2 +- src/Editor/Editor.pro | 13 +- src/Editor/PropertyEdit/CPropertyDelegate.cpp | 547 +++++++++++++++ src/Editor/PropertyEdit/CPropertyDelegate.h | 30 + src/Editor/PropertyEdit/CPropertyModel.cpp | 345 ++++++++++ src/Editor/PropertyEdit/CPropertyModel.h | 28 + src/Editor/PropertyEdit/CPropertyRelay.h | 29 + src/Editor/PropertyEdit/CPropertyView.cpp | 110 +++ src/Editor/PropertyEdit/CPropertyView.h | 23 + src/Editor/TestDialog.cpp | 13 +- src/Editor/TestDialog.h | 2 + src/Editor/TestDialog.ui | 121 +--- src/Editor/Widgets/WAnimParamsEditor.cpp | 4 +- src/Editor/Widgets/WDraggableSpinBox.cpp | 1 + src/Editor/Widgets/WPropertyEditor.cpp | 481 -------------- src/Editor/Widgets/WPropertyEditor.h | 36 - src/Editor/Widgets/WResourceSelector.cpp | 5 + src/Editor/Widgets/WResourceSelector.h | 1 + src/Editor/WorldEditor/CWorldEditor.cpp | 26 +- src/Editor/WorldEditor/CWorldEditor.ui | 627 +++++++++--------- src/Editor/WorldEditor/WModifyTab.cpp | 58 +- src/Editor/WorldEditor/WModifyTab.h | 4 - src/Editor/WorldEditor/WModifyTab.ui | 73 +- templates/mp2/Enums/Item.xml | 114 ++++ templates/mp2/Script/Pickup.xml | 4 +- templates/mp3/Enums/InventorySlot.xml | 64 -- templates/mp3/Enums/Item.xml | 64 ++ templates/mp3/Script/EffectRepulsor.xml | 2 +- templates/mp3/Script/Pickup.xml | 2 +- templates/mp3/Script/ShipCommandIcon.xml | 2 +- templates/mp3/Script/SpecialFunction.xml | 2 +- templates/mp3/Structs/ConditionalTest.xml | 2 +- 42 files changed, 1828 insertions(+), 1248 deletions(-) create mode 100644 src/Editor/PropertyEdit/CPropertyDelegate.cpp create mode 100644 src/Editor/PropertyEdit/CPropertyDelegate.h create mode 100644 src/Editor/PropertyEdit/CPropertyModel.cpp create mode 100644 src/Editor/PropertyEdit/CPropertyModel.h create mode 100644 src/Editor/PropertyEdit/CPropertyRelay.h create mode 100644 src/Editor/PropertyEdit/CPropertyView.cpp create mode 100644 src/Editor/PropertyEdit/CPropertyView.h delete mode 100644 src/Editor/Widgets/WPropertyEditor.cpp delete mode 100644 src/Editor/Widgets/WPropertyEditor.h create mode 100644 templates/mp2/Enums/Item.xml delete mode 100644 templates/mp3/Enums/InventorySlot.xml create mode 100644 templates/mp3/Enums/Item.xml diff --git a/src/Common/TString.h b/src/Common/TString.h index cce82d58..67db62fe 100644 --- a/src/Common/TString.h +++ b/src/Common/TString.h @@ -737,7 +737,7 @@ public: TString Out = std::to_string(value); int NumZeroes = Out.Size() - (Out.IndexOf(".") + 1); - while (Out.Back() == '\0' && NumZeroes > MinDecimals) + while (Out.Back() == '0' && NumZeroes > MinDecimals) { Out = Out.ChopBack(1); NumZeroes--; diff --git a/src/Core/Resource/CAnimationParameters.cpp b/src/Core/Resource/CAnimationParameters.cpp index d9dfd56a..20b389a8 100644 --- a/src/Core/Resource/CAnimationParameters.cpp +++ b/src/Core/Resource/CAnimationParameters.cpp @@ -15,9 +15,9 @@ CAnimationParameters::CAnimationParameters() mUnknown4 = 0; } -CAnimationParameters::CAnimationParameters(IInputStream& SCLY, EGame game) +CAnimationParameters::CAnimationParameters(IInputStream& SCLY, EGame Game) { - mGame = game; + mGame = Game; mpCharSet = nullptr; mNodeIndex = 0; mUnknown1 = 0; @@ -25,28 +25,28 @@ CAnimationParameters::CAnimationParameters(IInputStream& SCLY, EGame game) mUnknown3 = 0; mUnknown4 = 0; - if (game <= eEchoes) + if (Game <= eEchoes) { - u32 animSetID = SCLY.ReadLong(); + u32 AnimSetID = SCLY.ReadLong(); mNodeIndex = SCLY.ReadLong(); mUnknown1 = SCLY.ReadLong(); - mpCharSet = gResCache.GetResource(animSetID, "ANCS"); + mpCharSet = gResCache.GetResource(AnimSetID, "ANCS"); } - else if (game <= eCorruption) + else if (Game <= eCorruption) { - u64 charID = SCLY.ReadLongLong(); + u64 CharID = SCLY.ReadLongLong(); mUnknown1 = SCLY.ReadLong(); - mpCharSet = gResCache.GetResource(charID, "CHAR"); + mpCharSet = gResCache.GetResource(CharID, "CHAR"); } - else if (game == eReturns) + else if (Game == eReturns) { SCLY.Seek(-6, SEEK_CUR); - u32 offset = SCLY.Tell(); - u32 propID = SCLY.ReadLong(); + u32 Offset = SCLY.Tell(); + u32 PropID = SCLY.ReadLong(); SCLY.Seek(2, SEEK_CUR); mUnknown1 = (u32) SCLY.ReadByte(); @@ -64,21 +64,30 @@ CAnimationParameters::CAnimationParameters(IInputStream& SCLY, EGame game) else if (mUnknown1 != 0x80) { - Log::FileError(SCLY.GetSourceString(), offset, - "Unexpected AnimationParameters byte: " + TString::HexString(mUnknown1, true, true, 2) + " (property " + TString::HexString(propID, true, true, 8) + ")"); + Log::FileError(SCLY.GetSourceString(), Offset, + "Unexpected AnimationParameters byte: " + TString::HexString(mUnknown1, true, true, 2) + " (property " + TString::HexString(PropID, true, true, 8) + ")"); } } } -CModel* CAnimationParameters::GetCurrentModel(s32 nodeIndex) +CModel* CAnimationParameters::GetCurrentModel(s32 NodeIndex /*= -1*/) { if (!mpCharSet) return nullptr; if (mpCharSet->Type() != eAnimSet) return nullptr; - if (nodeIndex == -1) nodeIndex = mNodeIndex; + if (NodeIndex == -1) NodeIndex = mNodeIndex; - CAnimSet *pSet = static_cast(mpCharSet.RawPointer()); - if (pSet->getNodeCount() <= (u32) nodeIndex) return nullptr; - return pSet->getNodeModel(nodeIndex); + if (mpCharSet->getNodeCount() <= (u32) NodeIndex) return nullptr; + return mpCharSet->getNodeModel(NodeIndex); +} + +TString CAnimationParameters::GetCurrentCharacterName(s32 NodeIndex /*= -1*/) +{ + if (!mpCharSet) return ""; + if (mpCharSet->Type() != eAnimSet) return ""; + if (NodeIndex == -1) NodeIndex = mNodeIndex; + + if (mpCharSet->getNodeCount() <= (u32) NodeIndex) return ""; + return mpCharSet->getNodeName((u32) NodeIndex); } // ************ GETTERS ************ @@ -87,7 +96,7 @@ EGame CAnimationParameters::Version() return mGame; } -CResource* CAnimationParameters::Resource() +CAnimSet* CAnimationParameters::AnimSet() { return mpCharSet; } @@ -97,9 +106,9 @@ u32 CAnimationParameters::CharacterIndex() return mNodeIndex; } -u32 CAnimationParameters::Unknown(u32 index) +u32 CAnimationParameters::Unknown(u32 Index) { - switch (index) + switch (Index) { case 0: return mUnknown1; case 1: return mUnknown2; @@ -121,18 +130,18 @@ void CAnimationParameters::SetResource(CResource *pRes) Log::Error("Resource with invalid type passed to CAnimationParameters: " + pRes->Source()); } -void CAnimationParameters::SetNodeIndex(u32 index) +void CAnimationParameters::SetNodeIndex(u32 Index) { - mNodeIndex = index; + mNodeIndex = Index; } -void CAnimationParameters::SetUnknown(u32 index, u32 value) +void CAnimationParameters::SetUnknown(u32 Index, u32 Value) { - switch (index) + switch (Index) { - case 0: mUnknown1 = value; - case 1: mUnknown2 = value; - case 2: mUnknown3 = value; - case 3: mUnknown4 = value; + case 0: mUnknown1 = Value; + case 1: mUnknown2 = Value; + case 2: mUnknown3 = Value; + case 3: mUnknown4 = Value; } } diff --git a/src/Core/Resource/CAnimationParameters.h b/src/Core/Resource/CAnimationParameters.h index b4e5425f..d225fa0a 100644 --- a/src/Core/Resource/CAnimationParameters.h +++ b/src/Core/Resource/CAnimationParameters.h @@ -1,15 +1,15 @@ #ifndef CANIMATIONPARAMETERS_H #define CANIMATIONPARAMETERS_H -#include "CResource.h" -#include "TResPtr.h" +#include "CAnimSet.h" #include "EGame.h" +#include "TResPtr.h" #include "Core/Resource/Model/CModel.h" class CAnimationParameters { EGame mGame; - TResPtr mpCharSet; + TResPtr mpCharSet; u32 mNodeIndex; u32 mUnknown1; @@ -19,19 +19,20 @@ class CAnimationParameters public: CAnimationParameters(); - CAnimationParameters(IInputStream& SCLY, EGame game); - CModel* GetCurrentModel(s32 nodeIndex = -1); + CAnimationParameters(IInputStream& SCLY, EGame Game); + CModel* GetCurrentModel(s32 NodeIndex = -1); + TString GetCurrentCharacterName(s32 NodeIndex = -1); // Getters EGame Version(); - CResource* Resource(); + CAnimSet* AnimSet(); u32 CharacterIndex(); u32 Unknown(u32 index); // Setters void SetResource(CResource *pRes); - void SetNodeIndex(u32 index); - void SetUnknown(u32 index, u32 value); + void SetNodeIndex(u32 Index); + void SetUnknown(u32 Index, u32 Value); }; #endif // CANIMATIONPARAMETERS_H diff --git a/src/Core/Resource/Factory/CScriptLoader.cpp b/src/Core/Resource/Factory/CScriptLoader.cpp index 2315bcea..1f47d000 100644 --- a/src/Core/Resource/Factory/CScriptLoader.cpp +++ b/src/Core/Resource/Factory/CScriptLoader.cpp @@ -138,7 +138,7 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& SCLY) } case eCharacterProperty: { - TAnimParamsProperty *pAnimCast = static_cast(pProp); + TCharacterProperty *pAnimCast = static_cast(pProp); pAnimCast->Set(CAnimationParameters(SCLY, mVersion)); break; } diff --git a/src/Core/Resource/Factory/CTemplateLoader.cpp b/src/Core/Resource/Factory/CTemplateLoader.cpp index 647c3534..98c3a2ff 100644 --- a/src/Core/Resource/Factory/CTemplateLoader.cpp +++ b/src/Core/Resource/Factory/CTemplateLoader.cpp @@ -77,7 +77,7 @@ IPropertyTemplate* CTemplateLoader::LoadProperty(XMLElement *pElem, CStructTempl while (pParams) { TString ParamName = TString(pParams->Name()).ToLower(); - TString ParamVal = TString(pParams->GetText()).ToLower(); + TString ParamVal = TString(pParams->GetText()); // Load versions if (ParamName == "versions") diff --git a/src/Core/Resource/Script/CScriptObject.cpp b/src/Core/Resource/Script/CScriptObject.cpp index bac95965..39be98a8 100644 --- a/src/Core/Resource/Script/CScriptObject.cpp +++ b/src/Core/Resource/Script/CScriptObject.cpp @@ -12,7 +12,7 @@ CScriptObject::CScriptObject(CGameArea *pArea, CScriptLayer *pLayer, CScriptTemp , mHasInGameModel(false) { mpTemplate->AddObject(this); - mpProperties = (CPropertyStruct*) pTemplate->BaseStruct()->InstantiateProperty(); + mpProperties = (CPropertyStruct*) pTemplate->BaseStruct()->InstantiateProperty(nullptr); } CScriptObject::~CScriptObject() diff --git a/src/Core/Resource/Script/CScriptTemplate.cpp b/src/Core/Resource/Script/CScriptTemplate.cpp index aeb2a68c..31f32c2a 100644 --- a/src/Core/Resource/Script/CScriptTemplate.cpp +++ b/src/Core/Resource/Script/CScriptTemplate.cpp @@ -233,7 +233,7 @@ CModel* CScriptTemplate::FindDisplayModel(CPropertyStruct *pProperties) else if (pProp->Type() == eCharacterProperty) { - TAnimParamsProperty *pParams = static_cast(pProp); + TCharacterProperty *pParams = static_cast(pProp); pRes = pParams->Get().GetCurrentModel(it->ForceNodeIndex); } } @@ -332,7 +332,7 @@ bool CScriptTemplate::HasInGameModel(CPropertyStruct *pProperties) else if (pProp->Type() == eCharacterProperty) { - TAnimParamsProperty *pParams = static_cast(pProp); + TCharacterProperty *pParams = static_cast(pProp); pRes = pParams->Get().GetCurrentModel(it->ForceNodeIndex); } diff --git a/src/Core/Resource/Script/IProperty.cpp b/src/Core/Resource/Script/IProperty.cpp index 712bd771..2d6e9b7a 100644 --- a/src/Core/Resource/Script/IProperty.cpp +++ b/src/Core/Resource/Script/IProperty.cpp @@ -2,21 +2,26 @@ #include "IPropertyTemplate.h" // ************ IProperty ************ -IPropertyTemplate* IProperty::Template() +IPropertyTemplate* IProperty::Template() const { return mpTemplate; } -TString IProperty::Name() +TString IProperty::Name() const { return mpTemplate->Name(); } -u32 IProperty::ID() +u32 IProperty::ID() const { return mpTemplate->PropertyID(); } +TIDString IProperty::IDString(bool FullPath) const +{ + return mpTemplate->IDString(FullPath); +} + // ************ CPropertyStruct ************ CPropertyStruct::~CPropertyStruct() { @@ -24,12 +29,12 @@ CPropertyStruct::~CPropertyStruct() delete *it; } -IProperty* CPropertyStruct::PropertyByIndex(u32 index) +IProperty* CPropertyStruct::PropertyByIndex(u32 index) const { return mProperties[index]; } -IProperty* CPropertyStruct::PropertyByID(u32 ID) +IProperty* CPropertyStruct::PropertyByID(u32 ID) const { for (auto it = mProperties.begin(); it != mProperties.end(); it++) { @@ -39,7 +44,7 @@ IProperty* CPropertyStruct::PropertyByID(u32 ID) return nullptr; } -IProperty* CPropertyStruct::PropertyByIDString(const TIDString& rkStr) +IProperty* CPropertyStruct::PropertyByIDString(const TIDString& rkStr) const { // Resolve namespace u32 NSStart = rkStr.IndexOf(":"); @@ -68,7 +73,7 @@ IProperty* CPropertyStruct::PropertyByIDString(const TIDString& rkStr) } } -CPropertyStruct* CPropertyStruct::StructByIndex(u32 index) +CPropertyStruct* CPropertyStruct::StructByIndex(u32 index) const { IProperty *pProp = PropertyByIndex(index); @@ -78,7 +83,7 @@ CPropertyStruct* CPropertyStruct::StructByIndex(u32 index) return nullptr; } -CPropertyStruct* CPropertyStruct::StructByID(u32 ID) +CPropertyStruct* CPropertyStruct::StructByID(u32 ID) const { IProperty *pProp = PropertyByID(ID); @@ -88,7 +93,7 @@ CPropertyStruct* CPropertyStruct::StructByID(u32 ID) return nullptr; } -CPropertyStruct* CPropertyStruct::StructByIDString(const TIDString& rkStr) +CPropertyStruct* CPropertyStruct::StructByIDString(const TIDString& rkStr) const { IProperty *pProp = PropertyByIDString(rkStr); @@ -119,8 +124,8 @@ void CArrayProperty::Resize(u32 Size) } } -CStructTemplate* CArrayProperty::SubStructTemplate() +CStructTemplate* CArrayProperty::SubStructTemplate() const { - // CArrayTemplate inherits from CStructTemplate. It defines the substruct structure. + // CArrayTemplate inherits from CStructTemplate. The template defines the substruct structure. return static_cast(Template()); } diff --git a/src/Core/Resource/Script/IProperty.h b/src/Core/Resource/Script/IProperty.h index 208a5c2e..d290e27a 100644 --- a/src/Core/Resource/Script/IProperty.h +++ b/src/Core/Resource/Script/IProperty.h @@ -25,16 +25,29 @@ typedef TString TIDString; class IProperty { friend class CScriptLoader; -protected: - IPropertyTemplate *mpTemplate; -public: - IProperty(IPropertyTemplate *pTemp) : mpTemplate(pTemp) {} - virtual ~IProperty() {} - virtual EPropertyType Type() = 0; - IPropertyTemplate* Template(); - TString Name(); - u32 ID(); +protected: + class CPropertyStruct *mpParent; + IPropertyTemplate *mpTemplate; + +public: + IProperty(IPropertyTemplate *pTemp, CPropertyStruct *pParent) + : mpParent(pParent) + , mpTemplate(pTemp) + { + } + + virtual ~IProperty() {} + virtual EPropertyType Type() const = 0; + virtual TString ToString() const { return ""; } + + inline CPropertyStruct* Parent() const { return mpParent; } + + // These functions can't be in the header to avoid circular includes with IPropertyTemplate.h + IPropertyTemplate* Template() const; + TString Name() const; + u32 ID() const; + TIDString IDString(bool FullPath) const; }; /* @@ -46,15 +59,17 @@ class TTypedProperty : public IProperty friend class CScriptLoader; ValueClass mValue; public: - TTypedProperty(IPropertyTemplate *pTemp) - : IProperty(pTemp) {} + TTypedProperty(IPropertyTemplate *pTemp, CPropertyStruct *pParent) + : IProperty(pTemp, pParent) {} TTypedProperty(IPropertyTemplate *pTemp, PropType v) : IProperty(pTemp), mValue(v) {} ~TTypedProperty() {} - inline EPropertyType Type() { return TypeEnum; } - inline PropType Get() { return mValue.Get(); } + virtual EPropertyType Type() const { return TypeEnum; } + virtual TString ToString() const { return mValue.ToString(); } + + inline PropType Get() const { return mValue.Get(); } inline void Set(PropType v) { mValue.Set(v); } }; typedef TTypedProperty TBoolProperty; @@ -68,7 +83,7 @@ typedef TTypedProperty typedef TTypedProperty TVector3Property; typedef TTypedProperty TColorProperty; typedef TTypedProperty TFileProperty; -typedef TTypedProperty TAnimParamsProperty; +typedef TTypedProperty TCharacterProperty; typedef TTypedProperty, eUnknownProperty, CUnknownValue> TUnknownProperty; /* @@ -79,25 +94,25 @@ class CPropertyStruct : public IProperty friend class CScriptLoader; std::vector mProperties; public: - CPropertyStruct(IPropertyTemplate *pTemp) - : IProperty(pTemp) {} + CPropertyStruct(IPropertyTemplate *pTemp, CPropertyStruct *pParent) + : IProperty(pTemp, pParent) {} ~CPropertyStruct(); - EPropertyType Type() { return eStructProperty; } + EPropertyType Type() const { return eStructProperty; } // Inline - inline u32 Count() { return mProperties.size(); } + inline u32 Count() const { return mProperties.size(); } inline void AddSubProperty(IProperty *pProp) { mProperties.push_back(pProp); } inline IProperty* operator[](u32 index) { return mProperties[index]; } // Functions - IProperty* PropertyByIndex(u32 index); - IProperty* PropertyByID(u32 ID); - IProperty* PropertyByIDString(const TIDString& rkStr); - CPropertyStruct* StructByIndex(u32 index); - CPropertyStruct* StructByID(u32 ID); - CPropertyStruct* StructByIDString(const TIDString& rkStr); + IProperty* PropertyByIndex(u32 index) const; + IProperty* PropertyByID(u32 ID) const; + IProperty* PropertyByIDString(const TIDString& rkStr) const; + CPropertyStruct* StructByIndex(u32 index) const; + CPropertyStruct* StructByID(u32 ID) const; + CPropertyStruct* StructByIDString(const TIDString& rkStr) const; }; /* @@ -109,20 +124,25 @@ class CArrayProperty : public IProperty std::vector mSubStructs; public: - CArrayProperty(IPropertyTemplate *pTemp) - : IProperty(pTemp) {} + CArrayProperty(IPropertyTemplate *pTemp, CPropertyStruct *pParent) + : IProperty(pTemp, pParent) {} - EPropertyType Type() { return eArrayProperty; } + ~CArrayProperty() { + for (u32 iSub = 0; iSub < mSubStructs.size(); iSub++) + delete mSubStructs[iSub]; + } + + EPropertyType Type() const { return eArrayProperty; } // Inline - inline u32 Count() { return mSubStructs.size(); } + 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); } // Functions void Resize(u32 Size); - CStructTemplate* SubStructTemplate(); + CStructTemplate* SubStructTemplate() const; }; #endif // IPROPERTY diff --git a/src/Core/Resource/Script/IPropertyTemplate.h b/src/Core/Resource/Script/IPropertyTemplate.h index 0410a1ad..4c4c7031 100644 --- a/src/Core/Resource/Script/IPropertyTemplate.h +++ b/src/Core/Resource/Script/IPropertyTemplate.h @@ -66,9 +66,11 @@ public: { if (rkParamName == "should_cook") { - if (rkValue == "always") + TString lValue = rkValue.ToLower(); + + if (lValue == "always") mCookPreference = eAlwaysCook; - else if (rkValue == "never") + else if (lValue == "never") mCookPreference = eNeverCook; else mCookPreference = eNoCookPreference; @@ -78,7 +80,7 @@ public: mDescription = rkValue; } - virtual IProperty* InstantiateProperty() = 0; + virtual IProperty* InstantiateProperty(CPropertyStruct *pParent) = 0; inline TString Name() const { @@ -152,14 +154,14 @@ public: IPropertyTemplate::SetParam(rkParamName, rkValue); if (rkParamName == "default") - mDefaultValue.FromString(rkValue); + mDefaultValue.FromString(rkValue.ToLower()); } - virtual IProperty* InstantiateProperty() + virtual IProperty* InstantiateProperty(CPropertyStruct *pParent) { typedef TTypedProperty TPropertyType; - TPropertyType *pOut = new TPropertyType(this); + TPropertyType *pOut = new TPropertyType(this, pParent); pOut->Set(GetDefaultValue()); return pOut; } @@ -215,7 +217,7 @@ public: if (rkParamName == "range") { - TStringList Components = rkValue.Split(", "); + TStringList Components = rkValue.ToLower().Split(", "); if (Components.size() == 2) { @@ -271,9 +273,9 @@ public: virtual bool CanHaveDefault() const { return false; } virtual bool IsNumerical() const { return false; } - IProperty* InstantiateProperty() + IProperty* InstantiateProperty(CPropertyStruct *pParent) { - return new TFileProperty(this); + return new TFileProperty(this, pParent); } void SetAllowedExtensions(const TStringList& rkExtensions) @@ -342,9 +344,9 @@ public: virtual bool CanHaveDefault() const { return true; } virtual bool IsNumerical() const { return false; } - virtual IProperty* InstantiateProperty() + virtual IProperty* InstantiateProperty(CPropertyStruct *pParent) { - TEnumProperty *pEnum = new TEnumProperty(this); + TEnumProperty *pEnum = new TEnumProperty(this, pParent); u32 Index = EnumeratorIndex(GetDefaultValue()); pEnum->Set(Index); return pEnum; @@ -411,9 +413,9 @@ public: virtual bool CanHaveDefault() const { return true; } virtual bool IsNumerical() const { return false; } - virtual IProperty* InstantiateProperty() + virtual IProperty* InstantiateProperty(CPropertyStruct *pParent) { - TBitfieldProperty *pBitfield = new TBitfieldProperty(this); + TBitfieldProperty *pBitfield = new TBitfieldProperty(this, pParent); pBitfield->Set(GetDefaultValue()); return pBitfield; } @@ -466,13 +468,13 @@ public: bool CanHaveDefault() const { return false; } bool IsNumerical() const { return false; } - IProperty* InstantiateProperty() + IProperty* InstantiateProperty(CPropertyStruct *pParent) { - CPropertyStruct *pStruct = new CPropertyStruct(this); + CPropertyStruct *pStruct = new CPropertyStruct(this, pParent); for (u32 iSub = 0; iSub < mSubProperties.size(); iSub++) { - IProperty *pSubProp = mSubProperties[iSub]->InstantiateProperty(); + IProperty *pSubProp = mSubProperties[iSub]->InstantiateProperty(pStruct); pStruct->AddSubProperty(pSubProp); } @@ -516,14 +518,14 @@ public: EPropertyType Type() const { return eArrayProperty; } - IProperty* InstantiateProperty() + IProperty* InstantiateProperty(CPropertyStruct *pParent) { - return new CArrayProperty(this); + return new CArrayProperty(this, pParent); } CPropertyStruct* CreateSubStruct() { - return (CPropertyStruct*) CStructTemplate::InstantiateProperty(); + return (CPropertyStruct*) CStructTemplate::InstantiateProperty(nullptr); } }; diff --git a/src/Core/ScriptExtra/CDoorExtra.cpp b/src/Core/ScriptExtra/CDoorExtra.cpp index 47a965b3..7b48787c 100644 --- a/src/Core/ScriptExtra/CDoorExtra.cpp +++ b/src/Core/ScriptExtra/CDoorExtra.cpp @@ -72,7 +72,7 @@ void CDoorExtra::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo) { if (!mpShieldModel) return; if (ViewInfo.GameMode && !mpInstance->IsActive()) return; - if ((ViewInfo.ShowFlags & eShowObjectGeometry) == 0) return; + if (!ViewInfo.GameMode && ((ViewInfo.ShowFlags & eShowObjectGeometry) == 0)) return; if (mpParent->IsVisible() && ViewInfo.ViewFrustum.BoxInFrustum(AABox())) { diff --git a/src/Editor/Editor.pro b/src/Editor/Editor.pro index 993b49d1..a7ffe732 100644 --- a/src/Editor/Editor.pro +++ b/src/Editor/Editor.pro @@ -98,7 +98,6 @@ HEADERS += \ Widgets/WColorPicker.h \ Widgets/WDraggableSpinBox.h \ Widgets/WIntegralSpinBox.h \ - Widgets/WPropertyEditor.h \ Widgets/WResourceSelector.h \ Widgets/WRollout.h \ Widgets/WScanPreviewPanel.h \ @@ -130,7 +129,11 @@ HEADERS += \ Undo/CInvertSelectionCommand.h \ WorldEditor/CPoiMapEditDialog.h \ WorldEditor/CPoiMapModel.h \ - WorldEditor/CPoiListDialog.h + WorldEditor/CPoiListDialog.h \ + PropertyEdit/CPropertyModel.h \ + PropertyEdit/CPropertyDelegate.h \ + PropertyEdit/CPropertyView.h \ + PropertyEdit/CPropertyRelay.h # Source Files SOURCES += \ @@ -148,7 +151,6 @@ SOURCES += \ Widgets/WColorPicker.cpp \ Widgets/WDraggableSpinBox.cpp \ Widgets/WIntegralSpinBox.cpp \ - Widgets/WPropertyEditor.cpp \ Widgets/WResourceSelector.cpp \ Widgets/WRollout.cpp \ Widgets/WScanPreviewPanel.cpp \ @@ -180,7 +182,10 @@ SOURCES += \ Undo/CSelectAllCommand.cpp \ Undo/CInvertSelectionCommand.cpp \ WorldEditor/CPoiMapEditDialog.cpp \ - WorldEditor/CPoiMapModel.cpp + WorldEditor/CPoiMapModel.cpp \ + PropertyEdit/CPropertyModel.cpp \ + PropertyEdit/CPropertyDelegate.cpp \ + PropertyEdit/CPropertyView.cpp # UI Files FORMS += \ diff --git a/src/Editor/PropertyEdit/CPropertyDelegate.cpp b/src/Editor/PropertyEdit/CPropertyDelegate.cpp new file mode 100644 index 00000000..96bde034 --- /dev/null +++ b/src/Editor/PropertyEdit/CPropertyDelegate.cpp @@ -0,0 +1,547 @@ +#include "CPropertyDelegate.h" +#include "CPropertyRelay.h" + +#include "Editor/UICommon.h" +#include "Editor/Widgets/WColorPicker.h" +#include "Editor/Widgets/WDraggableSpinBox.h" +#include "Editor/Widgets/WIntegralSpinBox.h" +#include "Editor/Widgets/WResourceSelector.h" + +#include +#include + +#include +#include +#include +#include + +// This macro should be used on every widget where changes should be reflected in realtime and not just when the edit is finished. +#define CONNECT_RELAY(Widget, Index, Signal) \ + CPropertyRelay *pRelay = new CPropertyRelay(Widget, Index); \ + connect(Widget, SIGNAL(Signal), pRelay, SLOT(OnWidgetEdited())); \ + connect(pRelay, SIGNAL(WidgetEdited(QWidget*, const QModelIndex&)), this, SLOT(WidgetEdited(QWidget*, const QModelIndex&))); + +CPropertyDelegate::CPropertyDelegate(QObject *pParent /*= 0*/) + : QStyledItemDelegate(pParent) + , mpModel(nullptr) +{ +} + +void CPropertyDelegate::SetModel(CPropertyModel *pModel) +{ + mpModel = pModel; +} + +QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionViewItem& /*rkOption*/, const QModelIndex& rkIndex) const +{ + if (!mpModel) return nullptr; + IProperty *pProp = mpModel->PropertyForIndex(rkIndex, false); + QWidget *pOut = nullptr; + + if (pProp) + { + switch (pProp->Type()) + { + case eBoolProperty: + pOut = new QCheckBox(pParent); + break; + + case eShortProperty: + case eLongProperty: + pOut = new WIntegralSpinBox(pParent); + break; + + case eFloatProperty: + { + WDraggableSpinBox *pSpinBox = new WDraggableSpinBox(pParent); + CONNECT_RELAY(pSpinBox, rkIndex, valueChanged(double)) + pSpinBox->setSingleStep(0.1); + pOut = pSpinBox; + break; + } + + case eColorProperty: + { + WColorPicker *pColorPicker = new WColorPicker(pParent); + CONNECT_RELAY(pColorPicker, rkIndex, colorChanged(QColor)) + pOut = pColorPicker; + break; + } + + case eStringProperty: + pOut = new QLineEdit(pParent); + break; + + case eEnumProperty: + { + QComboBox *pComboBox = new QComboBox(pParent); + CEnumTemplate *pTemp = static_cast(pProp->Template()); + + for (u32 iEnum = 0; iEnum < pTemp->NumEnumerators(); iEnum++) + pComboBox->addItem(TO_QSTRING(pTemp->EnumeratorName(iEnum))); + + pOut = pComboBox; + break; + } + + case eFileProperty: + { + WResourceSelector *pSelector = new WResourceSelector(pParent); + CFileTemplate *pTemp = static_cast(pProp->Template()); + pSelector->SetAllowedExtensions(pTemp->Extensions()); + pOut = pSelector; + break; + } + + } + } + + // Check for sub-property of vector/color/character + else if (rkIndex.internalId() & 0x1) + { + pProp = mpModel->PropertyForIndex(rkIndex, true); + + // Handle character + if (pProp->Type() == eCharacterProperty) + pOut = CreateCharacterEditor(pParent, rkIndex); + + // Handle bitfield + else if (pProp->Type() == eBitfieldProperty) + pOut = new QCheckBox(pParent); + + // Handle vector/color + else + { + WDraggableSpinBox *pSpinBox = new WDraggableSpinBox(pParent); + CONNECT_RELAY(pSpinBox, rkIndex, valueChanged(double)) + pSpinBox->setSingleStep(0.1); + + // Limit to range of 0-1 on colors + pProp = mpModel->PropertyForIndex(rkIndex, true); + + if (pProp->Type() == eColorProperty) + { + pSpinBox->setMinimum(0.0); + pSpinBox->setMaximum(1.0); + } + + pOut = pSpinBox; + } + } + + if (pOut) + { + pOut->setFocusPolicy(Qt::StrongFocus); + } + + return pOut; +} + +void CPropertyDelegate::setEditorData(QWidget *pEditor, const QModelIndex &rkIndex) const +{ + if (pEditor) + { + // Set editor data for regular property + IProperty *pProp = mpModel->PropertyForIndex(rkIndex, false); + + if (pProp) + { + switch (pProp->Type()) + { + + case eBoolProperty: + { + QCheckBox *pCheckBox = static_cast(pEditor); + TBoolProperty *pBool = static_cast(pProp); + pCheckBox->setChecked(pBool->Get()); + break; + } + + case eShortProperty: + { + WIntegralSpinBox *pSpinBox = static_cast(pEditor); + TShortProperty *pShort = static_cast(pProp); + pSpinBox->setValue(pShort->Get()); + break; + } + + + case eLongProperty: + { + WIntegralSpinBox *pSpinBox = static_cast(pEditor); + TLongProperty *pLong = static_cast(pProp); + pSpinBox->setValue(pLong->Get()); + break; + } + + case eFloatProperty: + { + WDraggableSpinBox *pSpinBox = static_cast(pEditor); + TFloatProperty *pFloat = static_cast(pProp); + pSpinBox->setValue(pFloat->Get()); + break; + } + + case eColorProperty: + { + WColorPicker *pColorPicker = static_cast(pEditor); + TColorProperty *pColor = static_cast(pProp); + + CColor SrcColor = pColor->Get(); + QColor Color; + Color.setRed(SrcColor.r * 255); + Color.setGreen(SrcColor.g * 255); + Color.setBlue(SrcColor.b * 255); + Color.setAlpha(SrcColor.a * 255); + + pColorPicker->setColor(Color); + break; + } + + case eStringProperty: + { + QLineEdit *pLineEdit = static_cast(pEditor); + TStringProperty *pString = static_cast(pProp); + pLineEdit->setText(TO_QSTRING(pString->Get())); + break; + } + + case eEnumProperty: + { + QComboBox *pComboBox = static_cast(pEditor); + TEnumProperty *pEnum = static_cast(pProp); + pComboBox->setCurrentIndex(pEnum->Get()); + break; + } + + case eFileProperty: + { + WResourceSelector *pSelector = static_cast(pEditor); + TFileProperty *pFile = static_cast(pProp); + pSelector->SetResource(pFile->Get()); + break; + } + + } + } + + // Set editor data for character/bitfield/vector/color sub-property + else if (rkIndex.internalId() & 0x1) + { + pProp = mpModel->PropertyForIndex(rkIndex, true); + + if (pProp->Type() == eCharacterProperty) + SetCharacterEditorData(pEditor, rkIndex); + + else if (pProp->Type() == eBitfieldProperty) + { + QCheckBox *pCheckBox = static_cast(pEditor); + TBitfieldProperty *pBitfield = static_cast(pProp); + u32 Mask = static_cast(pBitfield->Template())->FlagMask(rkIndex.row()); + bool Set = (pBitfield->Get() & Mask) != 0; + pCheckBox->setChecked(Set); + } + + else + { + WDraggableSpinBox *pSpinBox = static_cast(pEditor); + float Value; + + if (pProp->Type() == eVector3Property) + { + TVector3Property *pVector = static_cast(pProp); + CVector3f Vector = pVector->Get(); + + if (rkIndex.row() == 0) Value = Vector.x; + if (rkIndex.row() == 1) Value = Vector.y; + if (rkIndex.row() == 2) Value = Vector.z; + } + + else if (pProp->Type() == eColorProperty) + { + TColorProperty *pColor = static_cast(pProp); + CColor Color = pColor->Get(); + + if (rkIndex.row() == 0) Value = Color.r; + if (rkIndex.row() == 1) Value = Color.g; + if (rkIndex.row() == 2) Value = Color.b; + if (rkIndex.row() == 3) Value = Color.a; + } + + pSpinBox->setValue((double) Value); + } + } + } +} + +void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pModel*/, const QModelIndex &rkIndex) const +{ + if (!mpModel) return; + if (!pEditor) return; + + IProperty *pProp = mpModel->PropertyForIndex(rkIndex, false); + + if (pProp) + { + switch (pProp->Type()) + { + + case eBoolProperty: + { + QCheckBox *pCheckBox = static_cast(pEditor); + TBoolProperty *pBool = static_cast(pProp); + pBool->Set(pCheckBox->isChecked()); + break; + } + + case eShortProperty: + { + WIntegralSpinBox *pSpinBox = static_cast(pEditor); + TShortProperty *pShort = static_cast(pProp); + pShort->Set(pSpinBox->value()); + break; + } + + case eLongProperty: + { + WIntegralSpinBox *pSpinBox = static_cast(pEditor); + TLongProperty *pLong = static_cast(pProp); + pLong->Set(pSpinBox->value()); + break; + } + + case eFloatProperty: + { + WDraggableSpinBox *pSpinBox = static_cast(pEditor); + TFloatProperty *pFloat = static_cast(pProp); + pFloat->Set((float) pSpinBox->value()); + break; + } + + case eColorProperty: + { + WColorPicker *pColorPicker = static_cast(pEditor); + TColorProperty *pColor = static_cast(pProp); + + QColor SrcColor = pColorPicker->getColor(); + CColor Color; + Color.r = SrcColor.red() / 255.f; + Color.g = SrcColor.green() / 255.f; + 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; + } + + case eStringProperty: + { + QLineEdit *pLineEdit = static_cast(pEditor); + TStringProperty *pString = static_cast(pProp); + pString->Set(TO_TSTRING(pLineEdit->text())); + break; + } + + case eEnumProperty: + { + QComboBox *pComboBox = static_cast(pEditor); + TEnumProperty *pEnum = static_cast(pProp); + pEnum->Set(pComboBox->currentIndex()); + break; + } + + } + } + + // Check for character/bitfield/vector/color sub-properties + else if (rkIndex.internalId() & 0x1) + { + pProp = mpModel->PropertyForIndex(rkIndex, true); + + if (pProp->Type() == eCharacterProperty) + SetCharacterModelData(pEditor, rkIndex); + + else if (pProp->Type() == eBitfieldProperty) + { + QCheckBox *pCheckBox = static_cast(pEditor); + TBitfieldProperty *pBitfield = static_cast(pProp); + u32 Mask = static_cast(pProp->Template())->FlagMask(rkIndex.row()); + + int Flags = pBitfield->Get(); + if (pCheckBox->isChecked()) Flags |= Mask; + else Flags &= ~Mask; + pBitfield->Set(Flags); + } + + else + { + WDraggableSpinBox *pSpinBox = static_cast(pEditor); + + if (pProp->Type() == eVector3Property) + { + TVector3Property *pVector = static_cast(pProp); + CVector3f Value = pVector->Get(); + + if (rkIndex.row() == 0) Value.x = (float) pSpinBox->value(); + if (rkIndex.row() == 1) Value.y = (float) pSpinBox->value(); + if (rkIndex.row() == 2) Value.z = (float) pSpinBox->value(); + + pVector->Set(Value); + } + + else if (pProp->Type() == eColorProperty) + { + TColorProperty *pColor = static_cast(pProp); + CColor Value = pColor->Get(); + + if (rkIndex.row() == 0) Value.r = (float) pSpinBox->value(); + if (rkIndex.row() == 1) Value.g = (float) pSpinBox->value(); + if (rkIndex.row() == 2) Value.b = (float) pSpinBox->value(); + if (rkIndex.row() == 3) Value.a = (float) pSpinBox->value(); + + pColor->Set(Value); + } + + mpModel->dataChanged(rkIndex.parent(), rkIndex.parent()); + } + } +} + +bool CPropertyDelegate::eventFilter(QObject *pObject, QEvent *pEvent) +{ + if (pEvent->type() == QEvent::Wheel) + { + QWidget *pWidget = static_cast(pObject); + + if (!pWidget->hasFocus()) + return true; + + pEvent->ignore(); + return false; + } + + return QStyledItemDelegate::eventFilter(pObject, pEvent); +} + +// Character properties have separate functions because they're somewhat complicated - they have different layouts in different games +QWidget* CPropertyDelegate::CreateCharacterEditor(QWidget *pParent, const QModelIndex& rkIndex) const +{ + TCharacterProperty *pProp = static_cast(mpModel->PropertyForIndex(rkIndex, true)); + CAnimationParameters Params = pProp->Get(); + + // Determine property type + EPropertyType Type = DetermineCharacterPropType(Params.Version(), rkIndex); + if (Type == eUnknownProperty) return nullptr; + + // Create widget + if (Type == eFileProperty) + { + WResourceSelector *pSelector = new WResourceSelector(pParent); + + if (Params.Version() <= eEchoes) + pSelector->SetAllowedExtensions("ANCS"); + else + pSelector->SetAllowedExtensions("CHAR"); + + return pSelector; + } + + if (Type == eEnumProperty) + { + QComboBox *pComboBox = new QComboBox(pParent); + CAnimSet *pAnimSet = Params.AnimSet(); + + if (pAnimSet) + { + for (u32 iChr = 0; iChr < pAnimSet->getNodeCount(); iChr++) + pComboBox->addItem(TO_QSTRING(pAnimSet->getNodeName(iChr))); + } + + return pComboBox; + } + + if (Type == eLongProperty) + return new WIntegralSpinBox(pParent); + + return nullptr; +} + +void CPropertyDelegate::SetCharacterEditorData(QWidget *pEditor, const QModelIndex& rkIndex) const +{ + TCharacterProperty *pProp = static_cast(mpModel->PropertyForIndex(rkIndex, true)); + CAnimationParameters Params = pProp->Get(); + EPropertyType Type = DetermineCharacterPropType(Params.Version(), rkIndex); + + if (Type == eFileProperty) + { + static_cast(pEditor)->SetResource(Params.AnimSet()); + } + + else if (Type == eEnumProperty) + { + static_cast(pEditor)->setCurrentIndex(Params.CharacterIndex()); + } + + else if (Type == eLongProperty) + { + int UnkIndex = (Params.Version() <= eEchoes ? rkIndex.row() - 2 : rkIndex.row() - 1); + u32 Value = Params.Unknown(UnkIndex); + static_cast(pEditor)->setValue(Value); + } +} + +void CPropertyDelegate::SetCharacterModelData(QWidget *pEditor, const QModelIndex& rkIndex) const +{ + TCharacterProperty *pProp = static_cast(mpModel->PropertyForIndex(rkIndex, true)); + CAnimationParameters Params = pProp->Get(); + EPropertyType Type = DetermineCharacterPropType(Params.Version(), rkIndex); + + if (Type == eFileProperty) + { + Params.SetResource( static_cast(pEditor)->GetResource() ); + } + + else if (Type == eEnumProperty) + { + Params.SetNodeIndex( static_cast(pEditor)->currentIndex() ); + } + + else if (Type == eLongProperty) + { + int UnkIndex = (Params.Version() <= eEchoes ? rkIndex.row() - 2 : rkIndex.row() - 1); + Params.SetUnknown(UnkIndex, static_cast(pEditor)->value() ); + } + + pProp->Set(Params); +} + +EPropertyType CPropertyDelegate::DetermineCharacterPropType(EGame Game, const QModelIndex& rkIndex) const +{ + if (Game <= eEchoes) + { + if (rkIndex.row() == 0) return eFileProperty; + else if (rkIndex.row() == 1) return eEnumProperty; + else if (rkIndex.row() == 2) return eLongProperty; + } + else if (Game <= eCorruption) + { + if (rkIndex.row() == 0) return eFileProperty; + else if (rkIndex.row() == 1) return eLongProperty; + } + else + { + if (rkIndex.row() == 0) return eFileProperty; + else if (rkIndex.row() <= 3) return eLongProperty; + } + return eUnknownProperty; +} + +// ************ PUBLIC SLOTS ************ +void CPropertyDelegate::WidgetEdited(QWidget *pWidget, const QModelIndex& rkIndex) +{ + // 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. + setModelData(pWidget, mpModel, rkIndex); +} diff --git a/src/Editor/PropertyEdit/CPropertyDelegate.h b/src/Editor/PropertyEdit/CPropertyDelegate.h new file mode 100644 index 00000000..45080c01 --- /dev/null +++ b/src/Editor/PropertyEdit/CPropertyDelegate.h @@ -0,0 +1,30 @@ +#ifndef CPROPERTYDELEGATE_H +#define CPROPERTYDELEGATE_H + +#include +#include "CPropertyModel.h" + +class CPropertyDelegate : public QStyledItemDelegate +{ + Q_OBJECT + + CPropertyModel *mpModel; + +public: + CPropertyDelegate(QObject *pParent = 0); + void SetModel(CPropertyModel *pModel); + 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; + bool eventFilter(QObject *pObject, QEvent *pEvent); + + QWidget* CreateCharacterEditor(QWidget *pParent, const QModelIndex& rkIndex) const; + void SetCharacterEditorData(QWidget *pEditor, const QModelIndex& rkIndex) const; + void SetCharacterModelData(QWidget *pEditor, const QModelIndex& rkIndex) const; + EPropertyType DetermineCharacterPropType(EGame Game, const QModelIndex& rkIndex) const; + +public slots: + void WidgetEdited(QWidget *pWidget, const QModelIndex& rkIndex); +}; + +#endif // CPROPERTYDELEGATE_H diff --git a/src/Editor/PropertyEdit/CPropertyModel.cpp b/src/Editor/PropertyEdit/CPropertyModel.cpp new file mode 100644 index 00000000..e26a833f --- /dev/null +++ b/src/Editor/PropertyEdit/CPropertyModel.cpp @@ -0,0 +1,345 @@ +#include "CPropertyModel.h" +#include "Editor/UICommon.h" +#include +#include +#include + +CPropertyModel::CPropertyModel(QObject *pParent /*= 0*/) + : QAbstractItemModel(pParent) + , mpBaseStruct(nullptr) +{ +} + +void CPropertyModel::SetBaseStruct(CPropertyStruct *pBaseStruct) +{ + beginResetModel(); + mpBaseStruct = pBaseStruct; + endResetModel(); +} + +IProperty* CPropertyModel::PropertyForIndex(const QModelIndex& rkIndex, bool HandleFlaggedPointers) const +{ + if (!rkIndex.isValid()) return mpBaseStruct; + + if (rkIndex.internalId() & 0x1) + { + if (HandleFlaggedPointers) + { + void *pID = (void*) (rkIndex.internalId() & ~0x1); + return static_cast(pID); + } + else + return nullptr; + } + + return static_cast(rkIndex.internalPointer()); +} + +int CPropertyModel::columnCount(const QModelIndex& /*rkParent*/) const +{ + return 2; +} + +int CPropertyModel::rowCount(const QModelIndex& rkParent) const +{ + if (!mpBaseStruct) return 0; + if (rkParent.internalId() & 0x1) return 0; + IProperty *pProp = PropertyForIndex(rkParent, false); + if (pProp == mpBaseStruct) return mpBaseStruct->Count(); + + switch (pProp->Type()) + { + case eStructProperty: + return static_cast(pProp)->Count(); + + case eBitfieldProperty: + return static_cast(pProp->Template())->NumFlags(); + + case eVector3Property: + return 3; + + case eColorProperty: + return 4; + + case eCharacterProperty: + { + CAnimationParameters Params = static_cast(pProp)->Get(); + if (Params.Version() <= eEchoes) return 3; + if (Params.Version() <= eCorruption) return 2; + return 5; + } + + default: + return 0; + } +} + +QVariant CPropertyModel::headerData(int Section, Qt::Orientation Orientation, int Role) const +{ + if (Orientation == Qt::Horizontal && Role == Qt::DisplayRole) + { + if (Section == 0) return "Name"; + if (Section == 1) return "Value"; + } + return QVariant::Invalid; +} + +QVariant CPropertyModel::data(const QModelIndex& rkIndex, int Role) const +{ + if (!rkIndex.isValid()) + return QVariant::Invalid; + + if (Role == Qt::DisplayRole || (Role == Qt::ToolTipRole && rkIndex.column() == 1) ) + { + if (rkIndex.internalId() & 0x1) + { + IProperty *pProp = PropertyForIndex(rkIndex, true); + + if (pProp->Type() == eColorProperty) + { + if (rkIndex.column() == 0) + { + if (rkIndex.row() == 0) return "R"; + if (rkIndex.row() == 1) return "G"; + if (rkIndex.row() == 2) return "B"; + if (rkIndex.row() == 3) return "A"; + } + + else if (rkIndex.column() == 1) + { + TStringList Strings = pProp->ToString().Split(" ,"); + + int i = 0; + for (auto it = Strings.begin(); it != Strings.end(); it++) + { + if (i == rkIndex.row()) return TO_QSTRING(*it); + i++; + } + } + } + + else if (pProp->Type() == eVector3Property) + { + if (rkIndex.column() == 0) + { + if (rkIndex.row() == 0) return "X"; + if (rkIndex.row() == 1) return "Y"; + if (rkIndex.row() == 2) return "Z"; + } + + else if (rkIndex.column() == 1) + { + TStringList Strings = pProp->ToString().Split(" ,"); + + int i = 0; + for (auto it = Strings.begin(); it != Strings.end(); it++) + { + if (i == rkIndex.row()) return TO_QSTRING(*it); + i++; + } + } + } + + else if (pProp->Type() == eBitfieldProperty) + { + CBitfieldTemplate *pBitfield = static_cast(pProp->Template()); + + if (rkIndex.column() == 0) + return TO_QSTRING(pBitfield->FlagName(rkIndex.row())); + + if (rkIndex.column() == 1) + { + if (Role == Qt::DisplayRole) + return ""; + else + return TO_QSTRING(TString::HexString(pBitfield->FlagMask(rkIndex.row()), true, true, 8)); + } + } + + else if (pProp->Type() == eCharacterProperty) + { + TCharacterProperty *pChar = static_cast(pProp); + CAnimationParameters Params = pChar->Get(); + + // There are three different layouts for this property - one for MP1/2, one for MP3, and one for DKCR + if (Params.Version() <= eEchoes) + { + if (rkIndex.column() == 0) + { + if (rkIndex.row() == 0) return "AnimSet"; + if (rkIndex.row() == 1) return "Character"; + if (rkIndex.row() == 2) return "Default Anim"; + } + + // For column 1, rows 0/1 have persistent editors so we only handle 2 + if (rkIndex.column() == 1 && rkIndex.row() == 2) + return QString::number(Params.Unknown(0)); + } + + else if (Params.Version() <= eCorruption) + { + if (rkIndex.column() == 0) + { + if (rkIndex.row() == 0) return "Character"; + if (rkIndex.row() == 1) return "Default Anim"; + } + + // Same deal here, only handle row 1 + if (rkIndex.column() == 1 && rkIndex.row() == 1) + return QString::number(Params.Unknown(0)); + } + + else + { + if (rkIndex.column() == 0) + { + if (rkIndex.row() == 0) return "Character"; + else return "Unknown " + QString::number(rkIndex.row()); + } + + if (rkIndex.column() == 1 && rkIndex.row() > 0) + return QString::number(Params.Unknown(rkIndex.row() - 1)); + } + } + } + + else + { + IProperty *pProp = PropertyForIndex(rkIndex, false); + + if (rkIndex.column() == 0) + return TO_QSTRING(pProp->Name()); + + if (rkIndex.column() == 1) + { + switch (pProp->Type()) + { + // Enclose vector property text in parentheses + case eVector3Property: + return "(" + TO_QSTRING(pProp->ToString()) + ")"; + + // Display character name for characters + case eCharacterProperty: + return TO_QSTRING(static_cast(pProp)->Get().GetCurrentCharacterName()); + + // Display enumerator name for enums (but only on ToolTipRole) + case eEnumProperty: + if (Role == Qt::ToolTipRole) + { + TEnumProperty *pEnum = static_cast(pProp); + CEnumTemplate *pTemp = static_cast(pEnum->Template()); + return TO_QSTRING(pTemp->EnumeratorName(pEnum->Get())); + } + else return ""; + + // No display text on properties with persistent editors + case eBoolProperty: + case eFileProperty: + case eColorProperty: + if (Role == Qt::DisplayRole) + return ""; + // fall through + // Display property value to string for everything else + default: + return TO_QSTRING(pProp->ToString()); + } + } + } + } + + if (Role == Qt::ToolTipRole && rkIndex.column() == 0) + { + if (!(rkIndex.internalId() & 0x1)) + { + IProperty *pProp = PropertyForIndex(rkIndex, false); + QString Text = QString("%1 (%2)").arg(TO_QSTRING(pProp->Name())).arg(TO_QSTRING(PropEnumToPropString(pProp->Type()))); + TString Desc = pProp->Template()->Description(); + if (!Desc.IsEmpty()) Text += "
" + TO_QSTRING(Desc); + return Text; + } + } + + if (Role == Qt::SizeHintRole) + { + return QSize(0, 23); + } + + return QVariant::Invalid; +} + +QModelIndex CPropertyModel::index(int Row, int Column, const QModelIndex& rkParent) const +{ + // Invalid index + 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); + + // Struct + if (pParent->Type() == eStructProperty) + { + IProperty *pProp = static_cast(pParent)->PropertyByIndex(Row); + 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 QModelIndex(); +} + +QModelIndex CPropertyModel::parent(const QModelIndex& rkChild) const +{ + // Invalid index + if (!rkChild.isValid()) + return QModelIndex(); + + // Find parent property + IProperty *pParent; + + if (rkChild.internalId() & 0x1) + pParent = PropertyForIndex(rkChild, true); + else + pParent = PropertyForIndex(rkChild, false)->Parent(); + + if (pParent == mpBaseStruct) + return QModelIndex(); + + // Iterate over grandfather properties until we find the row + CPropertyStruct *pGrandparent = pParent->Parent(); + + for (u32 iProp = 0; iProp < pGrandparent->Count(); iProp++) + { + if (pGrandparent->PropertyByIndex(iProp) == pParent) + return createIndex(iProp, rkChild.column(), pParent); + } + + return QModelIndex(); +} + +Qt::ItemFlags CPropertyModel::flags(const QModelIndex& rkIndex) const +{ + if (rkIndex.column() == 0) return Qt::ItemIsEnabled; + else return (Qt::ItemIsEnabled | Qt::ItemIsEditable); +} + +void CPropertyModel::UpdateSubProperties(const QModelIndex& rkIndex) +{ + IProperty *pProp = PropertyForIndex(rkIndex, false); + + if (pProp) + { + QVector 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); + } +} diff --git a/src/Editor/PropertyEdit/CPropertyModel.h b/src/Editor/PropertyEdit/CPropertyModel.h new file mode 100644 index 00000000..9714e3f8 --- /dev/null +++ b/src/Editor/PropertyEdit/CPropertyModel.h @@ -0,0 +1,28 @@ +#ifndef CPROPERTYMODEL_H +#define CPROPERTYMODEL_H + +#include +#include + +class CPropertyModel : public QAbstractItemModel +{ + Q_OBJECT + + CPropertyStruct *mpBaseStruct; + +public: + CPropertyModel(QObject *pParent = 0); + void SetBaseStruct(CPropertyStruct *pBaseStruct); + IProperty* PropertyForIndex(const QModelIndex& rkIndex, bool HandleFlaggedPointers) const; + + int columnCount(const QModelIndex& rkParent) const; + int rowCount(const QModelIndex& rkParent) const; + QVariant headerData(int Section, Qt::Orientation Orientation, int Role) const; + QVariant data(const QModelIndex& rkIndex, int Role) const; + 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); +}; + +#endif // CPROPERTYMODEL_H diff --git a/src/Editor/PropertyEdit/CPropertyRelay.h b/src/Editor/PropertyEdit/CPropertyRelay.h new file mode 100644 index 00000000..a38538fb --- /dev/null +++ b/src/Editor/PropertyEdit/CPropertyRelay.h @@ -0,0 +1,29 @@ +#ifndef TWIDGETWRAPPER +#define TWIDGETWRAPPER + +#include +#include + +// Small class that associates a QWidget with a QModelIndex and relays widget signals back to the delegate +// so that property edits can be reflected in other parts of the application in realtime instead of when the +// widget is done being edited. +class CPropertyRelay : public QObject +{ + Q_OBJECT + + QModelIndex mIndex; + QWidget *mpWidget; + +public: + CPropertyRelay(QWidget *pWidget, const QModelIndex& rkIndex) + : QObject(pWidget), mIndex(rkIndex), mpWidget(pWidget) {} + +public slots: + void OnWidgetEdited() { emit WidgetEdited(mpWidget, mIndex); } + +signals: + void WidgetEdited(QWidget *pWidget, const QModelIndex& rkIndex); +}; + +#endif // TWIDGETWRAPPER + diff --git a/src/Editor/PropertyEdit/CPropertyView.cpp b/src/Editor/PropertyEdit/CPropertyView.cpp new file mode 100644 index 00000000..3225e204 --- /dev/null +++ b/src/Editor/PropertyEdit/CPropertyView.cpp @@ -0,0 +1,110 @@ +#include "CPropertyView.h" +#include "CPropertyDelegate.h" +#include +#include +#include + +CPropertyView::CPropertyView(QWidget *pParent) + : QTreeView(pParent) +{ + mpModel = new CPropertyModel(this); + mpDelegate = new CPropertyDelegate(this); + setItemDelegateForColumn(1, mpDelegate); + setEditTriggers(AllEditTriggers); + setModel(mpModel); +} + +void CPropertyView::setModel(QAbstractItemModel *pModel) +{ + CPropertyModel *pPropModel = qobject_cast(pModel); + mpModel = pPropModel; + mpDelegate->SetModel(pPropModel); + QTreeView::setModel(pPropModel); + + if (pPropModel) + { + QModelIndex Root = pPropModel->index(0, 0, QModelIndex()); + SetPersistentEditors(Root); + setExpanded(Root, true); + } +} + +bool CPropertyView::event(QEvent *pEvent) +{ + if (pEvent->type() == QEvent::ToolTip) + { + QPoint MousePos = mapFromGlobal(QCursor::pos()); + QModelIndex Index = indexAt(MousePos); + QString Desc = mpModel->data(Index, Qt::ToolTipRole).toString(); + + if (!Desc.isEmpty()) + { + QToolTip::showText(MousePos, Desc, this); + pEvent->accept(); + } + else + { + QToolTip::hideText(); + pEvent->ignore(); + } + + return true; + } + + else return QTreeView::event(pEvent); +} + +void CPropertyView::SetBaseStruct(CPropertyStruct *pStruct) +{ + mpModel->SetBaseStruct(pStruct); + SetPersistentEditors(QModelIndex()); + + // Auto-expand EditorProperties + QModelIndex Index = mpModel->index(0, 0, QModelIndex()); + IProperty *pProp = mpModel->PropertyForIndex(Index, false); + if (pProp && pProp->ID() == 0x255A4580) + expand(Index); +} + +void CPropertyView::SetPersistentEditors(const QModelIndex& rkParent) +{ + u32 NumChildren = mpModel->rowCount(rkParent); + + for (u32 iChild = 0; iChild < NumChildren; iChild++) + { + QModelIndex ChildIndex = mpModel->index(iChild, 1, rkParent); + IProperty *pProp = mpModel->PropertyForIndex(ChildIndex, false); + EPropertyType Type = (pProp ? pProp->Type() : eInvalidProperty); + + // Handle persistent editors under character properties + if (!pProp && ChildIndex.internalId() & 0x1) + { + pProp = mpModel->PropertyForIndex(ChildIndex, true); + + if (pProp->Type() == eCharacterProperty) + { + EGame Game = static_cast(pProp)->Get().Version(); + Type = mpDelegate->DetermineCharacterPropType(Game, ChildIndex); + } + + if (pProp->Type() == eBitfieldProperty) + Type = eBoolProperty; + } + + switch (Type) + { + case eBoolProperty: + case eEnumProperty: + case eColorProperty: + case eFileProperty: + openPersistentEditor(ChildIndex); + break; + case eStructProperty: + setFirstColumnSpanned(iChild, rkParent, true); + break; + } + + SetPersistentEditors(ChildIndex); + } +} + diff --git a/src/Editor/PropertyEdit/CPropertyView.h b/src/Editor/PropertyEdit/CPropertyView.h new file mode 100644 index 00000000..6af5e081 --- /dev/null +++ b/src/Editor/PropertyEdit/CPropertyView.h @@ -0,0 +1,23 @@ +#ifndef CPROPERTYVIEW_H +#define CPROPERTYVIEW_H + +#include "CPropertyModel.h" +#include "CPropertyDelegate.h" +#include + +class CPropertyView : public QTreeView +{ + Q_OBJECT + + CPropertyModel *mpModel; + CPropertyDelegate *mpDelegate; + +public: + CPropertyView(QWidget *pParent = 0); + void setModel(QAbstractItemModel *pModel); + bool event(QEvent *pEvent); + void SetBaseStruct(CPropertyStruct *pStruct); + void SetPersistentEditors(const QModelIndex& rkParent); +}; + +#endif // CPROPERTYVIEW_H diff --git a/src/Editor/TestDialog.cpp b/src/Editor/TestDialog.cpp index eb22d7fa..4fa08be6 100644 --- a/src/Editor/TestDialog.cpp +++ b/src/Editor/TestDialog.cpp @@ -1,9 +1,13 @@ #include "TestDialog.h" #include "ui_TestDialog.h" +#include "Editor/PropertyEdit/CPropertyDelegate.h" #include "Editor/Widgets/WResourceSelector.h" #include "Editor/Widgets/WTextureGLWidget.h" #include #include +#include +#include +#include #include @@ -13,8 +17,13 @@ TestDialog::TestDialog(QWidget *parent) : { ui->setupUi(this); - CTexture *pTex = CTextureDecoder::LoadDDS(CFileInStream("E:/test2.dds", IOUtil::eLittleEndian)); - ui->widget->SetTexture(pTex); + CTemplateLoader::LoadGameTemplates(eCorruption); + CMasterTemplate *pMaster = CMasterTemplate::GetMasterForGame(eCorruption); + CScriptTemplate *pTemp = pMaster->TemplateByID("PCKP"); + + CPropertyStruct *pBase = static_cast(pTemp->BaseStruct()->InstantiateProperty(nullptr)); + ui->treeView->setItemDelegate(new CPropertyDelegate(ui->treeView)); + ui->treeView->SetBaseStruct(pBase); } TestDialog::~TestDialog() diff --git a/src/Editor/TestDialog.h b/src/Editor/TestDialog.h index 46e1bd69..89b06f23 100644 --- a/src/Editor/TestDialog.h +++ b/src/Editor/TestDialog.h @@ -2,6 +2,7 @@ #define TESTDIALOG_H #include +#include "Editor/PropertyEdit/CPropertyModel.h" namespace Ui { class TestDialog; @@ -10,6 +11,7 @@ class TestDialog; class TestDialog : public QDialog { Q_OBJECT + CPropertyModel *mpModel; public: explicit TestDialog(QWidget *parent = 0); diff --git a/src/Editor/TestDialog.ui b/src/Editor/TestDialog.ui index f51de9b9..57185d2d 100644 --- a/src/Editor/TestDialog.ui +++ b/src/Editor/TestDialog.ui @@ -15,109 +15,36 @@ - - - - - - PushButton - - - - - - - PushButton - - - - - - - - - - - - - - - RadioButton - - - - - - - RadioButton - - - - - - - - - CheckBox - - - - - - - GroupBox - - - - - - PushButton - - - - - - - CheckBox - - - - - - - - - - - 0 - 0 - - - - - 256 - 256 - - - - - + + + + 10 + + + + QAbstractItemView::AllEditTriggers + + + true + + + QAbstractItemView::NoSelection + + + QAbstractItemView::ScrollPerPixel + + + false + - WRollout - QWidget -
Editor/Widgets/WRollout.h
- 1 -
- - WTextureGLWidget - QWidget -
Editor/Widgets/WTextureGLWidget.h
- 1 + CPropertyView + QTreeView +
Editor/PropertyEdit/CPropertyView.h
diff --git a/src/Editor/Widgets/WAnimParamsEditor.cpp b/src/Editor/Widgets/WAnimParamsEditor.cpp index d56fb171..2bf74f6c 100644 --- a/src/Editor/Widgets/WAnimParamsEditor.cpp +++ b/src/Editor/Widgets/WAnimParamsEditor.cpp @@ -120,7 +120,7 @@ void WAnimParamsEditor::SetupUI() mpSelector = new WResourceSelector(this); mpSelector->SetAllowedExtensions(mParams.Version() <= eEchoes ? "ANCS" : "CHAR"); mpSelector->AdjustPreviewToParent(true); - mpSelector->SetResource(mParams.Resource()); + mpSelector->SetResource(mParams.AnimSet()); mpValueLayouts[0] = new QHBoxLayout(this); mpValueLayouts[0]->addWidget(mpLabels[0], 0); @@ -136,7 +136,7 @@ void WAnimParamsEditor::SetupUI() { // Create character select combo box mpCharComboBox = new QComboBox(this); - CAnimSet *pSet = static_cast(mParams.Resource()); + CAnimSet *pSet = static_cast(mParams.AnimSet()); if (pSet) for (u32 iChar = 0; iChar < pSet->getNodeCount(); iChar++) diff --git a/src/Editor/Widgets/WDraggableSpinBox.cpp b/src/Editor/Widgets/WDraggableSpinBox.cpp index 6744da7d..e4d45dc3 100644 --- a/src/Editor/Widgets/WDraggableSpinBox.cpp +++ b/src/Editor/Widgets/WDraggableSpinBox.cpp @@ -12,6 +12,7 @@ WDraggableSpinBox::WDraggableSpinBox(QWidget *parent) : QDoubleSpinBox(parent) mTrimTrailingZeroes = true; setMinimum(-1000000.0); setMaximum(1000000.0); + setDecimals(6); lineEdit()->installEventFilter(this); } diff --git a/src/Editor/Widgets/WPropertyEditor.cpp b/src/Editor/Widgets/WPropertyEditor.cpp deleted file mode 100644 index 8e4d42f1..00000000 --- a/src/Editor/Widgets/WPropertyEditor.cpp +++ /dev/null @@ -1,481 +0,0 @@ -#include "WPropertyEditor.h" -#include "WDraggableSpinBox.h" -#include "WIntegralSpinBox.h" -#include "WResourceSelector.h" -#include "WColorPicker.h" -#include "WVectorEditor.h" -#include "WAnimParamsEditor.h" -#include "Editor/UICommon.h" -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -static const QString gskNullProperty = "[NULL]"; -static const QString gskUnsupportedType = "Invalid property type"; - -WPropertyEditor::WPropertyEditor(QWidget *pParent, IProperty *pProperty) - : QWidget(pParent) -{ - mUI.PropertyName = new QLabel(gskNullProperty, this); - mUI.EditorWidget = nullptr; - mUI.Layout = new QHBoxLayout(this); - mUI.Layout->addWidget(mUI.PropertyName); - mUI.Layout->setContentsMargins(0,0,0,0); - setLayout(mUI.Layout); - - mpProperty = nullptr; - SetProperty(pProperty); -} - -WPropertyEditor::~WPropertyEditor() -{ - -} - -void WPropertyEditor::resizeEvent(QResizeEvent* /*pEvent*/) -{ - CreateLabelText(); -} - -void WPropertyEditor::SetProperty(IProperty *pProperty) -{ - if (pProperty) - { - bool IsNewProperty = ((!mpProperty) || (pProperty->Template() != mpProperty->Template())); - mpProperty = pProperty; - - if (IsNewProperty) - CreateEditor(); - else - UpdateEditor(); - } - - else - { - delete mUI.EditorWidget; - mUI.EditorWidget = nullptr; - - mpProperty = pProperty; - mUI.PropertyName->setText(gskNullProperty); - } -} - -void WPropertyEditor::CreateEditor() -{ - // Clear existing edit widget (if any) - delete mUI.EditorWidget; - - // Set name - mUI.PropertyName->setText(TO_QSTRING(mpProperty->Name())); - mUI.PropertyName->setToolTip(TO_QSTRING(mpProperty->Name())); - - // Set editor widget - switch (mpProperty->Type()) - { - - // Bool - QCheckBox - case eBoolProperty: - { - TBoolProperty *pBoolCast = static_cast(mpProperty); - QCheckBox *pCheckBox = new QCheckBox(this); - - pCheckBox->setChecked(pBoolCast->Get()); - - mUI.EditorWidget = pCheckBox; - break; - } - - // Byte - WIntegralSpinBox - case eByteProperty: - { - TByteProperty *pByteCast = static_cast(mpProperty); - QSpinBox *pSpinBox = new WIntegralSpinBox(this); - - pSpinBox->setRange(-128, 128); - pSpinBox->setFocusPolicy(Qt::StrongFocus); - pSpinBox->setContextMenuPolicy(Qt::NoContextMenu); - pSpinBox->setValue(pByteCast->Get()); - - mUI.EditorWidget = pSpinBox; - break; - } - - // Short - WIntegralSpinBox - case eShortProperty: - { - TShortProperty *pShortCast = static_cast(mpProperty); - QSpinBox *pSpinBox = new WIntegralSpinBox(this); - - pSpinBox->setRange(-32768, 32767); - pSpinBox->setFocusPolicy(Qt::StrongFocus); - pSpinBox->setContextMenuPolicy(Qt::NoContextMenu); - pSpinBox->setValue(pShortCast->Get()); - - mUI.EditorWidget = pSpinBox; - break; - } - - // Long - WIntegralSpinBox - case eLongProperty: - { - TLongProperty *pLongCast = static_cast(mpProperty); - QSpinBox *pSpinBox = new WIntegralSpinBox(this); - - pSpinBox->setRange(INT32_MIN, INT32_MAX); - pSpinBox->setFocusPolicy(Qt::StrongFocus); - pSpinBox->setContextMenuPolicy(Qt::NoContextMenu); - pSpinBox->setValue(pLongCast->Get()); - - mUI.EditorWidget = pSpinBox; - break; - } - - // Enum - QComboBox - case eEnumProperty: - { - TEnumProperty *pEnumCast = static_cast(mpProperty); - CEnumTemplate *pTemplate = static_cast(pEnumCast->Template()); - QComboBox *pComboBox = new QComboBox(this); - - for (u32 iEnum = 0; iEnum < pTemplate->NumEnumerators(); iEnum++) - { - TString name = pTemplate->EnumeratorName(iEnum); - pComboBox->addItem(TO_QSTRING(name)); - } - - u32 index = pEnumCast->Get(); - if (index < pTemplate->NumEnumerators()) pComboBox->setCurrentIndex(index); - pComboBox->setFocusPolicy(Qt::StrongFocus); - pComboBox->setContextMenuPolicy(Qt::NoContextMenu); - - mUI.EditorWidget = pComboBox; - break; - } - - // Bitfield - QGroupBox containing QCheckBoxes - case eBitfieldProperty: - { - TBitfieldProperty *pBitfieldCast = static_cast(mpProperty); - CBitfieldTemplate *pTemplate = static_cast(pBitfieldCast->Template()); - long value = pBitfieldCast->Get(); - - QGroupBox *pGroupBox = new QGroupBox(this); - QVBoxLayout *pBitfieldLayout = new QVBoxLayout(pGroupBox); - pBitfieldLayout->setContentsMargins(5,5,5,5); - pGroupBox->setLayout(pBitfieldLayout); - pGroupBox->setTitle(TO_QSTRING(pBitfieldCast->Name())); - mUI.PropertyName->hide(); - - for (u32 iFlag = 0; iFlag < pTemplate->NumFlags(); iFlag++) - { - TString flagName = pTemplate->FlagName(iFlag); - long mask = pTemplate->FlagMask(iFlag); - - QCheckBox *pCheckBox = new QCheckBox(TO_QSTRING(flagName), pGroupBox); - pCheckBox->setChecked((value & mask) != 0); - pBitfieldLayout->addWidget(pCheckBox); - } - - mUI.EditorWidget = pGroupBox; - break; - } - - // Float - WDraggableSpinBox - case eFloatProperty: - { - TFloatProperty *pFloatCast = static_cast(mpProperty); - WDraggableSpinBox *pDraggableSpinBox = new WDraggableSpinBox(this); - - pDraggableSpinBox->setDecimals(4); - pDraggableSpinBox->setFocusPolicy(Qt::StrongFocus); - pDraggableSpinBox->setContextMenuPolicy(Qt::NoContextMenu); - pDraggableSpinBox->setValue(pFloatCast->Get()); - - mUI.EditorWidget = pDraggableSpinBox; - break; - } - - // String - QLineEdit - case eStringProperty: - { - TStringProperty *pStringCast = static_cast(mpProperty); - QLineEdit *pLineEdit = new QLineEdit(this); - - pLineEdit->setText(TO_QSTRING(pStringCast->Get())); - pLineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - //pLineEdit->setCursorPosition(0); - - mUI.EditorWidget = pLineEdit; - break; - } - - // Vector3 - WVectorEditor (inside QGroupBox) - case eVector3Property: - { - TVector3Property *pVector3Cast = static_cast(mpProperty); - QGroupBox *pGroupBox = new QGroupBox(this); - WVectorEditor *pVectorEditor = new WVectorEditor(pGroupBox); - - QVBoxLayout *pGroupLayout = new QVBoxLayout(pGroupBox); - pGroupLayout->addWidget(pVectorEditor); - pGroupLayout->setContentsMargins(0,0,0,0); - pGroupBox->setLayout(pGroupLayout); - - pGroupBox->setTitle(TO_QSTRING(mpProperty->Name())); - pVectorEditor->SetValue(pVector3Cast->Get()); - pVectorEditor->SetOrientation(Qt::Vertical); - mUI.PropertyName->hide(); - - mUI.EditorWidget = pGroupBox; - break; - } - - // Color - WColorPicker - case eColorProperty: - { - TColorProperty *pColorCast = static_cast(mpProperty); - WColorPicker *pColorPicker = new WColorPicker(this); - - CColor color = pColorCast->Get(); - QColor qcolor = QColor(color.r * 255, color.g * 255, color.b * 255, color.a * 255); - pColorPicker->setColor(qcolor); - - mUI.EditorWidget = pColorPicker; - break; - } - - // File - WResourceSelector - case eFileProperty: - { - TFileProperty *pFileCast = static_cast(mpProperty); - CFileTemplate *pFileTemp = static_cast(pFileCast->Template()); - WResourceSelector *pResourceSelector = new WResourceSelector(this); - - pResourceSelector->AdjustPreviewToParent(true); - pResourceSelector->SetAllowedExtensions(pFileTemp->Extensions()); - pResourceSelector->SetResource(pFileCast->Get()); - - mUI.EditorWidget = pResourceSelector; - break; - } - - // Struct - QGroupBox - case eStructProperty: - { - CPropertyStruct *pStructCast = static_cast(mpProperty); - - QGroupBox *pGroupBox = new QGroupBox(this); - QVBoxLayout *pStructLayout = new QVBoxLayout(pGroupBox); - pStructLayout->setContentsMargins(5,5,5,5); - pGroupBox->setLayout(pStructLayout); - pGroupBox->setTitle(TO_QSTRING(pStructCast->Name())); - mUI.PropertyName->hide(); - - for (u32 p = 0; p < pStructCast->Count(); p++) - { - WPropertyEditor *pEditor = new WPropertyEditor(pGroupBox, pStructCast->PropertyByIndex(p)); - pStructLayout->addWidget(pEditor); - } - - mUI.EditorWidget = pGroupBox; - break; - } - - // AnimParams - WAnimParamsEditor - case eCharacterProperty: - { - TAnimParamsProperty *pAnimCast = static_cast(mpProperty); - CAnimationParameters params = pAnimCast->Get(); - - WAnimParamsEditor *pEditor = new WAnimParamsEditor(params, this); - pEditor->SetTitle(TO_QSTRING(pAnimCast->Name())); - - mUI.PropertyName->hide(); - mUI.EditorWidget = pEditor; - break; - } - - // Invalid - case eInvalidProperty: - default: - mUI.EditorWidget = new QLabel(gskUnsupportedType, this); - break; - } - - // For some reason setting a minimum size on group boxes flattens it... - if ((mpProperty->Type() != eStructProperty) && - (mpProperty->Type() != eBitfieldProperty) && - (mpProperty->Type() != eVector3Property) && - (mpProperty->Type() != eCharacterProperty)) - { - mUI.EditorWidget->setMinimumHeight(21); - mUI.EditorWidget->setMaximumHeight(21); - } - - mUI.Layout->addWidget(mUI.EditorWidget, 0); - CreateLabelText(); -} - -void WPropertyEditor::UpdateEditor() -{ - switch (mpProperty->Type()) - { - - case eBoolProperty: - { - TBoolProperty *pBoolCast = static_cast(mpProperty); - QCheckBox *pCheckBox = static_cast(mUI.EditorWidget); - pCheckBox->setChecked(pBoolCast->Get()); - break; - } - - case eByteProperty: - { - TByteProperty *pByteCast = static_cast(mpProperty); - QSpinBox *pSpinBox = static_cast(mUI.EditorWidget); - pSpinBox->setValue(pByteCast->Get()); - break; - } - - case eShortProperty: - { - TShortProperty *pShortCast = static_cast(mpProperty); - QSpinBox *pSpinBox = static_cast(mUI.EditorWidget); - pSpinBox->setValue(pShortCast->Get()); - break; - } - - case eLongProperty: - { - TLongProperty *pLongCast = static_cast(mpProperty); - QSpinBox *pSpinBox = static_cast(mUI.EditorWidget); - pSpinBox->setValue(pLongCast->Get()); - break; - } - - case eEnumProperty: - { - TEnumProperty *pEnumCast = static_cast(mpProperty); - QComboBox *pComboBox = static_cast(mUI.EditorWidget); - pComboBox->setCurrentIndex(pEnumCast->Get()); - break; - } - - case eBitfieldProperty: - { - TBitfieldProperty *pBitfieldCast = static_cast(mpProperty); - CBitfieldTemplate *pTemplate = static_cast(pBitfieldCast->Template()); - QGroupBox *pGroupBox = static_cast(mUI.EditorWidget); - - QObjectList ChildList = pGroupBox->children(); - long value = pBitfieldCast->Get(); - u32 propNum = 0; - - foreach (QObject *pObj, ChildList) - { - if (pObj != pGroupBox->layout()) - { - u32 mask = pTemplate->FlagMask(propNum); - QCheckBox *pCheckBox = static_cast(pObj); - pCheckBox->setChecked((value & mask) != 0); - propNum++; - } - } - break; - } - - case eFloatProperty: - { - TFloatProperty *pFloatCast = static_cast(mpProperty); - WDraggableSpinBox *pDraggableSpinBox = static_cast(mUI.EditorWidget); - pDraggableSpinBox->setValue(pFloatCast->Get()); - break; - } - - case eStringProperty: - { - TStringProperty *pStringCast = static_cast(mpProperty); - QLineEdit *pLineEdit = static_cast(mUI.EditorWidget); - pLineEdit->setText(TO_QSTRING(pStringCast->Get())); - pLineEdit->setCursorPosition(0); - break; - } - - case eVector3Property: - { - TVector3Property *pVector3Cast = static_cast(mpProperty); - QGroupBox *pGroupBox = static_cast(mUI.EditorWidget); - - WVectorEditor *pVectorEditor = static_cast(pGroupBox->children().first()); - pVectorEditor->SetValue(pVector3Cast->Get()); - break; - } - - case eColorProperty: - { - TColorProperty *pColorCast = static_cast(mpProperty); - WColorPicker *pColorPicker = static_cast(mUI.EditorWidget); - - CColor color = pColorCast->Get(); - QColor qcolor = QColor(color.r * 255, color.g * 255, color.b * 255, color.a * 255); - pColorPicker->setColor(qcolor); - - break; - } - - case eFileProperty: - { - TFileProperty *pFileCast = static_cast(mpProperty); - CFileTemplate *pFileTemp = static_cast(pFileCast->Template()); - WResourceSelector *pResourceSelector = static_cast(mUI.EditorWidget); - pResourceSelector->SetAllowedExtensions(pFileTemp->Extensions()); - pResourceSelector->SetResource(pFileCast->Get()); - break; - } - - case eStructProperty: - { - CPropertyStruct *pStructCast = static_cast(mpProperty); - QGroupBox *pGroupBox = static_cast(mUI.EditorWidget); - - QObjectList ChildList = pGroupBox->children(); - u32 PropNum = 0; - - foreach (QObject *pObj, ChildList) - { - if (pObj != pGroupBox->layout()) - { - IProperty *pProp = pStructCast->PropertyByIndex(PropNum); - static_cast(pObj)->SetProperty(pProp); - PropNum++; - } - } - break; - } - - case eCharacterProperty: - { - TAnimParamsProperty *pAnimCast = static_cast(mpProperty); - WAnimParamsEditor *pEditor = static_cast(mUI.EditorWidget); - pEditor->SetParameters(pAnimCast->Get()); - break; - } - - } - -} - -void WPropertyEditor::CreateLabelText() -{ - mUI.PropertyName->setText(TO_QSTRING(mpProperty->Name())); - QFontMetrics metrics(mUI.PropertyName->font()); - QString text = metrics.elidedText(TO_QSTRING(mpProperty->Name()), Qt::ElideRight, mUI.PropertyName->width()); - mUI.PropertyName->setText(text); -} diff --git a/src/Editor/Widgets/WPropertyEditor.h b/src/Editor/Widgets/WPropertyEditor.h deleted file mode 100644 index 62a4e694..00000000 --- a/src/Editor/Widgets/WPropertyEditor.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef WPROPERTYEDITOR_H -#define WPROPERTYEDITOR_H - -#include -#include -#include -#include - -class WPropertyEditor : public QWidget -{ - Q_OBJECT - - // Editor - IProperty *mpProperty; - - // UI - struct { - QLabel *PropertyName; - QWidget *EditorWidget; - QHBoxLayout *Layout; - } mUI; - -public: - explicit WPropertyEditor(QWidget *pParent = 0, IProperty *pProperty = 0); - ~WPropertyEditor(); - void resizeEvent(QResizeEvent *pEvent); - - void SetProperty(IProperty *pProperty); - -private: - void CreateEditor(); - void UpdateEditor(); - void CreateLabelText(); -}; - -#endif // WPROPERTYEDITOR_H diff --git a/src/Editor/Widgets/WResourceSelector.cpp b/src/Editor/Widgets/WResourceSelector.cpp index 65157716..d3bea77e 100644 --- a/src/Editor/Widgets/WResourceSelector.cpp +++ b/src/Editor/Widgets/WResourceSelector.cpp @@ -107,6 +107,11 @@ bool WResourceSelector::HasSupportedExtension(const CResourceInfo& rkRes) } // ************ GETTERS ************ +CResource* WResourceSelector::GetResource() +{ + return mResource.Load(); +} + QString WResourceSelector::GetText() { return mUI.LineEdit->text(); diff --git a/src/Editor/Widgets/WResourceSelector.h b/src/Editor/Widgets/WResourceSelector.h index 99f9a5d1..fc34c6fa 100644 --- a/src/Editor/Widgets/WResourceSelector.h +++ b/src/Editor/Widgets/WResourceSelector.h @@ -56,6 +56,7 @@ public: bool HasSupportedExtension(const CResourceInfo& rkRes); // Getters + CResource* GetResource(); QString GetText(); bool IsEditButtonEnabled(); bool IsExportButtonEnabled(); diff --git a/src/Editor/WorldEditor/CWorldEditor.cpp b/src/Editor/WorldEditor/CWorldEditor.cpp index a95ecc5d..12d078e7 100644 --- a/src/Editor/WorldEditor/CWorldEditor.cpp +++ b/src/Editor/WorldEditor/CWorldEditor.cpp @@ -37,22 +37,15 @@ CWorldEditor::CWorldEditor(QWidget *parent) : connect(&mRefreshTimer, SIGNAL(timeout()), this, SLOT(RefreshViewport())); mRefreshTimer.start(0); - // Create blank title bar with some space to allow for dragging the dock - QWidget *pOldTitleBar = ui->MainDock->titleBarWidget(); - - QWidget *pNewTitleBar = new QWidget(ui->MainDock); - QVBoxLayout *pTitleLayout = new QVBoxLayout(pNewTitleBar); - pTitleLayout->setSpacing(10); - pNewTitleBar->setLayout(pTitleLayout); - ui->MainDock->setTitleBarWidget(pNewTitleBar); - - delete pOldTitleBar; + // Initialize splitter + QList SplitterSizes; + SplitterSizes << width() * 0.775 << width() * 0.225; + ui->splitter->setSizes(SplitterSizes); // Initialize UI stuff ui->MainViewport->SetScene(this, &mScene); ui->ModifyTabContents->SetEditor(this); ui->InstancesTabContents->SetEditor(this, &mScene); - ui->MainDock->installEventFilter(this); ui->TransformSpinBox->SetOrientation(Qt::Horizontal); ui->TransformSpinBox->layout()->setContentsMargins(0,0,0,0); ui->CamSpeedSpinBox->SetDefaultValue(1.0); @@ -95,16 +88,8 @@ void CWorldEditor::closeEvent(QCloseEvent *) mpPoiDialog->close(); } -bool CWorldEditor::eventFilter(QObject *pObj, QEvent *pEvent) +bool CWorldEditor::eventFilter(QObject * /*pObj*/, QEvent * /*pEvent*/) { - if (pObj == ui->MainDock) - { - if (pEvent->type() == QEvent::Resize) - { - UpdateSelectionUI(); - } - } - return false; } @@ -114,7 +99,6 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea) ui->MainViewport->ResetHover(); ClearSelection(); ui->ModifyTabContents->ClearUI(); - ui->ModifyTabContents->ClearCachedEditors(); ui->InstancesTabContents->SetMaster(nullptr); ui->InstancesTabContents->SetArea(pArea); mUndoStack.clear(); diff --git a/src/Editor/WorldEditor/CWorldEditor.ui b/src/Editor/WorldEditor/CWorldEditor.ui index 572997f3..554a0b68 100644 --- a/src/Editor/WorldEditor/CWorldEditor.ui +++ b/src/Editor/WorldEditor/CWorldEditor.ui @@ -14,339 +14,211 @@ Prime World Editor - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - + - - - - 0 - 1 - + + + Qt::Horizontal - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Plain - - - - 3 - - - 3 - - - 3 - - - 3 - - - - - - 200 - 0 - - - - - 200 - 16777215 - - - - QFrame::Panel - - - QFrame::Sunken - - - 1 - - - 0 - - - - 3 + + + + + + + 0 + 1 + - - 3 + + + + + + + 0 + 0 + - - 3 + + QFrame::StyledPanel - - 3 + + QFrame::Plain - - - - QFrame::Plain - - - 1 - - - 0 - - - - - - - - - - - - - - 0 - 0 - - - - - 300 - 0 - - - - - - - - Qt::Vertical - - - - - - - - - Speed: + + + 3 - - - - - - - 50 - 16777215 - + + 3 - - Qt::NoFocus + + 3 - - Qt::NoContextMenu + + 3 - - true - - - QAbstractSpinBox::CorrectToNearestValue - - - false - - - 0.010000000000000 - - - 10.000000000000000 - - - 0.100000000000000 - - - 1.000000000000000 - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 0 - 0 - 1280 - 21 - - - - - File - - - - - - - Window - - - - - Models - - - - - - Edit - - - - - - - View - - - - Lighting - - - - - - - - Bloom - - - - - - - - - - - - - - - - - - - - - - - - Tools - - - - - - - - - - - - - - - Qt::NoContextMenu - - - toolBar_2 - - - false - - - TopToolBarArea - - - false - - - - - - - QDockWidget::DockWidgetMovable - - - Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea - - - - - - 2 - - - - - 0 - - - 0 - - - 0 - - - 0 - - + + + + + 200 + 0 + + + + + 200 + 16777215 + + + + QFrame::Panel + + + QFrame::Sunken + + + 1 + + + 0 + + + + 3 + + + 3 + + + 3 + + + 3 + + + + + QFrame::Plain + + + 1 + + + 0 + + + + + + + + + + + + + + 0 + 0 + + + + + 300 + 0 + + + + + + + + Qt::Vertical + + + + + + + + + Speed: + + + + + + + + 50 + 16777215 + + + + Qt::NoFocus + + + Qt::NoContextMenu + + + true + + + QAbstractSpinBox::CorrectToNearestValue + + + false + + + 0.010000000000000 + + + 10.000000000000000 + + + 0.100000000000000 + + + 1.000000000000000 + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + Qt::NoFocus @@ -463,9 +335,113 @@ - - + + + + + + + + 0 + 0 + 1280 + 21 + + + + + File + + + + + + Window + + + + + Models + + + + + + Edit + + + + + + + View + + + + Lighting + + + + + + + + Bloom + + + + + + + + + + + + + + + + + + + + + + + + Tools + + + + + + + + + + + + + + + Qt::NoContextMenu + + + toolBar_2 + + + false + + + TopToolBarArea + + + false + + + @@ -796,9 +772,6 @@ 1 - - TabWidget - diff --git a/src/Editor/WorldEditor/WModifyTab.cpp b/src/Editor/WorldEditor/WModifyTab.cpp index 54d53f72..d6ec5b6c 100644 --- a/src/Editor/WorldEditor/WModifyTab.cpp +++ b/src/Editor/WorldEditor/WModifyTab.cpp @@ -12,7 +12,10 @@ WModifyTab::WModifyTab(QWidget *pParent) : { ui->setupUi(this); - mpCurPropEditor = nullptr; + int PropViewWidth = ui->PropertyView->width(); + ui->PropertyView->header()->resizeSection(0, PropViewWidth * 0.3); + ui->PropertyView->header()->resizeSection(1, PropViewWidth * 0.3); + ui->PropertyView->header()->setSectionResizeMode(1, QHeaderView::Fixed); mpInLinkModel = new CLinkModel(this); mpInLinkModel->SetConnectionType(CLinkModel::eIncoming); @@ -41,7 +44,6 @@ void WModifyTab::SetEditor(CWorldEditor *pEditor) void WModifyTab::GenerateUI(QList& Selection) { - WPropertyEditor *pOldEditor = mpCurPropEditor; ClearUI(); if (Selection.size() == 1) @@ -54,39 +56,9 @@ void WModifyTab::GenerateUI(QList& Selection) ui->ObjectsTabWidget->show(); CScriptNode *pScriptNode = static_cast(mpSelectedNode); CScriptObject *pObj = pScriptNode->Object(); - CScriptTemplate *pTemplate = pObj->Template(); - CPropertyStruct *pProperties = pObj->Properties(); - // Check whether a cached UI for this object exists - auto it = mCachedPropEditors.find(pTemplate); - - // Load precached UI - if (it != mCachedPropEditors.end()) - { - mpCurPropEditor = *it; - mpCurPropEditor->SetProperty(pProperties); - } - - // Generate new UI - else - { - mpCurPropEditor = new WPropertyEditor(ui->PropertiesScrollContents, pProperties); - mCachedPropEditors[pTemplate] = mpCurPropEditor; - } - - ui->PropertiesScrollLayout->insertWidget(0, mpCurPropEditor); - mpCurPropEditor->show(); - - // Scroll back up to the top, but only if this is a new editor. - // (This is so clicking on multiple objects of the same type, or even - // the same object twice, won't cause you to lose your place.) - if (pOldEditor != mpCurPropEditor) - { - ui->PropertiesScrollArea->horizontalScrollBar()->setValue(0); - ui->PropertiesScrollArea->verticalScrollBar()->setValue(0); - } - - // Set up connection table model + // Set up UI + ui->PropertyView->SetBaseStruct(pObj->Properties()); mpInLinkModel->SetObject(pObj); mpOutLinkModel->SetObject(pObj); } @@ -98,25 +70,11 @@ void WModifyTab::GenerateUI(QList& Selection) void WModifyTab::ClearUI() { - if (mpCurPropEditor) - { - ui->PropertiesScrollLayout->removeWidget(mpCurPropEditor); - mpCurPropEditor->hide(); - mpCurPropEditor = nullptr; - } - ui->ObjectsTabWidget->hide(); + ui->PropertyView->SetBaseStruct(nullptr); ui->LightGroupBox->hide(); } -void WModifyTab::ClearCachedEditors() -{ - foreach(WPropertyEditor *pEditor, mCachedPropEditors) - delete pEditor; - - mCachedPropEditors.clear(); -} - void WModifyTab::OnLinkTableDoubleClick(QModelIndex Index) { if (Index.column() == 0) @@ -129,8 +87,6 @@ void WModifyTab::OnLinkTableDoubleClick(QModelIndex Index) Link = pNode->Object()->InLink(Index.row()); else if (sender() == ui->OutLinksTableView) Link = pNode->Object()->OutLink(Index.row()); - else - std::cout << "Error - OnLinkTableDoubleClick() activated by invalid sender\n"; CScriptNode *pLinkedNode = pNode->Scene()->ScriptNodeByID(Link.ObjectID); diff --git a/src/Editor/WorldEditor/WModifyTab.h b/src/Editor/WorldEditor/WModifyTab.h index 848fd993..4431a854 100644 --- a/src/Editor/WorldEditor/WModifyTab.h +++ b/src/Editor/WorldEditor/WModifyTab.h @@ -2,7 +2,6 @@ #define WMODIFYTAB_H #include "CLinkModel.h" -#include "Editor/Widgets/WPropertyEditor.h" #include #include @@ -24,8 +23,6 @@ class WModifyTab : public QWidget CWorldEditor *mpWorldEditor; CSceneNode *mpSelectedNode; - QMap mCachedPropEditors; - WPropertyEditor *mpCurPropEditor; CLinkModel *mpInLinkModel; CLinkModel *mpOutLinkModel; @@ -35,7 +32,6 @@ public: void SetEditor(CWorldEditor *pEditor); void GenerateUI(QList& Selection); void ClearUI(); - void ClearCachedEditors(); private: Ui::WModifyTab *ui; diff --git a/src/Editor/WorldEditor/WModifyTab.ui b/src/Editor/WorldEditor/WModifyTab.ui index 45dee2c9..912d63f0 100644 --- a/src/Editor/WorldEditor/WModifyTab.ui +++ b/src/Editor/WorldEditor/WModifyTab.ui @@ -49,59 +49,27 @@ 0 - - - QFrame::NoFrame + + + + 10 + - - QFrame::Plain + + alternate-background-color: rgb(35,35,35); - + + QAbstractItemView::AllEditTriggers + + true - - - - 0 - 0 - 276 - 457 - - - - - 0 - 0 - - - - - 9 - - - 9 - - - 9 - - - 9 - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - + + QAbstractItemView::NoSelection + + + QAbstractItemView::ScrollPerPixel + @@ -223,6 +191,13 @@ + + + CPropertyView + QTreeView +
Editor/PropertyEdit/CPropertyView.h
+
+
diff --git a/templates/mp2/Enums/Item.xml b/templates/mp2/Enums/Item.xml new file mode 100644 index 00000000..065700d6 --- /dev/null +++ b/templates/mp2/Enums/Item.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/mp2/Script/Pickup.xml b/templates/mp2/Script/Pickup.xml index 34d5b0fc..e7e656f1 100644 --- a/templates/mp2/Script/Pickup.xml +++ b/templates/mp2/Script/Pickup.xml @@ -9,9 +9,9 @@ 0.0, 0.0, 0.0 - + 0 - + 1 diff --git a/templates/mp3/Enums/InventorySlot.xml b/templates/mp3/Enums/InventorySlot.xml deleted file mode 100644 index 262c9107..00000000 --- a/templates/mp3/Enums/InventorySlot.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/templates/mp3/Enums/Item.xml b/templates/mp3/Enums/Item.xml new file mode 100644 index 00000000..9f30fdc5 --- /dev/null +++ b/templates/mp3/Enums/Item.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/mp3/Script/EffectRepulsor.xml b/templates/mp3/Script/EffectRepulsor.xml index f9b78f7a..e4898fb1 100644 --- a/templates/mp3/Script/EffectRepulsor.xml +++ b/templates/mp3/Script/EffectRepulsor.xml @@ -3,7 +3,7 @@ EffectRepulsor - + 0xFB73F2B8 diff --git a/templates/mp3/Script/Pickup.xml b/templates/mp3/Script/Pickup.xml index aeec04fc..13129d7c 100644 --- a/templates/mp3/Script/Pickup.xml +++ b/templates/mp3/Script/Pickup.xml @@ -10,7 +10,7 @@ 0.0, 0.0, 0.0 - + 0xFB73F2B8 diff --git a/templates/mp3/Script/ShipCommandIcon.xml b/templates/mp3/Script/ShipCommandIcon.xml index c71216f0..d19ba9de 100644 --- a/templates/mp3/Script/ShipCommandIcon.xml +++ b/templates/mp3/Script/ShipCommandIcon.xml @@ -21,7 +21,7 @@ - + 0xFB73F2B8 diff --git a/templates/mp3/Script/SpecialFunction.xml b/templates/mp3/Script/SpecialFunction.xml index 02d84391..ef119d53 100644 --- a/templates/mp3/Script/SpecialFunction.xml +++ b/templates/mp3/Script/SpecialFunction.xml @@ -88,7 +88,7 @@ 0 - + 0xFB73F2B8 diff --git a/templates/mp3/Structs/ConditionalTest.xml b/templates/mp3/Structs/ConditionalTest.xml index 11d3f1ac..71ff6938 100644 --- a/templates/mp3/Structs/ConditionalTest.xml +++ b/templates/mp3/Structs/ConditionalTest.xml @@ -7,7 +7,7 @@ false - + 0xFB73F2B8