Implemented new property editor, CPropertyView

This commit is contained in:
parax0 2016-01-22 13:53:57 -07:00
parent 26485b1151
commit 38942988d5
42 changed files with 1828 additions and 1248 deletions

View File

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

View File

@ -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<CAnimSet*>(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;
}
}

View File

@ -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<CResource> mpCharSet;
TResPtr<CAnimSet> 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

View File

@ -138,7 +138,7 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& SCLY)
}
case eCharacterProperty: {
TAnimParamsProperty *pAnimCast = static_cast<TAnimParamsProperty*>(pProp);
TCharacterProperty *pAnimCast = static_cast<TCharacterProperty*>(pProp);
pAnimCast->Set(CAnimationParameters(SCLY, mVersion));
break;
}

View File

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

View File

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

View File

@ -233,7 +233,7 @@ CModel* CScriptTemplate::FindDisplayModel(CPropertyStruct *pProperties)
else if (pProp->Type() == eCharacterProperty)
{
TAnimParamsProperty *pParams = static_cast<TAnimParamsProperty*>(pProp);
TCharacterProperty *pParams = static_cast<TCharacterProperty*>(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<TAnimParamsProperty*>(pProp);
TCharacterProperty *pParams = static_cast<TCharacterProperty*>(pProp);
pRes = pParams->Get().GetCurrentModel(it->ForceNodeIndex);
}

View File

@ -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<CStructTemplate*>(Template());
}

View File

@ -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<bool, eBoolProperty, CBoolValue> TBoolProperty;
@ -68,7 +83,7 @@ typedef TTypedProperty<TString, eStringProperty, CStringValue>
typedef TTypedProperty<CVector3f, eVector3Property, CVector3Value> TVector3Property;
typedef TTypedProperty<CColor, eColorProperty, CColorValue> TColorProperty;
typedef TTypedProperty<CResourceInfo, eFileProperty, CFileValue> TFileProperty;
typedef TTypedProperty<CAnimationParameters, eCharacterProperty, CCharacterValue> TAnimParamsProperty;
typedef TTypedProperty<CAnimationParameters, eCharacterProperty, CCharacterValue> TCharacterProperty;
typedef TTypedProperty<std::vector<u8>, eUnknownProperty, CUnknownValue> TUnknownProperty;
/*
@ -79,25 +94,25 @@ class CPropertyStruct : public IProperty
friend class CScriptLoader;
std::vector<IProperty*> 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<CPropertyStruct*> 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

View File

@ -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<PropType, PropTypeEnum, ValueClass> 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);
}
};

View File

@ -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()))
{

View File

@ -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 += \

View File

@ -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 <Core/Resource/Script/IProperty.h>
#include <Core/Resource/Script/IPropertyTemplate.h>
#include <QCheckBox>
#include <QComboBox>
#include <QEvent>
#include <QLineEdit>
// 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<CEnumTemplate*>(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<CFileTemplate*>(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<QCheckBox*>(pEditor);
TBoolProperty *pBool = static_cast<TBoolProperty*>(pProp);
pCheckBox->setChecked(pBool->Get());
break;
}
case eShortProperty:
{
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
TShortProperty *pShort = static_cast<TShortProperty*>(pProp);
pSpinBox->setValue(pShort->Get());
break;
}
case eLongProperty:
{
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
TLongProperty *pLong = static_cast<TLongProperty*>(pProp);
pSpinBox->setValue(pLong->Get());
break;
}
case eFloatProperty:
{
WDraggableSpinBox *pSpinBox = static_cast<WDraggableSpinBox*>(pEditor);
TFloatProperty *pFloat = static_cast<TFloatProperty*>(pProp);
pSpinBox->setValue(pFloat->Get());
break;
}
case eColorProperty:
{
WColorPicker *pColorPicker = static_cast<WColorPicker*>(pEditor);
TColorProperty *pColor = static_cast<TColorProperty*>(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<QLineEdit*>(pEditor);
TStringProperty *pString = static_cast<TStringProperty*>(pProp);
pLineEdit->setText(TO_QSTRING(pString->Get()));
break;
}
case eEnumProperty:
{
QComboBox *pComboBox = static_cast<QComboBox*>(pEditor);
TEnumProperty *pEnum = static_cast<TEnumProperty*>(pProp);
pComboBox->setCurrentIndex(pEnum->Get());
break;
}
case eFileProperty:
{
WResourceSelector *pSelector = static_cast<WResourceSelector*>(pEditor);
TFileProperty *pFile = static_cast<TFileProperty*>(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<QCheckBox*>(pEditor);
TBitfieldProperty *pBitfield = static_cast<TBitfieldProperty*>(pProp);
u32 Mask = static_cast<CBitfieldTemplate*>(pBitfield->Template())->FlagMask(rkIndex.row());
bool Set = (pBitfield->Get() & Mask) != 0;
pCheckBox->setChecked(Set);
}
else
{
WDraggableSpinBox *pSpinBox = static_cast<WDraggableSpinBox*>(pEditor);
float Value;
if (pProp->Type() == eVector3Property)
{
TVector3Property *pVector = static_cast<TVector3Property*>(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<TColorProperty*>(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<QCheckBox*>(pEditor);
TBoolProperty *pBool = static_cast<TBoolProperty*>(pProp);
pBool->Set(pCheckBox->isChecked());
break;
}
case eShortProperty:
{
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
TShortProperty *pShort = static_cast<TShortProperty*>(pProp);
pShort->Set(pSpinBox->value());
break;
}
case eLongProperty:
{
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
TLongProperty *pLong = static_cast<TLongProperty*>(pProp);
pLong->Set(pSpinBox->value());
break;
}
case eFloatProperty:
{
WDraggableSpinBox *pSpinBox = static_cast<WDraggableSpinBox*>(pEditor);
TFloatProperty *pFloat = static_cast<TFloatProperty*>(pProp);
pFloat->Set((float) pSpinBox->value());
break;
}
case eColorProperty:
{
WColorPicker *pColorPicker = static_cast<WColorPicker*>(pEditor);
TColorProperty *pColor = static_cast<TColorProperty*>(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<QLineEdit*>(pEditor);
TStringProperty *pString = static_cast<TStringProperty*>(pProp);
pString->Set(TO_TSTRING(pLineEdit->text()));
break;
}
case eEnumProperty:
{
QComboBox *pComboBox = static_cast<QComboBox*>(pEditor);
TEnumProperty *pEnum = static_cast<TEnumProperty*>(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<QCheckBox*>(pEditor);
TBitfieldProperty *pBitfield = static_cast<TBitfieldProperty*>(pProp);
u32 Mask = static_cast<CBitfieldTemplate*>(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<WDraggableSpinBox*>(pEditor);
if (pProp->Type() == eVector3Property)
{
TVector3Property *pVector = static_cast<TVector3Property*>(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<TColorProperty*>(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<QWidget*>(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<TCharacterProperty*>(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<TCharacterProperty*>(mpModel->PropertyForIndex(rkIndex, true));
CAnimationParameters Params = pProp->Get();
EPropertyType Type = DetermineCharacterPropType(Params.Version(), rkIndex);
if (Type == eFileProperty)
{
static_cast<WResourceSelector*>(pEditor)->SetResource(Params.AnimSet());
}
else if (Type == eEnumProperty)
{
static_cast<QComboBox*>(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<WIntegralSpinBox*>(pEditor)->setValue(Value);
}
}
void CPropertyDelegate::SetCharacterModelData(QWidget *pEditor, const QModelIndex& rkIndex) const
{
TCharacterProperty *pProp = static_cast<TCharacterProperty*>(mpModel->PropertyForIndex(rkIndex, true));
CAnimationParameters Params = pProp->Get();
EPropertyType Type = DetermineCharacterPropType(Params.Version(), rkIndex);
if (Type == eFileProperty)
{
Params.SetResource( static_cast<WResourceSelector*>(pEditor)->GetResource() );
}
else if (Type == eEnumProperty)
{
Params.SetNodeIndex( static_cast<QComboBox*>(pEditor)->currentIndex() );
}
else if (Type == eLongProperty)
{
int UnkIndex = (Params.Version() <= eEchoes ? rkIndex.row() - 2 : rkIndex.row() - 1);
Params.SetUnknown(UnkIndex, static_cast<WIntegralSpinBox*>(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);
}

View File

@ -0,0 +1,30 @@
#ifndef CPROPERTYDELEGATE_H
#define CPROPERTYDELEGATE_H
#include <QStyledItemDelegate>
#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

View File

@ -0,0 +1,345 @@
#include "CPropertyModel.h"
#include "Editor/UICommon.h"
#include <Core/Resource/Script/IProperty.h>
#include <Core/Resource/Script/IPropertyTemplate.h>
#include <QSize>
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<IProperty*>(pID);
}
else
return nullptr;
}
return static_cast<IProperty*>(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<CPropertyStruct*>(pProp)->Count();
case eBitfieldProperty:
return static_cast<CBitfieldTemplate*>(pProp->Template())->NumFlags();
case eVector3Property:
return 3;
case eColorProperty:
return 4;
case eCharacterProperty:
{
CAnimationParameters Params = static_cast<TCharacterProperty*>(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<CBitfieldTemplate*>(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<TCharacterProperty*>(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<TCharacterProperty*>(pProp)->Get().GetCurrentCharacterName());
// Display enumerator name for enums (but only on ToolTipRole)
case eEnumProperty:
if (Role == Qt::ToolTipRole)
{
TEnumProperty *pEnum = static_cast<TEnumProperty*>(pProp);
CEnumTemplate *pTemp = static_cast<CEnumTemplate*>(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("<b>%1</b> <i>(%2)</i>").arg(TO_QSTRING(pProp->Name())).arg(TO_QSTRING(PropEnumToPropString(pProp->Type())));
TString Desc = pProp->Template()->Description();
if (!Desc.IsEmpty()) Text += "<br/>" + 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<CPropertyStruct*>(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<int> Roles(Qt::DisplayRole);
if (pProp->Type() == eVector3Property)
emit dataChanged( index(0, 1, rkIndex), index(2, 1, rkIndex), Roles);
else if (pProp->Type() == eColorProperty)
emit dataChanged( index(0, 1, rkIndex), index(3, 1, rkIndex), Roles);
}
}

View File

@ -0,0 +1,28 @@
#ifndef CPROPERTYMODEL_H
#define CPROPERTYMODEL_H
#include <QAbstractItemModel>
#include <Core/Resource/Script/IProperty.h>
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

View File

@ -0,0 +1,29 @@
#ifndef TWIDGETWRAPPER
#define TWIDGETWRAPPER
#include <QModelIndex>
#include <QWidget>
// 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

View File

@ -0,0 +1,110 @@
#include "CPropertyView.h"
#include "CPropertyDelegate.h"
#include <Core/Resource/Script/IPropertyTemplate.h>
#include <QEvent>
#include <QToolTip>
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<CPropertyModel*>(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<TCharacterProperty*>(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);
}
}

View File

@ -0,0 +1,23 @@
#ifndef CPROPERTYVIEW_H
#define CPROPERTYVIEW_H
#include "CPropertyModel.h"
#include "CPropertyDelegate.h"
#include <QTreeView>
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

View File

@ -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 <Core/Resource/Factory/CTextureDecoder.h>
#include <Core/Resource/CResCache.h>
#include <Core/Resource/Script/CMasterTemplate.h>
#include <Core/Resource/Script/CScriptTemplate.h>
#include <Core/Resource/Factory/CTemplateLoader.h>
#include <iostream>
@ -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<CPropertyStruct*>(pTemp->BaseStruct()->InstantiateProperty(nullptr));
ui->treeView->setItemDelegate(new CPropertyDelegate(ui->treeView));
ui->treeView->SetBaseStruct(pBase);
}
TestDialog::~TestDialog()

View File

@ -2,6 +2,7 @@
#define TESTDIALOG_H
#include <QDialog>
#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);

View File

@ -15,109 +15,36 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="WRollout" name="RolloutTest" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>PushButton</string>
<widget class="CPropertyView" name="treeView">
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>PushButton</string>
<property name="editTriggers">
<set>QAbstractItemView::AllEditTriggers</set>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox"/>
</item>
<item>
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QRadioButton" name="radioButton">
<property name="text">
<string>RadioButton</string>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButton_2">
<property name="text">
<string>RadioButton</string>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>CheckBox</string>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>GroupBox</string>
<property name="headerHidden">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QPushButton" name="pushButton_3">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_2">
<property name="text">
<string>CheckBox</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="WTextureGLWidget" name="widget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>256</width>
<height>256</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>WRollout</class>
<extends>QWidget</extends>
<header>Editor/Widgets/WRollout.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>WTextureGLWidget</class>
<extends>QWidget</extends>
<header>Editor/Widgets/WTextureGLWidget.h</header>
<container>1</container>
<class>CPropertyView</class>
<extends>QTreeView</extends>
<header>Editor/PropertyEdit/CPropertyView.h</header>
</customwidget>
</customwidgets>
<resources/>

View File

@ -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<CAnimSet*>(mParams.Resource());
CAnimSet *pSet = static_cast<CAnimSet*>(mParams.AnimSet());
if (pSet)
for (u32 iChar = 0; iChar < pSet->getNodeCount(); iChar++)

View File

@ -12,6 +12,7 @@ WDraggableSpinBox::WDraggableSpinBox(QWidget *parent) : QDoubleSpinBox(parent)
mTrimTrailingZeroes = true;
setMinimum(-1000000.0);
setMaximum(1000000.0);
setDecimals(6);
lineEdit()->installEventFilter(this);
}

View File

@ -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 <Core/Resource/CAnimSet.h>
#include <Core/Resource/Script/CScriptLayer.h>
#include <QCheckBox>
#include <QComboBox>
#include <QDoubleSpinBox>
#include <QFontMetrics>
#include <QGroupBox>
#include <QLineEdit>
#include <QSpinBox>
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<TBoolProperty*>(mpProperty);
QCheckBox *pCheckBox = new QCheckBox(this);
pCheckBox->setChecked(pBoolCast->Get());
mUI.EditorWidget = pCheckBox;
break;
}
// Byte - WIntegralSpinBox
case eByteProperty:
{
TByteProperty *pByteCast = static_cast<TByteProperty*>(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<TShortProperty*>(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<TLongProperty*>(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<TEnumProperty*>(mpProperty);
CEnumTemplate *pTemplate = static_cast<CEnumTemplate*>(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<TBitfieldProperty*>(mpProperty);
CBitfieldTemplate *pTemplate = static_cast<CBitfieldTemplate*>(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<TFloatProperty*>(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<TStringProperty*>(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<TVector3Property*>(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<TColorProperty*>(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<TFileProperty*>(mpProperty);
CFileTemplate *pFileTemp = static_cast<CFileTemplate*>(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<CPropertyStruct*>(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<TAnimParamsProperty*>(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<TBoolProperty*>(mpProperty);
QCheckBox *pCheckBox = static_cast<QCheckBox*>(mUI.EditorWidget);
pCheckBox->setChecked(pBoolCast->Get());
break;
}
case eByteProperty:
{
TByteProperty *pByteCast = static_cast<TByteProperty*>(mpProperty);
QSpinBox *pSpinBox = static_cast<QSpinBox*>(mUI.EditorWidget);
pSpinBox->setValue(pByteCast->Get());
break;
}
case eShortProperty:
{
TShortProperty *pShortCast = static_cast<TShortProperty*>(mpProperty);
QSpinBox *pSpinBox = static_cast<QSpinBox*>(mUI.EditorWidget);
pSpinBox->setValue(pShortCast->Get());
break;
}
case eLongProperty:
{
TLongProperty *pLongCast = static_cast<TLongProperty*>(mpProperty);
QSpinBox *pSpinBox = static_cast<QSpinBox*>(mUI.EditorWidget);
pSpinBox->setValue(pLongCast->Get());
break;
}
case eEnumProperty:
{
TEnumProperty *pEnumCast = static_cast<TEnumProperty*>(mpProperty);
QComboBox *pComboBox = static_cast<QComboBox*>(mUI.EditorWidget);
pComboBox->setCurrentIndex(pEnumCast->Get());
break;
}
case eBitfieldProperty:
{
TBitfieldProperty *pBitfieldCast = static_cast<TBitfieldProperty*>(mpProperty);
CBitfieldTemplate *pTemplate = static_cast<CBitfieldTemplate*>(pBitfieldCast->Template());
QGroupBox *pGroupBox = static_cast<QGroupBox*>(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<QCheckBox*>(pObj);
pCheckBox->setChecked((value & mask) != 0);
propNum++;
}
}
break;
}
case eFloatProperty:
{
TFloatProperty *pFloatCast = static_cast<TFloatProperty*>(mpProperty);
WDraggableSpinBox *pDraggableSpinBox = static_cast<WDraggableSpinBox*>(mUI.EditorWidget);
pDraggableSpinBox->setValue(pFloatCast->Get());
break;
}
case eStringProperty:
{
TStringProperty *pStringCast = static_cast<TStringProperty*>(mpProperty);
QLineEdit *pLineEdit = static_cast<QLineEdit*>(mUI.EditorWidget);
pLineEdit->setText(TO_QSTRING(pStringCast->Get()));
pLineEdit->setCursorPosition(0);
break;
}
case eVector3Property:
{
TVector3Property *pVector3Cast = static_cast<TVector3Property*>(mpProperty);
QGroupBox *pGroupBox = static_cast<QGroupBox*>(mUI.EditorWidget);
WVectorEditor *pVectorEditor = static_cast<WVectorEditor*>(pGroupBox->children().first());
pVectorEditor->SetValue(pVector3Cast->Get());
break;
}
case eColorProperty:
{
TColorProperty *pColorCast = static_cast<TColorProperty*>(mpProperty);
WColorPicker *pColorPicker = static_cast<WColorPicker*>(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<TFileProperty*>(mpProperty);
CFileTemplate *pFileTemp = static_cast<CFileTemplate*>(pFileCast->Template());
WResourceSelector *pResourceSelector = static_cast<WResourceSelector*>(mUI.EditorWidget);
pResourceSelector->SetAllowedExtensions(pFileTemp->Extensions());
pResourceSelector->SetResource(pFileCast->Get());
break;
}
case eStructProperty:
{
CPropertyStruct *pStructCast = static_cast<CPropertyStruct*>(mpProperty);
QGroupBox *pGroupBox = static_cast<QGroupBox*>(mUI.EditorWidget);
QObjectList ChildList = pGroupBox->children();
u32 PropNum = 0;
foreach (QObject *pObj, ChildList)
{
if (pObj != pGroupBox->layout())
{
IProperty *pProp = pStructCast->PropertyByIndex(PropNum);
static_cast<WPropertyEditor*>(pObj)->SetProperty(pProp);
PropNum++;
}
}
break;
}
case eCharacterProperty:
{
TAnimParamsProperty *pAnimCast = static_cast<TAnimParamsProperty*>(mpProperty);
WAnimParamsEditor *pEditor = static_cast<WAnimParamsEditor*>(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);
}

View File

@ -1,36 +0,0 @@
#ifndef WPROPERTYEDITOR_H
#define WPROPERTYEDITOR_H
#include <Core/Resource/Script/IProperty.h>
#include <QWidget>
#include <QHBoxLayout>
#include <QLabel>
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

View File

@ -107,6 +107,11 @@ bool WResourceSelector::HasSupportedExtension(const CResourceInfo& rkRes)
}
// ************ GETTERS ************
CResource* WResourceSelector::GetResource()
{
return mResource.Load();
}
QString WResourceSelector::GetText()
{
return mUI.LineEdit->text();

View File

@ -56,6 +56,7 @@ public:
bool HasSupportedExtension(const CResourceInfo& rkRes);
// Getters
CResource* GetResource();
QString GetText();
bool IsEditButtonEnabled();
bool IsExportButtonEnabled();

View File

@ -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<int> 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();

View File

@ -14,22 +14,14 @@
<string>Prime World Editor</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="">
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="CSceneViewport" name="MainViewport" native="true">
<property name="sizePolicy">
@ -214,139 +206,19 @@
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1280</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="ActionOpen"/>
<addaction name="ActionSave"/>
</widget>
<widget class="QMenu" name="menuWindow">
<property name="title">
<string>Window</string>
</property>
</widget>
<widget class="QMenu" name="menuModels">
<property name="title">
<string>Models</string>
</property>
<addaction name="actionOpen_model_viewer"/>
</widget>
<widget class="QMenu" name="menuEdit">
<property name="title">
<string>Edit</string>
</property>
<addaction name="ActionSelectAll"/>
<addaction name="ActionInvertSelection"/>
</widget>
<widget class="QMenu" name="menuView">
<property name="title">
<string>View</string>
</property>
<widget class="QMenu" name="menuLighting">
<property name="title">
<string>Lighting</string>
</property>
<addaction name="ActionNoLighting"/>
<addaction name="ActionBasicLighting"/>
<addaction name="ActionWorldLighting"/>
</widget>
<widget class="QMenu" name="menuBloom">
<property name="title">
<string>Bloom</string>
</property>
<addaction name="ActionNoBloom"/>
<addaction name="ActionBloomMaps"/>
<addaction name="ActionFakeBloom"/>
<addaction name="ActionBloom"/>
</widget>
<addaction name="ActionGameMode"/>
<addaction name="separator"/>
<addaction name="ActionDrawWorld"/>
<addaction name="ActionDrawObjects"/>
<addaction name="ActionDrawCollision"/>
<addaction name="ActionDrawObjectCollision"/>
<addaction name="ActionDrawLights"/>
<addaction name="ActionDrawSky"/>
<addaction name="separator"/>
<addaction name="menuLighting"/>
<addaction name="menuBloom"/>
<addaction name="separator"/>
<addaction name="ActionDisableBackfaceCull"/>
<addaction name="ActionDisableAlpha"/>
</widget>
<widget class="QMenu" name="menuTools">
<property name="title">
<string>Tools</string>
</property>
<addaction name="ActionEditLayers"/>
<addaction name="ActionEditPoiToWorldMap"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
<addaction name="menuTools"/>
<addaction name="menuView"/>
<addaction name="menuModels"/>
<addaction name="menuWindow"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QToolBar" name="FileToolBar">
<property name="contextMenuPolicy">
<enum>Qt::NoContextMenu</enum>
</property>
<property name="windowTitle">
<string>toolBar_2</string>
</property>
<property name="movable">
<bool>false</bool>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="ActionOpen"/>
<addaction name="ActionSave"/>
</widget>
<widget class="QDockWidget" name="MainDock">
<property name="features">
<set>QDockWidget::DockWidgetMovable</set>
</property>
<property name="allowedAreas">
<set>Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea</set>
</property>
<property name="windowTitle">
<string/>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="MainDockContents">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTabWidget" name="TabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
@ -463,9 +335,113 @@
</attribute>
</widget>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1280</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="ActionOpen"/>
<addaction name="ActionSave"/>
</widget>
<widget class="QMenu" name="menuWindow">
<property name="title">
<string>Window</string>
</property>
</widget>
<widget class="QMenu" name="menuModels">
<property name="title">
<string>Models</string>
</property>
<addaction name="actionOpen_model_viewer"/>
</widget>
<widget class="QMenu" name="menuEdit">
<property name="title">
<string>Edit</string>
</property>
<addaction name="ActionSelectAll"/>
<addaction name="ActionInvertSelection"/>
</widget>
<widget class="QMenu" name="menuView">
<property name="title">
<string>View</string>
</property>
<widget class="QMenu" name="menuLighting">
<property name="title">
<string>Lighting</string>
</property>
<addaction name="ActionNoLighting"/>
<addaction name="ActionBasicLighting"/>
<addaction name="ActionWorldLighting"/>
</widget>
<widget class="QMenu" name="menuBloom">
<property name="title">
<string>Bloom</string>
</property>
<addaction name="ActionNoBloom"/>
<addaction name="ActionBloomMaps"/>
<addaction name="ActionFakeBloom"/>
<addaction name="ActionBloom"/>
</widget>
<addaction name="ActionGameMode"/>
<addaction name="separator"/>
<addaction name="ActionDrawWorld"/>
<addaction name="ActionDrawObjects"/>
<addaction name="ActionDrawCollision"/>
<addaction name="ActionDrawObjectCollision"/>
<addaction name="ActionDrawLights"/>
<addaction name="ActionDrawSky"/>
<addaction name="separator"/>
<addaction name="menuLighting"/>
<addaction name="menuBloom"/>
<addaction name="separator"/>
<addaction name="ActionDisableBackfaceCull"/>
<addaction name="ActionDisableAlpha"/>
</widget>
<widget class="QMenu" name="menuTools">
<property name="title">
<string>Tools</string>
</property>
<addaction name="ActionEditLayers"/>
<addaction name="ActionEditPoiToWorldMap"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
<addaction name="menuTools"/>
<addaction name="menuView"/>
<addaction name="menuModels"/>
<addaction name="menuWindow"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QToolBar" name="FileToolBar">
<property name="contextMenuPolicy">
<enum>Qt::NoContextMenu</enum>
</property>
<property name="windowTitle">
<string>toolBar_2</string>
</property>
<property name="movable">
<bool>false</bool>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="ActionOpen"/>
<addaction name="ActionSave"/>
</widget>
<widget class="QToolBar" name="MainToolBar">
<property name="contextMenuPolicy">
@ -796,9 +772,6 @@
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>TabWidget</tabstop>
</tabstops>
<resources>
<include location="../Icons.qrc"/>
</resources>

View File

@ -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<CSceneNode*>& Selection)
{
WPropertyEditor *pOldEditor = mpCurPropEditor;
ClearUI();
if (Selection.size() == 1)
@ -54,39 +56,9 @@ void WModifyTab::GenerateUI(QList<CSceneNode*>& Selection)
ui->ObjectsTabWidget->show();
CScriptNode *pScriptNode = static_cast<CScriptNode*>(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<CSceneNode*>& 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);

View File

@ -2,7 +2,6 @@
#define WMODIFYTAB_H
#include "CLinkModel.h"
#include "Editor/Widgets/WPropertyEditor.h"
#include <Core/Scene/CSceneNode.h>
#include <QWidget>
@ -24,8 +23,6 @@ class WModifyTab : public QWidget
CWorldEditor *mpWorldEditor;
CSceneNode *mpSelectedNode;
QMap<CScriptTemplate*, WPropertyEditor*> mCachedPropEditors;
WPropertyEditor *mpCurPropEditor;
CLinkModel *mpInLinkModel;
CLinkModel *mpOutLinkModel;
@ -35,7 +32,6 @@ public:
void SetEditor(CWorldEditor *pEditor);
void GenerateUI(QList<CSceneNode*>& Selection);
void ClearUI();
void ClearCachedEditors();
private:
Ui::WModifyTab *ui;

View File

@ -49,59 +49,27 @@
<number>0</number>
</property>
<item>
<widget class="QScrollArea" name="PropertiesScrollArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
<widget class="CPropertyView" name="PropertyView">
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
<property name="styleSheet">
<string notr="true">alternate-background-color: rgb(35,35,35);</string>
</property>
<property name="widgetResizable">
<property name="editTriggers">
<set>QAbstractItemView::AllEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<widget class="QWidget" name="PropertiesScrollContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>276</width>
<height>457</height>
</rect>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<layout class="QVBoxLayout" name="PropertiesScrollLayout">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
@ -223,6 +191,13 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>CPropertyView</class>
<extends>QTreeView</extends>
<header>Editor/PropertyEdit/CPropertyView.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8"?>
<enum name="Item">
<enumerators>
<enumerator ID="0x0" name="Power Beam" />
<enumerator ID="0x1" name="Dark Beam" />
<enumerator ID="0x2" name="Light Beam" />
<enumerator ID="0x3" name="Annihilator Beam" />
<enumerator ID="0x4" name="Super Missile" />
<enumerator ID="0x5" name="Darkburst" />
<enumerator ID="0x6" name="Sunburst" />
<enumerator ID="0x7" name="Sonic Boom" />
<enumerator ID="0x8" name="Combat Visor" />
<enumerator ID="0x9" name="Scan Visor" />
<enumerator ID="0xA" name="Dark Visor" />
<enumerator ID="0xB" name="Echo Visor" />
<enumerator ID="0xC" name="Varia Suit" />
<enumerator ID="0xD" name="Dark Suit" />
<enumerator ID="0xE" name="Light Suit" />
<enumerator ID="0xF" name="Morph Ball" />
<enumerator ID="0x10" name="Boost Ball" />
<enumerator ID="0x11" name="Spider Ball" />
<enumerator ID="0x12" name="Morph Ball Bomb" />
<enumerator ID="0x13" name="" />
<enumerator ID="0x14" name="" />
<enumerator ID="0x15" name="" />
<enumerator ID="0x16" name="Charge Beam" />
<enumerator ID="0x17" name="Grapple Beam" />
<enumerator ID="0x18" name="Space Jump Boots" />
<enumerator ID="0x19" name="Gravity Boost" />
<enumerator ID="0x1A" name="Seeker Launcher" />
<enumerator ID="0x1B" name="Screw Attack" />
<enumerator ID="0x1C" name="Energy Transfer Module (Pickup)" />
<enumerator ID="0x1D" name="Sky Temple Key 1" />
<enumerator ID="0x1E" name="Sky Temple Key 2" />
<enumerator ID="0x1F" name="Sky Temple Key 3" />
<enumerator ID="0x20" name="Dark Agon Key 1" />
<enumerator ID="0x21" name="Dark Agon Key 2" />
<enumerator ID="0x22" name="Dark Agon Key 3" />
<enumerator ID="0x23" name="Dark Torvus Key 1" />
<enumerator ID="0x24" name="Dark Torvus Key 2" />
<enumerator ID="0x25" name="Dark Torvus Key 3" />
<enumerator ID="0x26" name="Ing Hive Key 1" />
<enumerator ID="0x27" name="Ing Hive Key 2" />
<enumerator ID="0x28" name="Ing Hive Key 3" />
<enumerator ID="0x29" name="Health Refill" />
<enumerator ID="0x2A" name="Energy Tank" />
<enumerator ID="0x2B" name="Power Bomb" />
<enumerator ID="0x2C" name="Missile" />
<enumerator ID="0x2D" name="Dark Ammo" />
<enumerator ID="0x2E" name="Light Ammo" />
<enumerator ID="0x2F" name="Item Percentage" />
<enumerator ID="0x30" name="NumPlayersJoined" />
<enumerator ID="0x31" name="NumPlayersInOptionsMenu" />
<enumerator ID="0x32" name="" />
<enumerator ID="0x33" name="" />
<enumerator ID="0x34" name="Switch Weapon Power" />
<enumerator ID="0x35" name="Switch Weapon Dark" />
<enumerator ID="0x36" name="Switch Weapon Light" />
<enumerator ID="0x37" name="Switch Weapon Annihilator" />
<enumerator ID="0x38" name="" />
<enumerator ID="0x39" name="Invisibility" />
<enumerator ID="0x3A" name="AmpDamage" />
<enumerator ID="0x3B" name="Invincibility" />
<enumerator ID="0x3C" name="" />
<enumerator ID="0x3D" name="" />
<enumerator ID="0x3E" name="" />
<enumerator ID="0x3F" name="" />
<enumerator ID="0x40" name="" />
<enumerator ID="0x41" name="" />
<enumerator ID="0x42" name="" />
<enumerator ID="0x43" name="" />
<enumerator ID="0x44" name="" />
<enumerator ID="0x45" name="" />
<enumerator ID="0x46" name="" />
<enumerator ID="0x47" name="" />
<enumerator ID="0x48" name="" />
<enumerator ID="0x49" name="" />
<enumerator ID="0x4A" name="" />
<enumerator ID="0x4B" name="" />
<enumerator ID="0x4C" name="" />
<enumerator ID="0x4D" name="" />
<enumerator ID="0x4E" name="" />
<enumerator ID="0x4F" name="" />
<enumerator ID="0x50" name="Coin" />
<enumerator ID="0x51" name="Unlimited Missiles" />
<enumerator ID="0x52" name="Unlimited Beam Ammo" />
<enumerator ID="0x53" name="Dark Shield" />
<enumerator ID="0x54" name="Light Shield" />
<enumerator ID="0x55" name="Absorb Attack" />
<enumerator ID="0x56" name="Death Ball" />
<enumerator ID="0x57" name="Scan Virus" />
<enumerator ID="0x58" name="" />
<enumerator ID="0x59" name="(Disable Beams/Beam Ammo?)" />
<enumerator ID="0x5A" name="(Disable Missiles?)" />
<enumerator ID="0x5B" name="(Disable Unmorph/Remove Morph Ball?)" />
<enumerator ID="0x5C" name="Disable Ball" />
<enumerator ID="0x5D" name="(Remove Space Jump?)" />
<enumerator ID="0x5E" name="" />
<enumerator ID="0x5F" name="Hacked Effect" />
<enumerator ID="0x60" name="CannonBall" />
<enumerator ID="0x61" name="Violet Translator" />
<enumerator ID="0x62" name="Amber Translator" />
<enumerator ID="0x63" name="Emerald Translator" />
<enumerator ID="0x64" name="Cobalt Translator" />
<enumerator ID="0x65" name="Sky Temple Key 4" />
<enumerator ID="0x66" name="Sky Temple Key 5" />
<enumerator ID="0x67" name="Sky Temple Key 6" />
<enumerator ID="0x68" name="Sky Temple Key 7" />
<enumerator ID="0x69" name="Sky Temple Key 8" />
<enumerator ID="0x6A" name="Sky Temple Key 9" />
<enumerator ID="0x6B" name="Energy Transfer Module (Inventory)" />
<enumerator ID="0x6C" name="Charge Combo" />
</enumerators>
</enum>

View File

@ -9,9 +9,9 @@
<property ID="0x2E686C2A" type="vector3f">
<default>0.0, 0.0, 0.0</default>
</property>
<property ID="0xA02EF0C4" type="long">
<enum ID="0xA02EF0C4" template="Enums/Item.xml">
<default>0</default>
</property>
</enum>
<property ID="0x28C71B54" type="long">
<default>1</default>
</property>

View File

@ -1,64 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<enum name="InventorySlot">
<enumerators>
<enumerator ID="0xFB73F2B8" name="Unknown 1"/>
<enumerator ID="0x93AD6DF9" name="Unknown 2"/>
<enumerator ID="0x50A0AAA5" name="Unknown 3"/>
<enumerator ID="0x35488520" name="Unknown 4"/>
<enumerator ID="0x922DA6A8" name="Unknown 5"/>
<enumerator ID="0x90F0CED4" name="Unknown 6"/>
<enumerator ID="0xB7F4E76D" name="Unknown 7"/>
<enumerator ID="0x719B5C5D" name="Unknown 8"/>
<enumerator ID="0x1F2950DC" name="Unknown 9"/>
<enumerator ID="0x1FF64711" name="Unknown 10"/>
<enumerator ID="0xB9876CD1" name="Unknown 11"/>
<enumerator ID="0x96664E97" name="Unknown 12"/>
<enumerator ID="0xB3CADC47" name="Unknown 13"/>
<enumerator ID="0x73D674EA" name="Unknown 14"/>
<enumerator ID="0x662B235A" name="Unknown 15"/>
<enumerator ID="0x95C0052A" name="Unknown 16"/>
<enumerator ID="0xD9CD9EDE" name="Unknown 17"/>
<enumerator ID="0xD02B0AD8" name="Unknown 18"/>
<enumerator ID="0x26B5C6C5" name="Unknown 19"/>
<enumerator ID="0x1D966CE8" name="Unknown 20"/>
<enumerator ID="0xB36AECDD" name="Unknown 21"/>
<enumerator ID="0x50499B43" name="Unknown 22"/>
<enumerator ID="0xABBC4C2E" name="Unknown 23"/>
<enumerator ID="0x336E6C92" name="Unknown 24"/>
<enumerator ID="0xAA673D28" name="Unknown 25"/>
<enumerator ID="0xDD600DBE" name="Unknown 26"/>
<enumerator ID="0x4304981D" name="Unknown 27"/>
<enumerator ID="0x3403A88B" name="Unknown 28"/>
<enumerator ID="0xAD0AF931" name="Unknown 29"/>
<enumerator ID="0xDA0DC9A7" name="Unknown 30"/>
<enumerator ID="0x4AB2D436" name="Unknown 31"/>
<enumerator ID="0x3DB5E4A0" name="Unknown 32"/>
<enumerator ID="0x482F8235" name="Unknown 33"/>
<enumerator ID="0xB21BB8C7" name="Unknown 34"/>
<enumerator ID="0x4D415752" name="Unknown 35"/>
<enumerator ID="0x5568B8C9" name="Unknown 36"/>
<enumerator ID="0x49E8A1AC" name="Unknown 37"/>
<enumerator ID="0x515556A0" name="Unknown 38"/>
<enumerator ID="0x8C4847AB" name="Unknown 39"/>
<enumerator ID="0x87560845" name="Unknown 40"/>
<enumerator ID="0x8FEBB10D" name="Unknown 41"/>
<enumerator ID="0xF4FFB39D" name="Unknown 42"/>
<enumerator ID="0xE5BA1551" name="Unknown 43"/>
<enumerator ID="0x57A20D1A" name="Unknown 44"/>
<enumerator ID="0x81A153FF" name="Unknown 45"/>
<enumerator ID="0x7DC366E4" name="Unknown 46"/>
<enumerator ID="0x51E1A9FB" name="Unknown 47"/>
<enumerator ID="0x7B6A8F3A" name="Unknown 48"/>
<enumerator ID="0xB42B43DE" name="Unknown 49"/>
<enumerator ID="0x898D3214" name="Unknown 50"/>
<enumerator ID="0x3F82745E" name="Unknown 51"/>
<enumerator ID="0xC05C27EB" name="Unknown 52"/>
<enumerator ID="0xB0D22357" name="Unknown 53"/>
<enumerator ID="0xE3179F1B" name="Unknown 54"/>
<enumerator ID="0xF99E7798" name="Unknown 55"/>
<enumerator ID="0x4408D67B" name="Unknown 56"/>
<enumerator ID="0x47E7BCEA" name="Unknown 57"/>
<enumerator ID="0x22390F26" name="Unknown 58"/>
<enumerator ID="0x38BE4C42" name="Unknown 59"/>
</enumerators>
</enum>

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<enum name="Item">
<enumerators>
<enumerator ID="0xFB73F2B8" name="PowerBeam" />
<enumerator ID="0x93AD6DF9" name="PlasmaBeam" />
<enumerator ID="0x50A0AAA5" name="NovaBeam" />
<enumerator ID="0x35488520" name="ChargeUpgrade" />
<enumerator ID="0x922DA6A8" name="Missile" />
<enumerator ID="0x90F0CED4" name="IceMissile" />
<enumerator ID="0xB7F4E76D" name="SeekerMissile" />
<enumerator ID="0x719B5C5D" name="GrappleBeamPull" />
<enumerator ID="0x1F2950DC" name="GrappleBeamSwing" />
<enumerator ID="0x1FF64711" name="GrappleBeamVoltage" />
<enumerator ID="0xB9876CD1" name="Bomb" />
<enumerator ID="0x96664E97" name="CombatVisor" />
<enumerator ID="0xB3CADC47" name="ScanVisor" />
<enumerator ID="0x73D674EA" name="CommandVisor" />
<enumerator ID="0x662B235A" name="XRayVisor" />
<enumerator ID="0x95C0052A" name="DoubleJump" />
<enumerator ID="0xD9CD9EDE" name="ScrewAttack" />
<enumerator ID="0xD02B0AD8" name="SuitType" />
<enumerator ID="0x26B5C6C5" name="Energy" />
<enumerator ID="0x1D966CE8" name="HypermodeEnergy" />
<enumerator ID="0xB36AECDD" name="EnergyTank" />
<enumerator ID="0x50499B43" name="ItemPercentage" />
<enumerator ID="0xABBC4C2E" name="Fuses" />
<enumerator ID="0x336E6C92" name="Fuse1" />
<enumerator ID="0xAA673D28" name="Fuse2" />
<enumerator ID="0xDD600DBE" name="Fuse3" />
<enumerator ID="0x4304981D" name="Fuse4" />
<enumerator ID="0x3403A88B" name="Fuse5" />
<enumerator ID="0xAD0AF931" name="Fuse6" />
<enumerator ID="0xDA0DC9A7" name="Fuse7" />
<enumerator ID="0x4AB2D436" name="Fuse8" />
<enumerator ID="0x3DB5E4A0" name="Fuse9" />
<enumerator ID="0x482F8235" name="MorphBall" />
<enumerator ID="0xB21BB8C7" name="BoostBall" />
<enumerator ID="0x4D415752" name="SpiderBall" />
<enumerator ID="0x5568B8C9" name="HyperModeTank" />
<enumerator ID="0x49E8A1AC" name="HyperModeBeam" />
<enumerator ID="0x515556A0" name="HyperModeMissile" />
<enumerator ID="0x8C4847AB" name="HyperModeBall" />
<enumerator ID="0x87560845" name="HyperModeGrapple" />
<enumerator ID="0x8FEBB10D" name="HyperModePermanent" />
<enumerator ID="0xF4FFB39D" name="HyperModePhaaze" />
<enumerator ID="0xE5BA1551" name="HyperModeOriginal" />
<enumerator ID="0x57A20D1A" name="ShipGrapple" />
<enumerator ID="0x81A153FF" name="ShipMissile" />
<enumerator ID="0x7DC366E4" name="FaceCorruptionLevel" />
<enumerator ID="0x51E1A9FB" name="PhazonBall" />
<enumerator ID="0x7B6A8F3A" name="CannonBall" />
<enumerator ID="0xB42B43DE" name="ActivateMorphballBoost" />
<enumerator ID="0x898D3214" name="HyperShot" />
<enumerator ID="0x3F82745E" name="CommandVisorJammed" />
<enumerator ID="0xC05C27EB" name="Stat_EnemiesKilled" />
<enumerator ID="0xB0D22357" name="Stat_ShotsFired" />
<enumerator ID="0xE3179F1B" name="Stat_DamageReceived" />
<enumerator ID="0xF99E7798" name="Stat_DataSaves" />
<enumerator ID="0x4408D67B" name="Stat_HypermodeUses" />
<enumerator ID="0x47E7BCEA" name="Stat_CommandoKills" />
<enumerator ID="0x22390F26" name="Stat_TinCanHighScore" />
<enumerator ID="0x38BE4C42" name="Stat_TinCanCurrentScore" />
</enumerators>
</enum>

View File

@ -3,7 +3,7 @@
<name>EffectRepulsor</name>
<properties>
<struct ID="0x255A4580" template="Structs/EditorProperties.xml"/>
<enum ID="0xA169D424" template="Enums/InventorySlot.xml">
<enum ID="0xA169D424" template="Enums/Item.xml">
<default>0xFB73F2B8</default>
</enum>
<property ID="0xB68C6D96" type="file" extensions="PART"/>

View File

@ -10,7 +10,7 @@
<property ID="0x2E686C2A" type="vector3f">
<default>0.0, 0.0, 0.0</default>
</property>
<enum ID="0xA02EF0C4" template="Enums/InventorySlot.xml">
<enum ID="0xA02EF0C4" template="Enums/Item.xml">
<default>0xFB73F2B8</default>
</enum>
<property ID="0x28C71B54" type="long">

View File

@ -21,7 +21,7 @@
<property ID="0x6D10C987" type="character"/>
<property ID="0x97ADB194" type="character"/>
<property ID="0xA797679C" type="character"/>
<enum ID="0x08072DA5" template="Enums/InventorySlot.xml">
<enum ID="0x08072DA5" template="Enums/Item.xml">
<default>0xFB73F2B8</default>
</enum>
<enum ID="0x48EF8ADE">

View File

@ -88,7 +88,7 @@
<property ID="0xB581574B" type="long">
<default>0</default>
</property>
<enum ID="0x3FA164BC" template="Enums/InventorySlot.xml">
<enum ID="0x3FA164BC" template="Enums/Item.xml">
<default>0xFB73F2B8</default>
</enum>
<property ID="0x5ECF8F67" type="file" extensions="UNKN"/>

View File

@ -7,7 +7,7 @@
<property ID="0x794F9BEB" type="bool">
<default>false</default>
</property>
<enum ID="0xD3AF8D72" template="Enums/InventorySlot.xml">
<enum ID="0xD3AF8D72" template="Enums/Item.xml">
<default>0xFB73F2B8</default>
</enum>
<property ID="0x03BDEA98" type="long">