mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-05-25 16:51:38 +00:00
Fixed a lot of property bugs, fixed more various VS2017 compiler errors, property editor works correctly now
This commit is contained in:
parent
6cbc2a3208
commit
4faadbda61
@ -6,7 +6,7 @@
|
||||
|
||||
class CVectorOutStream : public IOutputStream
|
||||
{
|
||||
static const u32 skAllocSize = 1024; // must be power of 2
|
||||
static const u32 skAllocSize = 1; // must be 1 or a power of 2
|
||||
|
||||
std::vector<char> *mpVector;
|
||||
bool mOwnsVector;
|
||||
|
@ -932,7 +932,46 @@ public:
|
||||
|
||||
static _TString FromFloat(float Value, int MinDecimals = 1)
|
||||
{
|
||||
return Format("%f.*", Value, MinDecimals);
|
||||
// Initial float -> string conversion
|
||||
std::basic_stringstream<CharType> SStream;
|
||||
if (MinDecimals > 0) SStream.setf(std::ios_base::showpoint);
|
||||
SStream.setf(std::ios_base::fixed, std::ios_base::floatfield);
|
||||
SStream << Value;
|
||||
_TString Out = SStream.str();
|
||||
|
||||
// Make sure we have the right number of decimals
|
||||
int DecIdx = Out.IndexOf(CHAR_LITERAL('.'));
|
||||
|
||||
if (DecIdx == -1 && MinDecimals > 0)
|
||||
{
|
||||
DecIdx = Out.Size();
|
||||
Out.Append(CHAR_LITERAL('.'));
|
||||
}
|
||||
|
||||
int NumZeroes = (DecIdx == -1 ? 0 : Out.Size() - (DecIdx + 1));
|
||||
|
||||
// Add extra zeroes to meet the minimum decimal count
|
||||
if (NumZeroes < MinDecimals)
|
||||
{
|
||||
for (int iDec = 0; iDec < (MinDecimals - NumZeroes); iDec++)
|
||||
Out.Append(CHAR_LITERAL('.'));
|
||||
}
|
||||
|
||||
// Remove unnecessary trailing zeroes from the end of the string
|
||||
else if (NumZeroes > MinDecimals)
|
||||
{
|
||||
while (Out.Back() == CHAR_LITERAL('0') && NumZeroes > MinDecimals && NumZeroes > 0)
|
||||
{
|
||||
Out = Out.ChopBack(1);
|
||||
NumZeroes--;
|
||||
}
|
||||
|
||||
// Remove decimal point
|
||||
if (NumZeroes == 0)
|
||||
Out = Out.ChopBack(1);
|
||||
}
|
||||
|
||||
return Out;
|
||||
}
|
||||
|
||||
static _TString FileSizeString(u64 Size, u32 NumDecimals = 2)
|
||||
|
@ -112,7 +112,7 @@ public:
|
||||
inline void SetOptions(FMaterialOptions Options) { mOptions = Options; Update(); }
|
||||
inline void SetVertexDescription(FVertexDescription Desc) { mVtxDesc = Desc; Update(); }
|
||||
inline void SetBlendMode(GLenum SrcFac, GLenum DstFac) { mBlendSrcFac = SrcFac; mBlendDstFac = DstFac; mRecalcHash = true; }
|
||||
inline void SetKonst(CColor& Konst, u32 KIndex) { mKonstColors[KIndex] = Konst; Update(); }
|
||||
inline void SetKonst(const CColor& Konst, u32 KIndex) { mKonstColors[KIndex] = Konst; Update(); }
|
||||
inline void SetIndTexture(CTexture *pTex) { mpIndirectTexture = pTex; }
|
||||
inline void SetLightingEnabled(bool Enabled) { mLightingEnabled = Enabled; Update(); }
|
||||
|
||||
|
@ -24,7 +24,7 @@ public:
|
||||
|
||||
CVertex() {}
|
||||
|
||||
CVertex(CVector3f& rPos)
|
||||
CVertex(const CVector3f& rPos)
|
||||
{
|
||||
Position = rPos;
|
||||
}
|
||||
|
@ -88,6 +88,9 @@ bool CScriptObject::IsEditorProperty(IPropertyNew *pProp)
|
||||
(pProp == mScale.Property()) ||
|
||||
(pProp == mActive.Property()) ||
|
||||
(pProp == mLightParameters.Property()) ||
|
||||
(pProp->Parent() == mPosition.Property()) ||
|
||||
(pProp->Parent() == mRotation.Property()) ||
|
||||
(pProp->Parent() == mScale.Property()) ||
|
||||
(pProp->Parent() == mLightParameters.Property())
|
||||
);
|
||||
}
|
||||
|
@ -55,11 +55,6 @@ void IPropertyNew::_CalcOffset()
|
||||
}
|
||||
}
|
||||
|
||||
u32 IPropertyNew::_GetOffset() const
|
||||
{
|
||||
return mOffset;
|
||||
}
|
||||
|
||||
void IPropertyNew::_ClearChildren()
|
||||
{
|
||||
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
||||
@ -118,7 +113,7 @@ void IPropertyNew::InitFromArchetype(IPropertyNew* pOther)
|
||||
{
|
||||
//@todo maybe somehow use Serialize for this instead?
|
||||
mpArchetype = pOther;
|
||||
mFlags = pOther->mFlags & ~EPropertyFlag::ArchetypeCopyFlags;
|
||||
mFlags = pOther->mFlags & EPropertyFlag::ArchetypeCopyFlags;
|
||||
mID = pOther->mID;
|
||||
mName = pOther->mName;
|
||||
mDescription = pOther->mDescription;
|
||||
@ -161,7 +156,8 @@ void* IPropertyNew::RawValuePtr(void* pData) const
|
||||
return pData;
|
||||
|
||||
void* pBasePtr = (mpPointerParent ? mpPointerParent->GetChildDataPointer(pData) : pData);
|
||||
return ((char*)pBasePtr + mOffset);
|
||||
void* pValuePtr = ((char*)pBasePtr + mOffset);
|
||||
return pValuePtr;
|
||||
}
|
||||
|
||||
IPropertyNew* IPropertyNew::ChildByID(u32 ID) const
|
||||
@ -342,8 +338,7 @@ IPropertyNew* IPropertyNew::Create(EPropertyTypeNew Type,
|
||||
}
|
||||
|
||||
IPropertyNew* IPropertyNew::CreateCopy(IPropertyNew* pArchetype,
|
||||
IPropertyNew* pParent,
|
||||
bool CallPostInit /*= true*/)
|
||||
IPropertyNew* pParent)
|
||||
{
|
||||
// Note this is mainly going to be used to create copies from struct/enum/flag archetype properties.
|
||||
// Properties that have archetypes will never be the root property of a script template, and there
|
||||
@ -354,11 +349,5 @@ IPropertyNew* IPropertyNew::CreateCopy(IPropertyNew* pArchetype,
|
||||
IPropertyNew* pOut = Create(pArchetype->Type(), pParent, pParent->mpMasterTemplate, pParent->mpScriptTemplate, false);
|
||||
pOut->InitFromArchetype(pArchetype);
|
||||
pArchetype->mSubInstances.push_back(pOut);
|
||||
|
||||
if (CallPostInit)
|
||||
{
|
||||
pOut->PostInitialize();
|
||||
}
|
||||
|
||||
return pOut;
|
||||
}
|
||||
|
@ -157,7 +157,6 @@ protected:
|
||||
/** Private constructor - use static methods to instantiate */
|
||||
IPropertyNew();
|
||||
void _CalcOffset();
|
||||
u32 _GetOffset() const;
|
||||
void _ClearChildren();
|
||||
|
||||
/** Called after property is created and fully initialized */
|
||||
@ -213,6 +212,7 @@ public:
|
||||
inline TString Description() const;
|
||||
inline TString Suffix() const;
|
||||
inline TIDString IDString(bool FullyQualified) const;
|
||||
inline u32 Offset() const;
|
||||
inline u32 ID() const;
|
||||
|
||||
inline bool IsArchetype() const { return mFlags.HasFlag(EPropertyFlag::IsArchetype); }
|
||||
@ -227,8 +227,7 @@ public:
|
||||
bool CallPostInit = true);
|
||||
|
||||
static IPropertyNew* CreateCopy(IPropertyNew* pArchetype,
|
||||
IPropertyNew* pParent,
|
||||
bool CallPostInit = true);
|
||||
IPropertyNew* pParent);
|
||||
};
|
||||
|
||||
inline ECookPreferenceNew IPropertyNew::CookPreference() const
|
||||
@ -298,12 +297,17 @@ inline TString IPropertyNew::Suffix() const
|
||||
|
||||
inline TString IPropertyNew::IDString(bool FullyQualified) const
|
||||
{
|
||||
if (FullyQualified && mpParent != nullptr)
|
||||
if (FullyQualified && mpParent != nullptr && mpParent->Parent() != nullptr)
|
||||
return mpParent->IDString(FullyQualified) + ":" + TString::HexString(mID);
|
||||
else
|
||||
return TString::HexString(mID);
|
||||
}
|
||||
|
||||
inline u32 IPropertyNew::Offset() const
|
||||
{
|
||||
return mOffset;
|
||||
}
|
||||
|
||||
inline u32 IPropertyNew::ID() const
|
||||
{
|
||||
return mID;
|
||||
|
@ -24,8 +24,9 @@ class CArrayProperty : public TTypedPropertyNew<int, EPropertyTypeNew::Array>
|
||||
{
|
||||
friend class CTemplateLoader;
|
||||
/** This class inherits from TTypedPropertyNew<int> in order to expose the array
|
||||
* count value. Outside users can edit this value and we respond by updating the
|
||||
* allocated space, handling destruction/construction, etc.
|
||||
* count value (the first member of SScriptArray). Outside users can edit this
|
||||
* value and we respond by updating the allocated space, handling item destruction
|
||||
* and construction, etc.
|
||||
*/
|
||||
IPropertyNew* mpItemArchetype;
|
||||
|
||||
@ -99,7 +100,7 @@ public:
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
u32 Count = ArrayCount(pData);
|
||||
Arc.SerializePrimitive(Count);
|
||||
Arc.SerializeContainerSize(Count, "ArrayElement");
|
||||
|
||||
if (Arc.IsReader())
|
||||
Resize(pData, Count);
|
||||
@ -115,6 +116,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void InitFromArchetype(IPropertyNew* pOther)
|
||||
{
|
||||
TTypedPropertyNew::InitFromArchetype(pOther);
|
||||
CArrayProperty* pOtherArray = static_cast<CArrayProperty*>(pOther);
|
||||
mpItemArchetype = IPropertyNew::CreateCopy(pOtherArray->mpItemArchetype, this);
|
||||
}
|
||||
|
||||
u32 ArrayCount(void* pPropertyData) const
|
||||
{
|
||||
return ValueRef(pPropertyData);
|
||||
|
@ -18,6 +18,12 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void InitFromArchetype(IPropertyNew* pOther)
|
||||
{
|
||||
TTypedPropertyNew::InitFromArchetype(pOther);
|
||||
mTypeFilter = static_cast<CAssetProperty*>(pOther)->mTypeFilter;
|
||||
}
|
||||
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
Arc.SerializePrimitive( ValueRef(pData) );
|
||||
|
@ -46,6 +46,13 @@ public:
|
||||
Arc.SerializePrimitive( (u32&) ValueRef(pData) );
|
||||
}
|
||||
|
||||
virtual void InitFromArchetype(IPropertyNew* pOther)
|
||||
{
|
||||
TTypedPropertyNew::InitFromArchetype(pOther);
|
||||
TEnumPropertyBase* pOtherEnum = static_cast<TEnumPropertyBase*>(pOther);
|
||||
mValues = pOtherEnum->mValues;
|
||||
}
|
||||
|
||||
virtual TString GetTemplateFileName()
|
||||
{
|
||||
ASSERT(IsArchetype() || mpArchetype);
|
||||
|
@ -75,11 +75,30 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void PostInitialize()
|
||||
{
|
||||
TTypedPropertyNew::PostInitialize();
|
||||
|
||||
// Create AllFlags mask
|
||||
mAllFlags = 0;
|
||||
|
||||
for (int FlagIdx = 0; FlagIdx < mBitFlags.size(); FlagIdx++)
|
||||
mAllFlags |= mBitFlags[FlagIdx].Mask;
|
||||
}
|
||||
|
||||
virtual void SerializeValue(void* pData, IArchive& rArc) const
|
||||
{
|
||||
rArc.SerializeHexPrimitive( (u32&) ValueRef(pData) );
|
||||
}
|
||||
|
||||
virtual void InitFromArchetype(IPropertyNew* pOther)
|
||||
{
|
||||
TTypedPropertyNew::InitFromArchetype(pOther);
|
||||
CFlagsProperty* pOtherFlags = static_cast<CFlagsProperty*>(pOther);
|
||||
mBitFlags = pOtherFlags->mBitFlags;
|
||||
mAllFlags = pOtherFlags->mAllFlags;
|
||||
}
|
||||
|
||||
virtual TString GetTemplateFileName()
|
||||
{
|
||||
ASSERT(IsArchetype() || mpArchetype);
|
||||
|
@ -18,7 +18,7 @@ public:
|
||||
Arc.SerializePrimitive( (float&) ValueRef(pData) );
|
||||
}
|
||||
|
||||
virtual TString ValueAsString(void* pData)
|
||||
virtual TString ValueAsString(void* pData) const
|
||||
{
|
||||
return TString::FromFloat( Value(pData) );
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ public:
|
||||
Arc.SerializePrimitive( (u32&) ValueRef(pData) );
|
||||
}
|
||||
|
||||
virtual TString ValueAsString(void* pData)
|
||||
virtual TString ValueAsString(void* pData) const
|
||||
{
|
||||
return TString::FromInt32( Value(pData), 0, 10 );
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ public:
|
||||
if (!mChildren.empty())
|
||||
{
|
||||
IPropertyNew* pLastChild = mChildren.back();
|
||||
return _GetOffset() + pLastChild->DataSize();
|
||||
return (pLastChild->Offset() - Offset()) + pLastChild->DataSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -36,7 +36,11 @@ public:
|
||||
|
||||
virtual u32 DataAlignment() const
|
||||
{
|
||||
return (mChildren.empty() ? 1 : mChildren[0]->DataAlignment());
|
||||
// TODO. Should be aligned with the first child, but this function is called before children are loaded.
|
||||
// So for now just use 8 to ensure correct alignment for all child types, but this is wasteful...
|
||||
return 8;
|
||||
|
||||
//return (mChildren.empty() ? 1 : mChildren[0]->DataAlignment());
|
||||
}
|
||||
|
||||
virtual void Construct(void* pData) const
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
/** Accessors */
|
||||
inline CScriptObject* Object() const { return mpObject; }
|
||||
inline PropertyClass* Property() const { return mpProperty; }
|
||||
inline ValueType Get() const { ASSERT(IsValid()); return *((ValueType*) mpProperty->RawValuePtr( mpObject->PropertyData() )); }
|
||||
inline ValueType Get() const { return IsValid() ? *((ValueType*) mpProperty->RawValuePtr( mpObject->PropertyData() )) : ValueType(); }
|
||||
inline void Set(const ValueType& kIn) const { if (IsValid()) *((ValueType*) mpProperty->RawValuePtr( mpObject->PropertyData() )) = kIn; }
|
||||
inline bool IsValid() const { return mpObject != nullptr && mpProperty != nullptr; }
|
||||
|
||||
|
@ -496,13 +496,13 @@ void CScriptNode::PropertyModified(IPropertyNew* pProp)
|
||||
if (pProp == pTemplate->NameProperty())
|
||||
SetName("[" + mpInstance->Template()->Name() + "] " + mpInstance->InstanceName());
|
||||
|
||||
else if (pProp == pTemplate->PositionProperty())
|
||||
else if (pProp == pTemplate->PositionProperty() || pProp->Parent() == pTemplate->PositionProperty())
|
||||
mPosition = mpInstance->Position();
|
||||
|
||||
else if (pProp == pTemplate->RotationProperty())
|
||||
else if (pProp == pTemplate->RotationProperty() || pProp->Parent() == pTemplate->RotationProperty())
|
||||
mRotation = CQuaternion::FromEuler(mpInstance->Rotation());
|
||||
|
||||
else if (pProp == pTemplate->ScaleProperty())
|
||||
else if (pProp == pTemplate->ScaleProperty() || pProp->Parent() == pTemplate->ScaleProperty())
|
||||
mScale = mpInstance->Scale();
|
||||
|
||||
MarkTransformChanged();
|
||||
@ -560,7 +560,7 @@ void CScriptNode::GeneratePosition()
|
||||
if (!mHasValidPosition)
|
||||
{
|
||||
// Default to center of the active area; this is to prevent recursion issues
|
||||
CTransform4f& AreaTransform = mpScene->ActiveArea()->Transform();
|
||||
CTransform4f AreaTransform = mpScene->ActiveArea()->Transform();
|
||||
mPosition = CVector3f(AreaTransform[0][3], AreaTransform[1][3], AreaTransform[2][3]);
|
||||
mHasValidPosition = true;
|
||||
MarkTransformChanged();
|
||||
|
@ -764,9 +764,10 @@ void CModelEditorWindow::ConvertToDDS()
|
||||
if (Input.isEmpty()) return;
|
||||
|
||||
TString TexFilename = TO_TSTRING(Input);
|
||||
CTexture *pTex = CTextureDecoder::LoadDDS( CFileInStream(TexFilename, IOUtil::eLittleEndian), nullptr );
|
||||
TString OutName = TexFilename.GetFilePathWithoutExtension() + ".dds";
|
||||
CFileInStream InTextureFile(TexFilename, IOUtil::eLittleEndian);
|
||||
CTexture *pTex = CTextureDecoder::LoadTXTR( InTextureFile, nullptr );
|
||||
|
||||
TString OutName = TexFilename.GetFilePathWithoutExtension() + ".dds";
|
||||
CFileOutStream Out(OutName, IOUtil::eLittleEndian);
|
||||
if (!Out.IsValid()) QMessageBox::warning(this, "Error", "Couldn't open output DDS!");
|
||||
|
||||
@ -786,7 +787,8 @@ void CModelEditorWindow::ConvertToTXTR()
|
||||
if (Input.isEmpty()) return;
|
||||
|
||||
TString TexFilename = TO_TSTRING(Input);
|
||||
CTexture *pTex = CTextureDecoder::LoadDDS(CFileInStream(TexFilename, IOUtil::eLittleEndian), nullptr);
|
||||
CFileInStream InTextureFile = CFileInStream(TexFilename, IOUtil::eLittleEndian);
|
||||
CTexture *pTex = CTextureDecoder::LoadDDS(InTextureFile, nullptr);
|
||||
TString OutName = TexFilename.GetFilePathWithoutExtension() + ".txtr";
|
||||
|
||||
if ((pTex->TexelFormat() != eDXT1) || (pTex->NumMipMaps() > 1))
|
||||
|
@ -354,16 +354,40 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
|
||||
if (!mpModel) return;
|
||||
if (!pEditor) return;
|
||||
|
||||
//FIXME
|
||||
/* IPropertyNew *pProp = mpModel->PropertyForIndex(rkIndex, false);
|
||||
bool HadEditInProgress = mEditInProgress;
|
||||
mEditInProgress = mInRelayWidgetEdit && (pEditor->hasFocus() || pProp->Type() == EPropertyTypeNew::Color);
|
||||
bool EditJustFinished = (!mEditInProgress && HadEditInProgress);
|
||||
|
||||
bool Matches = false;
|
||||
IUndoCommand* pCommand = nullptr;
|
||||
IEditPropertyCommand* pCommand = nullptr;
|
||||
IPropertyNew *pProp = mpModel->PropertyForIndex(rkIndex, true);
|
||||
void* pData = mpModel->GetPropertyData();
|
||||
|
||||
if (pProp)
|
||||
{
|
||||
EPropertyTypeNew Type = pProp->Type();
|
||||
|
||||
if (Type != EPropertyTypeNew::Array)
|
||||
{
|
||||
// TODO: support this for non script object properties
|
||||
pCommand = new CEditScriptPropertyCommand(mpEditor, mpModel->GetScriptObject(), pProp);
|
||||
pCommand->SaveOldData();
|
||||
|
||||
// Handle sub-properties of flags and animation sets
|
||||
if (rkIndex.internalId() & 0x80000000)
|
||||
{
|
||||
if (pProp->Type() == EPropertyTypeNew::AnimationSet)
|
||||
SetCharacterModelData(pEditor, rkIndex);
|
||||
|
||||
else if (pProp->Type() == EPropertyTypeNew::Flags)
|
||||
{
|
||||
QCheckBox* pCheckBox = static_cast<QCheckBox*>(pEditor);
|
||||
CFlagsProperty* pFlags = static_cast<CFlagsProperty*>(pProp);
|
||||
u32 Mask = pFlags->FlagMask(rkIndex.row());
|
||||
|
||||
int Flags = pFlags->Value(pData);
|
||||
if (pCheckBox->isChecked()) Flags |= Mask;
|
||||
else Flags &= ~Mask;
|
||||
pFlags->ValueRef(pData) = Flags;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
switch (pProp->Type())
|
||||
{
|
||||
@ -371,80 +395,93 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
|
||||
case EPropertyTypeNew::Bool:
|
||||
{
|
||||
QCheckBox *pCheckBox = static_cast<QCheckBox*>(pEditor);
|
||||
bool NewValue =
|
||||
pCommand = new TEditScriptPropertyCommand<CBoolProperty>(pProp, mpModel->GetScriptObject(), mpEditor, pCheckBox->isChecked(),
|
||||
bool NewValue = TEditScriptPropertyCommand<CBoolProperty>(pProp,
|
||||
TBoolProperty *pBool = static_cast<TBoolProperty*>(pProp);
|
||||
pBool->Set(pCheckBox->isChecked());
|
||||
CBoolProperty* pBool = static_cast<CBoolProperty*>(pProp);
|
||||
pBool->ValueRef(pData) = pCheckBox->isChecked();
|
||||
break;
|
||||
}
|
||||
|
||||
case eShortProperty:
|
||||
case EPropertyTypeNew::Short:
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
|
||||
TShortProperty *pShort = static_cast<TShortProperty*>(pProp);
|
||||
pShort->Set(pSpinBox->value());
|
||||
WIntegralSpinBox* pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
|
||||
CShortProperty* pShort = static_cast<CShortProperty*>(pProp);
|
||||
pShort->ValueRef(pData) = pSpinBox->value();
|
||||
break;
|
||||
}
|
||||
|
||||
case eLongProperty:
|
||||
case eSoundProperty:
|
||||
case EPropertyTypeNew::Int:
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
|
||||
TLongProperty *pLong = static_cast<TLongProperty*>(pProp);
|
||||
pLong->Set(pSpinBox->value());
|
||||
WIntegralSpinBox* pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
|
||||
CIntProperty* pInt = static_cast<CIntProperty*>(pProp);
|
||||
pInt->ValueRef(pData) = pSpinBox->value();
|
||||
break;
|
||||
}
|
||||
|
||||
case eFloatProperty:
|
||||
case EPropertyTypeNew::Sound:
|
||||
{
|
||||
WDraggableSpinBox *pSpinBox = static_cast<WDraggableSpinBox*>(pEditor);
|
||||
TFloatProperty *pFloat = static_cast<TFloatProperty*>(pProp);
|
||||
pFloat->Set((float) pSpinBox->value());
|
||||
WIntegralSpinBox* pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
|
||||
CSoundProperty* pSound = static_cast<CSoundProperty*>(pProp);
|
||||
pSound->ValueRef(pData) = pSpinBox->value();
|
||||
break;
|
||||
}
|
||||
|
||||
case eColorProperty:
|
||||
case EPropertyTypeNew::Float:
|
||||
{
|
||||
WColorPicker *pColorPicker = static_cast<WColorPicker*>(pEditor);
|
||||
TColorProperty *pColor = static_cast<TColorProperty*>(pProp);
|
||||
WDraggableSpinBox* pSpinBox = static_cast<WDraggableSpinBox*>(pEditor);
|
||||
CFloatProperty* pFloat = static_cast<CFloatProperty*>(pProp);
|
||||
pFloat->ValueRef(pData) = (float) pSpinBox->value();
|
||||
break;
|
||||
}
|
||||
|
||||
case EPropertyTypeNew::Color:
|
||||
{
|
||||
WColorPicker* pColorPicker = static_cast<WColorPicker*>(pEditor);
|
||||
CColorProperty* pColor = static_cast<CColorProperty*>(pProp);
|
||||
|
||||
QColor Color = pColorPicker->Color();
|
||||
pColor->Set(TO_CCOLOR(Color));
|
||||
pColor->ValueRef(pData) = TO_CCOLOR(Color);
|
||||
break;
|
||||
}
|
||||
|
||||
case eStringProperty:
|
||||
case EPropertyTypeNew::String:
|
||||
{
|
||||
QLineEdit *pLineEdit = static_cast<QLineEdit*>(pEditor);
|
||||
TStringProperty *pString = static_cast<TStringProperty*>(pProp);
|
||||
pString->Set(TO_TSTRING(pLineEdit->text()));
|
||||
QLineEdit* pLineEdit = static_cast<QLineEdit*>(pEditor);
|
||||
CStringProperty* pString = static_cast<CStringProperty*>(pProp);
|
||||
pString->ValueRef(pData) = TO_TSTRING(pLineEdit->text());
|
||||
break;
|
||||
}
|
||||
|
||||
case eEnumProperty:
|
||||
case EPropertyTypeNew::Enum:
|
||||
case EPropertyTypeNew::Choice:
|
||||
{
|
||||
QComboBox *pComboBox = static_cast<QComboBox*>(pEditor);
|
||||
TEnumProperty *pEnum = static_cast<TEnumProperty*>(pProp);
|
||||
CEnumTemplate *pTemp = static_cast<CEnumTemplate*>(pProp->Template());
|
||||
pEnum->Set(pTemp->EnumeratorID(pComboBox->currentIndex()));
|
||||
QComboBox* pComboBox = static_cast<QComboBox*>(pEditor);
|
||||
CEnumProperty* pEnum = static_cast<CEnumProperty*>(pProp);
|
||||
pEnum->ValueRef(pData) = pEnum->ValueID(pComboBox->currentIndex());
|
||||
break;
|
||||
}
|
||||
|
||||
case eAssetProperty:
|
||||
case EPropertyTypeNew::Asset:
|
||||
{
|
||||
CResourceSelector *pSelector = static_cast<CResourceSelector*>(pEditor);
|
||||
CResourceEntry *pEntry = pSelector->Entry();
|
||||
CResourceSelector* pSelector = static_cast<CResourceSelector*>(pEditor);
|
||||
CResourceEntry* pEntry = pSelector->Entry();
|
||||
|
||||
TAssetProperty *pAsset = static_cast<TAssetProperty*>(pProp);
|
||||
pAsset->Set(pEntry ? pEntry->ID() : CAssetID::InvalidID(mpEditor->CurrentGame()));
|
||||
CAssetProperty* pAsset = static_cast<CAssetProperty*>(pProp);
|
||||
pAsset->ValueRef(pData) = (pEntry ? pEntry->ID() : CAssetID::InvalidID(pAsset->Game()));
|
||||
break;
|
||||
}
|
||||
|
||||
case eArrayProperty:
|
||||
}
|
||||
}
|
||||
|
||||
pCommand->SaveNewData();
|
||||
}
|
||||
|
||||
// Array
|
||||
else
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
|
||||
CArrayProperty *pArray = static_cast<CArrayProperty*>(pProp);
|
||||
//FIXME
|
||||
/*
|
||||
WIntegralSpinBox* pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
|
||||
CArrayProperty* pArray = static_cast<CArrayProperty*>(pProp);
|
||||
int NewCount = pSpinBox->value();
|
||||
|
||||
if (pArray->Count() != NewCount)
|
||||
@ -452,91 +489,35 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
|
||||
CResizeScriptArrayCommand *pCmd = new CResizeScriptArrayCommand(pProp, mpEditor, mpModel, NewCount);
|
||||
mpEditor->UndoStack()->push(pCmd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
// Check for character/bitfield/vector/color sub-properties
|
||||
else if (rkIndex.internalId() & 0x1)
|
||||
{
|
||||
pProp = mpModel->PropertyForIndex(rkIndex, true);
|
||||
|
||||
IPropertyValue *pRawValue = pProp->RawValue();
|
||||
pOldValue = pRawValue ? pRawValue->Clone() : nullptr;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pProp && pOldValue)
|
||||
if (pCommand)
|
||||
{
|
||||
// Check for edit in progress
|
||||
bool Matches = pOldValue->Matches(pProp->RawValue());
|
||||
bool DataChanged = pCommand->IsNewDataDifferent();
|
||||
|
||||
if (!Matches && mInRelayWidgetEdit && (pEditor->hasFocus() || pProp->Type() == eColorProperty))
|
||||
if (DataChanged && mInRelayWidgetEdit && (pEditor->hasFocus() || pProp->Type() == EPropertyTypeNew::Color))
|
||||
mEditInProgress = true;
|
||||
|
||||
bool EditInProgress = mEditInProgress;
|
||||
bool EditWasInProgress = mEditInProgress;
|
||||
|
||||
// Check for edit finished
|
||||
if (!mInRelayWidgetEdit || (!pEditor->hasFocus() && pProp->Type() != eColorProperty))
|
||||
if (!mInRelayWidgetEdit || (!pEditor->hasFocus() && pProp->Type() != EPropertyTypeNew::Color))
|
||||
mEditInProgress = false;
|
||||
|
||||
// Create undo command
|
||||
if (!Matches || EditInProgress)
|
||||
// Push undo command
|
||||
if (DataChanged || EditWasInProgress)
|
||||
{
|
||||
// Always consider the edit done for bool properties
|
||||
CEditScriptPropertyCommand *pCommand = new CEditScriptPropertyCommand(pProp, mpEditor, pOldValue, (!mEditInProgress || pProp->Type() == eBoolProperty));
|
||||
pCommand->SetEditComplete(!mEditInProgress || pProp->Type() == EPropertyTypeNew::Bool);
|
||||
mpEditor->UndoStack()->push(pCommand);
|
||||
}
|
||||
|
||||
else
|
||||
delete pOldValue;
|
||||
}*/
|
||||
delete pCommand;
|
||||
}
|
||||
}
|
||||
|
||||
bool CPropertyDelegate::eventFilter(QObject *pObject, QEvent *pEvent)
|
||||
@ -558,18 +539,16 @@ bool CPropertyDelegate::eventFilter(QObject *pObject, QEvent *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
|
||||
{
|
||||
//FIXME
|
||||
/* TCharacterProperty *pProp = static_cast<TCharacterProperty*>(mpModel->PropertyForIndex(rkIndex, true));
|
||||
CAnimationParameters Params = pProp->Get();
|
||||
CAnimationSetProperty* pAnimSetProp = TPropCast<CAnimationSetProperty>(mpModel->PropertyForIndex(rkIndex, true));
|
||||
CAnimationParameters Params = pAnimSetProp->Value(mpModel->GetPropertyData());
|
||||
|
||||
// Determine property type
|
||||
EPropertyType Type = DetermineCharacterPropType(Params.Version(), rkIndex);
|
||||
if (Type == eUnknownProperty) return nullptr;
|
||||
EPropertyTypeNew Type = DetermineCharacterPropType(Params.Version(), rkIndex);
|
||||
|
||||
// Create widget
|
||||
if (Type == eAssetProperty)
|
||||
if (Type == EPropertyTypeNew::Asset)
|
||||
{
|
||||
CResourceSelector *pSelector = new CResourceSelector(pParent);
|
||||
CResourceSelector* pSelector = new CResourceSelector(pParent);
|
||||
pSelector->SetFrameVisible(false);
|
||||
|
||||
if (Params.Version() <= eEchoes)
|
||||
@ -581,94 +560,87 @@ QWidget* CPropertyDelegate::CreateCharacterEditor(QWidget *pParent, const QModel
|
||||
return pSelector;
|
||||
}
|
||||
|
||||
if (Type == eEnumProperty)
|
||||
else if (Type == EPropertyTypeNew::Enum || Type == EPropertyTypeNew::Choice)
|
||||
{
|
||||
QComboBox *pComboBox = new QComboBox(pParent);
|
||||
|
||||
CAnimSet *pAnimSet = Params.AnimSet();
|
||||
QComboBox* pComboBox = new QComboBox(pParent);
|
||||
CAnimSet* pAnimSet = Params.AnimSet();
|
||||
|
||||
if (pAnimSet)
|
||||
{
|
||||
for (u32 iChr = 0; iChr < pAnimSet->NumCharacters(); iChr++)
|
||||
pComboBox->addItem(TO_QSTRING(pAnimSet->Character(iChr)->Name));
|
||||
for (u32 CharIdx = 0; CharIdx < pAnimSet->NumCharacters(); CharIdx++)
|
||||
pComboBox->addItem(TO_QSTRING(pAnimSet->Character(CharIdx)->Name));
|
||||
}
|
||||
|
||||
CONNECT_RELAY(pComboBox, rkIndex, currentIndexChanged(int));
|
||||
return pComboBox;
|
||||
}
|
||||
|
||||
if (Type == eLongProperty)
|
||||
else if (Type == EPropertyTypeNew::Int)
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = new WIntegralSpinBox(pParent);
|
||||
CONNECT_RELAY(pSpinBox, rkIndex, valueChanged(int));
|
||||
return pSpinBox;
|
||||
}*/
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CPropertyDelegate::SetCharacterEditorData(QWidget *pEditor, const QModelIndex& rkIndex) const
|
||||
{
|
||||
//FIXME
|
||||
/*
|
||||
TCharacterProperty *pProp = static_cast<TCharacterProperty*>(mpModel->PropertyForIndex(rkIndex, true));
|
||||
CAnimationParameters Params = pProp->Get();
|
||||
EPropertyType Type = DetermineCharacterPropType(Params.Version(), rkIndex);
|
||||
CAnimationSetProperty* pAnimSetProp = TPropCast<CAnimationSetProperty>(mpModel->PropertyForIndex(rkIndex, true));
|
||||
CAnimationParameters Params = pAnimSetProp->Value(mpModel->GetPropertyData());
|
||||
EPropertyTypeNew Type = DetermineCharacterPropType(Params.Version(), rkIndex);
|
||||
|
||||
if (Type == eAssetProperty)
|
||||
if (Type == EPropertyTypeNew::Asset)
|
||||
{
|
||||
static_cast<CResourceSelector*>(pEditor)->SetResource(Params.AnimSet());
|
||||
}
|
||||
|
||||
else if (Type == eEnumProperty)
|
||||
else if (Type == EPropertyTypeNew::Enum || Type == EPropertyTypeNew::Choice)
|
||||
{
|
||||
static_cast<QComboBox*>(pEditor)->setCurrentIndex(Params.CharacterIndex());
|
||||
}
|
||||
|
||||
else if (Type == eLongProperty && !pEditor->hasFocus())
|
||||
else if (Type == EPropertyTypeNew::Int && !pEditor->hasFocus())
|
||||
{
|
||||
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
|
||||
{
|
||||
//FIXME
|
||||
/*
|
||||
CAnimationSetProperty* pAnimSet = TPropCast<CAnimationSetProperty>(mpModel->PropertyForIndex(rkIndex, true));
|
||||
CAnimationParameters Params = pAnimSet->Get();
|
||||
EPropertyType Type = DetermineCharacterPropType(Params.Version(), rkIndex);
|
||||
CAnimationSetProperty* pAnimSetProp = TPropCast<CAnimationSetProperty>(mpModel->PropertyForIndex(rkIndex, true));
|
||||
CAnimationParameters Params = pAnimSetProp->Value(mpModel->GetPropertyData());
|
||||
EPropertyTypeNew Type = DetermineCharacterPropType(Params.Version(), rkIndex);
|
||||
|
||||
if (Type == eAssetProperty)
|
||||
if (Type == EPropertyTypeNew::Asset)
|
||||
{
|
||||
CResourceEntry *pEntry = static_cast<CResourceSelector*>(pEditor)->Entry();
|
||||
Params.SetResource( pEntry ? pEntry->ID() : CAssetID::InvalidID(mpEditor->CurrentGame()) );
|
||||
}
|
||||
|
||||
else if (Type == eEnumProperty)
|
||||
else if (Type == EPropertyTypeNew::Enum || Type == EPropertyTypeNew::Choice)
|
||||
{
|
||||
Params.SetCharIndex( static_cast<QComboBox*>(pEditor)->currentIndex() );
|
||||
}
|
||||
|
||||
else if (Type == eLongProperty)
|
||||
else if (Type == EPropertyTypeNew::Int)
|
||||
{
|
||||
int UnkIndex = (Params.Version() <= eEchoes ? rkIndex.row() - 2 : rkIndex.row() - 1);
|
||||
Params.SetUnknown(UnkIndex, static_cast<WIntegralSpinBox*>(pEditor)->value() );
|
||||
}
|
||||
|
||||
pProp->Set(Params);
|
||||
pAnimSetProp->ValueRef(mpModel->GetPropertyData()) = Params;
|
||||
|
||||
// If we just updated the resource, make sure all the sub-properties of the character are flagged as changed.
|
||||
// We want to do this -after- updating the anim params on the property, which is why we have a second type check.
|
||||
if (Type == eAssetProperty)
|
||||
if (Type == EPropertyTypeNew::Asset)
|
||||
{
|
||||
QModelIndex ParentIndex = rkIndex.parent();
|
||||
mpModel->dataChanged(mpModel->index(1, 1, ParentIndex), mpModel->index(mpModel->rowCount(ParentIndex) - 1, 1, ParentIndex));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
EPropertyTypeNew CPropertyDelegate::DetermineCharacterPropType(EGame Game, const QModelIndex& rkIndex) const
|
||||
|
@ -18,14 +18,14 @@ CPropertyModel::CPropertyModel(QObject *pParent /*= 0*/)
|
||||
|
||||
int CPropertyModel::RecursiveBuildArrays(IPropertyNew* pProperty, int ParentID)
|
||||
{
|
||||
int MyID = mProperties.size();
|
||||
mProperties << SProperty();
|
||||
SProperty& Property = mProperties.back();
|
||||
Property.pProperty = pProperty;
|
||||
Property.ParentID = ParentID;
|
||||
|
||||
int MyID = mProperties.size() - 1;
|
||||
mProperties[MyID].pProperty = pProperty;
|
||||
mProperties[MyID].ParentID = ParentID;
|
||||
|
||||
int RowNumber = (ParentID >= 0 ? mProperties[ParentID].ChildIDs.size() : 0);
|
||||
Property.Index = createIndex(RowNumber, 0, pProperty);
|
||||
mProperties[MyID].Index = createIndex(RowNumber, 0, MyID);
|
||||
|
||||
if (pProperty->Type() == EPropertyTypeNew::Array)
|
||||
{
|
||||
@ -34,7 +34,7 @@ int CPropertyModel::RecursiveBuildArrays(IPropertyNew* pProperty, int ParentID)
|
||||
for (u32 ElementIdx = 0; ElementIdx < pArray->ArrayCount(mpPropertyData); ElementIdx++)
|
||||
{
|
||||
int NewChildID = RecursiveBuildArrays( pArray->Archetype(), MyID );
|
||||
Property.ChildIDs.push_back(NewChildID);
|
||||
mProperties[MyID].ChildIDs.push_back(NewChildID);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -42,7 +42,7 @@ int CPropertyModel::RecursiveBuildArrays(IPropertyNew* pProperty, int ParentID)
|
||||
for (u32 ChildIdx = 0; ChildIdx < pProperty->NumChildren(); ChildIdx++)
|
||||
{
|
||||
int NewChildID = RecursiveBuildArrays( pProperty->ChildByIndex(ChildIdx), MyID );
|
||||
Property.ChildIDs.push_back(NewChildID);
|
||||
mProperties[MyID].ChildIDs.push_back(NewChildID);
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ void CPropertyModel::ConfigureIntrinsic(CGameProject* pProject, IPropertyNew* pR
|
||||
|
||||
void CPropertyModel::ConfigureScript(CGameProject* pProject, IPropertyNew* pRootProperty, CScriptObject* pObject)
|
||||
{
|
||||
ConfigureIntrinsic(pProject, pRootProperty, pObject);
|
||||
ConfigureIntrinsic(pProject, pRootProperty, pObject ? pObject->PropertyData() : nullptr);
|
||||
mpObject = pObject;
|
||||
}
|
||||
|
||||
@ -166,7 +166,7 @@ QVariant CPropertyModel::data(const QModelIndex& rkIndex, int Role) const
|
||||
|
||||
if (Role == Qt::DisplayRole || (Role == Qt::ToolTipRole && rkIndex.column() == 1) )
|
||||
{
|
||||
if (rkIndex.internalId() & 0x1)
|
||||
if (rkIndex.internalId() & 0x80000000)
|
||||
{
|
||||
IPropertyNew *pProp = PropertyForIndex(rkIndex, true);
|
||||
EPropertyTypeNew Type = pProp->Type();
|
||||
@ -321,11 +321,6 @@ QVariant CPropertyModel::data(const QModelIndex& rkIndex, int Role) const
|
||||
|
||||
// No display text on properties with persistent editors
|
||||
case EPropertyTypeNew::Bool:
|
||||
if (Role == Qt::DisplayRole)
|
||||
return TPropCast<CBoolProperty>(pProp)->Value(mpPropertyData) ? "True" : "False";
|
||||
else
|
||||
return "";
|
||||
|
||||
case EPropertyTypeNew::Asset:
|
||||
case EPropertyTypeNew::Color:
|
||||
if (Role == Qt::DisplayRole)
|
||||
@ -341,12 +336,12 @@ QVariant CPropertyModel::data(const QModelIndex& rkIndex, int Role) const
|
||||
|
||||
if (Role == Qt::ToolTipRole && rkIndex.column() == 0)
|
||||
{
|
||||
if (!(rkIndex.internalId() & 0x1))
|
||||
if (!(rkIndex.internalId() & 0x80000000))
|
||||
{
|
||||
// Add name
|
||||
IPropertyNew *pProp = PropertyForIndex(rkIndex, false);
|
||||
QString DisplayText = data(rkIndex, Qt::DisplayRole).toString();
|
||||
QString Text = QString("<b>%1</b> <i>(%2)</i>").arg(DisplayText).arg(TO_QSTRING(PropEnumToPropString(pProp->Type())));
|
||||
QString Text = QString("<b>%1</b> <i>(%2)</i>").arg(DisplayText).arg(pProp->HashableTypeName());
|
||||
|
||||
// Add uncooked notification
|
||||
if (pProp->CookPreference() == ECookPreferenceNew::Never)
|
||||
@ -444,7 +439,10 @@ QModelIndex CPropertyModel::parent(const QModelIndex& rkChild) const
|
||||
else
|
||||
ID = mProperties[ID].ParentID;
|
||||
|
||||
if (ID >= 0)
|
||||
return mProperties[ID].Index;
|
||||
else
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
Qt::ItemFlags CPropertyModel::flags(const QModelIndex& rkIndex) const
|
||||
|
@ -81,7 +81,7 @@ void CPropertyView::SetEditor(CWorldEditor *pEditor)
|
||||
{
|
||||
mpEditor = pEditor;
|
||||
mpDelegate->SetEditor(pEditor);
|
||||
connect(mpEditor, SIGNAL(PropertyModified(CScriptObject*,IProperty*)), mpModel, SLOT(NotifyPropertyModified(CScriptObject*,IProperty*)));
|
||||
connect(mpEditor, SIGNAL(PropertyModified(CScriptObject*,IPropertyNew*)), mpModel, SLOT(NotifyPropertyModified(CScriptObject*,IPropertyNew*)));
|
||||
}
|
||||
|
||||
void CPropertyView::SetInstance(CScriptObject *pObj)
|
||||
|
@ -63,6 +63,7 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
|
||||
mpProxyModel = new CResourceProxyModel(this);
|
||||
mpProxyModel->setSourceModel(mpModel);
|
||||
mpUI->ResourceTableView->setModel(mpProxyModel);
|
||||
mpUI->ResourceTableView->resizeRowsToContents();
|
||||
|
||||
QHeaderView *pHeader = mpUI->ResourceTableView->horizontalHeader();
|
||||
pHeader->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
@ -158,6 +159,7 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
|
||||
connect(mpUI->ResourceTableView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(OnResourceSelectionChanged(QModelIndex)));
|
||||
connect(mpProxyModel, SIGNAL(rowsInserted(QModelIndex,int,int)), mpUI->ResourceTableView, SLOT(resizeRowsToContents()));
|
||||
connect(mpProxyModel, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)), mpUI->ResourceTableView, SLOT(resizeRowsToContents()));
|
||||
connect(mpProxyModel, SIGNAL(modelReset()), mpUI->ResourceTableView, SLOT(resizeRowsToContents()));
|
||||
connect(mpFilterAllBox, SIGNAL(toggled(bool)), this, SLOT(OnFilterTypeBoxTicked(bool)));
|
||||
connect(gpEdApp, SIGNAL(ActiveProjectChanged(CGameProject*)), this, SLOT(UpdateStore()));
|
||||
}
|
||||
@ -874,6 +876,9 @@ void CResourceBrowser::UpdateFilter()
|
||||
UpdateDescriptionLabel();
|
||||
mpProxyModel->SetSearchString( TO_TSTRING(mpUI->SearchBar->text()) );
|
||||
mpProxyModel->invalidate();
|
||||
|
||||
// not sure why I need to do this here? but the resize mode seems to get reset otherwise
|
||||
mpUI->ResourceTableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
}
|
||||
|
||||
void CResourceBrowser::UpdateUndoActionStates()
|
||||
|
@ -7,29 +7,83 @@
|
||||
#include "Editor/PropertyEdit/CPropertyModel.h"
|
||||
#include "Editor/WorldEditor/CWorldEditor.h"
|
||||
|
||||
template<class PropertyClass>
|
||||
class TEditScriptPropertyCommand : public IUndoCommand
|
||||
class IEditPropertyCommand : public IUndoCommand
|
||||
{
|
||||
typedef typename PropertyClass::ValueType ValueType;
|
||||
std::vector<char> mOldData;
|
||||
std::vector<char> mNewData;
|
||||
|
||||
CWorldEditor *mpEditor;
|
||||
CInstancePtr mpInstance;
|
||||
PropertyClass* mpProperty;
|
||||
ValueType mOldValue;
|
||||
ValueType mNewValue;
|
||||
protected:
|
||||
IPropertyNew* mpProperty;
|
||||
bool mCommandEnded;
|
||||
bool mSavedOldData;
|
||||
bool mSavedNewData;
|
||||
|
||||
/** Save the current state of the object properties to the given data buffer */
|
||||
void SaveObjectStateToArray(std::vector<char>& rVector)
|
||||
{
|
||||
CVectorOutStream MemStream(&rVector, IOUtil::kSystemEndianness);
|
||||
CBasicBinaryWriter Writer(&MemStream, CSerialVersion(IArchive::skCurrentArchiveVersion, 0, mpProperty->Game()));
|
||||
|
||||
std::vector<void*> DataPointers;
|
||||
GetObjectDataPointers(DataPointers);
|
||||
|
||||
for (int PtrIdx = 0; PtrIdx < DataPointers.size(); PtrIdx++)
|
||||
{
|
||||
void* pData = DataPointers[PtrIdx];
|
||||
mpProperty->SerializeValue(pData, Writer);
|
||||
}
|
||||
}
|
||||
|
||||
/** Restore the state of the object properties from the given data buffer */
|
||||
void RestoreObjectStateFromArray(std::vector<char>& rArray)
|
||||
{
|
||||
CBasicBinaryReader Reader(rArray.data(), rArray.size(), CSerialVersion(IArchive::skCurrentArchiveVersion, 0, mpProperty->Game()));
|
||||
|
||||
std::vector<void*> DataPointers;
|
||||
GetObjectDataPointers(DataPointers);
|
||||
|
||||
for (int PtrIdx = 0; PtrIdx < DataPointers.size(); PtrIdx++)
|
||||
{
|
||||
void* pData = DataPointers[PtrIdx];
|
||||
mpProperty->SerializeValue(pData, Reader);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
TEditScriptPropertyCommand(PropertyClass* pProp, CScriptObject* pInstance, CWorldEditor* pEditor, ValueType NewValue, bool IsDone, const QString& rkCommandName = "Edit Property")
|
||||
IEditPropertyCommand(IPropertyNew* pProperty, const QString& rkCommandName = "Edit Property")
|
||||
: IUndoCommand(rkCommandName)
|
||||
, mpEditor(pEditor)
|
||||
, mpInstance(pInstance)
|
||||
, mpProperty(pProp)
|
||||
, mOldValue(pProp->Value(pInstance->PropertyData()))
|
||||
, mNewValue(NewValue)
|
||||
, mCommandEnded(IsDone)
|
||||
, mpProperty(pProperty)
|
||||
, mSavedOldData(false)
|
||||
, mSavedNewData(false)
|
||||
{}
|
||||
|
||||
void SaveOldData()
|
||||
{
|
||||
SaveObjectStateToArray(mOldData);
|
||||
mSavedOldData = true;
|
||||
}
|
||||
|
||||
void SaveNewData()
|
||||
{
|
||||
SaveObjectStateToArray(mNewData);
|
||||
mSavedNewData = true;
|
||||
}
|
||||
|
||||
bool IsNewDataDifferent()
|
||||
{
|
||||
if (mOldData.size() != mNewData.size()) return false;
|
||||
return memcmp(mOldData.data(), mNewData.data(), mNewData.size()) != 0;
|
||||
}
|
||||
|
||||
void SetEditComplete(bool IsComplete)
|
||||
{
|
||||
mCommandEnded = IsComplete;
|
||||
}
|
||||
|
||||
/** Interface */
|
||||
virtual void GetObjectDataPointers(std::vector<void*>& rOutPointers) const = 0;
|
||||
|
||||
/** IUndoCommand/QUndoCommand interface */
|
||||
int id() const
|
||||
{
|
||||
return eEditScriptPropertyCmd;
|
||||
@ -39,32 +93,46 @@ public:
|
||||
{
|
||||
if (!mCommandEnded)
|
||||
{
|
||||
TEditScriptPropertyCommand* pkCmd = dynamic_cast<TEditScriptPropertyCommand>(pkOther);
|
||||
const IEditPropertyCommand* pkCmd = dynamic_cast<const IEditPropertyCommand*>(pkOther);
|
||||
|
||||
if (pkCmd && pkCmd->mpProperty == mpProperty && pkCmd->mpInstance == mpInstance)
|
||||
if (pkCmd && pkCmd->mpProperty == mpProperty)
|
||||
{
|
||||
mNewValue = pkCmd->mNewValue;
|
||||
std::vector<void*> MyPointers;
|
||||
GetObjectDataPointers(MyPointers);
|
||||
|
||||
std::vector<void*> TheirPointers;
|
||||
pkCmd->GetObjectDataPointers(TheirPointers);
|
||||
|
||||
if (TheirPointers.size() == MyPointers.size())
|
||||
{
|
||||
for (int PtrIdx = 0; PtrIdx < MyPointers.size(); PtrIdx++)
|
||||
{
|
||||
if (MyPointers[PtrIdx] != TheirPointers[PtrIdx])
|
||||
return false;
|
||||
}
|
||||
|
||||
// Match
|
||||
mNewData = pkCmd->mNewData;
|
||||
mCommandEnded = pkCmd->mCommandEnded;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void undo()
|
||||
{
|
||||
void* pData = mpInstance->PropertyData();
|
||||
mpProperty->ValueRef(pData) = mOldValue;
|
||||
mpEditor->OnPropertyModified(mpProperty);
|
||||
ASSERT(mSavedOldData && mSavedNewData);
|
||||
RestoreObjectStateFromArray(mOldData);
|
||||
mCommandEnded = true;
|
||||
}
|
||||
|
||||
void redo()
|
||||
{
|
||||
void* pData = mpInstance->PropertyData();
|
||||
mpProperty->ValueRef(pData) = mNewValue;
|
||||
mpEditor->OnPropertyModified(mpProperty);
|
||||
ASSERT(mSavedOldData && mSavedNewData);
|
||||
RestoreObjectStateFromArray(mNewData);
|
||||
}
|
||||
|
||||
bool AffectsCleanState() const
|
||||
@ -73,22 +141,46 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/*class CEditScriptPropertyCommand : public IUndoCommand
|
||||
class CEditScriptPropertyCommand : public IEditPropertyCommand
|
||||
{
|
||||
CWorldEditor *mpEditor;
|
||||
CPropertyPtr mpProp;
|
||||
IPropertyValue *mpOldValue;
|
||||
IPropertyValue *mpNewValue;
|
||||
bool mCommandEnded;
|
||||
std::vector<CInstancePtr> mInstances;
|
||||
CWorldEditor* mpEditor;
|
||||
|
||||
public:
|
||||
CEditScriptPropertyCommand(IProperty *pProp, CWorldEditor *pEditor, IPropertyValue *pOldValue, bool IsDone, const QString& rkCommandName = "Edit Property");
|
||||
~CEditScriptPropertyCommand();
|
||||
int id() const;
|
||||
bool mergeWith(const QUndoCommand *pkOther);
|
||||
void undo();
|
||||
void redo();
|
||||
bool AffectsCleanState() const { return true; }
|
||||
};*/
|
||||
CEditScriptPropertyCommand(CWorldEditor* pEditor, CScriptObject* pInstance, IPropertyNew* pProperty, const QString& rkCommandName = "Edit Property")
|
||||
: IEditPropertyCommand(pProperty, rkCommandName)
|
||||
, mpEditor(pEditor)
|
||||
{
|
||||
mInstances.push_back( CInstancePtr(pInstance) );
|
||||
}
|
||||
|
||||
virtual void GetObjectDataPointers(std::vector<void*>& rOutPointers) const override
|
||||
{
|
||||
rOutPointers.resize(mInstances.size());
|
||||
|
||||
for (int InstanceIdx = 0; InstanceIdx < mInstances.size(); InstanceIdx++)
|
||||
{
|
||||
rOutPointers[InstanceIdx] = mInstances[InstanceIdx]->PropertyData();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo() override
|
||||
{
|
||||
IEditPropertyCommand::undo();
|
||||
NotifyWorldEditor();
|
||||
}
|
||||
|
||||
virtual void redo() override
|
||||
{
|
||||
IEditPropertyCommand::redo();
|
||||
NotifyWorldEditor();
|
||||
}
|
||||
|
||||
void NotifyWorldEditor()
|
||||
{
|
||||
for (int InstanceIdx = 0; InstanceIdx < mInstances.size(); InstanceIdx++)
|
||||
mpEditor->OnPropertyModified(*mInstances[InstanceIdx], mpProperty);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CEDITSCRIPTPROPERTYCOMMAND_H
|
||||
|
@ -34,8 +34,10 @@ protected slots:
|
||||
|
||||
if ( mpSoftValidator )
|
||||
{
|
||||
QString Text = text();
|
||||
int DummyPos;
|
||||
if ( mpSoftValidator->validate(text(), DummyPos) == QValidator::Acceptable )
|
||||
|
||||
if ( mpSoftValidator->validate(Text, DummyPos) == QValidator::Acceptable )
|
||||
{
|
||||
NewValidity = true;
|
||||
setStyleSheet("border: 1px solid green");
|
||||
|
@ -569,11 +569,12 @@ void CWorldEditor::OnLinksModified(const QList<CScriptObject*>& rkInstances)
|
||||
emit InstanceLinksModified(rkInstances);
|
||||
}
|
||||
|
||||
void CWorldEditor::OnPropertyModified(IPropertyNew *pProp)
|
||||
void CWorldEditor::OnPropertyModified(CScriptObject* pObject, IPropertyNew *pProp)
|
||||
{
|
||||
if (!mpSelection->IsEmpty() && mpSelection->Front()->NodeType() == eScriptNode)
|
||||
CScriptNode *pScript = mScene.NodeForInstance(pObject);
|
||||
|
||||
if (pScript)
|
||||
{
|
||||
CScriptNode *pScript = static_cast<CScriptNode*>(mpSelection->Front());
|
||||
pScript->PropertyModified(pProp);
|
||||
|
||||
// If this is an editor property, update other parts of the UI to reflect the new value.
|
||||
@ -581,6 +582,8 @@ void CWorldEditor::OnPropertyModified(IPropertyNew *pProp)
|
||||
{
|
||||
UpdateStatusBar();
|
||||
UpdateSelectionUI();
|
||||
mpSelection->UpdateBounds();
|
||||
}
|
||||
}
|
||||
|
||||
// If this is a model/character, then we'll treat this as a modified selection. This is to make sure the selection bounds updates.
|
||||
@ -596,8 +599,7 @@ void CWorldEditor::OnPropertyModified(IPropertyNew *pProp)
|
||||
SelectionModified();
|
||||
|
||||
// Emit signal so other widgets can react to the property change
|
||||
emit PropertyModified(pScript->Instance(), pProp);
|
||||
}
|
||||
emit PropertyModified(pObject, pProp);
|
||||
}
|
||||
|
||||
void CWorldEditor::SetSelectionActive(bool Active)
|
||||
|
@ -122,7 +122,7 @@ public slots:
|
||||
|
||||
void OnActiveProjectChanged(CGameProject *pProj);
|
||||
void OnLinksModified(const QList<CScriptObject*>& rkInstances);
|
||||
void OnPropertyModified(IPropertyNew *pProp);
|
||||
void OnPropertyModified(CScriptObject* pObject, IPropertyNew *pProp);
|
||||
void SetSelectionActive(bool Active);
|
||||
void SetSelectionInstanceNames(const QString& rkNewName, bool IsDone);
|
||||
void SetSelectionLayer(CScriptLayer *pLayer);
|
||||
|
@ -65,7 +65,7 @@ void WEditorProperties::SyncToEditor(CWorldEditor *pEditor)
|
||||
connect(mpEditor, SIGNAL(SelectionModified()), this, SLOT(OnSelectionModified()));
|
||||
connect(mpEditor, SIGNAL(LayersModified()), this, SLOT(OnLayersModified()));
|
||||
connect(mpEditor, SIGNAL(InstancesLayerChanged(QList<CScriptNode*>)), this, SLOT(OnInstancesLayerChanged(QList<CScriptNode*>)));
|
||||
connect(mpEditor, SIGNAL(PropertyModified(CScriptObject*,IProperty*)), this, SLOT(OnPropertyModified(CScriptObject*,IProperty*)));
|
||||
connect(mpEditor, SIGNAL(PropertyModified(CScriptObject*,IPropertyNew*)), this, SLOT(OnPropertyModified(CScriptObject*,IPropertyNew*)));
|
||||
|
||||
OnLayersModified();
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Load templates
|
||||
CTemplateLoader::LoadGameList();
|
||||
CTemplateLoader::LoadAllGames();
|
||||
//CTemplateLoader::LoadAllGames();
|
||||
//CTemplateWriter::SaveAllTemplates();
|
||||
|
||||
// Execute application
|
||||
|
@ -139,16 +139,6 @@ float CMatrix4f::Determinant() const
|
||||
}
|
||||
|
||||
// ************ OPERATORS ************
|
||||
inline float* CMatrix4f::operator[](long Index)
|
||||
{
|
||||
return m[Index];
|
||||
}
|
||||
|
||||
inline const float* CMatrix4f::operator[](long Index) const
|
||||
{
|
||||
return m[Index];
|
||||
}
|
||||
|
||||
CVector3f CMatrix4f::operator*(const CVector3f& rkVec) const
|
||||
{
|
||||
// For vec3 multiplication, the vector w component is considered to be 1.0
|
||||
|
@ -42,4 +42,14 @@ public:
|
||||
static const CMatrix4f skIdentity;
|
||||
};
|
||||
|
||||
inline float* CMatrix4f::operator[](long Index)
|
||||
{
|
||||
return m[Index];
|
||||
}
|
||||
|
||||
inline const float* CMatrix4f::operator[](long Index) const
|
||||
{
|
||||
return m[Index];
|
||||
}
|
||||
|
||||
#endif // CMATRIX4_H
|
||||
|
@ -43,7 +43,7 @@ void CVector3f::Serialize(IArchive& rArc)
|
||||
|
||||
TString CVector3f::ToString() const
|
||||
{
|
||||
return TString::Format("%f.1, %f.1, %f.1", X, Y, Z);
|
||||
return TString::Format("%.1f, %.1f, %.1f", X, Y, Z);
|
||||
}
|
||||
|
||||
// ************ SWIZZLE ************
|
||||
|
Loading…
x
Reference in New Issue
Block a user