Various property cleanup, fixing more broken stuff, trialing new features

This commit is contained in:
Aruki 2018-07-16 02:29:29 -06:00
parent a90f1d0441
commit 148449e50b
37 changed files with 383 additions and 184 deletions

View File

@ -25,4 +25,7 @@
// temporary home for ALIGN macro, moving later // temporary home for ALIGN macro, moving later
#define ALIGN(Val, Align) ((Val + (Align-1)) & ~(Align-1)) #define ALIGN(Val, Align) ((Val + (Align-1)) & ~(Align-1))
// temporary home for MEMBER_OFFSET macro
#define MEMBER_OFFSET(TypeName, MemberName) ( (int) (long long) &((TypeName*)0)->MemberName )
#endif // COMMON_H #endif // COMMON_H

View File

@ -18,12 +18,12 @@ void CAreaAttributes::SetObject(CScriptObject *pObj)
mpObject = pObj; mpObject = pObj;
mGame = pTemplate->MasterTemplate()->Game(); mGame = pTemplate->MasterTemplate()->Game();
mNeedSky = CBoolRef(pObj, pProperties->ChildByIndex(1)); mNeedSky = CBoolRef(pObj->PropertyData(), pProperties->ChildByIndex(1));
if (mGame == ePrime) if (mGame == ePrime)
mOverrideSky = CAssetRef(pObj, pProperties->ChildByIndex(7)); mOverrideSky = CAssetRef(pObj->PropertyData(), pProperties->ChildByIndex(7));
else if (mGame > ePrime) else if (mGame > ePrime)
mOverrideSky = CAssetRef(pObj, pProperties->ChildByID(0xD208C9FA)); mOverrideSky = CAssetRef(pObj->PropertyData(), pProperties->ChildByID(0xD208C9FA));
} }
bool CAreaAttributes::IsLayerEnabled() const bool CAreaAttributes::IsLayerEnabled() const

View File

@ -24,13 +24,13 @@ public:
{ {
if (Game <= ePrime) if (Game <= ePrime)
{ {
mWorldLightingOptions = TEnumRef<EWorldLightingOptions>(InStruct.Object(), InStruct.Property()->ChildByIndex(0x7)); mWorldLightingOptions = TEnumRef<EWorldLightingOptions>(InStruct.DataPointer(), InStruct.Property()->ChildByIndex(0x7));
mLightLayer = CIntRef(InStruct.Object(), InStruct.Property()->ChildByIndex(0xD)); mLightLayer = CIntRef(InStruct.DataPointer(), InStruct.Property()->ChildByIndex(0xD));
} }
else else
{ {
mWorldLightingOptions = TEnumRef<EWorldLightingOptions>(InStruct.Object(), InStruct.Property()->ChildByID(0x6B5E7509)); mWorldLightingOptions = TEnumRef<EWorldLightingOptions>(InStruct.DataPointer(), InStruct.Property()->ChildByID(0x6B5E7509));
mLightLayer = CIntRef(InStruct.Object(), InStruct.Property()->ChildByID(0x1F715FD3)); mLightLayer = CIntRef(InStruct.DataPointer(), InStruct.Property()->ChildByID(0x1F715FD3));
} }
} }
} }

View File

@ -1,5 +1,6 @@
#include "CLight.h" #include "CLight.h"
#include "Core/Render/CGraphics.h" #include "Core/Render/CGraphics.h"
#include <Common/Common.h>
#include <cmath> #include <cmath>
#include <float.h> #include <float.h>
@ -127,6 +128,52 @@ void CLight::SetAngleAtten(float AngleCoefA, float AngleCoefB, float AngleCoefC)
mAngleAttenCoefficients.Z = AngleCoefC; mAngleAttenCoefficients.Z = AngleCoefC;
} }
CStructPropertyNew* CLight::GetProperties() const
{
//@todo MP1 properties only
//@todo we cannot display full properties because a lot of them are discarded on load
static CStructPropertyNew* pProperties = nullptr;
if (!pProperties)
{
pProperties = (CStructPropertyNew*) IPropertyNew::CreateIntrinsic(EPropertyTypeNew::Struct,
nullptr,
0,
"Light");
CChoiceProperty* pLightType = (CChoiceProperty*) IPropertyNew::CreateIntrinsic(EPropertyTypeNew::Choice,
pProperties,
MEMBER_OFFSET(CLight, mType),
"LightType");
pLightType->AddValue("LocalAmbient", eLocalAmbient);
pLightType->AddValue("Directional", eDirectional);
pLightType->AddValue("Spot", eSpot);
pLightType->AddValue("Custom", eCustom);
IPropertyNew::CreateIntrinsic(EPropertyTypeNew::Color,
pProperties,
MEMBER_OFFSET(CLight, mColor),
"Color");
IPropertyNew::CreateIntrinsic(EPropertyTypeNew::Vector,
pProperties,
MEMBER_OFFSET(CLight, mPosition),
"Position");
IPropertyNew::CreateIntrinsic(EPropertyTypeNew::Vector,
pProperties,
MEMBER_OFFSET(CLight, mDirection),
"Direction");
IPropertyNew::CreateIntrinsic(EPropertyTypeNew::Float,
pProperties,
MEMBER_OFFSET(CLight, mSpotCutoff),
"SpotCutoff");
}
return pProperties;
}
// ************ OTHER ************ // ************ OTHER ************
void CLight::Load() const void CLight::Load() const
{ {

View File

@ -1,6 +1,7 @@
#ifndef CLIGHT_H #ifndef CLIGHT_H
#define CLIGHT_H #define CLIGHT_H
#include "Core/Resource/Script/Property/Properties.h"
#include <Common/CColor.h> #include <Common/CColor.h>
#include <Common/FileIO/IInputStream.h> #include <Common/FileIO/IInputStream.h>
#include <Math/CVector3f.h> #include <Math/CVector3f.h>
@ -62,6 +63,8 @@ public:
void SetDistAtten(float DistCoefA, float DistCoefB, float DistCoefC); void SetDistAtten(float DistCoefA, float DistCoefB, float DistCoefC);
void SetAngleAtten(float AngleCoefA, float AngleCoefB, float AngleCoefC); void SetAngleAtten(float AngleCoefA, float AngleCoefB, float AngleCoefC);
CStructPropertyNew* GetProperties() const;
// Other // Other
void Load() const; void Load() const;

View File

@ -196,7 +196,7 @@ IPropertyNew* CTemplateLoader::LoadProperty(XMLElement* pElem, CScriptTemplate*
// no archetype, so do normal create // no archetype, so do normal create
if (!pProp) if (!pProp)
{ {
pProp = IPropertyNew::Create(Type, pParent, mpMaster, pScript, false); pProp = IPropertyNew::Create(Type, pParent, mGame, pScript, false);
} }
// we need to have a valid property by this point // we need to have a valid property by this point
@ -340,7 +340,7 @@ IPropertyNew* CTemplateLoader::LoadProperty(XMLElement* pElem, CScriptTemplate*
} }
else else
{ {
pArray->mpItemArchetype = IPropertyNew::Create(EPropertyTypeNew::Struct, pArray, mpMaster, pScript, false); pArray->mpItemArchetype = IPropertyNew::Create(EPropertyTypeNew::Struct, pArray, mGame, pScript, false);
pStruct = TPropCast<CStructPropertyNew>(pArray->mpItemArchetype); pStruct = TPropCast<CStructPropertyNew>(pArray->mpItemArchetype);
pStruct->mFlags = EPropertyFlag::IsAtomic | EPropertyFlag::IsArrayArchetype; pStruct->mFlags = EPropertyFlag::IsAtomic | EPropertyFlag::IsArrayArchetype;
} }
@ -389,8 +389,9 @@ CStructPropertyNew* CTemplateLoader::LoadStructArchetype(const TString& rkTempla
pArchetype = TPropCast<CStructPropertyNew>( pArchetype = TPropCast<CStructPropertyNew>(
IPropertyNew::Create(EPropertyTypeNew::Struct, IPropertyNew::Create(EPropertyTypeNew::Struct,
nullptr, nullptr,
mpMaster, mGame,
nullptr, false) nullptr,
false)
); );
ASSERT(pArchetype != nullptr); ASSERT(pArchetype != nullptr);
@ -458,7 +459,7 @@ CEnumProperty* CTemplateLoader::LoadEnumArchetype(const TString& rkTemplateFileN
pArchetype = static_cast<CEnumProperty*>( pArchetype = static_cast<CEnumProperty*>(
IPropertyNew::Create(bIsChoice ? EPropertyTypeNew::Choice : EPropertyTypeNew::Enum, IPropertyNew::Create(bIsChoice ? EPropertyTypeNew::Choice : EPropertyTypeNew::Enum,
nullptr, nullptr,
mpMaster, mGame,
nullptr, nullptr,
false) false)
); );
@ -500,8 +501,9 @@ CFlagsProperty* CTemplateLoader::LoadFlagsArchetype(const TString& rkTemplateFil
pArchetype = TPropCast<CFlagsProperty>( pArchetype = TPropCast<CFlagsProperty>(
IPropertyNew::Create(EPropertyTypeNew::Flags, IPropertyNew::Create(EPropertyTypeNew::Flags,
nullptr, nullptr,
mpMaster, mGame,
nullptr, false) nullptr,
false)
); );
ASSERT(pArchetype != nullptr); ASSERT(pArchetype != nullptr);
@ -600,11 +602,6 @@ void CTemplateLoader::LoadBitFlags(XMLElement *pFlagsElem, CFlagsProperty* pFlag
} }
} }
enum class ETest
{
ValueA = (true ? 0 : (u32) reinterpret_cast<u64>("ValueA"))
};
// ************ SCRIPT OBJECT ************ // ************ SCRIPT OBJECT ************
CScriptTemplate* CTemplateLoader::LoadScriptTemplate(XMLDocument *pDoc, const TString& rkTemplateName, u32 ObjectID) CScriptTemplate* CTemplateLoader::LoadScriptTemplate(XMLDocument *pDoc, const TString& rkTemplateName, u32 ObjectID)
{ {
@ -612,7 +609,7 @@ CScriptTemplate* CTemplateLoader::LoadScriptTemplate(XMLDocument *pDoc, const TS
pScript->mObjectID = ObjectID; pScript->mObjectID = ObjectID;
pScript->mSourceFile = rkTemplateName; pScript->mSourceFile = rkTemplateName;
IPropertyNew* pBaseStruct = IPropertyNew::Create(EPropertyTypeNew::Struct, nullptr, mpMaster, pScript); IPropertyNew* pBaseStruct = IPropertyNew::Create(EPropertyTypeNew::Struct, nullptr, mGame, pScript);
pScript->mpProperties = std::make_unique<CStructPropertyNew>( *TPropCast<CStructPropertyNew>(pBaseStruct) ); pScript->mpProperties = std::make_unique<CStructPropertyNew>( *TPropCast<CStructPropertyNew>(pBaseStruct) );
XMLElement *pRoot = pDoc->FirstChildElement("ScriptTemplate"); XMLElement *pRoot = pDoc->FirstChildElement("ScriptTemplate");

View File

@ -17,15 +17,17 @@ CScriptObject::CScriptObject(u32 InstanceID, CGameArea *pArea, CScriptLayer *pLa
// Init properties // Init properties
CStructPropertyNew* pProperties = pTemplate->Properties(); CStructPropertyNew* pProperties = pTemplate->Properties();
u32 PropertiesSize = pProperties->DataSize(); u32 PropertiesSize = pProperties->DataSize();
mPropertyData.resize( PropertiesSize );
pProperties->Construct( mPropertyData.data() );
mInstanceName = CStringRef(this, pTemplate->NameProperty()); mPropertyData.resize( PropertiesSize );
mPosition = CVectorRef(this, pTemplate->PositionProperty()); void* pData = mPropertyData.data();
mRotation = CVectorRef(this, pTemplate->RotationProperty()); pProperties->Construct( pData );
mScale = CVectorRef(this, pTemplate->ScaleProperty());
mActive = CBoolRef(this, pTemplate->ActiveProperty()); mInstanceName = CStringRef(pData, pTemplate->NameProperty());
mLightParameters = CStructRef(this, pTemplate->LightParametersProperty()); mPosition = CVectorRef(pData, pTemplate->PositionProperty());
mRotation = CVectorRef(pData, pTemplate->RotationProperty());
mScale = CVectorRef(pData, pTemplate->ScaleProperty());
mActive = CBoolRef(pData, pTemplate->ActiveProperty());
mLightParameters = CStructRef(pData, pTemplate->LightParametersProperty());
} }
CScriptObject::~CScriptObject() CScriptObject::~CScriptObject()

View File

@ -255,12 +255,12 @@ bool IPropertyNew::HasAccurateName()
/** IPropertyNew Accessors */ /** IPropertyNew Accessors */
EGame IPropertyNew::Game() const EGame IPropertyNew::Game() const
{ {
return mpMasterTemplate->Game(); return mGame;
} }
IPropertyNew* IPropertyNew::Create(EPropertyTypeNew Type, IPropertyNew* IPropertyNew::Create(EPropertyTypeNew Type,
IPropertyNew* pParent, IPropertyNew* pParent,
CMasterTemplate* pMaster, EGame Game,
CScriptTemplate* pScript, CScriptTemplate* pScript,
bool CallPostInit /*= true*/) bool CallPostInit /*= true*/)
{ {
@ -316,7 +316,7 @@ IPropertyNew* IPropertyNew::Create(EPropertyTypeNew Type,
} }
// Set other metadata // Set other metadata
pOut->mpMasterTemplate = pMaster; pOut->mGame = Game;
pOut->mpScriptTemplate = pScript; pOut->mpScriptTemplate = pScript;
pOut->_CalcOffset(); pOut->_CalcOffset();
@ -344,8 +344,20 @@ IPropertyNew* IPropertyNew::CreateCopy(IPropertyNew* pArchetype,
// always be valid. // always be valid.
ASSERT(pParent != nullptr); ASSERT(pParent != nullptr);
IPropertyNew* pOut = Create(pArchetype->Type(), pParent, pParent->mpMasterTemplate, pParent->mpScriptTemplate, false); IPropertyNew* pOut = Create(pArchetype->Type(), pParent, pParent->mGame, pParent->mpScriptTemplate, false);
pOut->InitFromArchetype(pArchetype); pOut->InitFromArchetype(pArchetype);
pArchetype->mSubInstances.push_back(pOut); pArchetype->mSubInstances.push_back(pOut);
return pOut; return pOut;
} }
IPropertyNew* IPropertyNew::CreateIntrinsic(EPropertyTypeNew Type,
IPropertyNew* pParent,
u32 Offset,
const TString& rkName)
{
IPropertyNew* pOut = Create(Type, pParent, pParent ? pParent->mGame : eUnknownGame, nullptr, false);
pOut->mOffset = Offset;
pOut->SetName(rkName);
pOut->PostInitialize();
return pOut;
}

View File

@ -137,9 +137,8 @@ protected:
/** Child properties; these appear underneath this property on the UI */ /** Child properties; these appear underneath this property on the UI */
std::vector<IPropertyNew*> mChildren; std::vector<IPropertyNew*> mChildren;
/** Master template for the game this property belongs to. /** Game this property belongs to */
* Cannot be derived from mpScriptTemplate because mpScriptTemplate is null sometimes */ EGame mGame;
CMasterTemplate* mpMasterTemplate;
/** Script template that this property belongs to. Null for struct/enum/flag archetypes. */ /** Script template that this property belongs to. Null for struct/enum/flag archetypes. */
CScriptTemplate* mpScriptTemplate; CScriptTemplate* mpScriptTemplate;
@ -231,12 +230,17 @@ public:
/** Create */ /** Create */
static IPropertyNew* Create(EPropertyTypeNew Type, static IPropertyNew* Create(EPropertyTypeNew Type,
IPropertyNew* pParent, IPropertyNew* pParent,
CMasterTemplate* pMaster, EGame Game,
CScriptTemplate* pScript, CScriptTemplate* pScript,
bool CallPostInit = true); bool CallPostInit = true);
static IPropertyNew* CreateCopy(IPropertyNew* pArchetype, static IPropertyNew* CreateCopy(IPropertyNew* pArchetype,
IPropertyNew* pParent); IPropertyNew* pParent);
static IPropertyNew* CreateIntrinsic(EPropertyTypeNew Type,
IPropertyNew* pParent,
u32 Offset,
const TString& rkName);
}; };
inline ECookPreferenceNew IPropertyNew::CookPreference() const inline ECookPreferenceNew IPropertyNew::CookPreference() const
@ -284,11 +288,6 @@ inline CScriptTemplate* IPropertyNew::ScriptTemplate() const
return mpScriptTemplate; return mpScriptTemplate;
} }
inline CMasterTemplate* IPropertyNew::MasterTemplate() const
{
return mpMasterTemplate;
}
inline TString IPropertyNew::Name() const inline TString IPropertyNew::Name() const
{ {
return mName; return mName;

View File

@ -15,10 +15,10 @@ protected:
public: public:
virtual void PostInitialize() virtual void PostInitialize()
{ {
IPropertyNew* pR = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate); IPropertyNew* pR = Create(EPropertyTypeNew::Float, this, mGame, mpScriptTemplate);
IPropertyNew* pG = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate); IPropertyNew* pG = Create(EPropertyTypeNew::Float, this, mGame, mpScriptTemplate);
IPropertyNew* pB = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate); IPropertyNew* pB = Create(EPropertyTypeNew::Float, this, mGame, mpScriptTemplate);
IPropertyNew* pA = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate); IPropertyNew* pA = Create(EPropertyTypeNew::Float, this, mGame, mpScriptTemplate);
pR->SetName("R"); pR->SetName("R");
pG->SetName("G"); pG->SetName("G");
pB->SetName("B"); pB->SetName("B");

View File

@ -3,10 +3,10 @@
#include "../IPropertyNew.h" #include "../IPropertyNew.h"
/** There are two types of enum properties: in the game data enum and choice. /** There are two types of enum properties in the game data: enum and choice.
* *
* In the game, the difference is that choice properties are index-based, while * In the game, the difference is that choice properties are index-based, while
* enum properties are stored as a hash of the name of the enum. * enum properties are stored as a hash of the name of the enum value.
* *
* In PWE, however, they are both implemented the same way under the hood. * In PWE, however, they are both implemented the same way under the hood.
*/ */
@ -59,6 +59,11 @@ public:
return IsArchetype() ? mSourceFile : mpArchetype->GetTemplateFileName(); return IsArchetype() ? mSourceFile : mpArchetype->GetTemplateFileName();
} }
void AddValue(TString ValueName, u32 ValueID)
{
mValues.push_back( SEnumValue(ValueName, ValueID) );
}
inline u32 NumPossibleValues() const { return mValues.size(); } inline u32 NumPossibleValues() const { return mValues.size(); }
u32 ValueIndex(u32 ID) const u32 ValueIndex(u32 ID) const

View File

@ -15,9 +15,9 @@ protected:
public: public:
virtual void PostInitialize() virtual void PostInitialize()
{ {
IPropertyNew* pX = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate); IPropertyNew* pX = Create(EPropertyTypeNew::Float, this, mGame, mpScriptTemplate);
IPropertyNew* pY = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate); IPropertyNew* pY = Create(EPropertyTypeNew::Float, this, mGame, mpScriptTemplate);
IPropertyNew* pZ = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate); IPropertyNew* pZ = Create(EPropertyTypeNew::Float, this, mGame, mpScriptTemplate);
pX->SetName("X"); pX->SetName("X");
pY->SetName("Y"); pY->SetName("Y");
pZ->SetName("Z"); pZ->SetName("Z");

View File

@ -22,37 +22,37 @@
#include "CStructProperty.h" #include "CStructProperty.h"
#include "CVectorProperty.h" #include "CVectorProperty.h"
/** TPropertyRef: Embeds a reference to a property on a specific script object */ /** TPropertyRef: Embeds a reference to a property on a specific object */
template<class PropertyClass, typename ValueType = PropertyClass::ValueType> template<class PropertyClass, typename ValueType = PropertyClass::ValueType>
class TPropertyRef class TPropertyRef
{ {
/** Script object containing the property data being referenced */ /** Property data being referenced */
CScriptObject* mpObject; void* mpPropertyData;
/** Property being referenced */ /** Property being referenced */
PropertyClass* mpProperty; PropertyClass* mpProperty;
public: public:
TPropertyRef() TPropertyRef()
: mpObject(nullptr), mpProperty(nullptr) : mpPropertyData(nullptr), mpProperty(nullptr)
{} {}
TPropertyRef(CScriptObject* pInObject, IPropertyNew* pInProperty) explicit TPropertyRef(void* pInData, IPropertyNew* pInProperty)
: mpObject(pInObject), mpProperty( TPropCast<PropertyClass>(pInProperty) ) : mpPropertyData(pInData), mpProperty( TPropCast<PropertyClass>(pInProperty) )
{ {
} }
TPropertyRef(CScriptObject* pInObject, PropertyClass* pInProperty) explicit TPropertyRef(void* pInData, PropertyClass* pInProperty)
: mpObject(pInObject), mpProperty(pInProperty) : mpPropertyData(pInData), mpProperty(pInProperty)
{ {
} }
/** Accessors */ /** Accessors */
inline CScriptObject* Object() const { return mpObject; } inline void* DataPointer() const { return mpPropertyData; }
inline PropertyClass* Property() const { return mpProperty; } inline PropertyClass* Property() const { return mpProperty; }
inline ValueType Get() const { return IsValid() ? *((ValueType*) mpProperty->RawValuePtr( mpObject->PropertyData() )) : ValueType(); } inline ValueType Get() const { return IsValid() ? *((ValueType*) mpProperty->RawValuePtr( mpPropertyData )) : ValueType(); }
inline void Set(const ValueType& kIn) const { if (IsValid()) *((ValueType*) mpProperty->RawValuePtr( mpObject->PropertyData() )) = kIn; } inline void Set(const ValueType& kIn) const { if (IsValid()) *((ValueType*) mpProperty->RawValuePtr( mpPropertyData )) = kIn; }
inline bool IsValid() const { return mpObject != nullptr && mpProperty != nullptr; } inline bool IsValid() const { return mpPropertyData != nullptr && mpProperty != nullptr; }
/** Inline operators */ /** Inline operators */
inline operator ValueType() const inline operator ValueType() const
@ -101,12 +101,12 @@ public:
: TPropertyRef() : TPropertyRef()
{} {}
TEnumRef(CScriptObject* pInObject, IPropertyNew* pInProperty) TEnumRef(void* pInData, IPropertyNew* pInProperty)
: TPropertyRef(pInObject, pInProperty) : TPropertyRef(pInData, pInProperty)
{} {}
TEnumRef(CScriptObject* pInObject, CEnumProperty* pInProperty) TEnumRef(void* pInData, CEnumProperty* pInProperty)
: TPropertyRef(pInObject, pInProperty) : TPropertyRef(pInData, pInProperty)
{} {}
}; };

View File

@ -125,6 +125,19 @@ SRayIntersection CLightNode::RayNodeIntersectTest(const CRay& rkRay, u32 AssetID
return Out; return Out;
} }
CStructRef CLightNode::GetProperties() const
{
return CStructRef(mpLight, mpLight->GetProperties());
}
void CLightNode::PropertyModified(IPropertyNew* pProperty)
{
CSceneNode::PropertyModified(pProperty);
if (pProperty->Name() == "Position")
SetPosition( mpLight->Position() );
}
CLight* CLightNode::Light() CLight* CLightNode::Light()
{ {
return mpLight; return mpLight;

View File

@ -15,6 +15,8 @@ public:
void DrawSelection(); void DrawSelection();
void RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo); void RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo);
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo); SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo);
CStructRef GetProperties() const;
void PropertyModified(IPropertyNew* pProperty);
bool AllowsRotate() const { return false; } bool AllowsRotate() const { return false; }
CLight* Light(); CLight* Light();
CVector2f BillboardScale(); CVector2f BillboardScale();

View File

@ -69,6 +69,8 @@ public:
virtual bool IsVisible() const; virtual bool IsVisible() const;
virtual CColor TintColor(const SViewInfo& rkViewInfo) const; virtual CColor TintColor(const SViewInfo& rkViewInfo) const;
virtual CColor WireframeColor() const; virtual CColor WireframeColor() const;
virtual CStructRef GetProperties() const { return CStructRef(); }
virtual void PropertyModified(IPropertyNew* pProperty) {}
void OnLoadFinished(); void OnLoadFinished();
void Unparent(); void Unparent();

View File

@ -13,8 +13,8 @@ CScriptAttachNode::CScriptAttachNode(CScene *pScene, const SAttachment& rkAttach
CStructPropertyNew* pBaseStruct = pParent->Template()->Properties(); CStructPropertyNew* pBaseStruct = pParent->Template()->Properties();
mpAttachAssetProp = pBaseStruct->ChildByIDString(rkAttachment.AttachProperty); mpAttachAssetProp = pBaseStruct->ChildByIDString(rkAttachment.AttachProperty);
mAttachAssetRef = CAssetRef(pParent->Instance(), mpAttachAssetProp); mAttachAssetRef = CAssetRef(pParent->Instance()->PropertyData(), mpAttachAssetProp);
mAttachAnimSetRef = CAnimationSetRef(pParent->Instance(), mpAttachAssetProp); mAttachAnimSetRef = CAnimationSetRef(pParent->Instance()->PropertyData(), mpAttachAssetProp);
if (mpAttachAssetProp) AttachPropertyModified(); if (mpAttachAssetProp) AttachPropertyModified();
ParentDisplayAssetChanged(mpScriptNode->DisplayAsset()); ParentDisplayAssetChanged(mpScriptNode->DisplayAsset());

View File

@ -454,6 +454,11 @@ void CScriptNode::LinksModified()
if (mpExtra) mpExtra->LinksModified(); if (mpExtra) mpExtra->LinksModified();
} }
CStructRef CScriptNode::GetProperties() const
{
return CStructRef(mpInstance->PropertyData(), mpInstance->Template()->Properties());
}
void CScriptNode::PropertyModified(IPropertyNew* pProp) void CScriptNode::PropertyModified(IPropertyNew* pProp)
{ {
// Update volume // Update volume

View File

@ -47,9 +47,10 @@ public:
bool IsVisible() const; bool IsVisible() const;
CColor TintColor(const SViewInfo& rkViewInfo) const; CColor TintColor(const SViewInfo& rkViewInfo) const;
CColor WireframeColor() const; CColor WireframeColor() const;
CStructRef GetProperties() const;
void PropertyModified(IPropertyNew* pProp);
void LinksModified(); void LinksModified();
void PropertyModified(IPropertyNew* pProp);
void UpdatePreviewVolume(); void UpdatePreviewVolume();
void GeneratePosition(); void GeneratePosition();
void TestGameModeVisibility(); void TestGameModeVisibility();

View File

@ -17,17 +17,17 @@ CDamageableTriggerExtra::CDamageableTriggerExtra(CScriptObject *pInstance, CScen
CStructPropertyNew* pProperties = pInstance->Template()->Properties(); CStructPropertyNew* pProperties = pInstance->Template()->Properties();
// Fetch render side // Fetch render side
mRenderSide = TEnumRef<ERenderSide>(pInstance, pProperties->ChildByIndex(5)); mRenderSide = TEnumRef<ERenderSide>(pInstance->PropertyData(), pProperties->ChildByIndex(5));
if (mRenderSide.IsValid()) PropertyModified(mRenderSide.Property()); if (mRenderSide.IsValid()) PropertyModified(mRenderSide.Property());
// Fetch scale // Fetch scale
mPlaneSize = CVectorRef(pInstance, pProperties->ChildByIndex(2)); mPlaneSize = CVectorRef(pInstance->PropertyData(), pProperties->ChildByIndex(2));
if (mPlaneSize.IsValid()) PropertyModified(mPlaneSize.Property()); if (mPlaneSize.IsValid()) PropertyModified(mPlaneSize.Property());
// Fetch textures // Fetch textures
for (u32 TextureIdx = 0; TextureIdx < 3; TextureIdx++) for (u32 TextureIdx = 0; TextureIdx < 3; TextureIdx++)
{ {
mTextureAssets[TextureIdx] = CAssetRef(pInstance, pProperties->ChildByIndex(6 + TextureIdx)); mTextureAssets[TextureIdx] = CAssetRef(pInstance->PropertyData(), pProperties->ChildByIndex(6 + TextureIdx));
if (mTextureAssets[TextureIdx].IsValid()) PropertyModified(mTextureAssets[TextureIdx].Property()); if (mTextureAssets[TextureIdx].IsValid()) PropertyModified(mTextureAssets[TextureIdx].Property());
} }
} }

View File

@ -6,18 +6,18 @@ CDoorExtra::CDoorExtra(CScriptObject* pInstance, CScene* pScene, CScriptNode* pP
{ {
CStructPropertyNew* pProperties = pInstance->Template()->Properties(); CStructPropertyNew* pProperties = pInstance->Template()->Properties();
mShieldModelProp = CAssetRef(pInstance, pProperties->ChildByID(0xB20CC271)); mShieldModelProp = CAssetRef(pInstance->PropertyData(), pProperties->ChildByID(0xB20CC271));
if (mShieldModelProp.IsValid()) PropertyModified(mShieldModelProp.Property()); if (mShieldModelProp.IsValid()) PropertyModified(mShieldModelProp.Property());
if (mGame >= eEchoes) if (mGame >= eEchoes)
{ {
mShieldColorProp = CColorRef(pInstance, pProperties->ChildByID(0x47B4E863)); mShieldColorProp = CColorRef(pInstance->PropertyData(), pProperties->ChildByID(0x47B4E863));
if (mShieldColorProp.IsValid()) PropertyModified(mShieldColorProp.Property()); if (mShieldColorProp.IsValid()) PropertyModified(mShieldColorProp.Property());
} }
else else
{ {
mDisabledProp = CBoolRef(pInstance, pProperties->ChildByID(0xDEE730F5)); mDisabledProp = CBoolRef(pInstance->PropertyData(), pProperties->ChildByID(0xDEE730F5));
if (mDisabledProp.IsValid()) PropertyModified(mDisabledProp.Property()); if (mDisabledProp.IsValid()) PropertyModified(mDisabledProp.Property());
} }
} }

View File

@ -10,8 +10,8 @@ CPointOfInterestExtra::CPointOfInterestExtra(CScriptObject *pInstance, CScene *p
// Fetch scan data property // Fetch scan data property
CStructPropertyNew* pProperties = pInstance->Template()->Properties(); CStructPropertyNew* pProperties = pInstance->Template()->Properties();
if (mGame <= ePrime) mScanProperty = CAssetRef(pInstance, pProperties->ChildByIDString("0x04:0x00")); if (mGame <= ePrime) mScanProperty = CAssetRef(pInstance->PropertyData(), pProperties->ChildByIDString("0x04:0x00"));
else mScanProperty = CAssetRef(pInstance, pProperties->ChildByIDString("0xBDBEC295:0xB94E9BE7")); else mScanProperty = CAssetRef(pInstance->PropertyData(), pProperties->ChildByIDString("0xBDBEC295:0xB94E9BE7"));
PropertyModified(mScanProperty.Property()); PropertyModified(mScanProperty.Property());
} }

View File

@ -11,16 +11,16 @@ CRadiusSphereExtra::CRadiusSphereExtra(CScriptObject* pInstance, CScene* pScene,
switch (mObjectType) switch (mObjectType)
{ {
case 0x63: // Repulsor (MP1) case 0x63: // Repulsor (MP1)
mRadius = CFloatRef(pInstance, pProperties->ChildByID(3)); mRadius = CFloatRef(pInstance->PropertyData(), pProperties->ChildByID(3));
break; break;
case 0x68: // RadialDamage (MP1) case 0x68: // RadialDamage (MP1)
mRadius = CFloatRef(pInstance, pProperties->ChildByID(0x4)); mRadius = CFloatRef(pInstance->PropertyData(), pProperties->ChildByID(0x4));
break; break;
case FOURCC('REPL'): // Repulsor (MP2/MP3) case FOURCC('REPL'): // Repulsor (MP2/MP3)
case FOURCC('RADD'): // RadialDamage (MP2/MP3/DKCR) case FOURCC('RADD'): // RadialDamage (MP2/MP3/DKCR)
mRadius = CFloatRef(pInstance, pProperties->ChildByID(0x78C507EB)); mRadius = CFloatRef(pInstance->PropertyData(), pProperties->ChildByID(0x78C507EB));
break; break;
} }
} }

View File

@ -13,7 +13,7 @@ CSandwormExtra::CSandwormExtra(CScriptObject* pInstance, CScene* pScene, CScript
} }
// Get pincers scale // Get pincers scale
mPincersScale = CFloatRef(pInstance, pInstance->Template()->Properties()->ChildByID(0x3DB583AE)); mPincersScale = CFloatRef(pInstance->PropertyData(), pInstance->Template()->Properties()->ChildByID(0x3DB583AE));
if (mPincersScale.IsValid()) PropertyModified(mPincersScale.Property()); if (mPincersScale.IsValid()) PropertyModified(mPincersScale.Property());
} }

View File

@ -6,7 +6,7 @@
CSplinePathExtra::CSplinePathExtra(CScriptObject* pInstance, CScene* pScene, CScriptNode* pParent) CSplinePathExtra::CSplinePathExtra(CScriptObject* pInstance, CScene* pScene, CScriptNode* pParent)
: CScriptExtra(pInstance, pScene, pParent) : CScriptExtra(pInstance, pScene, pParent)
{ {
mPathColor = CColorRef(pInstance, pInstance->Template()->Properties()->ChildByID(0x00DD86E2)); mPathColor = CColorRef(pInstance->PropertyData(), pInstance->Template()->Properties()->ChildByID(0x00DD86E2));
} }
void CSplinePathExtra::PropertyModified(IPropertyNew* pProperty) void CSplinePathExtra::PropertyModified(IPropertyNew* pProperty)

View File

@ -362,10 +362,13 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
{ {
EPropertyTypeNew Type = pProp->Type(); EPropertyTypeNew Type = pProp->Type();
QVector<CScriptObject*> Objects;
Objects << mpModel->GetScriptObject();
if (Type != EPropertyTypeNew::Array) if (Type != EPropertyTypeNew::Array)
{ {
// TODO: support this for non script object properties // TODO: support this for non script object properties
pCommand = new CEditScriptPropertyCommand(mpEditor, rkIndex, mpModel); pCommand = new CEditScriptPropertyCommand(pProp, mpEditor, Objects, rkIndex);
pCommand->SaveOldData(); pCommand->SaveOldData();
// Handle sub-properties of flags and animation sets // Handle sub-properties of flags and animation sets
@ -478,7 +481,7 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
// Array // Array
else else
{ {
pCommand = new CResizeScriptArrayCommand(mpEditor, rkIndex, mpModel); pCommand = new CResizeScriptArrayCommand(pProp, mpEditor, Objects, mpModel, rkIndex);
pCommand->SaveOldData(); pCommand->SaveOldData();
WIntegralSpinBox* pSpinBox = static_cast<WIntegralSpinBox*>(pEditor); WIntegralSpinBox* pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);

View File

@ -84,6 +84,14 @@ void CPropertyView::SetEditor(CWorldEditor *pEditor)
connect(mpEditor, SIGNAL(PropertyModified(CScriptObject*,IPropertyNew*)), mpModel, SLOT(NotifyPropertyModified(CScriptObject*,IPropertyNew*))); connect(mpEditor, SIGNAL(PropertyModified(CScriptObject*,IPropertyNew*)), mpModel, SLOT(NotifyPropertyModified(CScriptObject*,IPropertyNew*)));
} }
void CPropertyView::SetProperties(CStructRef InProperties)
{
mpObject = nullptr;
mpModel->SetBoldModifiedProperties(false); // todo, we prob want this, but can't set default properties on non script yet
mpModel->ConfigureIntrinsic(nullptr, InProperties.Property(), InProperties.DataPointer());
SetPersistentEditors(QModelIndex());
}
void CPropertyView::SetInstance(CScriptObject *pObj) void CPropertyView::SetInstance(CScriptObject *pObj)
{ {
mpObject = pObj; mpObject = pObj;
@ -131,7 +139,7 @@ void CPropertyView::UpdateEditorProperties(const QModelIndex& rkParent)
continue; continue;
} }
else if (mpObject->IsEditorProperty(pProp)) else if (mpObject && mpObject->IsEditorProperty(pProp))
{ {
mpModel->dataChanged(Index1, Index1); mpModel->dataChanged(Index1, Index1);

View File

@ -24,6 +24,7 @@ public:
void setModel(QAbstractItemModel *pModel); void setModel(QAbstractItemModel *pModel);
bool event(QEvent *pEvent); bool event(QEvent *pEvent);
void SetEditor(CWorldEditor *pEditor); void SetEditor(CWorldEditor *pEditor);
void SetProperties(CStructRef InProperties);
void SetInstance(CScriptObject *pObj); void SetInstance(CScriptObject *pObj);
void UpdateEditorProperties(const QModelIndex& rkParent); void UpdateEditorProperties(const QModelIndex& rkParent);

View File

@ -7,23 +7,56 @@
class CEditScriptPropertyCommand : public IEditPropertyCommand class CEditScriptPropertyCommand : public IEditPropertyCommand
{ {
std::vector<CInstancePtr> mInstances; protected:
QVector<CInstancePtr> mInstances;
CWorldEditor* mpEditor; CWorldEditor* mpEditor;
QModelIndex mIndex;
public: public:
CEditScriptPropertyCommand(CWorldEditor* pEditor, const QModelIndex& rkIndex, CPropertyModel* pInModel, const QString& rkCommandName = "Edit Property") CEditScriptPropertyCommand(IPropertyNew* pProperty,
: IEditPropertyCommand(rkIndex, pInModel, rkCommandName) CWorldEditor* pEditor,
const QVector<CScriptObject*>& rkInstances,
QModelIndex Index = QModelIndex(),
const QString& rkCommandName = "Edit Property")
: IEditPropertyCommand(pProperty, rkCommandName)
, mpEditor(pEditor) , mpEditor(pEditor)
, mIndex(Index)
{ {
mInstances.push_back( CInstancePtr(pInModel->GetScriptObject()) ); // If the property being passed in is part of an array archetype, then we MUST have a QModelIndex.
// Without the index, there's no way to identify the correct child being edited.
if (!Index.isValid() && pProperty && pProperty->IsArrayArchetype())
{
while (pProperty && pProperty->IsArrayArchetype())
{
pProperty = pProperty->Parent();
}
ASSERT(pProperty && !pProperty->IsArrayArchetype());
}
// Convert CScriptObject pointers to CInstancePtrs
mInstances.reserve( rkInstances.size() );
for (int i = 0; i < rkInstances.size(); i++)
mInstances.push_back( CInstancePtr(rkInstances[i]) );
} }
virtual void GetObjectDataPointers(std::vector<void*>& rOutPointers) const override virtual void GetObjectDataPointers(QVector<void*>& rOutPointers) const override
{ {
// todo: support multiple objects being edited at once on the property view
if (mIndex.isValid())
{
ASSERT(mInstances.size() == 1);
rOutPointers << mInstances[0]->PropertyData();
return;
}
// grab instance pointers
ASSERT(!mpProperty->IsArrayArchetype());
rOutPointers.resize(mInstances.size()); rOutPointers.resize(mInstances.size());
//@todo support multiple objects for (int i = 0; i < mInstances.size(); i++)
rOutPointers[0] = mpModel->DataPointerForIndex(mIndex); rOutPointers[i] = mInstances[i]->PropertyData();
} }
virtual void undo() override virtual void undo() override

View File

@ -5,45 +5,88 @@
class CResizeScriptArrayCommand : public CEditScriptPropertyCommand class CResizeScriptArrayCommand : public CEditScriptPropertyCommand
{ {
/** Property model the edit was performed on */
CPropertyModel* mpModel;
/** Old/new model row counts; we store this here to support editing arrays on multiple instances at once */
int mOldRowCount;
int mNewRowCount;
public: public:
CResizeScriptArrayCommand(CWorldEditor* pEditor, const QModelIndex& rkIndex, CPropertyModel* pInModel, const QString& rkCommandName = "Resize Array") CResizeScriptArrayCommand(IPropertyNew* pProperty,
: CEditScriptPropertyCommand(pEditor, rkIndex, pInModel, rkCommandName) CWorldEditor* pEditor,
{} const QVector<CScriptObject*>& rkInstances,
CPropertyModel* pModel = nullptr,
QModelIndex Index = QModelIndex(),
const QString& rkCommandName = "Resize Array"
)
: CEditScriptPropertyCommand(pProperty, pEditor, rkInstances, Index, rkCommandName)
, mpModel(nullptr)
, mOldRowCount(-1)
, mNewRowCount(-1)
{
if (Index.isValid())
{
ASSERT(mpModel != nullptr);
mpModel = pModel;
}
}
bool mergeWith(const QUndoCommand *pkOther) bool mergeWith(const QUndoCommand *pkOther)
{ {
return false; return false;
} }
virtual void SaveOldData() override
{
CEditScriptPropertyCommand::SaveOldData();
if (mpModel)
{
mOldRowCount = mpModel->rowCount(mIndex);
}
}
virtual void SaveNewData() override
{
CEditScriptPropertyCommand::SaveNewData();
if (mpModel)
{
mNewRowCount = mpModel->rowCount(mIndex);
}
}
// Note in some cases undo/redo may be called when the change has already been applied outside of the undo command // Note in some cases undo/redo may be called when the change has already been applied outside of the undo command
// This is why we need to check the array's actual current size instead of assuming it will match one of the arrays // This is why we need to check the array's actual current size instead of assuming it will match one of the arrays
void undo() void undo()
{ {
// unpleasant cast, but easiest/fastest way to access the sizes if (mpModel)
int NewSize = *((int*)mOldData.data()); {
int OldSize = CurrentArrayCount(); mpModel->ArrayAboutToBeResized(mIndex, mOldRowCount);
}
mpModel->ArrayAboutToBeResized(mIndex, NewSize);
CEditScriptPropertyCommand::undo(); CEditScriptPropertyCommand::undo();
mpModel->ArrayResized(mIndex, OldSize);
if (mpModel)
{
mpModel->ArrayResized(mIndex, mNewRowCount);
}
} }
void redo() void redo()
{ {
// unpleasant cast, but easiest/fastest way to access the sizes if (mpModel)
int NewSize = *((int*)mNewData.data()); {
int OldSize = CurrentArrayCount(); mpModel->ArrayAboutToBeResized(mIndex, mNewRowCount);
}
mpModel->ArrayAboutToBeResized(mIndex, NewSize);
CEditScriptPropertyCommand::redo(); CEditScriptPropertyCommand::redo();
mpModel->ArrayResized(mIndex, OldSize);
}
int CurrentArrayCount() if (mpModel)
{ {
void* pData = mpModel->DataPointerForIndex(mIndex); mpModel->ArrayResized(mIndex, mOldRowCount);
CArrayProperty* pArray = TPropCast<CArrayProperty>(mpProperty); }
return pArray->ArrayCount(pData);
} }
}; };

View File

@ -6,12 +6,11 @@ void IEditPropertyCommand::SaveObjectStateToArray(std::vector<char>& rVector)
CVectorOutStream MemStream(&rVector, IOUtil::kSystemEndianness); CVectorOutStream MemStream(&rVector, IOUtil::kSystemEndianness);
CBasicBinaryWriter Writer(&MemStream, CSerialVersion(IArchive::skCurrentArchiveVersion, 0, mpProperty->Game())); CBasicBinaryWriter Writer(&MemStream, CSerialVersion(IArchive::skCurrentArchiveVersion, 0, mpProperty->Game()));
std::vector<void*> DataPointers; QVector<void*> DataPointers;
GetObjectDataPointers(DataPointers); GetObjectDataPointers(DataPointers);
for (int PtrIdx = 0; PtrIdx < DataPointers.size(); PtrIdx++) foreach (void* pData, DataPointers)
{ {
void* pData = DataPointers[PtrIdx];
mpProperty->SerializeValue(pData, Writer); mpProperty->SerializeValue(pData, Writer);
} }
} }
@ -21,29 +20,25 @@ void IEditPropertyCommand::RestoreObjectStateFromArray(std::vector<char>& rArray
{ {
CBasicBinaryReader Reader(rArray.data(), rArray.size(), CSerialVersion(IArchive::skCurrentArchiveVersion, 0, mpProperty->Game())); CBasicBinaryReader Reader(rArray.data(), rArray.size(), CSerialVersion(IArchive::skCurrentArchiveVersion, 0, mpProperty->Game()));
std::vector<void*> DataPointers; QVector<void*> DataPointers;
GetObjectDataPointers(DataPointers); GetObjectDataPointers(DataPointers);
for (int PtrIdx = 0; PtrIdx < DataPointers.size(); PtrIdx++) foreach (void* pData, DataPointers)
{ {
void* pData = DataPointers[PtrIdx];
mpProperty->SerializeValue(pData, Reader); mpProperty->SerializeValue(pData, Reader);
} }
} }
IEditPropertyCommand::IEditPropertyCommand( IEditPropertyCommand::IEditPropertyCommand(
const QModelIndex& rkInIndex, IPropertyNew* pProperty,
CPropertyModel* pInModel,
const QString& rkCommandName /*= "Edit Property"*/ const QString& rkCommandName /*= "Edit Property"*/
) )
: IUndoCommand(rkCommandName) : IUndoCommand(rkCommandName)
, mIndex(rkInIndex) , mpProperty(pProperty)
, mpModel(pInModel)
, mSavedOldData(false) , mSavedOldData(false)
, mSavedNewData(false) , mSavedNewData(false)
{ {
mpProperty = mpModel->PropertyForIndex(rkInIndex, true); ASSERT(mpProperty);
ASSERT(mpModel && mpProperty);
} }
void IEditPropertyCommand::SaveOldData() void IEditPropertyCommand::SaveOldData()
@ -81,12 +76,12 @@ bool IEditPropertyCommand::mergeWith(const QUndoCommand *pkOther)
{ {
const IEditPropertyCommand* pkCmd = dynamic_cast<const IEditPropertyCommand*>(pkOther); const IEditPropertyCommand* pkCmd = dynamic_cast<const IEditPropertyCommand*>(pkOther);
if (pkCmd && pkCmd->mIndex == mIndex && pkCmd->mpProperty == mpProperty) if (pkCmd && pkCmd->mpProperty == mpProperty)
{ {
std::vector<void*> MyPointers; QVector<void*> MyPointers;
GetObjectDataPointers(MyPointers); GetObjectDataPointers(MyPointers);
std::vector<void*> TheirPointers; QVector<void*> TheirPointers;
pkCmd->GetObjectDataPointers(TheirPointers); pkCmd->GetObjectDataPointers(TheirPointers);
if (TheirPointers.size() == MyPointers.size()) if (TheirPointers.size() == MyPointers.size())

View File

@ -8,11 +8,10 @@
class IEditPropertyCommand : public IUndoCommand class IEditPropertyCommand : public IUndoCommand
{ {
protected: protected:
// Has to be std::vector for compatibility with CVectorOutStream
std::vector<char> mOldData; std::vector<char> mOldData;
std::vector<char> mNewData; std::vector<char> mNewData;
QModelIndex mIndex;
CPropertyModel* mpModel;
IPropertyNew* mpProperty; IPropertyNew* mpProperty;
bool mCommandEnded; bool mCommandEnded;
bool mSavedOldData; bool mSavedOldData;
@ -26,18 +25,18 @@ protected:
public: public:
IEditPropertyCommand( IEditPropertyCommand(
const QModelIndex& rkInIndex, IPropertyNew* pProperty,
CPropertyModel* pInModel,
const QString& rkCommandName = "Edit Property" const QString& rkCommandName = "Edit Property"
); );
void SaveOldData(); virtual void SaveOldData();
void SaveNewData(); virtual void SaveNewData();
bool IsNewDataDifferent(); bool IsNewDataDifferent();
void SetEditComplete(bool IsComplete); void SetEditComplete(bool IsComplete);
/** Interface */ /** Interface */
virtual void GetObjectDataPointers(std::vector<void*>& rOutPointers) const = 0; virtual void GetObjectDataPointers(QVector<void*>& rOutPointers) const = 0;
/** IUndoCommand/QUndoCommand interface */ /** IUndoCommand/QUndoCommand interface */
int id() const; int id() const;

View File

@ -128,18 +128,14 @@ void CTemplateEditDialog::ApplyChanges()
// ************ PROTECTED ************ // ************ PROTECTED ************
void CTemplateEditDialog::AddTemplate(IPropertyNew* pProp) void CTemplateEditDialog::AddTemplate(IPropertyNew* pProp)
{ {
//FIXME TString Source = pProp->GetTemplateFileName();
/* if (pProp->Archetype() != nullptr)
if (!Source.IsEmpty())
{ {
TString Source = pProp->GetTemplateFileName(); CStructPropertyNew* pStruct = pProp->MasterTemplate()->StructAtSource(Source);
if (!Source.IsEmpty()) if (!mStructTemplatesToResave.contains(pStruct))
{ mStructTemplatesToResave << pStruct;
CStructTemplate *pStruct = pProp->MasterTemplate()->StructAtSource(Source);
if (!mStructTemplatesToResave.contains(pStruct))
mStructTemplatesToResave << pStruct;
}
} }
else else
@ -156,13 +152,12 @@ void CTemplateEditDialog::AddTemplate(IPropertyNew* pProp)
{ {
Log::Error("Can't determine where property " + pProp->IDString(true) + " comes from"); Log::Error("Can't determine where property " + pProp->IDString(true) + " comes from");
} }
}*/ }
} }
void CTemplateEditDialog::UpdateDescription(const TString& rkNewDesc) void CTemplateEditDialog::UpdateDescription(const TString& rkNewDesc)
{ {
//FIXME mpProperty->SetDescription(rkNewDesc);
/* mpProperty->SetDescription(rkNewDesc);
AddTemplate(mpProperty); AddTemplate(mpProperty);
// Update all copies of this property in memory with the new description // Update all copies of this property in memory with the new description
@ -170,13 +165,13 @@ void CTemplateEditDialog::UpdateDescription(const TString& rkNewDesc)
if (!SourceFile.IsEmpty()) if (!SourceFile.IsEmpty())
{ {
const std::vector<IPropertyTemplate*> *pkTemplates = CMasterTemplate::TemplatesWithMatchingID(mpProperty); const std::vector<IPropertyNew*>* pkTemplates = CMasterTemplate::TemplatesWithMatchingID(mpProperty);
if (pkTemplates) if (pkTemplates)
{ {
for (u32 iTemp = 0; iTemp < pkTemplates->size(); iTemp++) for (u32 TemplateIdx = 0; TemplateIdx < pkTemplates->size(); TemplateIdx++)
{ {
IPropertyTemplate *pTemp = pkTemplates->at(iTemp); IPropertyNew* pTemp = pkTemplates->at(TemplateIdx);
if (pTemp->FindStructSource() == SourceFile && pTemp->Description() == mOriginalDescription) if (pTemp->FindStructSource() == SourceFile && pTemp->Description() == mOriginalDescription)
pTemp->SetDescription(rkNewDesc); pTemp->SetDescription(rkNewDesc);
@ -185,11 +180,11 @@ void CTemplateEditDialog::UpdateDescription(const TString& rkNewDesc)
} }
// Update equivalent properties with new description // Update equivalent properties with new description
foreach (IPropertyTemplate *pTemp, mEquivalentProperties) foreach (IPropertyNew* pProperty, mEquivalentProperties)
{ {
pTemp->SetDescription(rkNewDesc); pProperty->SetDescription(rkNewDesc);
AddTemplate(pTemp); AddTemplate(pProperty);
}*/ }
} }
void CTemplateEditDialog::FindEquivalentProperties(IPropertyNew *pTemp) void CTemplateEditDialog::FindEquivalentProperties(IPropertyNew *pTemp)

View File

@ -24,10 +24,9 @@ class CTemplateEditDialog : public QDialog
bool mOriginalNameWasValid; bool mOriginalNameWasValid;
// These members help track what templates need to be updated and resaved after the user clicks OK // These members help track what templates need to be updated and resaved after the user clicks OK
//FIXME QVector<CScriptTemplate*> mScriptTemplatesToResave;
// QVector<CScriptTemplate*> mScriptTemplatesToResave; QVector<CStructPropertyNew*> mStructTemplatesToResave;
// QVector<CStructTemplate*> mStructTemplatesToResave; QVector<IPropertyNew*> mEquivalentProperties;
// QVector<IPropertyTemplate*> mEquivalentProperties;
public: public:
CTemplateEditDialog(IPropertyNew* pProperty, QWidget *pParent = 0); CTemplateEditDialog(IPropertyNew* pProperty, QWidget *pParent = 0);

View File

@ -577,11 +577,16 @@ void CWorldEditor::OnPropertyModified(CScriptObject* pObject, IPropertyNew *pPro
{ {
pScript->PropertyModified(pProp); pScript->PropertyModified(pProp);
// If this is an editor property, update other parts of the UI to reflect the new value. // If this is the name, update other parts of the UI to reflect the new value.
if ( pScript->Instance()->IsEditorProperty(pProp) ) if ( pProp->Name() == "Name" )
{ {
UpdateStatusBar(); UpdateStatusBar();
UpdateSelectionUI(); UpdateSelectionUI();
}
else if (pProp->Name() == "Position" ||
pProp->Name() == "Rotation" ||
pProp->Name() == "Scale")
{
mpSelection->UpdateBounds(); mpSelection->UpdateBounds();
} }
} }
@ -613,9 +618,7 @@ void CWorldEditor::SetSelectionActive(bool Active)
{ {
CScriptNode* pScript = static_cast<CScriptNode*>(*It); CScriptNode* pScript = static_cast<CScriptNode*>(*It);
CScriptObject* pInst = pScript->Instance(); CScriptObject* pInst = pScript->Instance();
Objects << pInst;
if (pInst->IsActive())
Objects << pInst;
} }
} }
@ -623,13 +626,40 @@ void CWorldEditor::SetSelectionActive(bool Active)
{ {
mUndoStack.beginMacro("Toggle Active"); mUndoStack.beginMacro("Toggle Active");
/*foreach (CScriptObject *pInst, Objects) while (!Objects.isEmpty())
{ {
IProperty *pActive = pInst->ActiveProperty(); QVector<CScriptObject*> CommandObjects;
IPropertyValue *pOld = pActive->RawValue()->Clone(); CScriptTemplate* pTemplate = Objects[0]->Template();
pInst->SetActive(Active); CBoolProperty* pActiveProperty = pTemplate->ActiveProperty();
mUndoStack.push(new CEditScriptPropertyCommand(pActive, this, pOld, true));
}*/ for (int ObjIdx = 0; ObjIdx < Objects.size(); ObjIdx++)
{
if (Objects[ObjIdx]->Template() == pTemplate)
{
CommandObjects << Objects[ObjIdx];
Objects.removeAt(ObjIdx);
ObjIdx--;
}
}
if (pActiveProperty)
{
CEditScriptPropertyCommand* pCommand = new CEditScriptPropertyCommand(
pActiveProperty,
this,
CommandObjects
);
pCommand->SaveOldData();
foreach (CScriptObject* pInstance, CommandObjects)
pInstance->SetActive(Active);
pCommand->SaveNewData();
mUndoStack.push(pCommand);
}
}
mUndoStack.endMacro(); mUndoStack.endMacro();
} }

View File

@ -69,7 +69,6 @@ void WModifyTab::ClearUI()
{ {
ui->ObjectsTabWidget->hide(); ui->ObjectsTabWidget->hide();
ui->PropertyView->SetInstance(nullptr); ui->PropertyView->SetInstance(nullptr);
ui->LightGroupBox->hide();
mpSelectedNode = nullptr; mpSelectedNode = nullptr;
} }
@ -85,22 +84,32 @@ void WModifyTab::GenerateUI()
{ {
mpSelectedNode = mpWorldEditor->Selection()->Front(); mpSelectedNode = mpWorldEditor->Selection()->Front();
// todo: set up editing UI for Light Nodes
if (mpSelectedNode->NodeType() == eScriptNode) if (mpSelectedNode->NodeType() == eScriptNode)
{ {
ui->ObjectsTabWidget->show();
CScriptNode *pScriptNode = static_cast<CScriptNode*>(mpSelectedNode); CScriptNode *pScriptNode = static_cast<CScriptNode*>(mpSelectedNode);
CScriptObject *pObj = pScriptNode->Instance(); CScriptObject *pObj = pScriptNode->Instance();
// Set up UI // Set up UI
ui->ObjectsTabWidget->show();
ui->PropertyView->SetInstance(pObj); ui->PropertyView->SetInstance(pObj);
ui->LightGroupBox->hide();
ui->InLinksTableView->clearSelection();
ui->OutLinksTableView->clearSelection();
mpInLinkModel->SetObject(pObj); mpInLinkModel->SetObject(pObj);
mpOutLinkModel->SetObject(pObj); mpOutLinkModel->SetObject(pObj);
} }
// disabled this for now! implemented it as a quick test, it's cool it works,
// but it's buggy & not ready for deployment
#if 0
else
{
CStructRef Properties = mpSelectedNode->GetProperties();
ui->PropertyView->SetProperties(Properties);
if (Properties.IsValid())
ui->ObjectsTabWidget->show();
}
#endif
ui->InLinksTableView->clearSelection();
ui->OutLinksTableView->clearSelection();
} }
} }

View File

@ -108,7 +108,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>278</width> <width>278</width>
<height>442</height> <height>475</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
@ -369,13 +369,6 @@
</widget> </widget>
</widget> </widget>
</item> </item>
<item>
<widget class="QGroupBox" name="LightGroupBox">
<property name="title">
<string>Light</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>