Massive overhaul of property system done over the last few months. There is unfinished/broken stuff still, but it compiles now.
This commit is contained in:
parent
7099b97529
commit
ce3dfdc397
|
@ -1,8 +1,13 @@
|
|||
# CONFIG += PUBLIC_RELEASE
|
||||
|
||||
win32: {
|
||||
QMAKE_CXXFLAGS += /WX \ # Treat warnings as errors
|
||||
/wd4267 # Disable C4267: conversion from 'size_t' to 'type', possible loss of data
|
||||
QMAKE_CXXFLAGS += /WX \ # Treat warnings as errors
|
||||
/wd4267 \ # Disable C4267: conversion from 'size_t' to 'type', possible loss of data
|
||||
/wd4100 \ # Disable C4100: unreferenced formal parameter
|
||||
/wd4101 \ # Disable C4101: unreferenced local variable
|
||||
/wd4189 # Disable C4189: local variable is initialized but not referenced
|
||||
|
||||
QMAKE_CXXFLAGS_WARN_ON -= -w34100 -w34189 # Override C4100 and C4189 being set to w3 in Qt's default .qmake.conf file
|
||||
}
|
||||
|
||||
BUILD_DIR = $$PWD/../build
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include "types.h"
|
||||
#include "AssertMacro.h"
|
||||
#include "CAssetID.h"
|
||||
#include "CColor.h"
|
||||
|
@ -15,10 +16,13 @@
|
|||
#include "Flags.h"
|
||||
#include "Log.h"
|
||||
#include "TString.h"
|
||||
#include "types.h"
|
||||
#include "Hash/CCRC32.h"
|
||||
#include "Hash/CFNV1A.h"
|
||||
#include "Serialization/Binary.h"
|
||||
#include "Serialization/XML.h"
|
||||
#include "NBasics.h"
|
||||
|
||||
// temporary home for ALIGN macro, moving later
|
||||
#define ALIGN(Val, Align) ((Val + (Align-1)) & ~(Align-1))
|
||||
|
||||
#endif // COMMON_H
|
||||
|
|
|
@ -84,7 +84,8 @@ HEADERS += \
|
|||
FileIO\CFileLock.h \
|
||||
FileIO.h \
|
||||
Common.h \
|
||||
Hash/CCRC32.h
|
||||
Hash/CCRC32.h \
|
||||
NBasics.h
|
||||
|
||||
# Source Files
|
||||
SOURCES += \
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#include "CVectorOutStream.h"
|
||||
#include "Common/Common.h"
|
||||
|
||||
CVectorOutStream::CVectorOutStream()
|
||||
: mpVector(new std::vector<char>)
|
||||
, mOwnsVector(true)
|
||||
, mPos(0)
|
||||
, mUsed(0)
|
||||
{
|
||||
mDataEndianness = IOUtil::eBigEndian;
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ CVectorOutStream::CVectorOutStream(IOUtil::EEndianness DataEndianness)
|
|||
: mpVector(new std::vector<char>)
|
||||
, mOwnsVector(true)
|
||||
, mPos(0)
|
||||
, mUsed(0)
|
||||
{
|
||||
mDataEndianness = DataEndianness;
|
||||
}
|
||||
|
@ -22,7 +21,6 @@ CVectorOutStream::CVectorOutStream(u32 InitialSize, IOUtil::EEndianness DataEndi
|
|||
: mpVector(new std::vector<char>(InitialSize))
|
||||
, mOwnsVector(true)
|
||||
, mPos(0)
|
||||
, mUsed(0)
|
||||
{
|
||||
mDataEndianness = DataEndianness;
|
||||
}
|
||||
|
@ -31,7 +29,6 @@ CVectorOutStream::CVectorOutStream(std::vector<char> *pVector, IOUtil::EEndianne
|
|||
: mpVector(pVector)
|
||||
, mOwnsVector(false)
|
||||
, mPos(0)
|
||||
, mUsed(0)
|
||||
{
|
||||
mDataEndianness = DataEndianness;
|
||||
}
|
||||
|
@ -45,12 +42,18 @@ void CVectorOutStream::WriteBytes(const void *pkSrc, u32 Count)
|
|||
{
|
||||
if (!IsValid()) return;
|
||||
|
||||
if ((mPos + Count) > mpVector->size())
|
||||
mpVector->resize(mPos + Count);
|
||||
u32 NewSize = mPos + Count;
|
||||
|
||||
if (NewSize > mpVector->size())
|
||||
{
|
||||
if (NewSize > mpVector->capacity())
|
||||
mpVector->reserve( ALIGN(mPos + Count, skAllocSize) );
|
||||
|
||||
mpVector->resize(NewSize);
|
||||
}
|
||||
|
||||
memcpy(mpVector->data() + mPos, pkSrc, Count);
|
||||
mPos += Count;
|
||||
if (mPos > mUsed) mUsed = mPos;
|
||||
}
|
||||
|
||||
bool CVectorOutStream::Seek(s32 Offset, u32 Origin)
|
||||
|
@ -68,7 +71,7 @@ bool CVectorOutStream::Seek(s32 Offset, u32 Origin)
|
|||
break;
|
||||
|
||||
case SEEK_END:
|
||||
mPos = mUsed - Offset;
|
||||
mPos = mpVector->size() - Offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -81,9 +84,6 @@ bool CVectorOutStream::Seek(s32 Offset, u32 Origin)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (mPos > mUsed)
|
||||
mUsed = mPos;
|
||||
|
||||
if (mPos > mpVector->size())
|
||||
mpVector->resize(mPos);
|
||||
|
||||
|
@ -107,20 +107,19 @@ bool CVectorOutStream::IsValid() const
|
|||
|
||||
u32 CVectorOutStream::Size() const
|
||||
{
|
||||
return mUsed;
|
||||
}
|
||||
|
||||
u32 CVectorOutStream::SizeRemaining() const
|
||||
{
|
||||
return mpVector->size() - mPos;
|
||||
return mPos;
|
||||
}
|
||||
|
||||
void CVectorOutStream::SetVector(std::vector<char> *pVector)
|
||||
{
|
||||
if (mOwnsVector) delete mpVector;
|
||||
if (mOwnsVector)
|
||||
{
|
||||
delete mpVector;
|
||||
mOwnsVector = false;
|
||||
}
|
||||
|
||||
mpVector = pVector;
|
||||
mPos = 0;
|
||||
mUsed = 0;
|
||||
}
|
||||
|
||||
void* CVectorOutStream::Data()
|
||||
|
@ -133,24 +132,8 @@ void* CVectorOutStream::DataAtPosition()
|
|||
return mpVector->data() + mPos;
|
||||
}
|
||||
|
||||
void CVectorOutStream::Expand(u32 Amount)
|
||||
{
|
||||
mpVector->resize(mpVector->size() + Amount);
|
||||
}
|
||||
|
||||
void CVectorOutStream::Shrink()
|
||||
{
|
||||
mpVector->resize(mUsed);
|
||||
}
|
||||
|
||||
void CVectorOutStream::Reset()
|
||||
{
|
||||
mPos = 0;
|
||||
mUsed = 0;
|
||||
}
|
||||
|
||||
void CVectorOutStream::Clear()
|
||||
{
|
||||
mPos = 0;
|
||||
mpVector->clear();
|
||||
Reset();
|
||||
}
|
||||
|
|
|
@ -6,10 +6,11 @@
|
|||
|
||||
class CVectorOutStream : public IOutputStream
|
||||
{
|
||||
static const u32 skAllocSize = 1024; // must be power of 2
|
||||
|
||||
std::vector<char> *mpVector;
|
||||
bool mOwnsVector;
|
||||
u32 mPos;
|
||||
u32 mUsed;
|
||||
|
||||
public:
|
||||
CVectorOutStream();
|
||||
|
@ -24,13 +25,9 @@ public:
|
|||
bool EoF() const;
|
||||
bool IsValid() const;
|
||||
u32 Size() const;
|
||||
u32 SizeRemaining() const;
|
||||
void SetVector(std::vector<char> *pVector);
|
||||
void *Data();
|
||||
void *DataAtPosition();
|
||||
void Expand(u32 Amount);
|
||||
void Shrink();
|
||||
void Reset();
|
||||
void Clear();
|
||||
};
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ public:
|
|||
TFlags() : mValue(0) {}
|
||||
TFlags(int Val) : mValue(Val) {}
|
||||
TFlags(u32 Val) : mValue(Val) {}
|
||||
TFlags(FlagEnum Val) : mValue(Val) {}
|
||||
TFlags(FlagEnum Val) : mValue((u32) Val) {}
|
||||
|
||||
inline operator int() const { return mValue; }
|
||||
inline bool operator!() const { return !mValue; }
|
||||
|
@ -22,25 +22,41 @@ public:
|
|||
inline void operator&=(int Mask) { mValue &= Mask; }
|
||||
inline void operator&=(u32 Mask) { mValue &= Mask; }
|
||||
inline void operator|=(TFlags Flags) { mValue |= Flags.mValue; }
|
||||
inline void operator|=(FlagEnum Flag) { mValue |= Flag; }
|
||||
inline void operator|=(FlagEnum Flag) { mValue |= (u32) Flag; }
|
||||
|
||||
inline TFlags operator|(TFlags Flags) const { return TFlags(FlagEnum(mValue | Flags.mValue)); }
|
||||
inline TFlags operator|(FlagEnum Flag) const { return TFlags(FlagEnum(mValue | Flag)); }
|
||||
inline TFlags operator|(FlagEnum Flag) const { return TFlags(FlagEnum(mValue | (u32) Flag)); }
|
||||
inline TFlags operator&(int Mask) const { return TFlags(FlagEnum(mValue & Mask)); }
|
||||
inline TFlags operator&(u32 Mask) const { return TFlags(FlagEnum(mValue & Mask)); }
|
||||
inline TFlags operator&(FlagEnum Flag) const { return TFlags(FlagEnum(mValue & Flag)); }
|
||||
inline TFlags operator&(FlagEnum Flag) const { return TFlags(FlagEnum(mValue & (u32) Flag)); }
|
||||
|
||||
inline bool HasFlag(FlagEnum Flag) const { return ((mValue & Flag) != 0); }
|
||||
inline bool HasFlag(FlagEnum Flag) const { return ((mValue & (u32) Flag) != 0); }
|
||||
inline bool HasAnyFlags(TFlags Flags) const { return ((mValue & Flags) != 0); }
|
||||
inline bool HasAllFlags(TFlags Flags) const { return ((mValue & Flags) == Flags); }
|
||||
inline void SetFlag(FlagEnum Flag) { mValue |= Flag; }
|
||||
inline void SetFlag(FlagEnum Flag) { mValue |= (u32) Flag; }
|
||||
inline void SetFlag(TFlags Flags) { mValue |= Flags; }
|
||||
inline void ClearFlag(FlagEnum Flag) { mValue &= ~Flag; }
|
||||
inline void ClearFlag(FlagEnum Flag) { mValue &= ~((u32) Flag); }
|
||||
inline void ClearFlag(TFlags Flags) { mValue &= ~Flags; }
|
||||
|
||||
inline void Serialize(IArchive& rArc) { rArc.SerializeHexPrimitive(mValue); }
|
||||
};
|
||||
#define DECLARE_FLAGS(Enum, FlagTypeName) typedef TFlags<Enum> FlagTypeName;
|
||||
|
||||
// Alternate version for enum class flags
|
||||
#define DECLARE_FLAGS_ENUMCLASS(Enum, FlagTypeName) \
|
||||
DECLARE_FLAGS(Enum, FlagTypeName) \
|
||||
inline int operator|(Enum Left, Enum Right) \
|
||||
{ \
|
||||
return (int) Left | (int) Right; \
|
||||
} \
|
||||
inline int operator&(Enum Left, Enum Right) \
|
||||
{ \
|
||||
return (int) Left & (int) Right; \
|
||||
} \
|
||||
inline int operator~(Enum Value) \
|
||||
{ \
|
||||
return ~((int) Value); \
|
||||
} \
|
||||
|
||||
#endif // FLAGS_H
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
#ifndef NBASICS_H
|
||||
#define NBASICS_H
|
||||
|
||||
#include "types.h"
|
||||
#include <vector>
|
||||
|
||||
namespace NBasics
|
||||
{
|
||||
|
||||
/** Remove an element from a vector */
|
||||
template<typename T>
|
||||
bool VectorRemoveOne(std::vector<T>& rVector, const T& rkElement)
|
||||
{
|
||||
for (auto Iter = rVector.begin(); Iter != rVector.end(); Iter++)
|
||||
{
|
||||
if (*Iter == rkElement)
|
||||
{
|
||||
rVector.erase(Iter);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Remove all occurrences of an element from a vector. Returns the number of elements that were removed. */
|
||||
template<typename T>
|
||||
int VectorRemoveAll(std::vector<T>& rVector, const T& rkElement)
|
||||
{
|
||||
int NumRemoved = 0;
|
||||
|
||||
for (auto Iter = rVector.begin(); Iter != rVector.end(); Iter++)
|
||||
{
|
||||
if (*Iter == rkElement)
|
||||
{
|
||||
Iter = rVector.erase(Iter);
|
||||
NumRemoved++;
|
||||
}
|
||||
}
|
||||
|
||||
return NumRemoved;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // NBASICS_H
|
|
@ -40,6 +40,15 @@ public:
|
|||
SetVersion(rkVersion);
|
||||
}
|
||||
|
||||
CBasicBinaryReader(void *pData, u32 DataSize, const CSerialVersion& rkVersion, IOUtil::EEndianness Endian = IOUtil::kSystemEndianness)
|
||||
: IArchive(true, false)
|
||||
, mMagicValid(true)
|
||||
, mOwnsStream(true)
|
||||
{
|
||||
mpStream = new CMemoryInStream(pData, DataSize, Endian);
|
||||
SetVersion(rkVersion);
|
||||
}
|
||||
|
||||
~CBasicBinaryReader()
|
||||
{
|
||||
if (mOwnsStream) delete mpStream;
|
||||
|
@ -74,6 +83,8 @@ public:
|
|||
virtual void SerializeHexPrimitive(u16& rValue) { rValue = mpStream->ReadShort(); }
|
||||
virtual void SerializeHexPrimitive(u32& rValue) { rValue = mpStream->ReadLong(); }
|
||||
virtual void SerializeHexPrimitive(u64& rValue) { rValue = mpStream->ReadLongLong(); }
|
||||
|
||||
virtual void BulkSerialize(void* pData, u32 Size) { mpStream->ReadBytes(pData, Size); }
|
||||
};
|
||||
|
||||
#endif // CBASICBINARYREADER
|
||||
|
|
|
@ -88,6 +88,8 @@ public:
|
|||
virtual void SerializeHexPrimitive(u16& rValue) { mpStream->WriteShort(rValue); }
|
||||
virtual void SerializeHexPrimitive(u32& rValue) { mpStream->WriteLong(rValue); }
|
||||
virtual void SerializeHexPrimitive(u64& rValue) { mpStream->WriteLongLong(rValue); }
|
||||
|
||||
virtual void BulkSerialize(void* pData, u32 Size) { mpStream->WriteBytes(pData, Size); }
|
||||
};
|
||||
|
||||
#endif // CBASICBINARYWRITER
|
||||
|
|
|
@ -177,6 +177,8 @@ public:
|
|||
virtual void SerializeHexPrimitive(u16& rValue) { rValue = mpStream->ReadShort(); }
|
||||
virtual void SerializeHexPrimitive(u32& rValue) { rValue = mpStream->ReadLong(); }
|
||||
virtual void SerializeHexPrimitive(u64& rValue) { rValue = mpStream->ReadLongLong(); }
|
||||
|
||||
virtual void BulkSerialize(void* pData, u32 Size) { mpStream->ReadBytes(pData, Size); }
|
||||
};
|
||||
|
||||
#endif // CBINARYREADER
|
||||
|
|
|
@ -164,6 +164,8 @@ public:
|
|||
virtual void SerializeHexPrimitive(u16& rValue) { mpStream->WriteShort(rValue); }
|
||||
virtual void SerializeHexPrimitive(u32& rValue) { mpStream->WriteLong(rValue); }
|
||||
virtual void SerializeHexPrimitive(u64& rValue) { mpStream->WriteLongLong(rValue); }
|
||||
|
||||
virtual void BulkSerialize(void* pData, u32 Size) { mpStream->WriteBytes(pData, Size); }
|
||||
};
|
||||
|
||||
#endif // CBINARYWRITER
|
||||
|
|
|
@ -135,6 +135,19 @@ public:
|
|||
virtual void SerializeHexPrimitive(u16& rValue) { rValue = (u16) ReadParam().ToInt32(16); }
|
||||
virtual void SerializeHexPrimitive(u32& rValue) { rValue = (u32) ReadParam().ToInt32(16); }
|
||||
virtual void SerializeHexPrimitive(u64& rValue) { rValue = (u64) ReadParam().ToInt32(16); }
|
||||
|
||||
virtual void BulkSerialize(void* pData, u32 Size)
|
||||
{
|
||||
char* pCharData = (char*) pData;
|
||||
TString StringData = ReadParam();
|
||||
ASSERT(StringData.Size() == Size*2);
|
||||
|
||||
for (u32 ByteIdx = 0; ByteIdx < Size; ByteIdx++)
|
||||
{
|
||||
*pCharData = (char) StringData.SubString(ByteIdx*2, 2).ToInt32(16);
|
||||
pCharData++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CXMLREADER
|
||||
|
|
|
@ -122,6 +122,17 @@ public:
|
|||
virtual void SerializeHexPrimitive(u16& rValue) { WriteParam(*TString::HexString(rValue, 4)); }
|
||||
virtual void SerializeHexPrimitive(u32& rValue) { WriteParam(*TString::HexString(rValue, 8)); }
|
||||
virtual void SerializeHexPrimitive(u64& rValue) { WriteParam(*TString::HexString((u32) rValue, 16)); }
|
||||
|
||||
virtual void BulkSerialize(void* pData, u32 Size)
|
||||
{
|
||||
char* pCharData = (char*) pData;
|
||||
TString OutString(Size*2);
|
||||
|
||||
for (u32 ByteIdx = 0; ByteIdx < Size; ByteIdx++)
|
||||
itoa(pCharData[ByteIdx], &OutString[ByteIdx*2], 16);
|
||||
|
||||
WriteParam(*OutString);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CXMLWRITER
|
||||
|
|
|
@ -404,6 +404,21 @@ public:
|
|||
virtual void SerializeHexPrimitive(u32& rValue) = 0;
|
||||
virtual void SerializeHexPrimitive(u64& rValue) = 0;
|
||||
|
||||
virtual void BulkSerialize(void* pData, u32 DataSize) = 0;
|
||||
|
||||
void SerializeBulkData(std::vector<char>& InArray)
|
||||
{
|
||||
u32 Size = InArray.size();
|
||||
SerializeContainerSize(Size, "Size");
|
||||
|
||||
if (IsReader())
|
||||
{
|
||||
InArray.resize(Size);
|
||||
}
|
||||
|
||||
BulkSerialize(InArray.data(), Size);
|
||||
}
|
||||
|
||||
// Accessors
|
||||
inline u16 ArchiveVersion() const { return mArchiveVersion; }
|
||||
inline u16 FileVersion() const { return mFileVersion; }
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "TString.h"
|
||||
#include "Hash/CCRC32.h"
|
||||
#include "Hash/CFNV1A.h"
|
||||
#include <FileIO/IOUtil.h>
|
||||
#include <codecvt>
|
||||
|
@ -7,13 +8,14 @@
|
|||
// ************ TString ************
|
||||
u32 TString::Hash32() const
|
||||
{
|
||||
CFNV1A Hash(CFNV1A::e32Bit);
|
||||
Hash.HashString(*this);
|
||||
return Hash.GetHash32();
|
||||
CCRC32 Hash;
|
||||
Hash.Hash(**this);
|
||||
return Hash.Digest();
|
||||
}
|
||||
|
||||
u64 TString::Hash64() const
|
||||
{
|
||||
// todo: replace with MD5
|
||||
CFNV1A Hash(CFNV1A::e64Bit);
|
||||
Hash.HashString(*this);
|
||||
return Hash.GetHash64();
|
||||
|
|
|
@ -932,46 +932,7 @@ public:
|
|||
|
||||
static _TString FromFloat(float Value, int MinDecimals = 1)
|
||||
{
|
||||
// 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;
|
||||
return Format("%f.*", Value, MinDecimals);
|
||||
}
|
||||
|
||||
static _TString FileSizeString(u64 Size, u32 NumDecimals = 2)
|
||||
|
|
|
@ -13,48 +13,30 @@ CAreaAttributes::~CAreaAttributes()
|
|||
|
||||
void CAreaAttributes::SetObject(CScriptObject *pObj)
|
||||
{
|
||||
mpObj = pObj;
|
||||
mGame = pObj->Template()->MasterTemplate()->Game();
|
||||
CScriptTemplate* pTemplate = pObj->Template();
|
||||
CStructPropertyNew* pProperties = pTemplate->Properties();
|
||||
|
||||
mpObject = pObj;
|
||||
mGame = pTemplate->MasterTemplate()->Game();
|
||||
mNeedSky = CBoolRef(pObj, pProperties->ChildByIndex(1));
|
||||
|
||||
if (mGame == ePrime)
|
||||
mOverrideSky = CAssetRef(pObj, pProperties->ChildByIndex(7));
|
||||
else if (mGame > ePrime)
|
||||
mOverrideSky = CAssetRef(pObj, pProperties->ChildByID(0xD208C9FA));
|
||||
}
|
||||
|
||||
bool CAreaAttributes::IsLayerEnabled() const
|
||||
{
|
||||
return mpObj->Layer()->IsActive();
|
||||
return mpObject->Layer()->IsActive();
|
||||
}
|
||||
|
||||
bool CAreaAttributes::IsSkyEnabled() const
|
||||
{
|
||||
CPropertyStruct *pBaseStruct = mpObj->Properties();
|
||||
|
||||
switch (mGame)
|
||||
{
|
||||
case ePrime:
|
||||
case eEchoesDemo:
|
||||
case eEchoes:
|
||||
case eCorruptionProto:
|
||||
case eCorruption:
|
||||
case eReturns:
|
||||
return static_cast<TBoolProperty*>(pBaseStruct->PropertyByIndex(1))->Get();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return mNeedSky.IsValid() ? mNeedSky.Get() : false;
|
||||
}
|
||||
|
||||
CModel* CAreaAttributes::SkyModel() const
|
||||
{
|
||||
CPropertyStruct *pBaseStruct = mpObj->Properties();
|
||||
|
||||
switch (mGame)
|
||||
{
|
||||
case ePrime:
|
||||
return gpResourceStore->LoadResource<CModel>( static_cast<TAssetProperty*>(pBaseStruct->PropertyByIndex(7))->Get() );
|
||||
case eEchoesDemo:
|
||||
case eEchoes:
|
||||
case eCorruptionProto:
|
||||
case eCorruption:
|
||||
case eReturns:
|
||||
return gpResourceStore->LoadResource<CModel>( static_cast<TAssetProperty*>(pBaseStruct->PropertyByID(0xD208C9FA))->Get() );
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
return mOverrideSky.IsValid() ? gpResourceStore->LoadResource<CModel>(mOverrideSky.Get()) : nullptr;
|
||||
}
|
||||
|
|
|
@ -2,11 +2,15 @@
|
|||
#define CAREAATTRIBUTES_H
|
||||
|
||||
#include "Core/Resource/Script/CScriptObject.h"
|
||||
#include "Core/Resource/Script/Property/Properties.h"
|
||||
|
||||
class CAreaAttributes
|
||||
{
|
||||
CScriptObject* mpObject;
|
||||
EGame mGame;
|
||||
CScriptObject *mpObj;
|
||||
|
||||
CBoolRef mNeedSky;
|
||||
CAssetRef mOverrideSky;
|
||||
|
||||
public:
|
||||
CAreaAttributes(CScriptObject *pObj);
|
||||
|
@ -16,7 +20,7 @@ public:
|
|||
bool IsSkyEnabled() const;
|
||||
CModel* SkyModel() const;
|
||||
|
||||
inline CScriptObject* Instance() const { return mpObj; }
|
||||
inline CScriptObject* Instance() const { return mpObject; }
|
||||
};
|
||||
|
||||
#endif // CAREAATTRIBUTES_H
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define CLIGHTPARAMETERS_H
|
||||
|
||||
#include "Core/Resource/Area/CGameArea.h"
|
||||
#include "Core/Resource/Script/IProperty.h"
|
||||
#include "Core/Resource/Script/Property/Properties.h"
|
||||
|
||||
enum EWorldLightingOptions
|
||||
{
|
||||
|
@ -14,48 +14,35 @@ enum EWorldLightingOptions
|
|||
|
||||
class CLightParameters
|
||||
{
|
||||
CPropertyStruct *mpStruct;
|
||||
EGame mGame;
|
||||
|
||||
TLongProperty *mpLightLayer;
|
||||
TEnumProperty *mpWorldLightingOptions;
|
||||
CIntRef mLightLayer;
|
||||
TEnumRef<EWorldLightingOptions> mWorldLightingOptions;
|
||||
|
||||
public:
|
||||
CLightParameters(CPropertyStruct *pStruct, EGame Game)
|
||||
: mpStruct(pStruct)
|
||||
, mGame(Game)
|
||||
, mpLightLayer(nullptr)
|
||||
, mpWorldLightingOptions(nullptr)
|
||||
CLightParameters(CStructRef InStruct, EGame Game)
|
||||
{
|
||||
if (mpStruct)
|
||||
if (InStruct.IsValid())
|
||||
{
|
||||
if (mGame <= ePrime)
|
||||
if (Game <= ePrime)
|
||||
{
|
||||
mpWorldLightingOptions = TPropCast<TEnumProperty>(mpStruct->PropertyByIndex(0x7));
|
||||
mpLightLayer = TPropCast<TLongProperty>(mpStruct->PropertyByIndex(0xD));
|
||||
mWorldLightingOptions = TEnumRef<EWorldLightingOptions>(InStruct.Object(), InStruct.Property()->ChildByIndex(0x7));
|
||||
mLightLayer = CIntRef(InStruct.Object(), InStruct.Property()->ChildByIndex(0xD));
|
||||
}
|
||||
else
|
||||
{
|
||||
mpWorldLightingOptions = TPropCast<TEnumProperty>(mpStruct->PropertyByID(0x6B5E7509));
|
||||
mpLightLayer = TPropCast<TLongProperty>(mpStruct->PropertyByID(0x1F715FD3));
|
||||
mWorldLightingOptions = TEnumRef<EWorldLightingOptions>(InStruct.Object(), InStruct.Property()->ChildByID(0x6B5E7509));
|
||||
mLightLayer = CIntRef(InStruct.Object(), InStruct.Property()->ChildByID(0x1F715FD3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline int LightLayerIndex() const
|
||||
{
|
||||
if (!mpLightLayer)
|
||||
return 0;
|
||||
else
|
||||
return mpLightLayer->Get();
|
||||
return mLightLayer.IsValid() ? mLightLayer.Get() : 0;
|
||||
}
|
||||
|
||||
inline EWorldLightingOptions WorldLightingOptions() const
|
||||
{
|
||||
if (mpWorldLightingOptions)
|
||||
return (EWorldLightingOptions) mpWorldLightingOptions->Get();
|
||||
else
|
||||
return eNormalLighting;
|
||||
return mWorldLightingOptions.IsValid() ? mWorldLightingOptions.Get() : eNormalLighting;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -232,7 +232,31 @@ HEADERS += \
|
|||
IUIRelay.h \
|
||||
Resource/CResTypeFilter.h \
|
||||
GameProject/COpeningBanner.h \
|
||||
Resource/Script/CPropertyNameGenerator.h
|
||||
Resource/Script/CPropertyNameGenerator.h \
|
||||
Resource/Script/IPropertyNew.h \
|
||||
Resource/Script/TPropertyProxy.h \
|
||||
Resource/Script/Property/CEnumProperty.h \
|
||||
Resource/Script/Property/CFlagsProperty.h \
|
||||
Resource/Script/Property/CAssetProperty.h \
|
||||
Resource/Script/Property/CPointerProperty.h \
|
||||
Resource/Script/Property/CArrayProperty.h \
|
||||
Resource/Script/Property/Properties.h \
|
||||
Resource/Script/Property/TPropertyRef.h \
|
||||
Resource/Script/Property/CBoolProperty.h \
|
||||
Resource/Script/Property/CByteProperty.h \
|
||||
Resource/Script/Property/CShortProperty.h \
|
||||
Resource/Script/Property/CIntProperty.h \
|
||||
Resource/Script/Property/CFloatProperty.h \
|
||||
Resource/Script/Property/CStringProperty.h \
|
||||
Resource/Script/Property/CSoundProperty.h \
|
||||
Resource/Script/Property/CAnimationProperty.h \
|
||||
Resource/Script/Property/CSequenceProperty.h \
|
||||
Resource/Script/Property/CSplineProperty.h \
|
||||
Resource/Script/Property/CAnimationSetProperty.h \
|
||||
Resource/Script/Property/CVectorProperty.h \
|
||||
Resource/Script/Property/CColorProperty.h \
|
||||
Resource/Script/Property/CStructProperty.h \
|
||||
Resource/Script/Property/CGuidProperty.h
|
||||
|
||||
# Source Files
|
||||
SOURCES += \
|
||||
|
@ -342,4 +366,5 @@ SOURCES += \
|
|||
IUIRelay.cpp \
|
||||
GameProject\COpeningBanner.cpp \
|
||||
IProgressNotifier.cpp \
|
||||
Resource/Script/CPropertyNameGenerator.cpp
|
||||
Resource/Script/CPropertyNameGenerator.cpp \
|
||||
Resource/Script/IPropertyNew.cpp
|
||||
|
|
|
@ -283,7 +283,8 @@ void GenerateAssetNames(CGameProject *pProj)
|
|||
|
||||
for (u32 iInst = 0; iInst < pLayer->NumInstances(); iInst++)
|
||||
{
|
||||
CScriptObject *pInst = pLayer->InstanceByIndex(iInst);
|
||||
CScriptObject* pInst = pLayer->InstanceByIndex(iInst);
|
||||
CStructPropertyNew* pProperties = pInst->Template()->Properties();
|
||||
|
||||
if (pInst->ObjectTypeID() == 0x42 || pInst->ObjectTypeID() == FOURCC('POIN'))
|
||||
{
|
||||
|
@ -292,12 +293,12 @@ void GenerateAssetNames(CGameProject *pProj)
|
|||
if (Name.StartsWith("POI_", false))
|
||||
{
|
||||
TIDString ScanIDString = (pProj->Game() <= ePrime ? "0x4:0x0" : "0xBDBEC295:0xB94E9BE7");
|
||||
TAssetProperty *pScanProperty = TPropCast<TAssetProperty>(pInst->PropertyByIDString(ScanIDString));
|
||||
CAssetProperty *pScanProperty = TPropCast<CAssetProperty>(pProperties->ChildByIDString(ScanIDString));
|
||||
ASSERT(pScanProperty); // Temporary assert to remind myself later to update this code when uncooked properties are added to the template
|
||||
|
||||
if (pScanProperty)
|
||||
{
|
||||
CAssetID ScanID = pScanProperty->Get();
|
||||
CAssetID ScanID = pScanProperty->Value(pInst->PropertyData());
|
||||
CResourceEntry *pEntry = pStore->FindEntry(ScanID);
|
||||
|
||||
if (pEntry && !pEntry->IsNamed())
|
||||
|
@ -327,12 +328,12 @@ void GenerateAssetNames(CGameProject *pProj)
|
|||
if (Name.EndsWith(".STRG", false))
|
||||
{
|
||||
u32 StringPropID = (pProj->Game() <= ePrime ? 0x4 : 0x9182250C);
|
||||
TAssetProperty *pStringProperty = TPropCast<TAssetProperty>(pInst->Properties()->PropertyByID(StringPropID));
|
||||
CAssetProperty *pStringProperty = TPropCast<CAssetProperty>(pProperties->ChildByID(StringPropID));
|
||||
ASSERT(pStringProperty); // Temporary assert to remind myself later to update this code when uncooked properties are added to the template
|
||||
|
||||
if (pStringProperty)
|
||||
{
|
||||
CAssetID StringID = pStringProperty->Get();
|
||||
CAssetID StringID = pStringProperty->Value(pInst->PropertyData());
|
||||
CResourceEntry *pEntry = pStore->FindEntry(StringID);
|
||||
|
||||
if (pEntry && !pEntry->IsNamed())
|
||||
|
@ -353,12 +354,12 @@ void GenerateAssetNames(CGameProject *pProj)
|
|||
pInst->ObjectTypeID() == 0x8 || pInst->ObjectTypeID() == FOURCC('PLAT'))
|
||||
{
|
||||
u32 ModelPropID = (pProj->Game() <= ePrime ? (pInst->ObjectTypeID() == 0x0 ? 0xA : 0x6) : 0xC27FFA8F);
|
||||
TAssetProperty *pModelProperty = TPropCast<TAssetProperty>(pInst->Properties()->PropertyByID(ModelPropID));
|
||||
CAssetProperty *pModelProperty = TPropCast<CAssetProperty>(pProperties->ChildByID(ModelPropID));
|
||||
ASSERT(pModelProperty); // Temporary assert to remind myself later to update this code when uncooked properties are added to the template
|
||||
|
||||
if (pModelProperty)
|
||||
{
|
||||
CAssetID ModelID = pModelProperty->Get();
|
||||
CAssetID ModelID = pModelProperty->Value(pInst->PropertyData());
|
||||
CResourceEntry *pEntry = pStore->FindEntry(ModelID);
|
||||
|
||||
if (pEntry && !pEntry->IsCategorized())
|
||||
|
|
|
@ -132,28 +132,32 @@ CScriptInstanceDependency* CScriptInstanceDependency::BuildTree(CScriptObject *p
|
|||
{
|
||||
CScriptInstanceDependency *pInst = new CScriptInstanceDependency();
|
||||
pInst->mObjectType = pInstance->ObjectTypeID();
|
||||
ParseStructDependencies(pInst, pInstance->Properties());
|
||||
ParseStructDependencies(pInst, pInstance, pInstance->Template()->Properties());
|
||||
return pInst;
|
||||
}
|
||||
|
||||
void CScriptInstanceDependency::ParseStructDependencies(CScriptInstanceDependency *pInst, CPropertyStruct *pStruct)
|
||||
void CScriptInstanceDependency::ParseStructDependencies(CScriptInstanceDependency* pInst, CScriptObject* pInstance, CStructPropertyNew *pStruct)
|
||||
{
|
||||
// Recursive function for parsing script dependencies and loading them into the script instance dependency
|
||||
for (u32 iProp = 0; iProp < pStruct->Count(); iProp++)
|
||||
void* pPropertyData = pInstance->PropertyData();
|
||||
|
||||
for (u32 PropertyIdx = 0; PropertyIdx < pStruct->NumChildren(); PropertyIdx++)
|
||||
{
|
||||
IProperty *pProp = pStruct->PropertyByIndex(iProp);
|
||||
EPropertyType Type = pProp->Type();
|
||||
IPropertyNew *pProp = pStruct->ChildByIndex(PropertyIdx);
|
||||
EPropertyTypeNew Type = pProp->Type();
|
||||
|
||||
if (Type == eStructProperty || Type == eArrayProperty)
|
||||
ParseStructDependencies(pInst, static_cast<CPropertyStruct*>(pProp));
|
||||
// Technically we aren't parsing array children, but it's not really worth refactoring this function
|
||||
// to support it when there aren't any array properties that contain any asset references anyway...
|
||||
if (Type == EPropertyTypeNew::Struct)
|
||||
ParseStructDependencies(pInst, pInstance, TPropCast<CStructPropertyNew>(pProp));
|
||||
|
||||
else if (Type == eSoundProperty)
|
||||
else if (Type == EPropertyTypeNew::Sound)
|
||||
{
|
||||
u32 SoundID = static_cast<TSoundProperty*>(pProp)->Get();
|
||||
u32 SoundID = TPropCast<CSoundProperty>(pProp)->Value(pPropertyData);
|
||||
|
||||
if (SoundID != -1)
|
||||
{
|
||||
CGameProject *pProj = pStruct->Instance()->Area()->Entry()->Project();
|
||||
CGameProject *pProj = pInstance->Area()->Entry()->Project();
|
||||
SSoundInfo Info = pProj->AudioManager()->GetSoundInfo(SoundID);
|
||||
|
||||
if (Info.pAudioGroup)
|
||||
|
@ -164,9 +168,9 @@ void CScriptInstanceDependency::ParseStructDependencies(CScriptInstanceDependenc
|
|||
}
|
||||
}
|
||||
|
||||
else if (Type == eAssetProperty)
|
||||
else if (Type == EPropertyTypeNew::Asset)
|
||||
{
|
||||
CAssetID ID = static_cast<TAssetProperty*>(pProp)->Get();
|
||||
CAssetID ID = TPropCast<CAssetProperty>(pProp)->Value(pPropertyData);
|
||||
|
||||
if (ID.IsValid())
|
||||
{
|
||||
|
@ -175,16 +179,15 @@ void CScriptInstanceDependency::ParseStructDependencies(CScriptInstanceDependenc
|
|||
}
|
||||
}
|
||||
|
||||
else if (Type == eCharacterProperty)
|
||||
else if (Type == EPropertyTypeNew::AnimationSet)
|
||||
{
|
||||
TCharacterProperty *pChar = static_cast<TCharacterProperty*>(pProp);
|
||||
CAnimationParameters Params = pChar->Get();
|
||||
CAnimationParameters Params = TPropCast<CAnimationSetProperty>(pProp)->Value(pPropertyData);
|
||||
CAssetID ID = Params.ID();
|
||||
|
||||
if (ID.IsValid())
|
||||
{
|
||||
// Character sets are removed starting in MP3, so we only need char property dependencies in Echoes and earlier
|
||||
if (pStruct->Instance()->Area()->Game() <= eEchoes)
|
||||
if (pStruct->Game() <= eEchoes)
|
||||
{
|
||||
CCharPropertyDependency *pDep = new CCharPropertyDependency(pProp->IDString(true), ID, Params.CharacterIndex());
|
||||
pInst->mChildren.push_back(pDep);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
class CScriptLayer;
|
||||
class CScriptObject;
|
||||
class CPropertyStruct;
|
||||
class CStructPropertyNew;
|
||||
class CAnimSet;
|
||||
class CAnimationParameters;
|
||||
struct SSetCharacter;
|
||||
|
@ -142,7 +142,7 @@ public:
|
|||
// Static
|
||||
static CScriptInstanceDependency* BuildTree(CScriptObject *pInstance);
|
||||
protected:
|
||||
static void ParseStructDependencies(CScriptInstanceDependency *pTree, CPropertyStruct *pStruct);
|
||||
static void ParseStructDependencies(CScriptInstanceDependency *pTree, CScriptObject* pInstance, CStructPropertyNew *pStruct);
|
||||
};
|
||||
|
||||
// Node representing an animset character. Indicates what index the character is within the animset.
|
||||
|
|
|
@ -136,6 +136,25 @@ void CAnimationParameters::Write(IOutputStream& rSCLY)
|
|||
}
|
||||
}
|
||||
|
||||
void CAnimationParameters::Serialize(IArchive& rArc)
|
||||
{
|
||||
if (rArc.IsReader())
|
||||
mGame = rArc.Game();
|
||||
|
||||
rArc << SERIAL("AnimationSetAsset", mCharacterID);
|
||||
|
||||
if (mGame <= eEchoes)
|
||||
rArc << SERIAL("CharacterID", mCharIndex);
|
||||
|
||||
rArc << SERIAL("AnimationID", mAnimIndex);
|
||||
|
||||
if (mGame >= eReturns)
|
||||
{
|
||||
rArc << SERIAL("Unknown0", mUnknown2)
|
||||
<< SERIAL("Unknown1", mUnknown3);
|
||||
}
|
||||
}
|
||||
|
||||
const SSetCharacter* CAnimationParameters::GetCurrentSetCharacter(s32 NodeIndex /*= -1*/)
|
||||
{
|
||||
CAnimSet *pSet = AnimSet();
|
||||
|
|
|
@ -20,6 +20,7 @@ public:
|
|||
CAnimationParameters(EGame Game);
|
||||
CAnimationParameters(IInputStream& rSCLY, EGame Game);
|
||||
void Write(IOutputStream& rSCLY);
|
||||
void Serialize(IArchive& rArc);
|
||||
|
||||
const SSetCharacter* GetCurrentSetCharacter(s32 NodeIndex = -1);
|
||||
CModel* GetCurrentModel(s32 NodeIndex = -1);
|
||||
|
|
|
@ -47,6 +47,12 @@ public:
|
|||
SetAcceptedTypes(Game, rkString.Split(","));
|
||||
}
|
||||
|
||||
void Serialize(IArchive& rArc)
|
||||
{
|
||||
if (rArc.IsReader()) mGame = rArc.Game();
|
||||
rArc << SERIAL_CONTAINER("AcceptedTypes", mAcceptedTypes, "Type");
|
||||
}
|
||||
|
||||
inline bool Accepts(EResType Type) const
|
||||
{
|
||||
return mAcceptedTypes.find(Type) != mAcceptedTypes.end();
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
|
||||
std::unordered_map<EResType, CResTypeInfo*> CResTypeInfo::smTypeMap;
|
||||
|
||||
CResTypeInfo::CResTypeInfo(EResType Type, const TString& rkTypeName)
|
||||
CResTypeInfo::CResTypeInfo(EResType Type, const TString& rkTypeName, const TString& rkRetroExtension)
|
||||
: mType(Type)
|
||||
, mTypeName(rkTypeName)
|
||||
, mRetroExtension(rkRetroExtension)
|
||||
, mCanBeSerialized(false)
|
||||
, mCanHaveDependencies(true)
|
||||
{
|
||||
|
@ -122,6 +123,27 @@ void Serialize(IArchive& rArc, CResTypeInfo*& rpType)
|
|||
}
|
||||
}
|
||||
|
||||
void Serialize(IArchive& rArc, EResType& rType)
|
||||
{
|
||||
CFourCC Extension;
|
||||
|
||||
if (rArc.IsWriter())
|
||||
{
|
||||
CResTypeInfo* pTypeInfo = CResTypeInfo::FindTypeInfo(rType);
|
||||
ASSERT(pTypeInfo != nullptr);
|
||||
Extension = pTypeInfo->CookedExtension(rArc.Game());
|
||||
}
|
||||
|
||||
rArc.SerializePrimitive(Extension);
|
||||
|
||||
if (rArc.IsReader())
|
||||
{
|
||||
CResTypeInfo* pTypeInfo = CResTypeInfo::TypeForCookedExtension(rArc.Game(), Extension);
|
||||
ASSERT(pTypeInfo != nullptr);
|
||||
rType = pTypeInfo->Type();
|
||||
}
|
||||
}
|
||||
|
||||
// ************ CREATION ************
|
||||
CResTypeInfo::CResTypeInfoFactory CResTypeInfo::smTypeInfoFactory;
|
||||
|
||||
|
@ -153,235 +175,235 @@ void CResTypeInfo::CResTypeInfoFactory::AddExtension(CResTypeInfo *pType, CFourC
|
|||
void CResTypeInfo::CResTypeInfoFactory::InitTypes()
|
||||
{
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAnimation, "Animation");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAnimation, "Animation", "ani");
|
||||
AddExtension(pType, "ANIM", ePrimeDemo, eReturns);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAnimCollisionPrimData, "Animation Collision Primitive Data");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAnimCollisionPrimData, "Animation Collision Primitive Data", "?");
|
||||
AddExtension(pType, "CPRM", eReturns, eReturns);
|
||||
pType->mCanHaveDependencies = false;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAnimEventData, "Animation Event Data");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAnimEventData, "Animation Event Data", "evnt");
|
||||
AddExtension(pType, "EVNT", ePrimeDemo, ePrime);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAnimSet, "Animation Character Set");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAnimSet, "Animation Character Set", "acs");
|
||||
AddExtension(pType, "ANCS", ePrimeDemo, eEchoes);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eArea, "Area");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eArea, "Area", "mrea");
|
||||
AddExtension(pType, "MREA", ePrimeDemo, eReturns);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAudioAmplitudeData, "Audio Amplitude Data");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAudioAmplitudeData, "Audio Amplitude Data", "?");
|
||||
AddExtension(pType, "CAAD", eCorruption, eCorruption);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAudioGroup, "Audio Group");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAudioGroup, "Audio Group", "agsc");
|
||||
AddExtension(pType, "AGSC", ePrimeDemo, eEchoes);
|
||||
pType->mCanHaveDependencies = false;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAudioMacro, "Audio Macro");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAudioMacro, "Audio Macro", "caud");
|
||||
AddExtension(pType, "CAUD", eCorruptionProto, eReturns);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAudioSample, "Audio Sample");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAudioSample, "Audio Sample", "csmp");
|
||||
AddExtension(pType, "CSMP", eCorruptionProto, eReturns);
|
||||
pType->mCanHaveDependencies = false;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAudioLookupTable, "Audio Lookup Table");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eAudioLookupTable, "Audio Lookup Table", "atbl");
|
||||
AddExtension(pType, "ATBL", ePrimeDemo, eCorruption);
|
||||
pType->mCanHaveDependencies = false;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eBinaryData, "Generic Data");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eBinaryData, "Generic Data", "dat");
|
||||
AddExtension(pType, "DUMB", ePrimeDemo, eCorruption);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eBurstFireData, "Burst Fire Data");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eBurstFireData, "Burst Fire Data", "bfre.bfrc");
|
||||
AddExtension(pType, "BFRC", eCorruptionProto, eCorruption);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eCharacter, "Character");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eCharacter, "Character", "char");
|
||||
AddExtension(pType, "CHAR", eCorruptionProto, eReturns);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eDependencyGroup, "Dependency Group");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eDependencyGroup, "Dependency Group", "?");
|
||||
AddExtension(pType, "DGRP", ePrimeDemo, eReturns);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eDynamicCollision, "Dynamic Collision");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eDynamicCollision, "Dynamic Collision", "dcln");
|
||||
AddExtension(pType, "DCLN", ePrimeDemo, eReturns);
|
||||
pType->mCanHaveDependencies = false;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eFont, "Font");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eFont, "Font", "rpff");
|
||||
AddExtension(pType, "FONT", ePrimeDemo, eReturns);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eGuiFrame, "Gui Frame");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eGuiFrame, "Gui Frame", "frme");
|
||||
AddExtension(pType, "FRME", ePrimeDemo, eReturns);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eGuiKeyFrame, "Gui Keyframe");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eGuiKeyFrame, "Gui Keyframe", "?");
|
||||
AddExtension(pType, "KFAM", ePrimeDemo, ePrimeDemo);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eHintSystem, "Hint System Data");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eHintSystem, "Hint System Data", "hint");
|
||||
AddExtension(pType, "HINT", ePrime, eCorruption);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eMapArea, "Area Map");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eMapArea, "Area Map", "mapa");
|
||||
AddExtension(pType, "MAPA", ePrimeDemo, eCorruption);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eMapWorld, "World Map");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eMapWorld, "World Map", "mapw");
|
||||
AddExtension(pType, "MAPW", ePrimeDemo, eCorruption);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eMapUniverse, "Universe Map");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eMapUniverse, "Universe Map", "mapu");
|
||||
AddExtension(pType, "MAPU", ePrimeDemo, eEchoes);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eMidi, "MIDI");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eMidi, "MIDI", "?");
|
||||
AddExtension(pType, "CSNG", ePrimeDemo, eEchoes);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eModel, "Model");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eModel, "Model", "cmdl");
|
||||
AddExtension(pType, "CMDL", ePrimeDemo, eReturns);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticle, "Particle System");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticle, "Particle System", "gpsm.part");
|
||||
AddExtension(pType, "PART", ePrimeDemo, eReturns);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticleCollisionResponse, "Collision Response Particle System");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticleCollisionResponse, "Collision Response Particle System", "crsm.crsc");
|
||||
AddExtension(pType, "CRSC", ePrimeDemo, eCorruption);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticleDecal, "Decal Particle System");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticleDecal, "Decal Particle System", "dpsm.dpsc");
|
||||
AddExtension(pType, "DPSC", ePrimeDemo, eCorruption);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticleElectric, "Electric Particle System");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticleElectric, "Electric Particle System", "elsm.elsc");
|
||||
AddExtension(pType, "ELSC", ePrimeDemo, eCorruption);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticleSorted, "Sorted Particle System");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticleSorted, "Sorted Particle System", "srsm.srsc");
|
||||
AddExtension(pType, "SRSC", eEchoesDemo, eEchoes);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticleSpawn, "Spawn Particle System");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticleSpawn, "Spawn Particle System", "spsm.spsc");
|
||||
AddExtension(pType, "SPSC", eEchoesDemo, eReturns);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticleSwoosh, "Swoosh Particle System");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticleSwoosh, "Swoosh Particle System", "swsh.swhc");
|
||||
AddExtension(pType, "SWHC", ePrimeDemo, eReturns);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticleTransform, "Transform Particle System");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticleTransform, "Transform Particle System", "xfsm.xfsc");
|
||||
AddExtension(pType, "XFSC", eReturns, eReturns);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticleWeapon, "Weapon Particle System");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eParticleWeapon, "Weapon Particle System", "wpsm.wpsc");
|
||||
AddExtension(pType, "WPSC", ePrimeDemo, eCorruption);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(ePathfinding, "Pathfinding Mesh");
|
||||
CResTypeInfo *pType = new CResTypeInfo(ePathfinding, "Pathfinding Mesh", "path");
|
||||
AddExtension(pType, "PATH", ePrimeDemo, eCorruption);
|
||||
pType->mCanHaveDependencies = false;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(ePortalArea, "Portal Area");
|
||||
CResTypeInfo *pType = new CResTypeInfo(ePortalArea, "Portal Area", "?");
|
||||
AddExtension(pType, "PTLA", eEchoesDemo, eCorruption);
|
||||
pType->mCanHaveDependencies = false;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eRuleSet, "Rule Set");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eRuleSet, "Rule Set", "rule");
|
||||
AddExtension(pType, "RULE", eEchoesDemo, eReturns);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eSaveArea, "Area Save Info");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eSaveArea, "Area Save Info", "sava");
|
||||
AddExtension(pType, "SAVA", eCorruptionProto, eCorruption);
|
||||
pType->mCanHaveDependencies = false;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eSaveWorld, "World Save Info");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eSaveWorld, "World Save Info", "savw");
|
||||
AddExtension(pType, "SAVW", ePrime, eReturns);
|
||||
pType->mCanHaveDependencies = false;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eScan, "Scan");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eScan, "Scan", "scan");
|
||||
AddExtension(pType, "SCAN", ePrimeDemo, eCorruption);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eSkeleton, "Skeleton");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eSkeleton, "Skeleton", "cin");
|
||||
AddExtension(pType, "CINF", ePrimeDemo, eReturns);
|
||||
pType->mCanHaveDependencies = false;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eSkin, "Skin");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eSkin, "Skin", "cskr");
|
||||
AddExtension(pType, "CSKR", ePrimeDemo, eReturns);
|
||||
pType->mCanHaveDependencies = false;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eSourceAnimData, "Source Animation Data");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eSourceAnimData, "Source Animation Data", "sand");
|
||||
AddExtension(pType, "SAND", eCorruptionProto, eCorruption);
|
||||
pType->mCanHaveDependencies = false; // all dependencies are added to the CHAR dependency tree
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eSpatialPrimitive, "Spatial Primitive");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eSpatialPrimitive, "Spatial Primitive", "?");
|
||||
AddExtension(pType, "CSPP", eEchoesDemo, eEchoes);
|
||||
pType->mCanHaveDependencies = false;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eStateMachine, "State Machine");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eStateMachine, "State Machine", "afsm");
|
||||
AddExtension(pType, "AFSM", ePrimeDemo, eEchoes);
|
||||
AddExtension(pType, "FSM2", eCorruptionProto, eCorruption);
|
||||
AddExtension(pType, "FSMC", eReturns, eReturns);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eStateMachine2, "State Machine 2");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eStateMachine2, "State Machine 2", "fsm2");
|
||||
AddExtension(pType, "FSM2", eEchoesDemo, eCorruption);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eStaticGeometryMap, "Static Scan Map");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eStaticGeometryMap, "Static Scan Map", "egmc");
|
||||
AddExtension(pType, "EGMC", eEchoesDemo, eCorruption);
|
||||
pType->mCanHaveDependencies = false;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eStreamedAudio, "Streamed Audio");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eStreamedAudio, "Streamed Audio", "?");
|
||||
AddExtension(pType, "STRM", eCorruptionProto, eReturns);
|
||||
pType->mCanHaveDependencies = false;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eStringList, "String List");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eStringList, "String List", "stlc");
|
||||
AddExtension(pType, "STLC", eEchoesDemo, eCorruptionProto);
|
||||
pType->mCanHaveDependencies = false;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eStringTable, "String Table");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eStringTable, "String Table", "strg");
|
||||
AddExtension(pType, "STRG", ePrimeDemo, eReturns);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eTexture, "Texture");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eTexture, "Texture", "txtr");
|
||||
AddExtension(pType, "TXTR", ePrimeDemo, eReturns);
|
||||
pType->mCanHaveDependencies = false;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eTweak, "Tweak Data");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eTweak, "Tweak Data", "ctwk");
|
||||
AddExtension(pType, "CTWK", ePrimeDemo, ePrime);
|
||||
pType->mCanHaveDependencies = false;
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eUserEvaluatorData, "User Evaluator Data");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eUserEvaluatorData, "User Evaluator Data", "user.usrc");
|
||||
AddExtension(pType, "USRC", eCorruptionProto, eCorruption);
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eWorld, "World");
|
||||
CResTypeInfo *pType = new CResTypeInfo(eWorld, "World", "mwld");
|
||||
AddExtension(pType, "MLVL", ePrimeDemo, eReturns);
|
||||
pType->mCanBeSerialized = true;
|
||||
}
|
||||
|
|
|
@ -20,13 +20,14 @@ class CResTypeInfo
|
|||
EResType mType;
|
||||
TString mTypeName;
|
||||
std::vector<SGameExtension> mCookedExtensions;
|
||||
TString mRetroExtension; // File extension in Retro's directory tree. We don't use it directly but it is needed for generating asset ID hashes
|
||||
bool mCanBeSerialized;
|
||||
bool mCanHaveDependencies;
|
||||
|
||||
static std::unordered_map<EResType, CResTypeInfo*> smTypeMap;
|
||||
|
||||
// Private Methods
|
||||
CResTypeInfo(EResType Type, const TString& rkTypeName);
|
||||
CResTypeInfo(EResType Type, const TString& rkTypeName, const TString& rkRetroExtension);
|
||||
~CResTypeInfo();
|
||||
|
||||
// Public Methods
|
||||
|
|
|
@ -1,118 +1,146 @@
|
|||
#include "CScriptCooker.h"
|
||||
#include "Core/Resource/Script/CLink.h"
|
||||
#include <Core/Resource/Script/Property/CArrayProperty.h>
|
||||
#include <Core/Resource/Script/Property/CAssetProperty.h>
|
||||
#include <Core/Resource/Script/Property/CEnumProperty.h>
|
||||
#include <Core/Resource/Script/Property/CFlagsProperty.h>
|
||||
|
||||
void CScriptCooker::WriteProperty(IOutputStream& rOut,IProperty *pProp, bool InSingleStruct)
|
||||
void CScriptCooker::WriteProperty(IOutputStream& rOut, IPropertyNew* pProperty, bool InAtomicStruct)
|
||||
{
|
||||
u32 SizeOffset = 0, PropStart = 0;
|
||||
void* pData = (mpArrayItemData ? mpArrayItemData : mpObject->PropertyData());
|
||||
|
||||
if (mGame >= eEchoesDemo && !InSingleStruct)
|
||||
if (mGame >= eEchoesDemo && !InAtomicStruct)
|
||||
{
|
||||
rOut.WriteLong(pProp->ID());
|
||||
rOut.WriteLong(pProperty->ID());
|
||||
SizeOffset = rOut.Tell();
|
||||
rOut.WriteShort(0x0);
|
||||
PropStart = rOut.Tell();
|
||||
}
|
||||
|
||||
switch (pProp->Type())
|
||||
switch (pProperty->Type())
|
||||
{
|
||||
|
||||
case eBoolProperty:
|
||||
case EPropertyTypeNew::Bool:
|
||||
{
|
||||
TBoolProperty *pBoolCast = static_cast<TBoolProperty*>(pProp);
|
||||
rOut.WriteBool(pBoolCast->Get());
|
||||
CBoolProperty* pBool = TPropCast<CBoolProperty>(pProperty);
|
||||
rOut.WriteBool( pBool->Value(pData) );
|
||||
break;
|
||||
}
|
||||
|
||||
case eByteProperty:
|
||||
case EPropertyTypeNew::Byte:
|
||||
{
|
||||
TByteProperty *pByteCast = static_cast<TByteProperty*>(pProp);
|
||||
rOut.WriteByte(pByteCast->Get());
|
||||
CByteProperty* pByte = TPropCast<CByteProperty>(pProperty);
|
||||
rOut.WriteByte( pByte->Value(pData) );
|
||||
break;
|
||||
}
|
||||
|
||||
case eShortProperty:
|
||||
case EPropertyTypeNew::Short:
|
||||
{
|
||||
TShortProperty *pShortCast = static_cast<TShortProperty*>(pProp);
|
||||
rOut.WriteShort(pShortCast->Get());
|
||||
CShortProperty* pShort = TPropCast<CShortProperty>(pProperty);
|
||||
rOut.WriteShort( pShort->Value(pData) );
|
||||
break;
|
||||
}
|
||||
|
||||
case eLongProperty:
|
||||
case EPropertyTypeNew::Int:
|
||||
{
|
||||
TLongProperty *pLongCast = static_cast<TLongProperty*>(pProp);
|
||||
rOut.WriteLong(pLongCast->Get());
|
||||
CIntProperty* pInt = TPropCast<CIntProperty>(pProperty);
|
||||
rOut.WriteLong( pInt->Value(pData) );
|
||||
break;
|
||||
}
|
||||
|
||||
case eEnumProperty:
|
||||
case EPropertyTypeNew::Float:
|
||||
{
|
||||
TEnumProperty *pEnumCast = static_cast<TEnumProperty*>(pProp);
|
||||
rOut.WriteLong(pEnumCast->Get());
|
||||
CFloatProperty* pFloat = TPropCast<CFloatProperty>(pProperty);
|
||||
rOut.WriteFloat( pFloat->Value(pData) );
|
||||
break;
|
||||
}
|
||||
|
||||
case eBitfieldProperty:
|
||||
case EPropertyTypeNew::Choice:
|
||||
{
|
||||
TBitfieldProperty *pBitfieldCast = static_cast<TBitfieldProperty*>(pProp);
|
||||
rOut.WriteLong(pBitfieldCast->Get());
|
||||
CChoiceProperty* pChoice = TPropCast<CChoiceProperty>(pProperty);
|
||||
rOut.WriteLong( pChoice->Value(pData) );
|
||||
break;
|
||||
}
|
||||
|
||||
case eFloatProperty:
|
||||
case EPropertyTypeNew::Enum:
|
||||
{
|
||||
TFloatProperty *pFloatCast = static_cast<TFloatProperty*>(pProp);
|
||||
rOut.WriteFloat(pFloatCast->Get());
|
||||
CEnumProperty* pEnum = TPropCast<CEnumProperty>(pProperty);
|
||||
rOut.WriteLong( pEnum->Value(pData) );
|
||||
break;
|
||||
}
|
||||
|
||||
case eStringProperty:
|
||||
case EPropertyTypeNew::Flags:
|
||||
{
|
||||
TStringProperty *pStringCast = static_cast<TStringProperty*>(pProp);
|
||||
rOut.WriteString(pStringCast->Get());
|
||||
CFlagsProperty* pFlags = TPropCast<CFlagsProperty>(pProperty);
|
||||
rOut.WriteLong( pFlags->Value(pData) );
|
||||
break;
|
||||
}
|
||||
|
||||
case eVector3Property:
|
||||
case EPropertyTypeNew::String:
|
||||
{
|
||||
TVector3Property *pVectorCast = static_cast<TVector3Property*>(pProp);
|
||||
pVectorCast->Get().Write(rOut);
|
||||
CStringProperty* pString = TPropCast<CStringProperty>(pProperty);
|
||||
rOut.WriteString( pString->Value(pData) );
|
||||
break;
|
||||
}
|
||||
|
||||
case eColorProperty:
|
||||
case EPropertyTypeNew::Vector:
|
||||
{
|
||||
TColorProperty *pColorCast = static_cast<TColorProperty*>(pProp);
|
||||
pColorCast->Get().Write(rOut, false);
|
||||
CVectorProperty* pVector = TPropCast<CVectorProperty>(pProperty);
|
||||
pVector->ValueRef(pData).Write(rOut);
|
||||
break;
|
||||
}
|
||||
|
||||
case eSoundProperty:
|
||||
case EPropertyTypeNew::Color:
|
||||
{
|
||||
TSoundProperty *pSoundCast = static_cast<TSoundProperty*>(pProp);
|
||||
rOut.WriteLong(pSoundCast->Get());
|
||||
CColorProperty* pColor = TPropCast<CColorProperty>(pProperty);
|
||||
pColor->ValueRef(pData).Write(rOut);
|
||||
break;
|
||||
}
|
||||
|
||||
case eAssetProperty:
|
||||
case EPropertyTypeNew::Asset:
|
||||
{
|
||||
TAssetProperty *pAssetCast = static_cast<TAssetProperty*>(pProp);
|
||||
pAssetCast->Get().Write(rOut);
|
||||
CAssetProperty* pAsset = TPropCast<CAssetProperty>(pProperty);
|
||||
pAsset->ValueRef(pData).Write(rOut);
|
||||
break;
|
||||
}
|
||||
|
||||
case eCharacterProperty:
|
||||
case EPropertyTypeNew::Sound:
|
||||
{
|
||||
TCharacterProperty *pCharCast = static_cast<TCharacterProperty*>(pProp);
|
||||
pCharCast->Get().Write(rOut);
|
||||
CSoundProperty* pSound = TPropCast<CSoundProperty>(pProperty);
|
||||
rOut.WriteLong( pSound->Value(pData) );
|
||||
break;
|
||||
}
|
||||
|
||||
case eMayaSplineProperty:
|
||||
case EPropertyTypeNew::Animation:
|
||||
{
|
||||
TMayaSplineProperty *pSplineCast = static_cast<TMayaSplineProperty*>(pProp);
|
||||
std::vector<u8> Buffer = pSplineCast->Get();
|
||||
if (!Buffer.empty()) rOut.WriteBytes(Buffer.data(), Buffer.size());
|
||||
CAnimationProperty* pAnim = TPropCast<CAnimationProperty>(pProperty);
|
||||
rOut.WriteLong( pAnim->Value(pData) );
|
||||
break;
|
||||
}
|
||||
|
||||
case EPropertyTypeNew::AnimationSet:
|
||||
{
|
||||
CAnimationSetProperty* pAnimSet = TPropCast<CAnimationSetProperty>(pProperty);
|
||||
pAnimSet->ValueRef(pData).Write(rOut);
|
||||
break;
|
||||
}
|
||||
|
||||
case EPropertyTypeNew::Sequence:
|
||||
{
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
|
||||
case EPropertyTypeNew::Spline:
|
||||
{
|
||||
CSplineProperty* pSpline = TPropCast<CSplineProperty>(pProperty);
|
||||
std::vector<char>& rBuffer = pSpline->ValueRef(pData);
|
||||
|
||||
if (!rBuffer.empty())
|
||||
{
|
||||
rOut.WriteBytes( rBuffer.data(), rBuffer.size() );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mGame < eReturns)
|
||||
|
@ -132,26 +160,35 @@ void CScriptCooker::WriteProperty(IOutputStream& rOut,IProperty *pProp, bool InS
|
|||
rOut.WriteByte(1);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case eStructProperty:
|
||||
case EPropertyTypeNew::Guid:
|
||||
{
|
||||
CPropertyStruct *pStruct = static_cast<CPropertyStruct*>(pProp);
|
||||
CStructTemplate *pTemp = static_cast<CStructTemplate*>(pStruct->Template());
|
||||
CGuidProperty* pGuid = TPropCast<CGuidProperty>(pProperty);
|
||||
std::vector<char>& rBuffer = pGuid->ValueRef(pData);
|
||||
|
||||
std::vector<IProperty*> PropertiesToWrite;
|
||||
if (rBuffer.empty())
|
||||
rBuffer.resize(16, 0);
|
||||
|
||||
for (u32 iProp = 0; iProp < pStruct->Count(); iProp++)
|
||||
rOut.WriteBytes( rBuffer.data(), rBuffer.size() );
|
||||
break;
|
||||
}
|
||||
|
||||
case EPropertyTypeNew::Struct:
|
||||
{
|
||||
CStructPropertyNew* pStruct = TPropCast<CStructPropertyNew>(pProperty);
|
||||
std::vector<IPropertyNew*> PropertiesToWrite;
|
||||
|
||||
for (u32 ChildIdx = 0; ChildIdx < pStruct->NumChildren(); ChildIdx++)
|
||||
{
|
||||
IProperty *pSubProp = pStruct->PropertyByIndex(iProp);\
|
||||
IPropertyNew *pChild = pStruct->ChildByIndex(ChildIdx);
|
||||
|
||||
if (pTemp->IsSingleProperty() || pSubProp->ShouldCook())
|
||||
PropertiesToWrite.push_back(pSubProp);
|
||||
if (pStruct->IsAtomic() || pChild->ShouldCook(pData))
|
||||
PropertiesToWrite.push_back(pChild);
|
||||
}
|
||||
|
||||
if (!pTemp->IsSingleProperty())
|
||||
if (!pStruct->IsAtomic())
|
||||
{
|
||||
if (mGame <= ePrime)
|
||||
rOut.WriteLong(PropertiesToWrite.size());
|
||||
|
@ -159,20 +196,27 @@ void CScriptCooker::WriteProperty(IOutputStream& rOut,IProperty *pProp, bool InS
|
|||
rOut.WriteShort((u16) PropertiesToWrite.size());
|
||||
}
|
||||
|
||||
for (u32 iProp = 0; iProp < PropertiesToWrite.size(); iProp++)
|
||||
WriteProperty(rOut, PropertiesToWrite[iProp], pTemp->IsSingleProperty());
|
||||
for (u32 PropertyIdx = 0; PropertyIdx < PropertiesToWrite.size(); PropertyIdx++)
|
||||
WriteProperty(rOut, PropertiesToWrite[PropertyIdx], pStruct->IsAtomic());
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case eArrayProperty:
|
||||
case EPropertyTypeNew::Array:
|
||||
{
|
||||
CArrayProperty *pArray = static_cast<CArrayProperty*>(pProp);
|
||||
rOut.WriteLong(pArray->Count());
|
||||
CArrayProperty* pArray = TPropCast<CArrayProperty>(pProperty);
|
||||
u32 Count = pArray->ArrayCount(pData);
|
||||
rOut.WriteLong(Count);
|
||||
|
||||
for (u32 iProp = 0; iProp < pArray->Count(); iProp++)
|
||||
WriteProperty(rOut, pArray->PropertyByIndex(iProp), true);
|
||||
void* pOldItemData = mpArrayItemData;
|
||||
|
||||
for (u32 ElementIdx = 0; ElementIdx < pArray->ArrayCount(pData); ElementIdx++)
|
||||
{
|
||||
mpArrayItemData = pArray->ItemPointer(pData, ElementIdx);
|
||||
WriteProperty(rOut, pArray->ArchetypeProperty(), true);
|
||||
}
|
||||
|
||||
mpArrayItemData = pOldItemData;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -209,15 +253,16 @@ void CScriptCooker::WriteInstance(IOutputStream& rOut, CScriptObject *pInstance)
|
|||
u32 NumLinks = pInstance->NumLinks(eOutgoing);
|
||||
IsPrime1 ? rOut.WriteLong(NumLinks) : rOut.WriteShort((u16) NumLinks);
|
||||
|
||||
for (u32 iLink = 0; iLink < pInstance->NumLinks(eOutgoing); iLink++)
|
||||
for (u32 LinkIdx = 0; LinkIdx < NumLinks; LinkIdx++)
|
||||
{
|
||||
CLink *pLink = pInstance->Link(eOutgoing, iLink);
|
||||
CLink *pLink = pInstance->Link(eOutgoing, LinkIdx);
|
||||
rOut.WriteLong(pLink->State());
|
||||
rOut.WriteLong(pLink->Message());
|
||||
rOut.WriteLong(pLink->ReceiverID());
|
||||
}
|
||||
|
||||
WriteProperty(rOut, pInstance->Properties(), false);
|
||||
mpObject = pInstance;
|
||||
WriteProperty(rOut, pInstance->Template()->Properties(), false);
|
||||
u32 InstanceEnd = rOut.Tell();
|
||||
|
||||
rOut.Seek(SizeOffset, SEEK_SET);
|
||||
|
@ -302,6 +347,6 @@ void CScriptCooker::WriteGeneratedLayer(IOutputStream& rOut)
|
|||
rOut.WriteByte(1); // Version
|
||||
rOut.WriteLong(mGeneratedObjects.size());
|
||||
|
||||
for (u32 InstIdx = 0; InstIdx < mGeneratedObjects.size(); InstIdx++)
|
||||
WriteInstance(rOut, mGeneratedObjects[InstIdx]);
|
||||
for (u32 ObjectIdx = 0; ObjectIdx < mGeneratedObjects.size(); ObjectIdx++)
|
||||
WriteInstance(rOut, mGeneratedObjects[ObjectIdx]);
|
||||
}
|
||||
|
|
|
@ -10,14 +10,18 @@
|
|||
class CScriptCooker
|
||||
{
|
||||
EGame mGame;
|
||||
CScriptObject* mpObject;
|
||||
void* mpArrayItemData;
|
||||
std::vector<CScriptObject*> mGeneratedObjects;
|
||||
bool mWriteGeneratedSeparately;
|
||||
|
||||
void WriteProperty(IOutputStream& rOut,IProperty *pProp, bool InSingleStruct);
|
||||
void WriteProperty(IOutputStream& rOut, IPropertyNew* pProperty, bool InAtomicStruct);
|
||||
|
||||
public:
|
||||
CScriptCooker(EGame Game, bool WriteGeneratedObjectsSeparately = true)
|
||||
: mGame(Game)
|
||||
, mpObject(nullptr)
|
||||
, mpArrayItemData(nullptr)
|
||||
, mWriteGeneratedSeparately(WriteGeneratedObjectsSeparately && mGame >= eEchoesDemo)
|
||||
{}
|
||||
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
#include "CTemplateWriter.h"
|
||||
#include "CAreaCooker.h"
|
||||
#include <Common/FileUtil.h>
|
||||
#include <Core/Resource/Script/IPropertyTemplate.h>
|
||||
|
||||
#include <tinyxml2.h>
|
||||
|
||||
#if 0
|
||||
using namespace tinyxml2;
|
||||
TString CTemplateWriter::smTemplatesDir = "../templates/";
|
||||
|
||||
|
@ -802,9 +804,9 @@ void CTemplateWriter::SavePropertyOverrides(XMLDocument *pDoc, XMLElement *pPare
|
|||
// Struct/array-specific parameters
|
||||
else if (pProp->Type() == eStructProperty || pProp->Type() == eArrayProperty)
|
||||
{
|
||||
CStructTemplate *pStruct = static_cast<CStructTemplate*>(pProp);
|
||||
CStructTemplate *pChildStruct = static_cast<CStructTemplate*>(pProp);
|
||||
CStructTemplate *pSourceStruct = static_cast<CStructTemplate*>(pSource);
|
||||
SavePropertyOverrides(pDoc, pElem, pStruct, pSourceStruct);
|
||||
SavePropertyOverrides(pDoc, pElem, pChildStruct, pSourceStruct);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -839,3 +841,4 @@ void CTemplateWriter::SaveBitFlags(XMLDocument *pDoc, XMLElement *pParent, CBitf
|
|||
pFlags->LinkEndChild(pElem);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "Core/Resource/Script/CScriptTemplate.h"
|
||||
#include <tinyxml2.h>
|
||||
|
||||
#if 0
|
||||
class CTemplateWriter
|
||||
{
|
||||
CTemplateWriter();
|
||||
|
@ -24,5 +25,6 @@ public:
|
|||
static void SaveEnumerators(tinyxml2::XMLDocument *pDoc, tinyxml2::XMLElement *pParent, CEnumTemplate *pTemp);
|
||||
static void SaveBitFlags(tinyxml2::XMLDocument *pDoc, tinyxml2::XMLElement *pParent, CBitfieldTemplate *pTemp);
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // CTEMPLATEWRITER_H
|
||||
|
|
|
@ -74,5 +74,8 @@ enum EResType
|
|||
eInvalidResType = -1
|
||||
};
|
||||
|
||||
// Defined in CResTypeInfo.cpp
|
||||
void Serialize(IArchive& rArc, EResType& rType);
|
||||
|
||||
#endif // ERESTYPE
|
||||
|
||||
|
|
|
@ -2,256 +2,294 @@
|
|||
#include "CTemplateLoader.h"
|
||||
#include "Core/GameProject/CResourceStore.h"
|
||||
#include "Core/Resource/Script/CMasterTemplate.h"
|
||||
#include "Core/Resource/Script/Property/CArrayProperty.h"
|
||||
#include "Core/Resource/Script/Property/CAssetProperty.h"
|
||||
#include "Core/Resource/Script/Property/CEnumProperty.h"
|
||||
#include "Core/Resource/Script/Property/CFlagsProperty.h"
|
||||
#include <Common/Log.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
// Whether to ensure the values of enum/flag properties are valid
|
||||
#define VALIDATE_PROPERTY_VALUES 1
|
||||
|
||||
CScriptLoader::CScriptLoader()
|
||||
: mpObj(nullptr)
|
||||
, mpArrayItemData(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY)
|
||||
void CScriptLoader::ReadProperty(IPropertyNew *pProp, u32 Size, IInputStream& rSCLY)
|
||||
{
|
||||
IPropertyTemplate *pTemp = pProp->Template();
|
||||
void* pData = (mpArrayItemData ? mpArrayItemData : mpObj->mPropertyData.data());
|
||||
|
||||
switch (pTemp->Type())
|
||||
switch (pProp->Type())
|
||||
{
|
||||
|
||||
case eBoolProperty:
|
||||
case EPropertyTypeNew::Bool:
|
||||
{
|
||||
TBoolProperty *pBoolCast = static_cast<TBoolProperty*>(pProp);
|
||||
pBoolCast->Set( (rSCLY.ReadByte() != 0) );
|
||||
CBoolProperty* pBool = TPropCast<CBoolProperty>(pProp);
|
||||
pBool->ValueRef(pData) = rSCLY.ReadBool();
|
||||
break;
|
||||
}
|
||||
|
||||
case eByteProperty:
|
||||
case EPropertyTypeNew::Byte:
|
||||
{
|
||||
TByteProperty *pByteCast = static_cast<TByteProperty*>(pProp);
|
||||
pByteCast->Set(rSCLY.ReadByte());
|
||||
CByteProperty* pByte = TPropCast<CByteProperty>(pProp);
|
||||
pByte->ValueRef(pData) = rSCLY.ReadByte();
|
||||
break;
|
||||
}
|
||||
|
||||
case eShortProperty:
|
||||
case EPropertyTypeNew::Short:
|
||||
{
|
||||
TShortProperty *pShortCast = static_cast<TShortProperty*>(pProp);
|
||||
pShortCast->Set(rSCLY.ReadShort());
|
||||
CShortProperty* pShort = TPropCast<CShortProperty>(pProp);
|
||||
pShort->ValueRef(pData) = rSCLY.ReadShort();
|
||||
break;
|
||||
}
|
||||
|
||||
case eLongProperty:
|
||||
case EPropertyTypeNew::Int:
|
||||
{
|
||||
TLongProperty *pLongCast = static_cast<TLongProperty*>(pProp);
|
||||
pLongCast->Set(rSCLY.ReadLong());
|
||||
CIntProperty* pInt = TPropCast<CIntProperty>(pProp);
|
||||
pInt->ValueRef(pData) = rSCLY.ReadLong();
|
||||
break;
|
||||
}
|
||||
|
||||
case eBitfieldProperty:
|
||||
case EPropertyTypeNew::Float:
|
||||
{
|
||||
TBitfieldProperty *pBitfieldCast = static_cast<TBitfieldProperty*>(pProp);
|
||||
pBitfieldCast->Set(rSCLY.ReadLong());
|
||||
|
||||
// Validate
|
||||
u32 Mask = 0;
|
||||
CBitfieldTemplate *pBitfieldTemp = static_cast<CBitfieldTemplate*>(pTemp);
|
||||
for (u32 iMask = 0; iMask < pBitfieldTemp->NumFlags(); iMask++)
|
||||
Mask |= pBitfieldTemp->FlagMask(iMask);
|
||||
|
||||
u32 Check = pBitfieldCast->Get() & ~Mask;
|
||||
if (Check != 0)
|
||||
Log::FileWarning(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Bitfield property \"" + pBitfieldTemp->FullName() + "\" + (" + pBitfieldTemp->IDString(true) + ") has flags set that aren't in the template: " + TString::HexString(Check));
|
||||
|
||||
CFloatProperty* pFloat = TPropCast<CFloatProperty>(pProp);
|
||||
pFloat->ValueRef(pData) = rSCLY.ReadFloat();
|
||||
break;
|
||||
}
|
||||
|
||||
case eEnumProperty:
|
||||
case EPropertyTypeNew::Choice:
|
||||
{
|
||||
TEnumProperty *pEnumCast = static_cast<TEnumProperty*>(pProp);
|
||||
CEnumTemplate *pEnumTemp = static_cast<CEnumTemplate*>(pTemp);
|
||||
u32 ID = rSCLY.ReadLong();
|
||||
CChoiceProperty* pChoice = TPropCast<CChoiceProperty>(pProp);
|
||||
pChoice->ValueRef(pData) = rSCLY.ReadLong();
|
||||
|
||||
// Validate
|
||||
u32 Index = pEnumTemp->EnumeratorIndex(ID);
|
||||
if (Index == -1) Log::FileError(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Enum property \"" + pEnumTemp->FullName() + "\" (" + pEnumTemp->IDString(true) + ") has invalid enumerator value: " + TString::HexString(ID));
|
||||
|
||||
pEnumCast->Set(ID);
|
||||
#if VALIDATE_PROPERTY_VALUES
|
||||
if (!pChoice->HasValidValue(pData))
|
||||
{
|
||||
u32 Value = pChoice->ValueRef(pData);
|
||||
Log::FileError(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Choice property \"" + pChoice->Name() + "\" (" + pChoice->IDString(true) + ") has unrecognized value: " + TString::HexString(Value));
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case eFloatProperty:
|
||||
case EPropertyTypeNew::Enum:
|
||||
{
|
||||
TFloatProperty *pFloatCast = static_cast<TFloatProperty*>(pProp);
|
||||
pFloatCast->Set(rSCLY.ReadFloat());
|
||||
CEnumProperty* pEnum = TPropCast<CEnumProperty>(pProp);
|
||||
pEnum->ValueRef(pData) = rSCLY.ReadLong();
|
||||
|
||||
#if VALIDATE_PROPERTY_VALUES
|
||||
if (!pEnum->HasValidValue(pData))
|
||||
{
|
||||
u32 Value = pEnum->ValueRef(pData);
|
||||
Log::FileError(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Enum property \"" + pEnum->Name() + "\" (" + pEnum->IDString(true) + ") has unrecognized value: " + TString::HexString(Value));
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case eStringProperty:
|
||||
case EPropertyTypeNew::Flags:
|
||||
{
|
||||
TStringProperty *pStringCast = static_cast<TStringProperty*>(pProp);
|
||||
pStringCast->Set(rSCLY.ReadString());
|
||||
CFlagsProperty* pFlags = TPropCast<CFlagsProperty>(pProp);
|
||||
pFlags->ValueRef(pData) = rSCLY.ReadLong();
|
||||
|
||||
#if VALIDATE_PROPERTY_VALUES
|
||||
u32 InvalidBits = pFlags->HasValidValue(pData);
|
||||
|
||||
if (InvalidBits)
|
||||
{
|
||||
Log::FileWarning(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Flags property \"" + pFlags->Name() + "\" + (" + pFlags->IDString(true) + ") has unrecognized flags set: " + TString::HexString(InvalidBits));
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case eVector3Property:
|
||||
case EPropertyTypeNew::String:
|
||||
{
|
||||
TVector3Property *pVector3Cast = static_cast<TVector3Property*>(pProp);
|
||||
pVector3Cast->Set(CVector3f(rSCLY));
|
||||
CStringProperty* pString = TPropCast<CStringProperty>(pProp);
|
||||
pString->ValueRef(pData) = rSCLY.ReadString();
|
||||
break;
|
||||
}
|
||||
|
||||
case eColorProperty:
|
||||
case EPropertyTypeNew::Vector:
|
||||
{
|
||||
TColorProperty *pColorCast = static_cast<TColorProperty*>(pProp);
|
||||
pColorCast->Set(CColor(rSCLY));
|
||||
CVectorProperty* pVector = TPropCast<CVectorProperty>(pProp);
|
||||
pVector->ValueRef(pData) = CVector3f(rSCLY);
|
||||
break;
|
||||
}
|
||||
|
||||
case eSoundProperty:
|
||||
case EPropertyTypeNew::Color:
|
||||
{
|
||||
TSoundProperty *pSoundCast = static_cast<TSoundProperty*>(pProp);
|
||||
pSoundCast->Set(rSCLY.ReadLong());
|
||||
CColorProperty* pColor = TPropCast<CColorProperty>(pProp);
|
||||
pColor->ValueRef(pData) = CColor(rSCLY);
|
||||
break;
|
||||
}
|
||||
|
||||
case eAssetProperty:
|
||||
case EPropertyTypeNew::Asset:
|
||||
{
|
||||
TAssetProperty *pAssetCast = static_cast<TAssetProperty*>(pProp);
|
||||
CAssetProperty* pAsset = TPropCast<CAssetProperty>(pProp);
|
||||
pAsset->ValueRef(pData) = CAssetID(rSCLY, mpMaster->Game());
|
||||
|
||||
// quick hacky fix - all games set version to DKCR for copy/paste
|
||||
CAssetID ID;
|
||||
if (mVersion == eReturns)
|
||||
ID = CAssetID(rSCLY, (EIDLength) Size);
|
||||
else
|
||||
ID = CAssetID(rSCLY, mVersion);
|
||||
#if VALIDATE_PROPERTY_VALUES
|
||||
CAssetID ID = pAsset->ValueRef(pData);
|
||||
|
||||
pAssetCast->Set(ID);
|
||||
|
||||
// Verify this is a valid resource type for this property
|
||||
if (ID.IsValid())
|
||||
{
|
||||
CResourceEntry *pEntry = gpResourceStore->FindEntry(ID);
|
||||
|
||||
if (pEntry)
|
||||
{
|
||||
const CResTypeFilter& rkFilter = static_cast<CAssetTemplate*>(pTemp)->TypeFilter();
|
||||
const CResTypeFilter& rkFilter = pAsset->GetTypeFilter();
|
||||
bool Valid = rkFilter.Accepts(pEntry->ResourceType());
|
||||
|
||||
if (!Valid)
|
||||
Log::FileWarning(rSCLY.GetSourceString(), rSCLY.Tell() - ID.Length(), "Asset property \"" + pTemp->FullName() + "\" (" + pTemp->IDString(true) + ") has a reference to an illegal asset type: " + pEntry->CookedExtension());
|
||||
Log::FileWarning(rSCLY.GetSourceString(), rSCLY.Tell() - ID.Length(), "Asset property \"" + pAsset->Name() + "\" (" + pAsset->IDString(true) + ") has a reference to an illegal asset type: " + pEntry->CookedExtension());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case eStructProperty:
|
||||
case EPropertyTypeNew::Sound:
|
||||
{
|
||||
CPropertyStruct *pStructCast = static_cast<CPropertyStruct*>(pProp);
|
||||
CSoundProperty* pSound = TPropCast<CSoundProperty>(pProp);
|
||||
pSound->ValueRef(pData) = rSCLY.ReadLong();
|
||||
break;
|
||||
}
|
||||
|
||||
case EPropertyTypeNew::Animation:
|
||||
{
|
||||
CAnimationProperty* pAnim = TPropCast<CAnimationProperty>(pProp);
|
||||
pAnim->ValueRef(pData) = rSCLY.ReadLong();
|
||||
break;
|
||||
}
|
||||
|
||||
case EPropertyTypeNew::AnimationSet:
|
||||
{
|
||||
CAnimationSetProperty* pAnimSet = TPropCast<CAnimationSetProperty>(pProp);
|
||||
pAnimSet->ValueRef(pData) = CAnimationParameters(rSCLY, mpMaster->Game());
|
||||
break;
|
||||
}
|
||||
|
||||
case EPropertyTypeNew::Sequence:
|
||||
{
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
|
||||
case EPropertyTypeNew::Spline:
|
||||
{
|
||||
CSplineProperty* pSpline = TPropCast<CSplineProperty>(pProp);
|
||||
std::vector<char>& Buffer = pSpline->ValueRef(pData);
|
||||
Buffer.resize(Size);
|
||||
rSCLY.ReadBytes(Buffer.data(), Buffer.size());
|
||||
break;
|
||||
}
|
||||
|
||||
case EPropertyTypeNew::Guid:
|
||||
{
|
||||
ASSERT(Size == 16);
|
||||
CGuidProperty* pGuid = TPropCast<CGuidProperty>(pProp);
|
||||
pGuid->ValueRef(pData).resize(16);
|
||||
rSCLY.ReadBytes(pGuid->ValueRef(pData).data(), 16);
|
||||
break;
|
||||
}
|
||||
|
||||
case EPropertyTypeNew::Struct:
|
||||
{
|
||||
CStructPropertyNew* pStruct = TPropCast<CStructPropertyNew>(pProp);
|
||||
|
||||
if (mVersion < eEchoesDemo)
|
||||
LoadStructMP1(rSCLY, pStructCast, static_cast<CStructTemplate*>(pStructCast->Template()));
|
||||
LoadStructMP1(rSCLY, pStruct);
|
||||
else
|
||||
LoadStructMP2(rSCLY, pStructCast, static_cast<CStructTemplate*>(pTemp));
|
||||
LoadStructMP2(rSCLY, pStruct);
|
||||
break;
|
||||
}
|
||||
|
||||
case eArrayProperty:
|
||||
case EPropertyTypeNew::Array:
|
||||
{
|
||||
CArrayProperty *pArrayCast = static_cast<CArrayProperty*>(pProp);
|
||||
CArrayProperty *pArray = TPropCast<CArrayProperty>(pProp);
|
||||
int Count = rSCLY.ReadLong();
|
||||
|
||||
pArrayCast->Resize(Count);
|
||||
pArray->Resize(pData, Count);
|
||||
void* pOldArrayItemData = mpArrayItemData;
|
||||
|
||||
for (int iElem = 0; iElem < Count; iElem++)
|
||||
// Make sure the array archetype is atomic... non-atomic array archetypes is not supported
|
||||
// because arrays can only have one possible archetype so having property IDs here wouldn't make sense
|
||||
ASSERT(pArray->ArchetypeProperty()->IsAtomic());
|
||||
|
||||
for (int ElementIdx = 0; ElementIdx < Count; ElementIdx++)
|
||||
{
|
||||
if (mVersion < eEchoesDemo)
|
||||
LoadStructMP1(rSCLY, static_cast<CPropertyStruct*>(pArrayCast->PropertyByIndex(iElem)), pArrayCast->SubStructTemplate());
|
||||
else
|
||||
LoadStructMP2(rSCLY, static_cast<CPropertyStruct*>(pArrayCast->PropertyByIndex(iElem)), pArrayCast->SubStructTemplate());
|
||||
/**
|
||||
* so this is kind of annoying, there isn't really any good way to cleanly integrate arrays into the property system
|
||||
* because calculating the pointer to an item requires knowing the array index, which the property itself can't store
|
||||
* because the same property object is used for every array element; and we can't dynamically add children to the array
|
||||
* based on its size either, because the same array property is shared between multiple script instances. so, instead,
|
||||
* we determine the item pointer ourselves and the array archetype property will respect it.
|
||||
*
|
||||
* arrays are an edge case anyway - they only really appear in Prime 1 and there are only a couple array properties in
|
||||
* the game. the only situation where an array property appears in other games is SequenceTimer, and that's going to be
|
||||
* migrated to Sequence properties eventually, so there isn't really any good reason to spend a lot of effort refactoring
|
||||
* things to make this cleaner
|
||||
*/
|
||||
mpArrayItemData = pArray->ItemPointer(pData, ElementIdx);
|
||||
ReadProperty(pArray->ArchetypeProperty(), 0, rSCLY);
|
||||
}
|
||||
|
||||
mpArrayItemData = pOldArrayItemData;
|
||||
break;
|
||||
}
|
||||
|
||||
case eCharacterProperty:
|
||||
{
|
||||
TCharacterProperty *pAnimCast = static_cast<TCharacterProperty*>(pProp);
|
||||
pAnimCast->Set(CAnimationParameters(rSCLY, mpMaster->Game()));
|
||||
break;
|
||||
}
|
||||
|
||||
case eMayaSplineProperty:
|
||||
{
|
||||
TMayaSplineProperty *pSplineCast = static_cast<TMayaSplineProperty*>(pProp);
|
||||
std::vector<u8> Buffer(Size);
|
||||
rSCLY.ReadBytes(Buffer.data(), Buffer.size());
|
||||
pSplineCast->Set(Buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
case eUnknownProperty:
|
||||
{
|
||||
TUnknownProperty *pUnknownCast = static_cast<TUnknownProperty*>(pProp);
|
||||
std::vector<u8> Buffer(Size);
|
||||
rSCLY.ReadBytes(Buffer.data(), Buffer.size());
|
||||
pUnknownCast->Set(Buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CScriptLoader::LoadStructMP1(IInputStream& rSCLY, CPropertyStruct *pStruct, CStructTemplate *pTemp)
|
||||
void CScriptLoader::LoadStructMP1(IInputStream& rSCLY, CStructPropertyNew* pStruct)
|
||||
{
|
||||
u32 StructStart = rSCLY.Tell();
|
||||
|
||||
// Verify property count
|
||||
u32 PropCount = pTemp->Count();
|
||||
u32 PropertyCount = pStruct->NumChildren();
|
||||
u32 Version = 0;
|
||||
|
||||
if (!pTemp->IsSingleProperty())
|
||||
if (!pStruct->IsAtomic())
|
||||
{
|
||||
u32 FilePropCount = rSCLY.ReadLong();
|
||||
Version = pTemp->VersionForPropertyCount(FilePropCount);
|
||||
|
||||
if (Version == -1)
|
||||
{
|
||||
TIDString IDString = pTemp->IDString(true);
|
||||
if (!IDString.IsEmpty()) IDString = " (" + IDString + ")";
|
||||
|
||||
Log::FileWarning(rSCLY.GetSourceString(), StructStart, "Struct \"" + pTemp->FullName() + "\" (" + IDString + ") template prop count doesn't match file; template is " + TString::HexString(PropCount, 2) + ", file is " + TString::HexString(FilePropCount, 2));
|
||||
Version = 0;
|
||||
}
|
||||
//@todo version checking
|
||||
}
|
||||
|
||||
// Parse properties
|
||||
for (u32 iProp = 0; iProp < PropCount; iProp++)
|
||||
for (u32 ChildIndex = 0; ChildIndex < PropertyCount; ChildIndex++)
|
||||
{
|
||||
IPropertyTemplate *pPropTemp = pTemp->PropertyByIndex(iProp);
|
||||
IProperty *pProp = pStruct->PropertyByIndex(iProp);
|
||||
IPropertyNew *pProperty = pStruct->ChildByIndex(ChildIndex);
|
||||
|
||||
if (pPropTemp->CookPreference() != eNeverCook && pPropTemp->IsInVersion(Version))
|
||||
ReadProperty(pProp, 0, rSCLY);
|
||||
//@todo version check
|
||||
if (pProperty->CookPreference() != ECookPreferenceNew::Never)
|
||||
ReadProperty(pProperty, 0, rSCLY);
|
||||
}
|
||||
}
|
||||
|
||||
CScriptObject* CScriptLoader::LoadObjectMP1(IInputStream& rSCLY)
|
||||
{
|
||||
u32 ObjStart = rSCLY.Tell();
|
||||
u32 StartOffset = rSCLY.Tell();
|
||||
u8 Type = rSCLY.ReadByte();
|
||||
u32 Size = rSCLY.ReadLong();
|
||||
u32 End = rSCLY.Tell() + Size;
|
||||
|
||||
CScriptTemplate *pTemp = mpMaster->TemplateByID((u32) Type);
|
||||
if (!pTemp)
|
||||
CScriptTemplate *pTemplate = mpMaster->TemplateByID((u32) Type);
|
||||
if (!pTemplate)
|
||||
{
|
||||
// No valid template for this object; can't load
|
||||
Log::FileError(rSCLY.GetSourceString(), ObjStart, "Unknown object ID encountered: " + TString::HexString(Type, 2));
|
||||
Log::FileError(rSCLY.GetSourceString(), StartOffset, "Unknown object ID encountered: " + TString::HexString(Type, 2));
|
||||
rSCLY.Seek(End, SEEK_SET);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
u32 InstanceID = rSCLY.ReadLong() & 0x03FFFFFF;
|
||||
if (InstanceID == 0x03FFFFFF) InstanceID = mpArea->FindUnusedInstanceID();
|
||||
mpObj = new CScriptObject(InstanceID, mpArea, mpLayer, pTemp);
|
||||
mpObj = new CScriptObject(InstanceID, mpArea, mpLayer, pTemplate);
|
||||
|
||||
// Load connections
|
||||
u32 NumLinks = rSCLY.ReadLong();
|
||||
|
@ -268,8 +306,8 @@ CScriptObject* CScriptLoader::LoadObjectMP1(IInputStream& rSCLY)
|
|||
}
|
||||
|
||||
// Load object...
|
||||
CPropertyStruct *pBase = mpObj->mpProperties;
|
||||
LoadStructMP1(rSCLY, pBase, static_cast<CStructTemplate*>(pBase->Template()));
|
||||
CStructPropertyNew* pProperties = pTemplate->Properties();
|
||||
LoadStructMP1(rSCLY, pProperties);
|
||||
|
||||
// Cleanup and return
|
||||
rSCLY.Seek(End, SEEK_SET);
|
||||
|
@ -288,11 +326,11 @@ CScriptLayer* CScriptLoader::LoadLayerMP1(IInputStream& rSCLY)
|
|||
mpLayer = new CScriptLayer(mpArea);
|
||||
mpLayer->Reserve(NumObjects);
|
||||
|
||||
for (u32 iObj = 0; iObj < NumObjects; iObj++)
|
||||
for (u32 ObjectIndex = 0; ObjectIndex < NumObjects; ObjectIndex++)
|
||||
{
|
||||
CScriptObject *pObj = LoadObjectMP1(rSCLY);
|
||||
if (pObj)
|
||||
mpLayer->AddInstance(pObj);
|
||||
CScriptObject *pObject = LoadObjectMP1(rSCLY);
|
||||
if (pObject)
|
||||
mpLayer->AddInstance(pObject);
|
||||
}
|
||||
|
||||
// Layer sizes are always a multiple of 32 - skip end padding before returning
|
||||
|
@ -301,46 +339,39 @@ CScriptLayer* CScriptLoader::LoadLayerMP1(IInputStream& rSCLY)
|
|||
return mpLayer;
|
||||
}
|
||||
|
||||
void CScriptLoader::LoadStructMP2(IInputStream& rSCLY, CPropertyStruct *pStruct, CStructTemplate *pTemp)
|
||||
void CScriptLoader::LoadStructMP2(IInputStream& rSCLY, CStructPropertyNew* pStruct)
|
||||
{
|
||||
// Verify property count
|
||||
u32 StructStart = rSCLY.Tell();
|
||||
StructStart += 0;
|
||||
u32 PropCount = pTemp->Count();
|
||||
u32 ChildCount = pStruct->NumChildren();
|
||||
|
||||
if (!pTemp->IsSingleProperty())
|
||||
PropCount = rSCLY.ReadShort();
|
||||
if (!pStruct->IsAtomic())
|
||||
ChildCount = rSCLY.ReadShort();
|
||||
|
||||
// Parse properties
|
||||
for (u32 iProp = 0; iProp < PropCount; iProp++)
|
||||
for (u32 ChildIdx = 0; ChildIdx < ChildCount; ChildIdx++)
|
||||
{
|
||||
IProperty *pProp;
|
||||
IPropertyTemplate *pPropTemp;
|
||||
IPropertyNew* pProperty = nullptr;
|
||||
u32 PropertyStart = rSCLY.Tell();
|
||||
u32 PropertyID = -1;
|
||||
u16 PropertyLength = 0;
|
||||
u16 PropertySize = 0;
|
||||
u32 NextProperty = 0;
|
||||
|
||||
if (pTemp->IsSingleProperty())
|
||||
if (pStruct->IsAtomic())
|
||||
{
|
||||
pProp = pStruct->PropertyByIndex(iProp);
|
||||
pPropTemp = pTemp->PropertyByIndex(iProp);
|
||||
pProperty = pStruct->ChildByIndex(ChildIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
PropertyID = rSCLY.ReadLong();
|
||||
PropertyLength = rSCLY.ReadShort();
|
||||
NextProperty = rSCLY.Tell() + PropertyLength;
|
||||
|
||||
pProp = pStruct->PropertyByID(PropertyID);
|
||||
pPropTemp = pTemp->PropertyByID(PropertyID);
|
||||
PropertySize = rSCLY.ReadShort();
|
||||
NextProperty = rSCLY.Tell() + PropertySize;
|
||||
pProperty = pStruct->ChildByID(PropertyID);
|
||||
}
|
||||
|
||||
if (!pPropTemp)
|
||||
if (!pProperty)
|
||||
Log::FileError(rSCLY.GetSourceString(), PropertyStart, "Can't find template for property " + TString::HexString(PropertyID) + " - skipping");
|
||||
|
||||
else
|
||||
ReadProperty(pProp, PropertyLength, rSCLY);
|
||||
ReadProperty(pProperty, PropertySize, rSCLY);
|
||||
|
||||
if (NextProperty > 0)
|
||||
rSCLY.Seek(NextProperty, SEEK_SET);
|
||||
|
@ -354,7 +385,7 @@ CScriptObject* CScriptLoader::LoadObjectMP2(IInputStream& rSCLY)
|
|||
u16 ObjectSize = rSCLY.ReadShort();
|
||||
u32 ObjEnd = rSCLY.Tell() + ObjectSize;
|
||||
|
||||
CScriptTemplate *pTemplate = mpMaster->TemplateByID(ObjectID);
|
||||
CScriptTemplate* pTemplate = mpMaster->TemplateByID(ObjectID);
|
||||
|
||||
if (!pTemplate)
|
||||
{
|
||||
|
@ -371,19 +402,19 @@ CScriptObject* CScriptLoader::LoadObjectMP2(IInputStream& rSCLY)
|
|||
u32 NumConnections = rSCLY.ReadShort();
|
||||
mpObj->mOutLinks.reserve(NumConnections);
|
||||
|
||||
for (u32 iCon = 0; iCon < NumConnections; iCon++)
|
||||
for (u32 LinkIdx = 0; LinkIdx < NumConnections; LinkIdx++)
|
||||
{
|
||||
u32 State = rSCLY.ReadLong();
|
||||
u32 Message = rSCLY.ReadLong();
|
||||
u32 ReceiverID = rSCLY.ReadLong() & 0x03FFFFFF;
|
||||
|
||||
CLink *pLink = new CLink(mpArea, State, Message, mpObj->mInstanceID, ReceiverID);
|
||||
CLink* pLink = new CLink(mpArea, State, Message, mpObj->mInstanceID, ReceiverID);
|
||||
mpObj->mOutLinks.push_back(pLink);
|
||||
}
|
||||
|
||||
// Load object
|
||||
rSCLY.Seek(0x6, SEEK_CUR); // Skip base struct ID + size
|
||||
LoadStructMP2(rSCLY, mpObj->mpProperties, mpObj->mpTemplate->BaseStruct());
|
||||
LoadStructMP2(rSCLY, pTemplate->Properties());
|
||||
|
||||
// Cleanup and return
|
||||
rSCLY.Seek(ObjEnd, SEEK_SET);
|
||||
|
@ -399,11 +430,11 @@ CScriptLayer* CScriptLoader::LoadLayerMP2(IInputStream& rSCLY)
|
|||
mpLayer = new CScriptLayer(mpArea);
|
||||
mpLayer->Reserve(NumObjects);
|
||||
|
||||
for (u32 iObj = 0; iObj < NumObjects; iObj++)
|
||||
for (u32 ObjectIdx = 0; ObjectIdx < NumObjects; ObjectIdx++)
|
||||
{
|
||||
CScriptObject *pObj = LoadObjectMP2(rSCLY);
|
||||
if (pObj)
|
||||
mpLayer->AddInstance(pObj);
|
||||
CScriptObject* pObject = LoadObjectMP2(rSCLY);
|
||||
if (pObject)
|
||||
mpLayer->AddInstance(pObject);
|
||||
}
|
||||
|
||||
return mpLayer;
|
||||
|
|
|
@ -10,19 +10,22 @@
|
|||
class CScriptLoader
|
||||
{
|
||||
EGame mVersion;
|
||||
CScriptObject *mpObj;
|
||||
CScriptLayer *mpLayer;
|
||||
CGameArea *mpArea;
|
||||
CScriptObject* mpObj;
|
||||
CScriptLayer* mpLayer;
|
||||
CGameArea* mpArea;
|
||||
CMasterTemplate *mpMaster;
|
||||
|
||||
CScriptLoader();
|
||||
void ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY);
|
||||
// Current array item pointer
|
||||
void* mpArrayItemData;
|
||||
|
||||
void LoadStructMP1(IInputStream& rSCLY, CPropertyStruct *pStruct, CStructTemplate *pTemp);
|
||||
CScriptLoader();
|
||||
void ReadProperty(IPropertyNew* pProp, u32 Size, IInputStream& rSCLY);
|
||||
|
||||
void LoadStructMP1(IInputStream& rSCLY, CStructPropertyNew* pStruct);
|
||||
CScriptObject* LoadObjectMP1(IInputStream& rSCLY);
|
||||
CScriptLayer* LoadLayerMP1(IInputStream& rSCLY);
|
||||
|
||||
void LoadStructMP2(IInputStream& rSCLY, CPropertyStruct *pStruct, CStructTemplate *pTemp);
|
||||
void LoadStructMP2(IInputStream& rSCLY, CStructPropertyNew* pStruct);
|
||||
CScriptObject* LoadObjectMP2(IInputStream& rSCLY);
|
||||
CScriptLayer* LoadLayerMP2(IInputStream& rSCLY);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "CTemplateLoader.h"
|
||||
#include "CAreaLoader.h"
|
||||
#include "Core/Resource/Script/IPropertyTemplate.h"
|
||||
#include "Core/Resource/Script/Property/Properties.h"
|
||||
#include <Common/FileUtil.h>
|
||||
#include <Common/Log.h>
|
||||
|
||||
|
@ -9,7 +10,105 @@ const TString CTemplateLoader::mskGameListPath = CTemplateLoader::mskTemplatesDi
|
|||
|
||||
using namespace tinyxml2;
|
||||
|
||||
IPropertyTemplate* CTemplateLoader::LoadProperty(XMLElement *pElem, CScriptTemplate *pScript, CStructTemplate *pStruct, const TString& rkTemplateName)
|
||||
// ugly macro because this is all temp code anyway so whatever
|
||||
#define SET_MEMBER_CASES_NUMERICAL(MemberName, Param, LParam) \
|
||||
case EPropertyTypeNew::Byte:\
|
||||
TPropCast<CByteProperty>(pProp)->MemberName = (s8) LParam.ToInt32(10);\
|
||||
break;\
|
||||
\
|
||||
case EPropertyTypeNew::Short:\
|
||||
TPropCast<CShortProperty>(pProp)->MemberName = (s16) LParam.ToInt32(10);\
|
||||
break;\
|
||||
\
|
||||
case EPropertyTypeNew::Int:\
|
||||
TPropCast<CIntProperty>(pProp)->MemberName = (s32) LParam.ToInt32(10);\
|
||||
break;\
|
||||
\
|
||||
case EPropertyTypeNew::Float:\
|
||||
TPropCast<CFloatProperty>(pProp)->MemberName = LParam.ToFloat();\
|
||||
break;\
|
||||
\
|
||||
|
||||
#define SET_MEMBER_CASES_NON_NUMERICAL(MemberName, Param, LParam) \
|
||||
case EPropertyTypeNew::Bool:\
|
||||
TPropCast<CBoolProperty>(pProp)->MemberName = (LParam == "true");\
|
||||
break;\
|
||||
\
|
||||
case EPropertyTypeNew::Choice:\
|
||||
TPropCast<CChoiceProperty>(pProp)->MemberName = LParam.ToInt32( LParam.StartsWith("0x") ? 16 : 10 );\
|
||||
break;\
|
||||
\
|
||||
case EPropertyTypeNew::Enum:\
|
||||
TPropCast<CEnumProperty>(pProp)->MemberName = LParam.ToInt32( LParam.StartsWith("0x") ? 16 : 10 );\
|
||||
break;\
|
||||
\
|
||||
case EPropertyTypeNew::Flags:\
|
||||
TPropCast<CFlagsProperty>(pProp)->MemberName = LParam.ToInt32( LParam.StartsWith("0x") ? 16 : 10 );\
|
||||
break;\
|
||||
\
|
||||
case EPropertyTypeNew::String:\
|
||||
TPropCast<CStringProperty>(pProp)->MemberName = Param;\
|
||||
break;\
|
||||
\
|
||||
case EPropertyTypeNew::Vector:\
|
||||
{\
|
||||
TStringList Components = Param.Split(", ");\
|
||||
if (Components.size() != 3) {\
|
||||
TPropCast<CVectorProperty>(pProp)->MemberName = CVector3f::skInfinite;\
|
||||
break;\
|
||||
}\
|
||||
float* pPtr = &TPropCast<CVectorProperty>(pProp)->MemberName.X;\
|
||||
for (auto it = Components.begin(); it != Components.end(); it++)\
|
||||
{\
|
||||
*pPtr = it->ToFloat();\
|
||||
pPtr++;\
|
||||
}\
|
||||
break;\
|
||||
}\
|
||||
case EPropertyTypeNew::Color:\
|
||||
{\
|
||||
TStringList Components = Param.Split(", ");\
|
||||
if (Components.size() < 3 || Components.size() > 4) {\
|
||||
TPropCast<CColorProperty>(pProp)->MemberName = CColor::skTransparentBlack;\
|
||||
break;\
|
||||
}\
|
||||
float* pPtr = &TPropCast<CColorProperty>(pProp)->MemberName.R;\
|
||||
TPropCast<CColorProperty>(pProp)->MemberName.A = 1.0f;\
|
||||
for (auto it = Components.begin(); it != Components.end(); it++) {\
|
||||
*pPtr = it->ToFloat();\
|
||||
pPtr++;\
|
||||
}\
|
||||
break;\
|
||||
}\
|
||||
case EPropertyTypeNew::Asset:\
|
||||
TPropCast<CAssetProperty>(pProp)->MemberName = CAssetID::FromString(Param);\
|
||||
break;\
|
||||
\
|
||||
case EPropertyTypeNew::Sound:\
|
||||
TPropCast<CSoundProperty>(pProp)->MemberName = LParam.ToInt32(10);\
|
||||
break;\
|
||||
\
|
||||
|
||||
#define SET_MEMBER_FROM_STRING_TYPED(MemberName, Param, LParam)\
|
||||
switch (Type)\
|
||||
{\
|
||||
SET_MEMBER_CASES_NON_NUMERICAL(MemberName, Param, LParam)\
|
||||
SET_MEMBER_CASES_NUMERICAL(MemberName, Param, LParam)\
|
||||
default:\
|
||||
ASSERT(false);\
|
||||
break;\
|
||||
}\
|
||||
|
||||
#define SET_MEMBER_FROM_STRING_NUMERICAL(MemberName, Param, LParam)\
|
||||
switch(Type)\
|
||||
{\
|
||||
SET_MEMBER_CASES_NUMERICAL(MemberName, Param, LParam)\
|
||||
default:\
|
||||
ASSERT(false);\
|
||||
break;\
|
||||
}\
|
||||
|
||||
IPropertyNew* CTemplateLoader::LoadProperty(XMLElement* pElem, CScriptTemplate* pScript, CStructPropertyNew* pParent, const TString& rkTemplateName)
|
||||
{
|
||||
TString NodeType = TString(pElem->Name()).ToLower();
|
||||
TString IDAttr = TString(pElem->Attribute("ID")).ToLower();
|
||||
|
@ -38,8 +137,8 @@ IPropertyTemplate* CTemplateLoader::LoadProperty(XMLElement *pElem, CScriptTempl
|
|||
}
|
||||
|
||||
// Does the property already exist (eg is this an override)?
|
||||
IPropertyTemplate *pProp = pStruct->PropertyByID(ID);
|
||||
EPropertyType Type;
|
||||
IPropertyNew* pProp = pParent->ChildByID(ID);
|
||||
EPropertyTypeNew Type;
|
||||
bool IsNewProperty = false;
|
||||
|
||||
// If it doesn't, then we'll need to create it.
|
||||
|
@ -50,7 +149,7 @@ IPropertyTemplate* CTemplateLoader::LoadProperty(XMLElement *pElem, CScriptTempl
|
|||
Type = PropStringToPropEnum(TypeStr);
|
||||
IsNewProperty = true;
|
||||
|
||||
if (Type == eInvalidProperty)
|
||||
if (Type == EPropertyTypeNew::Invalid)
|
||||
{
|
||||
if (TypeStr.IsEmpty())
|
||||
Log::Error(rkTemplateName + ": Property " + TString::HexString(ID) + " doesn't have a type set");
|
||||
|
@ -60,13 +159,56 @@ IPropertyTemplate* CTemplateLoader::LoadProperty(XMLElement *pElem, CScriptTempl
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
pProp = CreateProperty(ID, Type, Name, pScript, pStruct);
|
||||
// Load archetype if required
|
||||
bool bNeedsArchetype = ( Type == EPropertyTypeNew::Struct ||
|
||||
Type == EPropertyTypeNew::Enum ||
|
||||
Type == EPropertyTypeNew::Choice ||
|
||||
Type == EPropertyTypeNew::Flags );
|
||||
|
||||
if (bNeedsArchetype)
|
||||
{
|
||||
IPropertyNew* pArchetype = nullptr;
|
||||
|
||||
//todo: struct archetypes are not supposed to be optional but apparently some still don't have them
|
||||
if (!TemplateAttr.IsEmpty())
|
||||
{
|
||||
if (Type == EPropertyTypeNew::Struct)
|
||||
{
|
||||
pArchetype = LoadStructArchetype(TemplateAttr);
|
||||
}
|
||||
else if (Type == EPropertyTypeNew::Enum || Type == EPropertyTypeNew::Choice)
|
||||
{
|
||||
pArchetype = LoadEnumArchetype(TemplateAttr, Type == EPropertyTypeNew::Choice);
|
||||
}
|
||||
else if (Type == EPropertyTypeNew::Flags)
|
||||
{
|
||||
pArchetype = LoadFlagsArchetype(TemplateAttr);
|
||||
}
|
||||
}
|
||||
|
||||
// create property as a copy of the archetype
|
||||
if (pArchetype != nullptr)
|
||||
{
|
||||
pProp = IPropertyNew::CreateCopy(pArchetype, pParent);
|
||||
}
|
||||
}
|
||||
|
||||
// no archetype, so do normal create
|
||||
if (!pProp)
|
||||
{
|
||||
pProp = IPropertyNew::Create(Type, pParent, mpMaster, pScript, false);
|
||||
}
|
||||
|
||||
// we need to have a valid property by this point
|
||||
if (!pProp)
|
||||
{
|
||||
Log::Error(rkTemplateName + ": Property " + TString::HexString(ID) + " seems to be using a valid but unsupported property type? (" + TypeStr + ")");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Initialize parameters on the new property
|
||||
pProp->mID = ID;
|
||||
pProp->mName = Name;
|
||||
}
|
||||
else
|
||||
Type = pProp->Type();
|
||||
|
@ -79,6 +221,7 @@ IPropertyTemplate* CTemplateLoader::LoadProperty(XMLElement *pElem, CScriptTempl
|
|||
TString ParamName = TString(pParams->Name()).ToLower();
|
||||
TString ParamVal = TString(pParams->GetText());
|
||||
|
||||
#if 0
|
||||
// Load versions
|
||||
if (ParamName == "versions")
|
||||
{
|
||||
|
@ -100,245 +243,284 @@ IPropertyTemplate* CTemplateLoader::LoadProperty(XMLElement *pElem, CScriptTempl
|
|||
|
||||
// Otherwise, delegate it to the template to parse the parameter.
|
||||
// (This is done because there's no common base class for typed properties, so it's tough to handle this in the template loader.)
|
||||
else pProp->SetParam(ParamName, ParamVal);
|
||||
else
|
||||
Prop->SetParam(ParamName, ParamVal);
|
||||
#endif
|
||||
if (ParamName == "cook_pref")
|
||||
{
|
||||
TString lValue = ParamVal.ToLower();
|
||||
|
||||
if (lValue == "always")
|
||||
pProp->mCookPreference = ECookPreferenceNew::Always;
|
||||
else if (lValue == "never")
|
||||
pProp->mCookPreference = ECookPreferenceNew::Never;
|
||||
else
|
||||
pProp->mCookPreference = ECookPreferenceNew::Default;
|
||||
}
|
||||
else if (ParamName == "description")
|
||||
{
|
||||
pProp->mDescription = ParamVal;
|
||||
}
|
||||
else if (ParamName == "default")
|
||||
{
|
||||
TString lValue = ParamVal.ToLower();
|
||||
SET_MEMBER_FROM_STRING_TYPED(mDefaultValue, ParamVal, lValue);
|
||||
}
|
||||
else if (ParamName == "range")
|
||||
{
|
||||
TStringList Components = ParamVal.ToLower().Split(", ");
|
||||
TString Min = Components.front();
|
||||
TString Max = Components.back();
|
||||
SET_MEMBER_FROM_STRING_NUMERICAL(mMinValue, Min, Min);
|
||||
SET_MEMBER_FROM_STRING_NUMERICAL(mMaxValue, Max, Max);
|
||||
}
|
||||
else if (ParamName == "suffix")
|
||||
{
|
||||
pProp->SetSuffix(ParamVal);
|
||||
}
|
||||
|
||||
pParams = pParams->NextSiblingElement();
|
||||
}
|
||||
|
||||
// Asset-specific parameters
|
||||
if (Type == eAssetProperty)
|
||||
if (Type == EPropertyTypeNew::Asset)
|
||||
{
|
||||
TString ExtensionsAttr = pElem->Attribute("extensions");
|
||||
|
||||
if (!ExtensionsAttr.IsEmpty())
|
||||
{
|
||||
TStringList ExtensionsList = ExtensionsAttr.Split(", ");
|
||||
CAssetTemplate *pAsset = static_cast<CAssetTemplate*>(pProp);
|
||||
CAssetProperty* pAsset = TPropCast<CAssetProperty>(pProp);
|
||||
pAsset->SetTypeFilter(ExtensionsList);
|
||||
}
|
||||
}
|
||||
|
||||
// Enum-specific parameters
|
||||
else if (Type == eEnumProperty)
|
||||
else if (Type == EPropertyTypeNew::Enum || Type == EPropertyTypeNew::Choice)
|
||||
{
|
||||
CEnumTemplate *pEnum = static_cast<CEnumTemplate*>(pProp);
|
||||
|
||||
// Load template
|
||||
if (!TemplateAttr.IsEmpty())
|
||||
LoadEnumTemplate(TemplateAttr, pEnum);
|
||||
// use static_cast so we can do both enum and choice with this code
|
||||
CEnumProperty* pEnum = static_cast<CEnumProperty*>(pProp);
|
||||
|
||||
// Load embedded enumerators
|
||||
XMLElement *pEnumerators = pElem->FirstChildElement("enumerators");
|
||||
XMLElement* pEnumerators = pElem->FirstChildElement("enumerators");
|
||||
|
||||
if (pEnumerators)
|
||||
LoadEnumerators(pEnumerators, pEnum, rkTemplateName);
|
||||
}
|
||||
|
||||
// Bitfield-specific parameters
|
||||
else if (Type == eBitfieldProperty)
|
||||
else if (Type == EPropertyTypeNew::Flags)
|
||||
{
|
||||
CBitfieldTemplate *pBitfield = static_cast<CBitfieldTemplate*>(pProp);
|
||||
|
||||
// Load template
|
||||
if (!TemplateAttr.IsEmpty())
|
||||
LoadBitfieldTemplate(TemplateAttr, pBitfield);
|
||||
CFlagsProperty* pFlags = TPropCast<CFlagsProperty>(pProp);
|
||||
|
||||
// Load embedded flags
|
||||
XMLElement *pFlags = pElem->FirstChildElement("flags");
|
||||
XMLElement* pFlagsElem = pElem->FirstChildElement("flags");
|
||||
|
||||
if (pFlags)
|
||||
LoadBitFlags(pFlags, pBitfield, rkTemplateName);
|
||||
if (pFlagsElem)
|
||||
LoadBitFlags(pFlagsElem, pFlags, rkTemplateName);
|
||||
}
|
||||
|
||||
// Struct-specific parameters
|
||||
else if ( (Type == eStructProperty) || (Type == eArrayProperty) )
|
||||
else if ( (Type == EPropertyTypeNew::Struct) || (Type == EPropertyTypeNew::Array) )
|
||||
{
|
||||
CStructTemplate *pStruct = static_cast<CStructTemplate*>(pProp);
|
||||
CStructPropertyNew* pStruct = nullptr;
|
||||
|
||||
// Load template or struct type
|
||||
if (!TemplateAttr.IsEmpty())
|
||||
LoadStructTemplate(TemplateAttr, pStruct);
|
||||
if (Type == EPropertyTypeNew::Struct)
|
||||
{
|
||||
pStruct = TPropCast<CStructPropertyNew>(pProp);
|
||||
}
|
||||
else
|
||||
{
|
||||
CArrayProperty* pArray = TPropCast<CArrayProperty>(pProp);
|
||||
|
||||
if (IsNewProperty && TemplateAttr.IsEmpty() && Type == eStructProperty)
|
||||
pStruct->mIsSingleProperty = (TypeAttr == "single");
|
||||
if (pArray->mpArchetype != nullptr)
|
||||
{
|
||||
ASSERT(pArray->mpArchetype->Type() == EPropertyTypeNew::Struct);
|
||||
pStruct = TPropCast<CStructPropertyNew>(pArray->mpArchetype);
|
||||
}
|
||||
else
|
||||
{
|
||||
pArray->mpArchetype = IPropertyNew::Create(EPropertyTypeNew::Struct, pArray, mpMaster, pScript, false);
|
||||
pStruct = TPropCast<CStructPropertyNew>(pArray->mpArchetype);
|
||||
pStruct->mFlags = EPropertyFlag::IsAtomic | EPropertyFlag::IsArrayArchetype;
|
||||
}
|
||||
pStruct = TPropCast<CStructPropertyNew>(pArray->mpArchetype);
|
||||
}
|
||||
|
||||
// Load sub-properties and parameter overrides
|
||||
// Load parameter overrides
|
||||
XMLElement *pProperties = pElem->FirstChildElement("properties");
|
||||
|
||||
if (pProperties)
|
||||
{
|
||||
LoadProperties(pProperties, pScript, pStruct, rkTemplateName);
|
||||
}
|
||||
|
||||
if (Type == EPropertyTypeNew::Array)
|
||||
{
|
||||
pStruct->PostInitialize();
|
||||
}
|
||||
}
|
||||
|
||||
if (IsNewProperty)
|
||||
CMasterTemplate::AddProperty(pProp, mMasterDir + rkTemplateName);
|
||||
|
||||
pProp->PostInitialize();
|
||||
return pProp;
|
||||
}
|
||||
|
||||
#define CREATE_PROP_TEMP(Class) new Class(ID, rkName, eNoCookPreference, pScript, mpMaster, pStruct)
|
||||
IPropertyTemplate* CTemplateLoader::CreateProperty(u32 ID, EPropertyType Type, const TString& rkName, CScriptTemplate *pScript, CStructTemplate *pStruct)
|
||||
{
|
||||
IPropertyTemplate *pOut = pStruct->PropertyByID(ID);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case eBoolProperty: pOut = CREATE_PROP_TEMP(TBoolTemplate); break;
|
||||
case eByteProperty: pOut = CREATE_PROP_TEMP(TByteTemplate); break;
|
||||
case eShortProperty: pOut = CREATE_PROP_TEMP(TShortTemplate); break;
|
||||
case eLongProperty: pOut = CREATE_PROP_TEMP(TLongTemplate); break;
|
||||
case eFloatProperty: pOut = CREATE_PROP_TEMP(TFloatTemplate); break;
|
||||
case eStringProperty: pOut = CREATE_PROP_TEMP(TStringTemplate); break;
|
||||
case eVector3Property: pOut = CREATE_PROP_TEMP(TVector3Template); break;
|
||||
case eColorProperty: pOut = CREATE_PROP_TEMP(TColorTemplate); break;
|
||||
case eSoundProperty: pOut = CREATE_PROP_TEMP(TSoundTemplate); break;
|
||||
case eAssetProperty: pOut = CREATE_PROP_TEMP(CAssetTemplate); break;
|
||||
case eCharacterProperty: pOut = CREATE_PROP_TEMP(TCharacterTemplate); break;
|
||||
case eMayaSplineProperty: pOut = CREATE_PROP_TEMP(TMayaSplineTemplate); break;
|
||||
case eEnumProperty: pOut = CREATE_PROP_TEMP(CEnumTemplate); break;
|
||||
case eBitfieldProperty: pOut = CREATE_PROP_TEMP(CBitfieldTemplate); break;
|
||||
case eArrayProperty: pOut = CREATE_PROP_TEMP(CArrayTemplate); break;
|
||||
case eStructProperty: pOut = CREATE_PROP_TEMP(CStructTemplate); break;
|
||||
}
|
||||
|
||||
if (pOut)
|
||||
pStruct->mSubProperties.push_back(pOut);
|
||||
|
||||
return pOut;
|
||||
}
|
||||
|
||||
void CTemplateLoader::LoadStructTemplate(const TString& rkTemplateFileName, CStructTemplate *pStruct)
|
||||
CStructPropertyNew* CTemplateLoader::LoadStructArchetype(const TString& rkTemplateFileName)
|
||||
{
|
||||
// Check whether this struct has already been read
|
||||
auto it = mpMaster->mStructTemplates.find(rkTemplateFileName);
|
||||
CStructTemplate *pSource = (it == mpMaster->mStructTemplates.end() ? nullptr : it->second);
|
||||
CStructPropertyNew* pArchetype = (it == mpMaster->mStructTemplates.end() ? nullptr : it->second);
|
||||
|
||||
// If the source hasn't been read yet, then we read it and add it to master's list
|
||||
if (!pSource)
|
||||
// If the struct template hasn't been read yet, then we read it and add it to master's list
|
||||
if (!pArchetype)
|
||||
{
|
||||
XMLDocument Doc;
|
||||
OpenXML(mskTemplatesDir + mMasterDir + rkTemplateFileName, Doc);
|
||||
|
||||
if (!Doc.Error())
|
||||
{
|
||||
XMLElement *pRootElem;
|
||||
pArchetype = TPropCast<CStructPropertyNew>(
|
||||
IPropertyNew::Create(EPropertyTypeNew::Struct,
|
||||
nullptr,
|
||||
mpMaster,
|
||||
nullptr, false)
|
||||
);
|
||||
ASSERT(pArchetype != nullptr);
|
||||
|
||||
if (pStruct->Type() == eStructProperty)
|
||||
XMLElement* pRootElem = Doc.FirstChildElement("struct");
|
||||
ASSERT(pRootElem);
|
||||
|
||||
TString TypeAttr = TString(pRootElem->Attribute("type")).ToLower();
|
||||
ASSERT(!TypeAttr.IsEmpty())
|
||||
|
||||
if (TypeAttr == "single")
|
||||
pArchetype->mFlags |= EPropertyFlag::IsAtomic;
|
||||
|
||||
pArchetype->mFlags |= EPropertyFlag::IsArchetype;
|
||||
pArchetype->mTemplateFileName = rkTemplateFileName;
|
||||
pArchetype->mName = rkTemplateFileName.GetFileName(false);
|
||||
|
||||
#if 0
|
||||
if (pArchetype->mTypeName.Contains("Struct"))
|
||||
{
|
||||
pSource = new CStructTemplate(-1, nullptr, mpMaster);
|
||||
pRootElem = Doc.FirstChildElement("struct");
|
||||
|
||||
if (!pRootElem)
|
||||
{
|
||||
Log::Error(rkTemplateFileName + ": There is no root \"struct\" element");
|
||||
return;
|
||||
}
|
||||
|
||||
TString TypeAttr = TString(pRootElem->Attribute("type")).ToLower();
|
||||
|
||||
if (TypeAttr.IsEmpty())
|
||||
{
|
||||
Log::Error(rkTemplateFileName + ": There is no struct type specified");
|
||||
return;
|
||||
}
|
||||
|
||||
pSource->mIsSingleProperty = (TypeAttr == "single" ? true : false);
|
||||
pArchetype->mSourceFile = "Structs/" +
|
||||
GetGameShortName(mGame) +
|
||||
"-" +
|
||||
pArchetype->mTypeName +
|
||||
".xml";
|
||||
pArchetype->mTypeName = pArchetype->mSourceFile.GetFileName(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
else if (pStruct->Type() == eArrayProperty)
|
||||
{
|
||||
pSource = new CArrayTemplate(-1, nullptr, mpMaster);
|
||||
pRootElem = Doc.FirstChildElement("array");
|
||||
|
||||
if (!pRootElem)
|
||||
{
|
||||
Log::Error(rkTemplateFileName + ": There is no root \"array\" element");
|
||||
return;
|
||||
}
|
||||
}
|
||||
pSource->mSourceFile = rkTemplateFileName;
|
||||
pSource->mTypeName = pSource->mSourceFile.GetFileName(false);
|
||||
|
||||
// ignore struct name attribute - archetypes should always have the type name
|
||||
#if 0
|
||||
TString NameAttr = TString(pRootElem->Attribute("name"));
|
||||
if (!NameAttr.IsEmpty())
|
||||
pSource->mName = NameAttr;
|
||||
pArchetype->mName = NameAttr;
|
||||
#endif
|
||||
|
||||
// Read sub-properties
|
||||
XMLElement *pSubPropsElem = pRootElem->FirstChildElement("properties");
|
||||
XMLElement* pSubPropsElem = pRootElem->FirstChildElement("properties");
|
||||
ASSERT(pSubPropsElem);
|
||||
|
||||
if (pSubPropsElem)
|
||||
{
|
||||
LoadProperties(pSubPropsElem, nullptr, pSource, rkTemplateFileName);
|
||||
mpMaster->mStructTemplates[rkTemplateFileName] = pSource;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Log::Error(rkTemplateFileName + ": There is no \"properties\" block element");
|
||||
delete pSource;
|
||||
pSource = nullptr;
|
||||
}
|
||||
LoadProperties(pSubPropsElem, nullptr, pArchetype, rkTemplateFileName);
|
||||
mpMaster->mStructTemplates[rkTemplateFileName] = pArchetype;
|
||||
pArchetype->PostInitialize();
|
||||
}
|
||||
}
|
||||
|
||||
// Copy source to the new struct template
|
||||
if (pSource)
|
||||
pStruct->CopyStructData(pSource);
|
||||
ASSERT(pArchetype != nullptr);
|
||||
return pArchetype;
|
||||
}
|
||||
|
||||
void CTemplateLoader::LoadEnumTemplate(const TString& rkTemplateFileName, CEnumTemplate *pEnum)
|
||||
CEnumProperty* CTemplateLoader::LoadEnumArchetype(const TString& rkTemplateFileName, bool bIsChoice)
|
||||
{
|
||||
XMLDocument Doc;
|
||||
OpenXML(mskTemplatesDir + mMasterDir + rkTemplateFileName, Doc);
|
||||
// Check whether this struct has already been read
|
||||
auto it = mpMaster->mEnumTemplates.find(rkTemplateFileName);
|
||||
CEnumProperty* pArchetype = (it == mpMaster->mEnumTemplates.end() ? nullptr : it->second);
|
||||
|
||||
if (!Doc.Error())
|
||||
// If the enum template hasn't been read yet, then we read it and add it to master's list
|
||||
if (!pArchetype)
|
||||
{
|
||||
pEnum->mSourceFile = rkTemplateFileName;
|
||||
XMLElement *pRootElem = Doc.FirstChildElement("enum");
|
||||
XMLDocument Doc;
|
||||
OpenXML(mskTemplatesDir + mMasterDir + rkTemplateFileName, Doc);
|
||||
|
||||
if (!pRootElem)
|
||||
if (!Doc.Error())
|
||||
{
|
||||
Log::Error(rkTemplateFileName + ": There is no root \"enum\" element");
|
||||
return;
|
||||
// use static_cast so this code works for both enum and choice
|
||||
pArchetype = static_cast<CEnumProperty*>(
|
||||
IPropertyNew::Create(bIsChoice ? EPropertyTypeNew::Choice : EPropertyTypeNew::Enum,
|
||||
nullptr,
|
||||
mpMaster,
|
||||
nullptr,
|
||||
false)
|
||||
);
|
||||
ASSERT(pArchetype != nullptr);
|
||||
|
||||
pArchetype->mFlags |= EPropertyFlag::IsArchetype;
|
||||
pArchetype->mSourceFile = rkTemplateFileName;
|
||||
|
||||
XMLElement* pRootElem = Doc.FirstChildElement("enum");
|
||||
ASSERT(pRootElem);
|
||||
|
||||
XMLElement *pEnumers = pRootElem->FirstChildElement("enumerators");
|
||||
ASSERT(pEnumers);
|
||||
|
||||
LoadEnumerators(pEnumers, pArchetype, rkTemplateFileName);
|
||||
mpMaster->mEnumTemplates[rkTemplateFileName] = pArchetype;
|
||||
pArchetype->PostInitialize();
|
||||
}
|
||||
|
||||
XMLElement *pEnumers = pRootElem->FirstChildElement("enumerators");
|
||||
|
||||
if (pEnumers)
|
||||
LoadEnumerators(pEnumers, pEnum, rkTemplateFileName);
|
||||
|
||||
else
|
||||
Log::Error(rkTemplateFileName + ": There is no \"enumerators\" block element");
|
||||
|
||||
}
|
||||
|
||||
ASSERT(pArchetype != nullptr);
|
||||
return pArchetype;
|
||||
}
|
||||
|
||||
void CTemplateLoader::LoadBitfieldTemplate(const TString& rkTemplateFileName, CBitfieldTemplate *pBitfield)
|
||||
CFlagsProperty* CTemplateLoader::LoadFlagsArchetype(const TString& rkTemplateFileName)
|
||||
{
|
||||
XMLDocument Doc;
|
||||
OpenXML(mskTemplatesDir + mMasterDir + rkTemplateFileName, Doc);
|
||||
// Check whether this struct has already been read
|
||||
auto it = mpMaster->mFlagsTemplates.find(rkTemplateFileName);
|
||||
CFlagsProperty* pArchetype = (it == mpMaster->mFlagsTemplates.end() ? nullptr : it->second);
|
||||
|
||||
if (!Doc.Error())
|
||||
// If the enum template hasn't been read yet, then we read it and add it to master's list
|
||||
if (!pArchetype)
|
||||
{
|
||||
pBitfield->mSourceFile = rkTemplateFileName;
|
||||
XMLElement *pRootElem = Doc.FirstChildElement("bitfield");
|
||||
XMLDocument Doc;
|
||||
OpenXML(mskTemplatesDir + mMasterDir + rkTemplateFileName, Doc);
|
||||
|
||||
if (!pRootElem)
|
||||
if (!Doc.Error())
|
||||
{
|
||||
Log::Error(rkTemplateFileName + ": There is no root \"bitfield\" element");
|
||||
return;
|
||||
pArchetype = TPropCast<CFlagsProperty>(
|
||||
IPropertyNew::Create(EPropertyTypeNew::Flags,
|
||||
nullptr,
|
||||
mpMaster,
|
||||
nullptr, false)
|
||||
);
|
||||
ASSERT(pArchetype != nullptr);
|
||||
|
||||
pArchetype->mFlags |= EPropertyFlag::IsArchetype;
|
||||
pArchetype->mSourceFile = rkTemplateFileName;
|
||||
|
||||
XMLElement *pRootElem = Doc.FirstChildElement("bitfield");
|
||||
ASSERT(pRootElem);
|
||||
|
||||
XMLElement *pFlags = pRootElem->FirstChildElement("flags");
|
||||
ASSERT(pFlags);
|
||||
|
||||
LoadBitFlags(pFlags, pArchetype, rkTemplateFileName);
|
||||
mpMaster->mFlagsTemplates[rkTemplateFileName] = pArchetype;
|
||||
pArchetype->PostInitialize();
|
||||
}
|
||||
|
||||
XMLElement *pFlags = pRootElem->FirstChildElement("flags");
|
||||
|
||||
if (pFlags)
|
||||
LoadBitFlags(pFlags, pBitfield, rkTemplateFileName);
|
||||
|
||||
else
|
||||
Log::Error(rkTemplateFileName + ": There is no \"flags\" block element");
|
||||
}
|
||||
|
||||
ASSERT(pArchetype != nullptr);
|
||||
return pArchetype;
|
||||
}
|
||||
|
||||
void CTemplateLoader::LoadProperties(XMLElement *pPropertiesElem, CScriptTemplate *pScript, CStructTemplate *pStruct, const TString& rkTemplateName)
|
||||
void CTemplateLoader::LoadProperties(XMLElement *pPropertiesElem, CScriptTemplate *pScript, CStructPropertyNew* pStruct, const TString& rkTemplateName)
|
||||
{
|
||||
XMLElement *pChild = pPropertiesElem->FirstChildElement();
|
||||
|
||||
|
@ -359,12 +541,9 @@ void CTemplateLoader::LoadProperties(XMLElement *pPropertiesElem, CScriptTemplat
|
|||
|
||||
pChild = pChild->NextSiblingElement();
|
||||
}
|
||||
|
||||
pStruct->mVersionPropertyCounts.resize(mpMaster->NumGameVersions());
|
||||
pStruct->DetermineVersionPropertyCounts();
|
||||
}
|
||||
|
||||
void CTemplateLoader::LoadEnumerators(XMLElement *pEnumeratorsElem, CEnumTemplate *pTemp, const TString& rkTemplateName)
|
||||
void CTemplateLoader::LoadEnumerators(XMLElement *pEnumeratorsElem, CEnumProperty* pEnum, const TString& rkTemplateName)
|
||||
{
|
||||
XMLElement *pChild = pEnumeratorsElem->FirstChildElement("enumerator");
|
||||
|
||||
|
@ -376,10 +555,7 @@ void CTemplateLoader::LoadEnumerators(XMLElement *pEnumeratorsElem, CEnumTemplat
|
|||
if (pkID && pkName)
|
||||
{
|
||||
u32 EnumeratorID = TString(pkID).ToInt32();
|
||||
pTemp->mEnumerators.push_back(CEnumTemplate::SEnumerator(pkName, EnumeratorID));
|
||||
|
||||
if (EnumeratorID > 0xFF)
|
||||
pTemp->mUsesHashes = true;
|
||||
pEnum->mValues.push_back(CEnumProperty::SEnumValue(pkName, EnumeratorID));
|
||||
}
|
||||
|
||||
else
|
||||
|
@ -395,7 +571,7 @@ void CTemplateLoader::LoadEnumerators(XMLElement *pEnumeratorsElem, CEnumTemplat
|
|||
}
|
||||
}
|
||||
|
||||
void CTemplateLoader::LoadBitFlags(XMLElement *pFlagsElem, CBitfieldTemplate *pTemp, const TString& templateName)
|
||||
void CTemplateLoader::LoadBitFlags(XMLElement *pFlagsElem, CFlagsProperty* pFlags, const TString& kTemplateName)
|
||||
{
|
||||
XMLElement *pChild = pFlagsElem->FirstChildElement("flag");
|
||||
|
||||
|
@ -405,11 +581,11 @@ void CTemplateLoader::LoadBitFlags(XMLElement *pFlagsElem, CBitfieldTemplate *pT
|
|||
const char *pkName = pChild->Attribute("name");
|
||||
|
||||
if (pkMask && pkName)
|
||||
pTemp->mBitFlags.push_back(CBitfieldTemplate::SBitFlag(pkName, TString(pkMask).ToInt32()));
|
||||
pFlags->mBitFlags.push_back(CFlagsProperty::SBitFlag(pkName, TString(pkMask).ToInt32()));
|
||||
|
||||
else
|
||||
{
|
||||
TString LogErrorBase = templateName + ": Couldn't parse bit flag; ";
|
||||
TString LogErrorBase = kTemplateName + ": Couldn't parse bit flag; ";
|
||||
|
||||
if (!pkMask && pkName) Log::Error(LogErrorBase + "no mask (" + pkName + ")");
|
||||
else if (pkMask && !pkName) Log::Error(LogErrorBase + "no name (mask " + pkMask + ")");
|
||||
|
@ -420,24 +596,27 @@ void CTemplateLoader::LoadBitFlags(XMLElement *pFlagsElem, CBitfieldTemplate *pT
|
|||
}
|
||||
}
|
||||
|
||||
enum class ETest
|
||||
{
|
||||
ValueA = (true ? 0 : (u32) reinterpret_cast<u64>("ValueA"))
|
||||
};
|
||||
|
||||
// ************ SCRIPT OBJECT ************
|
||||
CScriptTemplate* CTemplateLoader::LoadScriptTemplate(XMLDocument *pDoc, const TString& rkTemplateName, u32 ObjectID)
|
||||
{
|
||||
CScriptTemplate *pScript = new CScriptTemplate(mpMaster);
|
||||
pScript->mObjectID = ObjectID;
|
||||
pScript->mpBaseStruct = new CStructTemplate(-1, pScript, mpMaster);
|
||||
pScript->mSourceFile = rkTemplateName;
|
||||
|
||||
IPropertyNew* pBaseStruct = IPropertyNew::Create(EPropertyTypeNew::Struct, nullptr, mpMaster, pScript);
|
||||
pScript->mpProperties = std::make_unique<CStructPropertyNew>( *TPropCast<CStructPropertyNew>(pBaseStruct) );
|
||||
|
||||
XMLElement *pRoot = pDoc->FirstChildElement("ScriptTemplate");
|
||||
|
||||
// Name
|
||||
XMLElement *pNameElem = pRoot->FirstChildElement("name");
|
||||
|
||||
if (pNameElem)
|
||||
{
|
||||
pScript->mTemplateName = pNameElem->GetText();
|
||||
pScript->mpBaseStruct->SetName(pScript->mTemplateName);
|
||||
}
|
||||
ASSERT(pNameElem);
|
||||
pScript->mpProperties->mName = pNameElem->GetText();
|
||||
|
||||
// Modules
|
||||
XMLElement *pModulesElem = pRoot->FirstChildElement("modules");
|
||||
|
@ -457,7 +636,7 @@ CScriptTemplate* CTemplateLoader::LoadScriptTemplate(XMLDocument *pDoc, const TS
|
|||
XMLElement *pPropsElem = pRoot->FirstChildElement("properties");
|
||||
|
||||
if (pPropsElem)
|
||||
LoadProperties(pPropsElem, pScript, pScript->mpBaseStruct, rkTemplateName);
|
||||
LoadProperties(pPropsElem, pScript, pScript->Properties(), rkTemplateName);
|
||||
else
|
||||
Log::Error(rkTemplateName + ": There is no \"properties\" block element");
|
||||
|
||||
|
@ -565,7 +744,7 @@ CScriptTemplate* CTemplateLoader::LoadScriptTemplate(XMLDocument *pDoc, const TS
|
|||
// Validate property asset
|
||||
if (Asset.AssetSource == CScriptTemplate::SEditorAsset::eProperty)
|
||||
{
|
||||
if (!pScript->mpBaseStruct->HasProperty(Asset.AssetLocation))
|
||||
if (!pScript->mpProperties->ChildByIDString(Asset.AssetLocation))
|
||||
{
|
||||
Log::Error(rkTemplateName + ": Invalid property for " + Type + " asset: " + ID);
|
||||
pAsset = pAsset->NextSiblingElement();
|
||||
|
@ -609,12 +788,12 @@ CScriptTemplate* CTemplateLoader::LoadScriptTemplate(XMLDocument *pDoc, const TS
|
|||
Attachment.AttachType = eAttach;
|
||||
|
||||
// Validate property
|
||||
IPropertyTemplate *pProp = pScript->mpBaseStruct->PropertyByIDString(Attachment.AttachProperty);
|
||||
IPropertyNew* pProp = pScript->mpProperties->ChildByIDString(Attachment.AttachProperty);
|
||||
|
||||
if (!pProp)
|
||||
Log::Error(rkTemplateName + ": Invalid property for attachment " + TString::FromInt32(AttachIdx) + ": " + Attachment.AttachProperty);
|
||||
else if (pProp->Type() != eCharacterProperty && (pProp->Type() != eAssetProperty || !static_cast<CAssetTemplate*>(pProp)->TypeFilter().Accepts(eModel)))
|
||||
Log::Error(rkTemplateName + ": Property referred to by attachment " + TString::FromInt32(AttachIdx) + " is not an attachable asset! Must be a file property that accepts CMDLs, or a character property.");
|
||||
else if (pProp->Type() != EPropertyTypeNew::AnimationSet && (pProp->Type() != EPropertyTypeNew::Asset || !TPropCast<CAssetProperty>(pProp)->GetTypeFilter().Accepts(eModel)))
|
||||
Log::Error(rkTemplateName + ": Property referred to by attachment " + TString::FromInt32(AttachIdx) + " is not an attachable asset! Must be a file property that accepts CMDLs, or an animation set property.");
|
||||
|
||||
else
|
||||
{
|
||||
|
@ -746,6 +925,7 @@ CScriptTemplate* CTemplateLoader::LoadScriptTemplate(XMLDocument *pDoc, const TS
|
|||
}
|
||||
}
|
||||
|
||||
pScript->PostLoad();
|
||||
return pScript;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
#include "Core/Resource/Script/CMasterTemplate.h"
|
||||
#include "Core/Resource/Script/CScriptTemplate.h"
|
||||
#include "Core/Resource/Script/IPropertyNew.h"
|
||||
#include "Core/Resource/Script/Property/CEnumProperty.h"
|
||||
#include "Core/Resource/Script/Property/CFlagsProperty.h"
|
||||
#include <tinyxml2.h>
|
||||
|
||||
class CTemplateLoader
|
||||
|
@ -20,23 +23,23 @@ class CTemplateLoader
|
|||
: mTemplatesDir(rkTemplatesDir) {}
|
||||
|
||||
// Load Property
|
||||
IPropertyTemplate* LoadProperty(tinyxml2::XMLElement *pElem, CScriptTemplate *pScript, CStructTemplate *pParentStruct, const TString& rkTemplateName);
|
||||
IPropertyTemplate* CreateProperty(u32 ID, EPropertyType Type, const TString& rkName, CScriptTemplate *pScript, CStructTemplate *pStruct);
|
||||
IPropertyNew* LoadProperty(tinyxml2::XMLElement* pElem, CScriptTemplate* pScript, CStructPropertyNew* pParentStruct, const TString& rkTemplateName);
|
||||
IPropertyNew* CreateProperty(u32 ID, EPropertyTypeNew Type, const TString& rkName, CScriptTemplate* pScript, CStructPropertyNew* pStruct);
|
||||
|
||||
void LoadStructTemplate(const TString& rkTemplateFileName, CStructTemplate *pStruct);
|
||||
void LoadEnumTemplate(const TString& rkTemplateFileName, CEnumTemplate *pEnum);
|
||||
void LoadBitfieldTemplate(const TString& rkTemplateFileName, CBitfieldTemplate *pBitfield);
|
||||
CStructPropertyNew* LoadStructArchetype(const TString& rkTemplateFileName);
|
||||
CEnumProperty* LoadEnumArchetype(const TString& rkTemplateFileName, bool bIsChoice);
|
||||
CFlagsProperty* LoadFlagsArchetype(const TString& rkTemplateFileName);
|
||||
|
||||
void LoadProperties(tinyxml2::XMLElement *pPropertiesElem, CScriptTemplate *pScript, CStructTemplate *pStruct, const TString& rkTemplateName);
|
||||
void LoadEnumerators(tinyxml2::XMLElement *pEnumeratorsElem, CEnumTemplate *pEnum, const TString& rkTemplateName);
|
||||
void LoadBitFlags(tinyxml2::XMLElement *pFlagsElem, CBitfieldTemplate *pBitfield, const TString& rkTemplateName);
|
||||
void LoadProperties(tinyxml2::XMLElement* pPropertiesElem, CScriptTemplate* pScript, CStructPropertyNew* pStruct, const TString& rkTemplateName);
|
||||
void LoadEnumerators(tinyxml2::XMLElement* pEnumeratorsElem, CEnumProperty* pEnum, const TString& rkTemplateName);
|
||||
void LoadBitFlags(tinyxml2::XMLElement* pFlagsElem, CFlagsProperty* pFlags, const TString& rkTemplateName);
|
||||
|
||||
// Load Script Object
|
||||
CScriptTemplate* LoadScriptTemplate(tinyxml2::XMLDocument *pDoc, const TString& rkTemplateName, u32 ObjectID);
|
||||
CScriptTemplate* LoadScriptTemplate(tinyxml2::XMLDocument* pDoc, const TString& rkTemplateName, u32 ObjectID);
|
||||
|
||||
// Load Master
|
||||
CMasterTemplate* LoadGameInfo(tinyxml2::XMLNode *pNode);
|
||||
void LoadMasterTemplate(tinyxml2::XMLDocument *pDoc, CMasterTemplate *pMaster);
|
||||
CMasterTemplate* LoadGameInfo(tinyxml2::XMLNode* pNode);
|
||||
void LoadMasterTemplate(tinyxml2::XMLDocument* pDoc, CMasterTemplate* pMaster);
|
||||
|
||||
// Utility
|
||||
static void OpenXML(const TString& rkPath, tinyxml2::XMLDocument& rDoc);
|
||||
|
@ -46,7 +49,7 @@ public:
|
|||
static void LoadGameList();
|
||||
static void LoadGameTemplates(EGame Game);
|
||||
static void LoadAllGames();
|
||||
static void LoadPropertyList(tinyxml2::XMLDocument *pDoc, const TString& rkListName);
|
||||
static void LoadPropertyList(tinyxml2::XMLDocument* pDoc, const TString& rkListName);
|
||||
};
|
||||
|
||||
#endif // CTEMPLATELOADER_H
|
||||
|
|
|
@ -88,7 +88,7 @@ SMessage CMasterTemplate::MessageByIndex(u32 Index)
|
|||
return (std::next(it, Index))->second;
|
||||
}
|
||||
|
||||
CStructTemplate* CMasterTemplate::StructAtSource(const TString& rkSource)
|
||||
CStructPropertyNew* CMasterTemplate::StructAtSource(const TString& rkSource)
|
||||
{
|
||||
auto InfoIt = mStructTemplates.find(rkSource);
|
||||
|
||||
|
@ -149,38 +149,44 @@ TString CMasterTemplate::PropertyName(u32 PropertyID)
|
|||
return "Unknown";
|
||||
}
|
||||
|
||||
u32 CMasterTemplate::CreatePropertyID(IPropertyTemplate *pTemp)
|
||||
// Removing these functions for now. I'm not sure of the best way to go about implementing them under the new system yet.
|
||||
u32 CMasterTemplate::CreatePropertyID(IPropertyNew* pProp)
|
||||
{
|
||||
// MP1 properties don't have IDs so we can use this function to create one to track instances of a particular property.
|
||||
// To ensure the IDs are unique we'll create a hash using two things: the struct source file and the ID string (relative to the struct).
|
||||
TString IDString = pTemp->IDString(false);
|
||||
TString Source;
|
||||
CStructTemplate *pStruct = pTemp->Parent();
|
||||
//
|
||||
// Note for properties that have accurate names we can apply a CRC32 to the name to generate a hash equivalent to what the hash would
|
||||
// have been if this were an MP2/3 property. In an ideal world where every property was named, this would be great. However, we have a
|
||||
// lot of properties that have generic names like "Unknown", and they should be tracked separately as they are in all likelihood
|
||||
// different properties. So for this reason, we only want to track sub-instances of one property under one ID.
|
||||
TString IDString = pProp->Archetype()->IDString(true);
|
||||
TString TemplateFile = pProp->GetTemplateFileName();
|
||||
|
||||
while (pStruct)
|
||||
{
|
||||
Source = pStruct->SourceFile();
|
||||
if (!Source.IsEmpty()) break;
|
||||
IDString.Prepend(pStruct->IDString(false) + ":");
|
||||
pStruct = pStruct->Parent();
|
||||
}
|
||||
|
||||
return IDString.Hash32() * Source.Hash32();
|
||||
CCRC32 Hash;
|
||||
Hash.Hash(*IDString);
|
||||
Hash.Hash(*TemplateFile);
|
||||
return Hash.Digest();
|
||||
}
|
||||
|
||||
void CMasterTemplate::AddProperty(IPropertyTemplate *pTemp, const TString& rkTemplateName /*= ""*/)
|
||||
void CMasterTemplate::AddProperty(IPropertyNew* pProp, const TString& rkTemplateName /*= ""*/)
|
||||
{
|
||||
u32 ID;
|
||||
|
||||
if (pTemp->Game() >= eEchoesDemo)
|
||||
ID = pTemp->PropertyID();
|
||||
if (pProp->Game() >= eEchoesDemo)
|
||||
ID = pProp->ID();
|
||||
|
||||
// Use a different ID for MP1
|
||||
else
|
||||
{
|
||||
// For MP1 we only really need to track properties that come from struct templates.
|
||||
if (!pTemp->IsFromStructTemplate()) return;
|
||||
else ID = CreatePropertyID(pTemp);
|
||||
IPropertyNew* pArchetype = pProp->Archetype();
|
||||
|
||||
if (!pArchetype ||
|
||||
pArchetype->ScriptTemplate() != nullptr ||
|
||||
pArchetype->RootParent()->Type() != EPropertyTypeNew::Struct)
|
||||
return;
|
||||
|
||||
ID = CreatePropertyID(pProp);
|
||||
}
|
||||
|
||||
auto it = smIDMap.find(ID);
|
||||
|
@ -189,7 +195,7 @@ void CMasterTemplate::AddProperty(IPropertyTemplate *pTemp, const TString& rkTem
|
|||
if (it != smIDMap.end())
|
||||
{
|
||||
SPropIDInfo& rInfo = it->second;
|
||||
rInfo.PropertyList.push_back(pTemp);
|
||||
rInfo.PropertyList.push_back(pProp);
|
||||
|
||||
if (!rkTemplateName.IsEmpty())
|
||||
{
|
||||
|
@ -214,15 +220,15 @@ void CMasterTemplate::AddProperty(IPropertyTemplate *pTemp, const TString& rkTem
|
|||
{
|
||||
SPropIDInfo Info;
|
||||
if (!rkTemplateName.IsEmpty()) Info.XMLList.push_back(rkTemplateName);
|
||||
Info.PropertyList.push_back(pTemp);
|
||||
Info.PropertyList.push_back(pProp);
|
||||
smIDMap[ID] = Info;
|
||||
}
|
||||
}
|
||||
|
||||
void CMasterTemplate::RenameProperty(IPropertyTemplate *pTemp, const TString& rkNewName)
|
||||
void CMasterTemplate::RenameProperty(IPropertyNew* pProp, const TString& rkNewName)
|
||||
{
|
||||
u32 ID = pTemp->PropertyID();
|
||||
if (ID <= 0xFF) ID = CreatePropertyID(pTemp);
|
||||
u32 ID = pProp->ID();
|
||||
if (ID <= 0xFF) ID = CreatePropertyID(pProp);
|
||||
RenameProperty(ID, rkNewName);
|
||||
}
|
||||
|
||||
|
@ -245,10 +251,10 @@ void CMasterTemplate::RenameProperty(u32 ID, const TString& rkNewName)
|
|||
{
|
||||
const SPropIDInfo& rkInfo = InfoIt->second;
|
||||
|
||||
for (u32 iTemp = 0; iTemp < rkInfo.PropertyList.size(); iTemp++)
|
||||
for (u32 PropertyIdx = 0; PropertyIdx < rkInfo.PropertyList.size(); PropertyIdx++)
|
||||
{
|
||||
if (Original.IsEmpty() || rkInfo.PropertyList[iTemp]->Name() == Original)
|
||||
rkInfo.PropertyList[iTemp]->SetName(rkNewName);
|
||||
if (Original.IsEmpty() || rkInfo.PropertyList[PropertyIdx]->Name() == Original)
|
||||
rkInfo.PropertyList[PropertyIdx]->SetName(rkNewName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -264,10 +270,10 @@ void CMasterTemplate::XMLsUsingID(u32 ID, std::vector<TString>& rOutList)
|
|||
}
|
||||
}
|
||||
|
||||
const std::vector<IPropertyTemplate*>* CMasterTemplate::TemplatesWithMatchingID(IPropertyTemplate *pTemp)
|
||||
const std::vector<IPropertyNew*>* CMasterTemplate::TemplatesWithMatchingID(IPropertyNew* pProp)
|
||||
{
|
||||
u32 ID = pTemp->PropertyID();
|
||||
if (ID <= 0xFF) ID = CreatePropertyID(pTemp);
|
||||
u32 ID = pProp->ID();
|
||||
if (ID <= 0xFF) ID = CreatePropertyID(pProp);
|
||||
|
||||
auto InfoIt = smIDMap.find(ID);
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "CLink.h"
|
||||
#include "CScriptTemplate.h"
|
||||
#include "Core/Resource/Script/Property/Properties.h"
|
||||
#include <Common/EGame.h>
|
||||
#include <Common/types.h>
|
||||
#include <map>
|
||||
|
@ -19,7 +20,9 @@ class CMasterTemplate
|
|||
bool mFullyLoaded;
|
||||
|
||||
std::vector<TString> mGameVersions;
|
||||
std::map<TString, CStructTemplate*> mStructTemplates;
|
||||
std::map<TString, CStructPropertyNew*> mStructTemplates;
|
||||
std::map<TString, CEnumProperty*> mEnumTemplates;
|
||||
std::map<TString, CFlagsProperty*> mFlagsTemplates;
|
||||
|
||||
std::map<u32, CScriptTemplate*> mTemplates;
|
||||
std::map<u32, SState> mStates;
|
||||
|
@ -28,7 +31,7 @@ class CMasterTemplate
|
|||
struct SPropIDInfo
|
||||
{
|
||||
std::vector<TString> XMLList; // List of script/struct templates that use this ID
|
||||
std::vector<IPropertyTemplate*> PropertyList; // List of all properties that use this ID
|
||||
std::vector<IPropertyNew*> PropertyList; // List of all properties that use this ID
|
||||
};
|
||||
static std::map<u32, SPropIDInfo> smIDMap;
|
||||
static std::map<EGame, CMasterTemplate*> smMasterMap;
|
||||
|
@ -48,7 +51,7 @@ public:
|
|||
SMessage MessageByID(u32 MessageID);
|
||||
SMessage MessageByID(const CFourCC& MessageID);
|
||||
SMessage MessageByIndex(u32 Index);
|
||||
CStructTemplate* StructAtSource(const TString& rkSource);
|
||||
CStructPropertyNew* StructAtSource(const TString& rkSource);
|
||||
|
||||
// Inline Accessors
|
||||
inline EGame Game() const { return mGame; }
|
||||
|
@ -66,12 +69,12 @@ public:
|
|||
static TString FindGameName(EGame Game);
|
||||
static EGame FindGameForName(const TString& rkName);
|
||||
static TString PropertyName(u32 PropertyID);
|
||||
static u32 CreatePropertyID(IPropertyTemplate *pTemp);
|
||||
static void AddProperty(IPropertyTemplate *pTemp, const TString& rkTemplateName = "");
|
||||
static void RenameProperty(IPropertyTemplate *pTemp, const TString& rkNewName);
|
||||
static u32 CreatePropertyID(IPropertyNew *pTemp);
|
||||
static void AddProperty(IPropertyNew *pTemp, const TString& rkTemplateName = "");
|
||||
static void RenameProperty(IPropertyNew *pTemp, const TString& rkNewName);
|
||||
static void RenameProperty(u32 ID, const TString& rkNewName);
|
||||
static void XMLsUsingID(u32 ID, std::vector<TString>& rOutList);
|
||||
static const std::vector<IPropertyTemplate*>* TemplatesWithMatchingID(IPropertyTemplate *pTemp);
|
||||
static const std::vector<IPropertyNew*>* TemplatesWithMatchingID(IPropertyNew *pTemp);
|
||||
};
|
||||
|
||||
#endif // CMASTERTEMPLATE_H
|
||||
|
|
|
@ -13,19 +13,29 @@ CScriptObject::CScriptObject(u32 InstanceID, CGameArea *pArea, CScriptLayer *pLa
|
|||
, mIsCheckingNearVisibleActivation(false)
|
||||
{
|
||||
mpTemplate->AddObject(this);
|
||||
mpProperties = (CPropertyStruct*) pTemplate->BaseStruct()->InstantiateProperty(this, nullptr);
|
||||
|
||||
mpInstanceName = mpTemplate->FindInstanceName(mpProperties);
|
||||
mpPosition = mpTemplate->FindPosition(mpProperties);
|
||||
mpRotation = mpTemplate->FindRotation(mpProperties);
|
||||
mpScale = mpTemplate->FindScale(mpProperties);
|
||||
mpActive = mpTemplate->FindActive(mpProperties);
|
||||
mpLightParameters = mpTemplate->FindLightParameters(mpProperties);
|
||||
// Init properties
|
||||
CStructPropertyNew* pProperties = pTemplate->Properties();
|
||||
u32 PropertiesSize = pProperties->DataSize();
|
||||
mPropertyData.resize( PropertiesSize );
|
||||
pProperties->Construct( mPropertyData.data() );
|
||||
|
||||
mInstanceName = CStringRef(this, pTemplate->NameProperty());
|
||||
mPosition = CVectorRef(this, pTemplate->PositionProperty());
|
||||
mRotation = CVectorRef(this, pTemplate->RotationProperty());
|
||||
mScale = CVectorRef(this, pTemplate->ScaleProperty());
|
||||
mActive = CBoolRef(this, pTemplate->ActiveProperty());
|
||||
mLightParameters = CStructRef(this, pTemplate->LightParametersProperty());
|
||||
}
|
||||
|
||||
CScriptObject::~CScriptObject()
|
||||
{
|
||||
if (mpProperties) delete mpProperties;
|
||||
if (!mPropertyData.empty())
|
||||
{
|
||||
mpTemplate->Properties()->Destruct( mPropertyData.data() );
|
||||
mPropertyData.clear();
|
||||
}
|
||||
|
||||
mpTemplate->RemoveObject(this);
|
||||
|
||||
// Note: Incoming links will be deleted by the sender.
|
||||
|
@ -34,6 +44,19 @@ CScriptObject::~CScriptObject()
|
|||
}
|
||||
|
||||
// ************ DATA MANIPULATION ************
|
||||
void CScriptObject::CopyProperties(CScriptObject* pObject)
|
||||
{
|
||||
ASSERT(pObject->Template() == Template());
|
||||
CSerialVersion Version(0, IArchive::skCurrentArchiveVersion, Template()->Game());
|
||||
|
||||
CVectorOutStream DataStream;
|
||||
CBasicBinaryWriter DataWriter(&DataStream, Version);
|
||||
Template()->Properties()->SerializeValue( pObject->PropertyData(), DataWriter );
|
||||
|
||||
CBasicBinaryReader DataReader(DataStream.Data(), DataStream.Size(), Version);
|
||||
Template()->Properties()->SerializeValue( PropertyData(), DataReader );
|
||||
}
|
||||
|
||||
void CScriptObject::EvaluateProperties()
|
||||
{
|
||||
EvaluateDisplayAsset();
|
||||
|
@ -43,12 +66,12 @@ CScriptObject::~CScriptObject()
|
|||
|
||||
void CScriptObject::EvaluateDisplayAsset()
|
||||
{
|
||||
mpDisplayAsset = mpTemplate->FindDisplayAsset(mpProperties, mActiveCharIndex, mActiveAnimIndex, mHasInGameModel);
|
||||
mpDisplayAsset = mpTemplate->FindDisplayAsset(PropertyData(), mActiveCharIndex, mActiveAnimIndex, mHasInGameModel);
|
||||
}
|
||||
|
||||
void CScriptObject::EvaluateCollisionModel()
|
||||
{
|
||||
mpCollision = mpTemplate->FindCollision(mpProperties);
|
||||
mpCollision = mpTemplate->FindCollision(PropertyData());
|
||||
}
|
||||
|
||||
void CScriptObject::EvaluateVolume()
|
||||
|
@ -57,15 +80,15 @@ void CScriptObject::EvaluateVolume()
|
|||
mVolumeScale = mpTemplate->VolumeScale(this);
|
||||
}
|
||||
|
||||
bool CScriptObject::IsEditorProperty(IProperty *pProp)
|
||||
bool CScriptObject::IsEditorProperty(IPropertyNew *pProp)
|
||||
{
|
||||
return ( (pProp == mpInstanceName) ||
|
||||
(pProp == mpPosition) ||
|
||||
(pProp == mpRotation) ||
|
||||
(pProp == mpScale) ||
|
||||
(pProp == mpActive) ||
|
||||
(pProp == mpLightParameters) ||
|
||||
(pProp->Parent() == mpLightParameters)
|
||||
return ( (pProp == mInstanceName.Property()) ||
|
||||
(pProp == mPosition.Property()) ||
|
||||
(pProp == mRotation.Property()) ||
|
||||
(pProp == mScale.Property()) ||
|
||||
(pProp == mActive.Property()) ||
|
||||
(pProp == mLightParameters.Property()) ||
|
||||
(pProp->Parent() == mLightParameters.Property())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
#ifndef CSCRIPTOBJECT_H
|
||||
#define CSCRIPTOBJECT_H
|
||||
|
||||
#include "IProperty.h"
|
||||
#include "IPropertyTemplate.h"
|
||||
#include "CScriptTemplate.h"
|
||||
#include "Core/Resource/Area/CGameArea.h"
|
||||
#include "Core/Resource/Model/CModel.h"
|
||||
#include "Core/Resource/CCollisionMeshGroup.h"
|
||||
#include "Core/Resource/Script/Property/Properties.h"
|
||||
|
||||
class CScriptLayer;
|
||||
class CLink;
|
||||
|
@ -30,14 +29,15 @@ class CScriptObject
|
|||
u32 mInstanceID;
|
||||
std::vector<CLink*> mOutLinks;
|
||||
std::vector<CLink*> mInLinks;
|
||||
CPropertyStruct *mpProperties;
|
||||
std::vector<char> mPropertyData;
|
||||
|
||||
CStringRef mInstanceName;
|
||||
CVectorRef mPosition;
|
||||
CVectorRef mRotation;
|
||||
CVectorRef mScale;
|
||||
CBoolRef mActive;
|
||||
CStructRef mLightParameters;
|
||||
|
||||
TStringProperty *mpInstanceName;
|
||||
TVector3Property *mpPosition;
|
||||
TVector3Property *mpRotation;
|
||||
TVector3Property *mpScale;
|
||||
TBoolProperty *mpActive;
|
||||
CPropertyStruct *mpLightParameters;
|
||||
TResPtr<CResource> mpDisplayAsset;
|
||||
TResPtr<CCollisionMeshGroup> mpCollision;
|
||||
u32 mActiveCharIndex;
|
||||
|
@ -54,11 +54,12 @@ public:
|
|||
CScriptObject(u32 InstanceID, CGameArea *pArea, CScriptLayer *pLayer, CScriptTemplate *pTemplate);
|
||||
~CScriptObject();
|
||||
|
||||
void CopyProperties(CScriptObject* pObject);
|
||||
void EvaluateProperties();
|
||||
void EvaluateDisplayAsset();
|
||||
void EvaluateCollisionModel();
|
||||
void EvaluateVolume();
|
||||
bool IsEditorProperty(IProperty *pProp);
|
||||
bool IsEditorProperty(IPropertyNew *pProp);
|
||||
void SetLayer(CScriptLayer *pLayer, u32 NewLayerIndex = -1);
|
||||
u32 LayerIndex() const;
|
||||
bool HasNearVisibleActivation() const;
|
||||
|
@ -73,39 +74,37 @@ public:
|
|||
CGameArea* Area() const { return mpArea; }
|
||||
CScriptLayer* Layer() const { return mpLayer; }
|
||||
u32 Version() const { return mVersion; }
|
||||
CPropertyStruct* Properties() const { return mpProperties; }
|
||||
u32 NumProperties() const { return mpProperties->Count(); }
|
||||
IProperty* PropertyByIndex(u32 Index) const { return mpProperties->PropertyByIndex(Index); }
|
||||
IProperty* PropertyByIDString(const TIDString& rkStr) const { return mpProperties->PropertyByIDString(rkStr); }
|
||||
u32 ObjectTypeID() const { return mpTemplate->ObjectID(); }
|
||||
u32 InstanceID() const { return mInstanceID; }
|
||||
u32 NumLinks(ELinkType Type) const { return (Type == eIncoming ? mInLinks.size() : mOutLinks.size()); }
|
||||
CLink* Link(ELinkType Type, u32 Index) const { return (Type == eIncoming ? mInLinks[Index] : mOutLinks[Index]); }
|
||||
void* PropertyData() const { return (void*) mPropertyData.data(); }
|
||||
|
||||
CVector3f Position() const { return mpPosition ? mpPosition->Get() : CVector3f::skZero; }
|
||||
CVector3f Rotation() const { return mpRotation ? mpRotation->Get() : CVector3f::skZero; }
|
||||
CVector3f Scale() const { return mpScale ? mpScale->Get() : CVector3f::skOne; }
|
||||
TString InstanceName() const { return mpInstanceName ? mpInstanceName->Get() : ""; }
|
||||
bool IsActive() const { return mpActive ? mpActive->Get() : false; }
|
||||
CVector3f Position() const { return mPosition.IsValid() ? mPosition.Get() : CVector3f::skZero; }
|
||||
CVector3f Rotation() const { return mRotation.IsValid() ? mRotation.Get() : CVector3f::skZero; }
|
||||
CVector3f Scale() const { return mScale.IsValid() ? mScale.Get() : CVector3f::skOne; }
|
||||
TString InstanceName() const { return mInstanceName.IsValid() ? mInstanceName.Get() : ""; }
|
||||
bool IsActive() const { return mActive.IsValid() ? mActive.Get() : false; }
|
||||
bool HasInGameModel() const { return mHasInGameModel; }
|
||||
CPropertyStruct* LightParameters() const { return mpLightParameters; }
|
||||
CStructRef LightParameters() const { return mLightParameters; }
|
||||
CResource* DisplayAsset() const { return mpDisplayAsset; }
|
||||
u32 ActiveCharIndex() const { return mActiveCharIndex; }
|
||||
u32 ActiveAnimIndex() const { return mActiveAnimIndex; }
|
||||
CCollisionMeshGroup* Collision() const { return mpCollision; }
|
||||
EVolumeShape VolumeShape() const { return mVolumeShape; }
|
||||
float VolumeScale() const { return mVolumeScale; }
|
||||
void SetPosition(const CVector3f& rkNewPos) { if (mpPosition) mpPosition->Set(rkNewPos); }
|
||||
void SetRotation(const CVector3f& rkNewRot) { if (mpRotation) mpRotation->Set(rkNewRot); }
|
||||
void SetScale(const CVector3f& rkNewScale) { if (mpScale) mpScale->Set(rkNewScale); }
|
||||
void SetName(const TString& rkNewName) { if (mpInstanceName) mpInstanceName->Set(rkNewName); }
|
||||
void SetActive(bool Active) { if (mpActive) mpActive->Set(Active); }
|
||||
void SetPosition(const CVector3f& rkNewPos) { mPosition.Set(rkNewPos); }
|
||||
void SetRotation(const CVector3f& rkNewRot) { mRotation.Set(rkNewRot); }
|
||||
void SetScale(const CVector3f& rkNewScale) { mScale.Set(rkNewScale); }
|
||||
void SetName(const TString& rkNewName) { mInstanceName.Set(rkNewName); }
|
||||
void SetActive(bool Active) { mActive.Set(Active); }
|
||||
|
||||
TVector3Property* PositionProperty() const { return mpPosition; }
|
||||
TVector3Property* RotationProperty() const { return mpRotation; }
|
||||
TVector3Property* ScaleProperty() const { return mpScale; }
|
||||
TStringProperty* InstanceNameProperty() const { return mpInstanceName; }
|
||||
TBoolProperty* ActiveProperty() const { return mpActive; }
|
||||
bool HasPosition() const { return mPosition.IsValid(); }
|
||||
bool HasRotation() const { return mRotation.IsValid(); }
|
||||
bool HasScale() const { return mScale.IsValid(); }
|
||||
bool HasInstanceName() const { return mInstanceName.IsValid(); }
|
||||
bool HasActive() const { return mActive.IsValid(); }
|
||||
bool HasLightParameters() const { return mLightParameters.IsValid(); }
|
||||
};
|
||||
|
||||
#endif // CSCRIPTOBJECT_H
|
||||
|
|
|
@ -10,8 +10,14 @@
|
|||
|
||||
CScriptTemplate::CScriptTemplate(CMasterTemplate *pMaster)
|
||||
: mpMaster(pMaster)
|
||||
, mpBaseStruct(nullptr)
|
||||
, mpProperties(nullptr)
|
||||
, mVisible(true)
|
||||
, mpNameProperty(nullptr)
|
||||
, mpPositionProperty(nullptr)
|
||||
, mpRotationProperty(nullptr)
|
||||
, mpScaleProperty(nullptr)
|
||||
, mpActiveProperty(nullptr)
|
||||
, mpLightParametersProperty(nullptr)
|
||||
, mPreviewScale(1.f)
|
||||
, mVolumeShape(eNoShape)
|
||||
, mVolumeScale(1.f)
|
||||
|
@ -20,7 +26,16 @@ CScriptTemplate::CScriptTemplate(CMasterTemplate *pMaster)
|
|||
|
||||
CScriptTemplate::~CScriptTemplate()
|
||||
{
|
||||
delete mpBaseStruct;
|
||||
}
|
||||
|
||||
void CScriptTemplate::PostLoad()
|
||||
{
|
||||
if (!mNameIDString.IsEmpty()) mpNameProperty = TPropCast<CStringProperty>( mpProperties->ChildByIDString(mNameIDString) );
|
||||
if (!mPositionIDString.IsEmpty()) mpPositionProperty = TPropCast<CVectorProperty>( mpProperties->ChildByIDString(mPositionIDString) );
|
||||
if (!mRotationIDString.IsEmpty()) mpRotationProperty = TPropCast<CVectorProperty>( mpProperties->ChildByIDString(mRotationIDString) );
|
||||
if (!mScaleIDString.IsEmpty()) mpScaleProperty = TPropCast<CVectorProperty>( mpProperties->ChildByIDString(mScaleIDString) );
|
||||
if (!mActiveIDString.IsEmpty()) mpActiveProperty = TPropCast<CBoolProperty>( mpProperties->ChildByIDString(mActiveIDString) );
|
||||
if (!mLightParametersIDString.IsEmpty()) mpLightParametersProperty = TPropCast<CStructPropertyNew>( mpProperties->ChildByIDString(mLightParametersIDString) );
|
||||
}
|
||||
|
||||
EGame CScriptTemplate::Game() const
|
||||
|
@ -29,14 +44,14 @@ EGame CScriptTemplate::Game() const
|
|||
}
|
||||
|
||||
// ************ PROPERTY FETCHING ************
|
||||
template<typename PropType, EPropertyType PropEnum>
|
||||
PropType TFetchProperty(CPropertyStruct *pProperties, const TIDString& rkID)
|
||||
template<class PropType>
|
||||
PropType* TFetchProperty(CStructPropertyNew* pProperties, const TIDString& rkID)
|
||||
{
|
||||
if (rkID.IsEmpty()) return nullptr;
|
||||
IProperty *pProp = pProperties->PropertyByIDString(rkID);
|
||||
IPropertyNew *pProp = pProperties->ChildByIDString(rkID);
|
||||
|
||||
if (pProp && (pProp->Type() == PropEnum))
|
||||
return static_cast<PropType>(pProp);
|
||||
return static_cast<PropType*>(pProp)->ValuePtr();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -80,39 +95,42 @@ s32 CScriptTemplate::CheckVolumeConditions(CScriptObject *pObj, bool LogErrors)
|
|||
// Private function
|
||||
if (mVolumeShape == eConditionalShape)
|
||||
{
|
||||
IProperty *pProp = pObj->Properties()->PropertyByIDString(mVolumeConditionIDString);
|
||||
TIDString PropID = mVolumeConditionIDString;
|
||||
IPropertyNew* pProp = pObj->Template()->Properties()->ChildByIDString( PropID );
|
||||
|
||||
// Get value of the condition test property (only boolean, integral, and enum types supported)
|
||||
void* pData = pObj->PropertyData();
|
||||
int Val;
|
||||
|
||||
switch (pProp->Type())
|
||||
{
|
||||
case eBoolProperty:
|
||||
Val = (static_cast<TBoolProperty*>(pProp)->Get() ? 1 : 0);
|
||||
case EPropertyTypeNew::Bool:
|
||||
Val = TPropCast<CBoolProperty>(pProp)->Value(pData) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case eByteProperty:
|
||||
Val = (int) static_cast<TByteProperty*>(pProp)->Get();
|
||||
case EPropertyTypeNew::Byte:
|
||||
Val = (int) TPropCast<CByteProperty>(pProp)->Value(pData);
|
||||
break;
|
||||
|
||||
case eShortProperty:
|
||||
Val = (int) static_cast<TShortProperty*>(pProp)->Get();
|
||||
case EPropertyTypeNew::Short:
|
||||
Val = (int) TPropCast<CShortProperty>(pProp)->Value(pData);
|
||||
break;
|
||||
|
||||
case eLongProperty:
|
||||
Val = (int) static_cast<TLongProperty*>(pProp)->Get();
|
||||
case EPropertyTypeNew::Int:
|
||||
Val = TPropCast<CIntProperty>(pProp)->Value(pData);
|
||||
break;
|
||||
|
||||
case eEnumProperty:
|
||||
Val = (int) static_cast<TEnumProperty*>(pProp)->Get();
|
||||
case EPropertyTypeNew::Enum:
|
||||
case EPropertyTypeNew::Choice:
|
||||
Val = TPropCast<CEnumProperty>(pProp)->Value(pData);
|
||||
break;
|
||||
}
|
||||
|
||||
// Test and check whether any of the conditions are true
|
||||
for (u32 iCon = 0; iCon < mVolumeConditions.size(); iCon++)
|
||||
for (u32 LinkIdx = 0; LinkIdx < mVolumeConditions.size(); LinkIdx++)
|
||||
{
|
||||
if (mVolumeConditions[iCon].Value == Val)
|
||||
return iCon;
|
||||
if (mVolumeConditions[LinkIdx].Value == Val)
|
||||
return LinkIdx;
|
||||
}
|
||||
|
||||
if (LogErrors)
|
||||
|
@ -122,37 +140,7 @@ s32 CScriptTemplate::CheckVolumeConditions(CScriptObject *pObj, bool LogErrors)
|
|||
return -1;
|
||||
}
|
||||
|
||||
TStringProperty* CScriptTemplate::FindInstanceName(CPropertyStruct *pProperties)
|
||||
{
|
||||
return TFetchProperty<TStringProperty*, eStringProperty>(pProperties, mNameIDString);
|
||||
}
|
||||
|
||||
TVector3Property* CScriptTemplate::FindPosition(CPropertyStruct *pProperties)
|
||||
{
|
||||
return TFetchProperty<TVector3Property*, eVector3Property>(pProperties, mPositionIDString);
|
||||
}
|
||||
|
||||
TVector3Property* CScriptTemplate::FindRotation(CPropertyStruct *pProperties)
|
||||
{
|
||||
return TFetchProperty<TVector3Property*, eVector3Property>(pProperties, mRotationIDString);
|
||||
}
|
||||
|
||||
TVector3Property* CScriptTemplate::FindScale(CPropertyStruct *pProperties)
|
||||
{
|
||||
return TFetchProperty<TVector3Property*, eVector3Property>(pProperties, mScaleIDString);
|
||||
}
|
||||
|
||||
TBoolProperty* CScriptTemplate::FindActive(CPropertyStruct *pProperties)
|
||||
{
|
||||
return TFetchProperty<TBoolProperty*, eBoolProperty>(pProperties, mActiveIDString);
|
||||
}
|
||||
|
||||
CPropertyStruct* CScriptTemplate::FindLightParameters(CPropertyStruct *pProperties)
|
||||
{
|
||||
return TFetchProperty<CPropertyStruct*, eStructProperty>(pProperties, mLightParametersIDString);
|
||||
}
|
||||
|
||||
CResource* CScriptTemplate::FindDisplayAsset(CPropertyStruct *pProperties, u32& rOutCharIndex, u32& rOutAnimIndex, bool& rOutIsInGame)
|
||||
CResource* CScriptTemplate::FindDisplayAsset(void* pPropertyData, u32& rOutCharIndex, u32& rOutAnimIndex, bool& rOutIsInGame)
|
||||
{
|
||||
rOutCharIndex = -1;
|
||||
rOutAnimIndex = -1;
|
||||
|
@ -170,25 +158,28 @@ CResource* CScriptTemplate::FindDisplayAsset(CPropertyStruct *pProperties, u32&
|
|||
// Property
|
||||
else
|
||||
{
|
||||
IProperty *pProp = pProperties->PropertyByIDString(it->AssetLocation);
|
||||
IPropertyNew* pProp = mpProperties->ChildByIDString(it->AssetLocation);
|
||||
|
||||
if (it->AssetType == SEditorAsset::eAnimParams && pProp->Type() == eCharacterProperty)
|
||||
if (it->AssetType == SEditorAsset::eAnimParams && pProp->Type() == EPropertyTypeNew::AnimationSet)
|
||||
{
|
||||
TCharacterProperty *pChar = static_cast<TCharacterProperty*>(pProp);
|
||||
pRes = pChar->Get().AnimSet();
|
||||
CAnimationSetProperty* pAnimSet = TPropCast<CAnimationSetProperty>(pProp);
|
||||
CAnimationParameters Params = pAnimSet->Value(pPropertyData);
|
||||
pRes = Params.AnimSet();
|
||||
|
||||
if (pRes)
|
||||
{
|
||||
u32 MaxNumChars = static_cast<CAnimSet*>(pRes)->NumCharacters();
|
||||
rOutCharIndex = (it->ForceNodeIndex >= 0 && it->ForceNodeIndex < (s32) MaxNumChars ? it->ForceNodeIndex : pChar->Get().CharacterIndex());
|
||||
rOutAnimIndex = pChar->Get().AnimIndex();
|
||||
rOutCharIndex = (it->ForceNodeIndex >= 0 && it->ForceNodeIndex < (s32) MaxNumChars ? it->ForceNodeIndex : Params.CharacterIndex());
|
||||
rOutAnimIndex = Params.AnimIndex();
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
TAssetProperty *pAsset = static_cast<TAssetProperty*>(pProp);
|
||||
CResourceEntry *pEntry = gpResourceStore->FindEntry(pAsset->Get());
|
||||
ASSERT(pProp->Type() == EPropertyTypeNew::Asset);
|
||||
CAssetProperty* pAsset = TPropCast<CAssetProperty>(pProp);
|
||||
CAssetID ID = pAsset->Value(pPropertyData);
|
||||
CResourceEntry *pEntry = gpResourceStore->FindEntry( ID );
|
||||
if (pEntry) pRes = pEntry->Load();
|
||||
}
|
||||
}
|
||||
|
@ -205,7 +196,7 @@ CResource* CScriptTemplate::FindDisplayAsset(CPropertyStruct *pProperties, u32&
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
CCollisionMeshGroup* CScriptTemplate::FindCollision(CPropertyStruct *pProperties)
|
||||
CCollisionMeshGroup* CScriptTemplate::FindCollision(void* pPropertyData)
|
||||
{
|
||||
for (auto it = mAssets.begin(); it != mAssets.end(); it++)
|
||||
{
|
||||
|
@ -219,12 +210,12 @@ CCollisionMeshGroup* CScriptTemplate::FindCollision(CPropertyStruct *pProperties
|
|||
// Property
|
||||
else
|
||||
{
|
||||
IProperty *pProp = pProperties->PropertyByIDString(it->AssetLocation);
|
||||
IPropertyNew* pProp = mpProperties->ChildByIDString(it->AssetLocation);
|
||||
|
||||
if (pProp->Type() == eAssetProperty)
|
||||
if (pProp->Type() == EPropertyTypeNew::Asset)
|
||||
{
|
||||
TAssetProperty *pAsset = static_cast<TAssetProperty*>(pProp);
|
||||
pRes = gpResourceStore->LoadResource( pAsset->Get(), eDynamicCollision );
|
||||
CAssetProperty* pAsset = TPropCast<CAssetProperty>(pProp);
|
||||
pRes = gpResourceStore->LoadResource( pAsset->Value(pPropertyData), eDynamicCollision );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#ifndef CSCRIPTTEMPLATE_H
|
||||
#define CSCRIPTTEMPLATE_H
|
||||
|
||||
#include "IPropertyTemplate.h"
|
||||
#include "IProperty.h"
|
||||
#include "Core/Resource/Script/Property/Properties.h"
|
||||
#include "EPropertyType.h"
|
||||
#include "EVolumeShape.h"
|
||||
#include "Core/Resource/Model/CModel.h"
|
||||
|
@ -12,6 +11,7 @@
|
|||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
class CMasterTemplate;
|
||||
class CScriptObject;
|
||||
typedef TString TIDString;
|
||||
|
||||
|
@ -64,10 +64,9 @@ private:
|
|||
s32 ForceNodeIndex; // Force animsets to use specific node instead of one from property
|
||||
};
|
||||
|
||||
CMasterTemplate *mpMaster;
|
||||
CStructTemplate *mpBaseStruct;
|
||||
CMasterTemplate* mpMaster;
|
||||
std::unique_ptr<CStructPropertyNew> mpProperties;
|
||||
std::list<CScriptObject*> mObjectList;
|
||||
TString mTemplateName;
|
||||
std::vector<TString> mModules;
|
||||
TString mSourceFile;
|
||||
u32 mObjectID;
|
||||
|
@ -80,6 +79,14 @@ private:
|
|||
TIDString mScaleIDString;
|
||||
TIDString mActiveIDString;
|
||||
TIDString mLightParametersIDString;
|
||||
|
||||
CStringProperty* mpNameProperty;
|
||||
CVectorProperty* mpPositionProperty;
|
||||
CVectorProperty* mpRotationProperty;
|
||||
CVectorProperty* mpScaleProperty;
|
||||
CBoolProperty* mpActiveProperty;
|
||||
CStructPropertyNew* mpLightParametersProperty;
|
||||
|
||||
std::vector<SEditorAsset> mAssets;
|
||||
std::vector<SAttachment> mAttachments;
|
||||
|
||||
|
@ -102,44 +109,38 @@ private:
|
|||
public:
|
||||
CScriptTemplate(CMasterTemplate *pMaster);
|
||||
~CScriptTemplate();
|
||||
void PostLoad();
|
||||
EGame Game() const;
|
||||
|
||||
// Property Fetching
|
||||
EVolumeShape VolumeShape(CScriptObject *pObj);
|
||||
float VolumeScale(CScriptObject *pObj);
|
||||
TStringProperty* FindInstanceName(CPropertyStruct *pProperties);
|
||||
TVector3Property* FindPosition(CPropertyStruct *pProperties);
|
||||
TVector3Property* FindRotation(CPropertyStruct *pProperties);
|
||||
TVector3Property* FindScale(CPropertyStruct *pProperties);
|
||||
TBoolProperty* FindActive(CPropertyStruct *pProperties);
|
||||
CPropertyStruct* FindLightParameters(CPropertyStruct *pProperties);
|
||||
CResource* FindDisplayAsset(CPropertyStruct *pProperties, u32& rOutCharIndex, u32& rOutAnimIndex, bool& rOutIsInGame);
|
||||
CCollisionMeshGroup* FindCollision(CPropertyStruct *pProperties);
|
||||
CResource* FindDisplayAsset(void* pPropertyData, u32& rOutCharIndex, u32& rOutAnimIndex, bool& rOutIsInGame);
|
||||
CCollisionMeshGroup* FindCollision(void* pPropertyData);
|
||||
|
||||
// Accessors
|
||||
inline CMasterTemplate* MasterTemplate() const { return mpMaster; }
|
||||
inline TString Name() const { return mTemplateName; }
|
||||
inline TString Name() const { return mpProperties->Name(); }
|
||||
inline ERotationType RotationType() const { return mRotationType; }
|
||||
inline EScaleType ScaleType() const { return mScaleType; }
|
||||
inline float PreviewScale() const { return mPreviewScale; }
|
||||
inline u32 ObjectID() const { return mObjectID; }
|
||||
inline bool IsVisible() const { return mVisible; }
|
||||
inline TString SourceFile() const { return mSourceFile; }
|
||||
inline CStructTemplate* BaseStruct() const { return mpBaseStruct; }
|
||||
inline CStructPropertyNew* Properties() const { return mpProperties.get(); }
|
||||
inline u32 NumAttachments() const { return mAttachments.size(); }
|
||||
const SAttachment& Attachment(u32 Index) const { return mAttachments[Index]; }
|
||||
const std::vector<TString>& RequiredModules() const { return mModules; }
|
||||
|
||||
inline bool HasName() const { return !mNameIDString.IsEmpty(); }
|
||||
inline bool HasPosition() const { return !mPositionIDString.IsEmpty(); }
|
||||
inline bool HasRotation() const { return !mRotationIDString.IsEmpty(); }
|
||||
inline bool HasScale() const { return !mScaleIDString.IsEmpty(); }
|
||||
inline bool HasActive() const { return !mActiveIDString.IsEmpty(); }
|
||||
inline CStringProperty* NameProperty() const { return mpNameProperty; }
|
||||
inline CVectorProperty* PositionProperty() const { return mpPositionProperty; }
|
||||
inline CVectorProperty* RotationProperty() const { return mpRotationProperty; }
|
||||
inline CVectorProperty* ScaleProperty() const { return mpScaleProperty; }
|
||||
inline CBoolProperty* ActiveProperty() const { return mpActiveProperty; }
|
||||
inline CStructPropertyNew* LightParametersProperty() const { return mpLightParametersProperty; }
|
||||
|
||||
inline void SetVisible(bool Visible) { mVisible = Visible; }
|
||||
|
||||
inline void DebugPrintProperties() { mpBaseStruct->DebugPrintProperties(""); }
|
||||
|
||||
// Object Tracking
|
||||
u32 NumObjects() const;
|
||||
const std::list<CScriptObject*>& ObjectList() const;
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#ifndef EPROPERTYTYPE
|
||||
#define EPROPERTYTYPE
|
||||
|
||||
#include "IPropertyNew.h"
|
||||
|
||||
#if 0
|
||||
#include <Common/TString.h>
|
||||
|
||||
enum EPropertyType
|
||||
|
@ -24,11 +27,12 @@ enum EPropertyType
|
|||
eUnknownProperty,
|
||||
eInvalidProperty
|
||||
};
|
||||
#endif
|
||||
|
||||
// functions defined in IPropertyTemplate.cpp
|
||||
EPropertyType PropStringToPropEnum(TString Prop);
|
||||
TString PropEnumToPropString(EPropertyType Prop);
|
||||
const char* HashablePropTypeName(EPropertyType Prop);
|
||||
EPropertyTypeNew PropStringToPropEnum(TString Prop);
|
||||
TString PropEnumToPropString(EPropertyTypeNew Prop);
|
||||
const char* HashablePropTypeName(EPropertyTypeNew Prop);
|
||||
|
||||
#endif // EPROPERTYTYPE
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "IProperty.h"
|
||||
#include "IPropertyTemplate.h"
|
||||
|
||||
#if 0
|
||||
// ************ IProperty ************
|
||||
bool IProperty::IsInArray() const
|
||||
{
|
||||
|
@ -241,3 +242,4 @@ TString CArrayProperty::ElementName() const
|
|||
{
|
||||
return static_cast<CArrayTemplate*>(Template())->ElementName();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef IPROPERTY
|
||||
#define IPROPERTY
|
||||
|
||||
#if 0
|
||||
#include "EPropertyType.h"
|
||||
#include "IPropertyValue.h"
|
||||
#include "Core/Resource/CResource.h"
|
||||
|
@ -297,6 +298,6 @@ PropertyClass* TPropCast(IProperty *pProp)
|
|||
{
|
||||
return (pProp && pProp->Type() == PropertyClass::StaticType() ? static_cast<PropertyClass*>(pProp) : nullptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // IPROPERTY
|
||||
|
||||
|
|
|
@ -0,0 +1,364 @@
|
|||
#include "IPropertyNew.h"
|
||||
#include "Property/CAssetProperty.h"
|
||||
#include "Property/CArrayProperty.h"
|
||||
#include "Property/CEnumProperty.h"
|
||||
#include "Property/CFlagsProperty.h"
|
||||
#include "Property/CPointerProperty.h"
|
||||
|
||||
#include "Core/Resource/Script/CMasterTemplate.h"
|
||||
#include "Core/Resource/Script/CScriptTemplate.h"
|
||||
|
||||
/** IPropertyNew */
|
||||
IPropertyNew::IPropertyNew()
|
||||
: mpParent( nullptr )
|
||||
, mpPointerParent( nullptr )
|
||||
, mpArchetype( nullptr )
|
||||
, mOffset( -1 )
|
||||
, mID( -1 )
|
||||
, mCookPreference( ECookPreferenceNew::Default )
|
||||
, mMinVersion( 0.0f )
|
||||
, mMaxVersion( FLT_MAX )
|
||||
{}
|
||||
|
||||
void IPropertyNew::_CalcOffset()
|
||||
{
|
||||
// For standard properties, append to the end of the parent.
|
||||
bool IsRootArrayArchetype = (IsArrayArchetype() && TPropCast<CArrayProperty>(mpParent) != nullptr);
|
||||
|
||||
if (mpParent && !IsRootArrayArchetype)
|
||||
{
|
||||
// When we have a parent, our data is usually located inside the parent's property data. So we want to
|
||||
// position ourself at the end of the parent's existing children so we don't overlap any other properties.
|
||||
IPropertyNew* pLastChild = (mpParent->mChildren.empty() ? nullptr : mpParent->mChildren.back());
|
||||
|
||||
if (pLastChild)
|
||||
{
|
||||
mOffset = pLastChild->mOffset + pLastChild->DataSize();
|
||||
}
|
||||
else if (mpParent != mpPointerParent)
|
||||
{
|
||||
mOffset = mpParent->mOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
mOffset = 0;
|
||||
}
|
||||
|
||||
mOffset = ALIGN(mOffset, DataAlignment());
|
||||
}
|
||||
// Array archetypes are accessed differently because they have no way of knowing
|
||||
// which array index is meant to be accessed. So the offset is 0 and the caller
|
||||
// is responsible for passing in a pointer to the correct array item.
|
||||
else
|
||||
{
|
||||
mOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
u32 IPropertyNew::_GetOffset() const
|
||||
{
|
||||
return mOffset;
|
||||
}
|
||||
|
||||
void IPropertyNew::_ClearChildren()
|
||||
{
|
||||
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
||||
delete mChildren[ChildIdx];
|
||||
|
||||
mChildren.clear();
|
||||
}
|
||||
|
||||
IPropertyNew::~IPropertyNew()
|
||||
{
|
||||
// Remove from archetype
|
||||
if( mpArchetype != nullptr )
|
||||
{
|
||||
NBasics::VectorRemoveOne(mpArchetype->mSubInstances, this);
|
||||
}
|
||||
|
||||
// If this is an archetype, all our sub-instances should have destructed first.
|
||||
if( IsArchetype() )
|
||||
{
|
||||
ASSERT(mSubInstances.empty());
|
||||
}
|
||||
|
||||
// Delete children
|
||||
_ClearChildren();
|
||||
}
|
||||
|
||||
const char* IPropertyNew::HashableTypeName() const
|
||||
{
|
||||
return PropEnumToHashableTypeName( Type() );
|
||||
}
|
||||
|
||||
void* IPropertyNew::GetChildDataPointer(void* pPropertyData) const
|
||||
{
|
||||
return pPropertyData;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void IPropertyNew::Serialize(IArchive& rArc)
|
||||
{
|
||||
if (rArc.Game() <= ePrime)
|
||||
{
|
||||
rArc << SERIAL("Name", mName);
|
||||
}
|
||||
|
||||
rArc << SERIAL_HEX("ID", mID)
|
||||
<< SERIAL("Description", mDescription)
|
||||
<< SERIAL("CookPref", mCookPref)
|
||||
<< SERIAL("MinVersion", mMinVersion)
|
||||
<< SERIAL("MaxVersion", mMaxVersion);
|
||||
|
||||
// Children don't get serialized for most property types
|
||||
}
|
||||
#endif
|
||||
|
||||
void IPropertyNew::InitFromArchetype(IPropertyNew* pOther)
|
||||
{
|
||||
//@todo maybe somehow use Serialize for this instead?
|
||||
mpArchetype = pOther;
|
||||
mFlags = pOther->mFlags & ~EPropertyFlag::ArchetypeCopyFlags;
|
||||
mID = pOther->mID;
|
||||
mName = pOther->mName;
|
||||
mDescription = pOther->mDescription;
|
||||
mSuffix = pOther->mSuffix;
|
||||
mCookPreference = pOther->mCookPreference;
|
||||
mMinVersion = pOther->mMinVersion;
|
||||
mMaxVersion = pOther->mMaxVersion;
|
||||
|
||||
// Copy children
|
||||
_ClearChildren();
|
||||
|
||||
for (u32 ChildIdx = 0; ChildIdx < pOther->mChildren.size(); ChildIdx++)
|
||||
{
|
||||
CreateCopy( pOther->mChildren[ChildIdx], this );
|
||||
}
|
||||
}
|
||||
|
||||
TString IPropertyNew::GetTemplateFileName()
|
||||
{
|
||||
if (mpScriptTemplate)
|
||||
{
|
||||
return mpScriptTemplate->SourceFile();
|
||||
}
|
||||
else if (IsArchetype())
|
||||
{
|
||||
IPropertyNew* pRootParent = RootParent();
|
||||
ASSERT(pRootParent != this);
|
||||
return pRootParent->GetTemplateFileName();
|
||||
}
|
||||
else
|
||||
{
|
||||
return mpArchetype->GetTemplateFileName();
|
||||
}
|
||||
}
|
||||
|
||||
void* IPropertyNew::RawValuePtr(void* pData) const
|
||||
{
|
||||
// For array archetypes, the caller needs to provide the pointer to the correct array item
|
||||
if (IsArrayArchetype())
|
||||
return pData;
|
||||
|
||||
void* pBasePtr = (mpPointerParent ? mpPointerParent->GetChildDataPointer(pData) : pData);
|
||||
return ((char*)pBasePtr + mOffset);
|
||||
}
|
||||
|
||||
IPropertyNew* IPropertyNew::ChildByID(u32 ID) const
|
||||
{
|
||||
for (u32 ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
||||
{
|
||||
if (mChildren[ChildIdx]->mID == ID)
|
||||
return mChildren[ChildIdx];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IPropertyNew* IPropertyNew::ChildByIDString(const TIDString& rkIdString)
|
||||
{
|
||||
// String must contain at least one ID!
|
||||
// some ID strings are formatted with 8 characters and some with 2 (plus the beginning "0x")
|
||||
ASSERT(rkIdString.Size() >= 4);
|
||||
|
||||
u32 IDEndPos = rkIdString.IndexOf(':');
|
||||
u32 NextChildID = -1;
|
||||
|
||||
if (IDEndPos == -1)
|
||||
NextChildID = rkIdString.ToInt32();
|
||||
else
|
||||
NextChildID = rkIdString.SubString(2, IDEndPos - 2).ToInt32();
|
||||
|
||||
if (NextChildID == 0xFFFFFFFF)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IPropertyNew* pNextChild = ChildByID(NextChildID);
|
||||
|
||||
// Check if we need to recurse
|
||||
if (IDEndPos != -1)
|
||||
{
|
||||
return pNextChild->ChildByIDString(rkIdString.ChopFront(IDEndPos + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
return pNextChild;
|
||||
}
|
||||
}
|
||||
|
||||
bool IPropertyNew::ShouldCook(void*pPropertyData) const
|
||||
{
|
||||
switch (mCookPreference)
|
||||
{
|
||||
case ECookPreferenceNew::Always:
|
||||
return true;
|
||||
|
||||
case ECookPreferenceNew::Never:
|
||||
return false;
|
||||
|
||||
default:
|
||||
return (Game() < eReturns ? true : !MatchesDefault(pPropertyData));
|
||||
}
|
||||
}
|
||||
|
||||
void IPropertyNew::SetName(const TString& rkNewName)
|
||||
{
|
||||
mName = rkNewName;
|
||||
mFlags.ClearFlag(EPropertyFlag::HasCachedNameCheck);
|
||||
}
|
||||
|
||||
void IPropertyNew::SetDescription(const TString& rkNewDescription)
|
||||
{
|
||||
mDescription = rkNewDescription;
|
||||
}
|
||||
|
||||
void IPropertyNew::SetSuffix(const TString& rkNewSuffix)
|
||||
{
|
||||
mSuffix = rkNewSuffix;
|
||||
}
|
||||
|
||||
bool IPropertyNew::HasAccurateName()
|
||||
{
|
||||
if (!mFlags.HasFlag(EPropertyFlag::HasCachedNameCheck))
|
||||
{
|
||||
CCRC32 Hash;
|
||||
Hash.Hash(*mName);
|
||||
Hash.Hash(HashableTypeName());
|
||||
u32 GeneratedID = Hash.Digest();
|
||||
|
||||
if (GeneratedID == mID)
|
||||
mFlags.SetFlag( EPropertyFlag::HasCorrectPropertyName );
|
||||
else
|
||||
mFlags.ClearFlag( EPropertyFlag::HasCorrectPropertyName );
|
||||
|
||||
mFlags.SetFlag(EPropertyFlag::HasCachedNameCheck);
|
||||
}
|
||||
|
||||
return mFlags.HasFlag( EPropertyFlag::HasCorrectPropertyName );
|
||||
}
|
||||
|
||||
/** IPropertyNew Accessors */
|
||||
EGame IPropertyNew::Game() const
|
||||
{
|
||||
return mpMasterTemplate->Game();
|
||||
}
|
||||
|
||||
IPropertyNew* IPropertyNew::Create(EPropertyTypeNew Type,
|
||||
IPropertyNew* pParent,
|
||||
CMasterTemplate* pMaster,
|
||||
CScriptTemplate* pScript,
|
||||
bool CallPostInit /*= true*/)
|
||||
{
|
||||
IPropertyNew* pOut = nullptr;
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case EPropertyTypeNew::Bool: pOut = new CBoolProperty; break;
|
||||
case EPropertyTypeNew::Byte: pOut = new CByteProperty; break;
|
||||
case EPropertyTypeNew::Short: pOut = new CShortProperty; break;
|
||||
case EPropertyTypeNew::Int: pOut = new CIntProperty; break;
|
||||
case EPropertyTypeNew::Float: pOut = new CFloatProperty; break;
|
||||
case EPropertyTypeNew::Choice: pOut = new CChoiceProperty; break;
|
||||
case EPropertyTypeNew::Enum: pOut = new CEnumProperty; break;
|
||||
case EPropertyTypeNew::Flags: pOut = new CFlagsProperty; break;
|
||||
case EPropertyTypeNew::String: pOut = new CStringProperty; break;
|
||||
case EPropertyTypeNew::Vector: pOut = new CVectorProperty; break;
|
||||
case EPropertyTypeNew::Color: pOut = new CColorProperty; break;
|
||||
case EPropertyTypeNew::Asset: pOut = new CAssetProperty; break;
|
||||
case EPropertyTypeNew::Sound: pOut = new CSoundProperty; break;
|
||||
case EPropertyTypeNew::Animation: pOut = new CAnimationProperty; break;
|
||||
case EPropertyTypeNew::AnimationSet: pOut = new CAnimationSetProperty; break;
|
||||
case EPropertyTypeNew::Sequence: pOut = new CSequenceProperty; break;
|
||||
case EPropertyTypeNew::Spline: pOut = new CSplineProperty; break;
|
||||
case EPropertyTypeNew::Guid: pOut = new CGuidProperty; break;
|
||||
case EPropertyTypeNew::Pointer: pOut = new CPointerProperty; break;
|
||||
case EPropertyTypeNew::Struct: pOut = new CStructPropertyNew; break;
|
||||
case EPropertyTypeNew::Array: pOut = new CArrayProperty; break;
|
||||
}
|
||||
|
||||
if (!pOut)
|
||||
{
|
||||
// this shouldn't be possible! unhandled type! someone fucked up!
|
||||
ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Set parent and offset
|
||||
pOut->mpParent = pParent;
|
||||
|
||||
if (pParent)
|
||||
{
|
||||
pOut->mFlags = pParent->mFlags & EPropertyFlag::InheritableFlags;
|
||||
|
||||
if (pParent->IsPointerType())
|
||||
{
|
||||
pOut->mpPointerParent = pParent;
|
||||
}
|
||||
else
|
||||
{
|
||||
pOut->mpPointerParent = pParent->mpPointerParent;
|
||||
}
|
||||
}
|
||||
|
||||
// Set other metadata
|
||||
pOut->mpMasterTemplate = pMaster;
|
||||
pOut->mpScriptTemplate = pScript;
|
||||
pOut->_CalcOffset();
|
||||
|
||||
// Add to the parent's array. This needs to be done -after- we calculate offset, as adding a child to
|
||||
// the parent property will change the offset that gets calculated.
|
||||
if (pParent)
|
||||
{
|
||||
pParent->mChildren.push_back(pOut);
|
||||
}
|
||||
|
||||
if (CallPostInit)
|
||||
{
|
||||
pOut->PostInitialize();
|
||||
}
|
||||
|
||||
return pOut;
|
||||
}
|
||||
|
||||
IPropertyNew* IPropertyNew::CreateCopy(IPropertyNew* pArchetype,
|
||||
IPropertyNew* pParent,
|
||||
bool CallPostInit /*= true*/)
|
||||
{
|
||||
// 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
|
||||
// is no case where we will be creating archetypes outside this context. As such, pParent should
|
||||
// always be valid.
|
||||
ASSERT(pParent != nullptr);
|
||||
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,432 @@
|
|||
#ifndef IPROPERTYNEW_H
|
||||
#define IPROPERTYNEW_H
|
||||
|
||||
#include "Core/Resource/Animation/CAnimationParameters.h"
|
||||
#include <Common/Common.h>
|
||||
#include <Math/CVector3f.h>
|
||||
#include <Math/MathUtil.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
/** Forward declares */
|
||||
class CMasterTemplate;
|
||||
class CScriptTemplate;
|
||||
class CStructPropertyNew;
|
||||
|
||||
/** Typedefs */
|
||||
typedef TString TIDString;
|
||||
|
||||
/** Property flags */
|
||||
enum class EPropertyFlag : u32
|
||||
{
|
||||
/** Property is an archetype (a template for other properties to copy from) */
|
||||
IsArchetype = 0x1,
|
||||
/** Property is an array archetype (a template for elements of an array property) */
|
||||
IsArrayArchetype = 0x2,
|
||||
/** This property and all its children are a single unit and do not have individual property IDs, sizes, etc. */
|
||||
IsAtomic = 0x4,
|
||||
/** We have cached whether the property name is correct */
|
||||
HasCachedNameCheck = 0x40000000,
|
||||
/** The name of the property is a match for the property ID hash */
|
||||
HasCorrectPropertyName = 0x80000000,
|
||||
|
||||
/** Flags that are left intact when copying from an archetype */
|
||||
ArchetypeCopyFlags = EPropertyFlag::IsAtomic,
|
||||
/** Flags that are inheritable from parent */
|
||||
InheritableFlags = EPropertyFlag::IsArchetype | EPropertyFlag::IsArrayArchetype | EPropertyFlag::IsAtomic,
|
||||
};
|
||||
DECLARE_FLAGS_ENUMCLASS(EPropertyFlag, FPropertyFlags)
|
||||
|
||||
/** Property type */
|
||||
enum class EPropertyTypeNew
|
||||
{
|
||||
Bool = FOURCC('BOOL'),
|
||||
Byte = FOURCC('BYTE'),
|
||||
Short = FOURCC('SHRT'),
|
||||
Int = FOURCC('INT '),
|
||||
Float = FOURCC('REAL'),
|
||||
Choice = FOURCC('CHOI'),
|
||||
Enum = FOURCC('ENUM'),
|
||||
Flags = FOURCC('FLAG'),
|
||||
String = FOURCC('STRG'),
|
||||
Vector = FOURCC('VECT'),
|
||||
Color = FOURCC('COLR'),
|
||||
Asset = FOURCC('ASST'),
|
||||
Sound = FOURCC('SOND'),
|
||||
Animation = FOURCC('ANIM'),
|
||||
AnimationSet = FOURCC('ANMS'),
|
||||
Sequence = FOURCC('SQNC'),
|
||||
Spline = FOURCC('SPLN'),
|
||||
Guid = FOURCC('GUID'),
|
||||
Pointer = FOURCC('PNTR'),
|
||||
Struct = FOURCC('STRC'),
|
||||
Array = FOURCC('ARRY'),
|
||||
Invalid = FOURCC('INVD')
|
||||
};
|
||||
inline void Serialize(IArchive& rArc, EPropertyTypeNew& rType)
|
||||
{
|
||||
rArc.SerializePrimitive( (CFourCC&) rType );
|
||||
}
|
||||
|
||||
inline const char* PropEnumToHashableTypeName(EPropertyTypeNew Type)
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
case EPropertyTypeNew::Bool: return "bool";
|
||||
case EPropertyTypeNew::Int: return "int";
|
||||
case EPropertyTypeNew::Float: return "float";
|
||||
case EPropertyTypeNew::Choice: return "choice";
|
||||
case EPropertyTypeNew::Enum: return "enum";
|
||||
case EPropertyTypeNew::Flags: return "Flags";
|
||||
case EPropertyTypeNew::String: return "string";
|
||||
case EPropertyTypeNew::Vector: return "Vector";
|
||||
case EPropertyTypeNew::Color: return "Color";
|
||||
case EPropertyTypeNew::Asset: return "asset";
|
||||
case EPropertyTypeNew::Sound: return "sound";
|
||||
case EPropertyTypeNew::Spline: return "spline";
|
||||
case EPropertyTypeNew::Guid: return "guid";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
/** Enum that describes when/how properties should be cooked out */
|
||||
enum class ECookPreferenceNew
|
||||
{
|
||||
Default,
|
||||
Always,
|
||||
Never
|
||||
};
|
||||
inline void Serialize(IArchive& rArc, ECookPreferenceNew& rPref)
|
||||
{
|
||||
rArc.SerializePrimitive( (u32&) rPref );
|
||||
}
|
||||
|
||||
/** New property class */
|
||||
class IPropertyNew
|
||||
{
|
||||
friend class CTemplateLoader;
|
||||
friend class CPropertyFactory;
|
||||
|
||||
protected:
|
||||
/** Flags */
|
||||
FPropertyFlags mFlags;
|
||||
|
||||
/** Parent property */
|
||||
IPropertyNew* mpParent;
|
||||
|
||||
/** Pointer parent; if non-null, this parent needs to be dereferenced to access the correct
|
||||
* memory region that our property data is stored in */
|
||||
IPropertyNew* mpPointerParent;
|
||||
|
||||
/** Archetype property; source property that we copied metadata from */
|
||||
IPropertyNew* mpArchetype;
|
||||
|
||||
/** Sub-instances of archetype properties. For non-archetypes, will be empty. @todo better
|
||||
* method of storing this? maybe a linked list? */
|
||||
std::vector<IPropertyNew*> mSubInstances;
|
||||
|
||||
/** Child properties; these appear underneath this property on the UI */
|
||||
std::vector<IPropertyNew*> mChildren;
|
||||
|
||||
/** Master template for the game this property belongs to.
|
||||
* Cannot be derived from mpScriptTemplate because mpScriptTemplate is null sometimes */
|
||||
CMasterTemplate* mpMasterTemplate;
|
||||
|
||||
/** Script template that this property belongs to. Null for struct/enum/flag archetypes. */
|
||||
CScriptTemplate* mpScriptTemplate;
|
||||
|
||||
/** Offset of this property within the property block */
|
||||
u32 mOffset;
|
||||
|
||||
/** Property ID. This ID is used to uniquely identify this property within this struct. */
|
||||
u32 mID;
|
||||
|
||||
/** Property metadata */
|
||||
TString mName;
|
||||
TString mDescription;
|
||||
TString mSuffix;
|
||||
ECookPreferenceNew mCookPreference;
|
||||
|
||||
/** Min/max allowed version number. These numbers correspond to the game's internal build number.
|
||||
* This is not used yet but in the future it can be used to configure certain properties to only
|
||||
* show up when certain versions of the game are being edited. The default values allow the
|
||||
* property to show up in all versions. */
|
||||
float mMinVersion;
|
||||
float mMaxVersion;
|
||||
|
||||
/** Private constructor - use static methods to instantiate */
|
||||
IPropertyNew();
|
||||
void _CalcOffset();
|
||||
u32 _GetOffset() const;
|
||||
void _ClearChildren();
|
||||
|
||||
/** Called after property is created and fully initialized */
|
||||
virtual void PostInitialize() {}
|
||||
|
||||
public:
|
||||
virtual ~IPropertyNew();
|
||||
|
||||
/** Interface */
|
||||
virtual EPropertyTypeNew Type() const = 0;
|
||||
virtual u32 DataSize() const = 0;
|
||||
virtual u32 DataAlignment() const = 0;
|
||||
virtual void Construct(void* pData) const = 0;
|
||||
virtual void Destruct(void* pData) const = 0;
|
||||
virtual bool MatchesDefault(void* pData) const = 0;
|
||||
virtual void RevertToDefault(void* pData) const = 0;
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const = 0;
|
||||
|
||||
virtual void PropertyValueChanged(void* pPropertyData) {}
|
||||
virtual bool IsNumericalType() const { return false; }
|
||||
virtual bool IsPointerType() const { return false; }
|
||||
virtual TString ValueAsString(void* pData) const { return ""; }
|
||||
|
||||
virtual const char* HashableTypeName() const;
|
||||
virtual void* GetChildDataPointer(void* pPropertyData) const;
|
||||
#if 0
|
||||
virtual void Serialize(IArchive& rArc);
|
||||
#endif
|
||||
virtual void InitFromArchetype(IPropertyNew* pOther);
|
||||
virtual TString GetTemplateFileName();
|
||||
|
||||
/** Utility methods */
|
||||
void* RawValuePtr(void* pData) const;
|
||||
IPropertyNew* ChildByID(u32 ID) const;
|
||||
IPropertyNew* ChildByIDString(const TIDString& rkIdString);
|
||||
bool ShouldCook(void* pPropertyData) const;
|
||||
void SetName(const TString& rkNewName);
|
||||
void SetDescription(const TString& rkNewDescription);
|
||||
void SetSuffix(const TString& rkNewSuffix);
|
||||
bool HasAccurateName();
|
||||
|
||||
/** Accessors */
|
||||
EGame Game() const;
|
||||
inline ECookPreferenceNew CookPreference() const;
|
||||
inline u32 NumChildren() const;
|
||||
inline IPropertyNew* ChildByIndex(u32 ChildIndex) const;
|
||||
inline IPropertyNew* Parent() const;
|
||||
inline IPropertyNew* RootParent();
|
||||
inline IPropertyNew* Archetype() const;
|
||||
inline CScriptTemplate* ScriptTemplate() const;
|
||||
inline CMasterTemplate* MasterTemplate() const;
|
||||
inline TString Name() const;
|
||||
inline TString Description() const;
|
||||
inline TString Suffix() const;
|
||||
inline TIDString IDString(bool FullyQualified) const;
|
||||
inline u32 ID() const;
|
||||
|
||||
inline bool IsArchetype() const { return mFlags.HasFlag(EPropertyFlag::IsArchetype); }
|
||||
inline bool IsArrayArchetype() const { return mFlags.HasFlag(EPropertyFlag::IsArrayArchetype); }
|
||||
inline bool IsAtomic() const { return mFlags.HasFlag(EPropertyFlag::IsAtomic); }
|
||||
|
||||
/** Create */
|
||||
static IPropertyNew* Create(EPropertyTypeNew Type,
|
||||
IPropertyNew* pParent,
|
||||
CMasterTemplate* pMaster,
|
||||
CScriptTemplate* pScript,
|
||||
bool CallPostInit = true);
|
||||
|
||||
static IPropertyNew* CreateCopy(IPropertyNew* pArchetype,
|
||||
IPropertyNew* pParent,
|
||||
bool CallPostInit = true);
|
||||
};
|
||||
|
||||
inline ECookPreferenceNew IPropertyNew::CookPreference() const
|
||||
{
|
||||
return mCookPreference;
|
||||
}
|
||||
|
||||
inline u32 IPropertyNew::NumChildren() const
|
||||
{
|
||||
return mChildren.size();
|
||||
}
|
||||
|
||||
inline IPropertyNew* IPropertyNew::ChildByIndex(u32 ChildIndex) const
|
||||
{
|
||||
ASSERT(ChildIndex >= 0 && ChildIndex < mChildren.size());
|
||||
return mChildren[ChildIndex];
|
||||
}
|
||||
|
||||
inline IPropertyNew* IPropertyNew::Parent() const
|
||||
{
|
||||
return mpParent;
|
||||
}
|
||||
|
||||
inline IPropertyNew* IPropertyNew::RootParent()
|
||||
{
|
||||
IPropertyNew* pParent = Parent();
|
||||
IPropertyNew* pOut = this;
|
||||
|
||||
while (pParent)
|
||||
{
|
||||
pOut = pParent;
|
||||
pParent = pParent->Parent();
|
||||
}
|
||||
|
||||
return pOut;
|
||||
}
|
||||
|
||||
inline IPropertyNew* IPropertyNew::Archetype() const
|
||||
{
|
||||
return mpArchetype;
|
||||
}
|
||||
|
||||
inline CScriptTemplate* IPropertyNew::ScriptTemplate() const
|
||||
{
|
||||
return mpScriptTemplate;
|
||||
}
|
||||
|
||||
inline CMasterTemplate* IPropertyNew::MasterTemplate() const
|
||||
{
|
||||
return mpMasterTemplate;
|
||||
}
|
||||
|
||||
inline TString IPropertyNew::Name() const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
inline TString IPropertyNew::Description() const
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
inline TString IPropertyNew::Suffix() const
|
||||
{
|
||||
return mSuffix;
|
||||
}
|
||||
|
||||
inline TString IPropertyNew::IDString(bool FullyQualified) const
|
||||
{
|
||||
if (FullyQualified && mpParent != nullptr)
|
||||
return mpParent->IDString(FullyQualified) + ":" + TString::HexString(mID);
|
||||
else
|
||||
return TString::HexString(mID);
|
||||
}
|
||||
|
||||
inline u32 IPropertyNew::ID() const
|
||||
{
|
||||
return mID;
|
||||
}
|
||||
|
||||
template<typename PropType, EPropertyTypeNew PropEnum>
|
||||
class TTypedPropertyNew : public IPropertyNew
|
||||
{
|
||||
friend class IPropertyNew;
|
||||
friend class CTemplateLoader;
|
||||
public:
|
||||
typedef PropType ValueType;
|
||||
|
||||
protected:
|
||||
PropType mDefaultValue;
|
||||
|
||||
TTypedPropertyNew()
|
||||
: IPropertyNew()
|
||||
{
|
||||
memset(&mDefaultValue, 0, sizeof(PropType));
|
||||
}
|
||||
|
||||
public:
|
||||
virtual EPropertyTypeNew Type() const { return PropEnum; }
|
||||
virtual u32 DataSize() const { return sizeof(PropType); }
|
||||
virtual u32 DataAlignment() const { return alignof(PropType); }
|
||||
virtual void Construct(void* pData) const { new(ValuePtr(pData)) PropType(mDefaultValue); }
|
||||
virtual void Destruct(void* pData) const { ValueRef(pData).~PropType(); }
|
||||
virtual bool MatchesDefault(void* pData) const { return ValueRef(pData) == mDefaultValue; }
|
||||
virtual void RevertToDefault(void* pData) const { ValueRef(pData) = mDefaultValue; }
|
||||
|
||||
virtual bool CanHaveDefault() const { return true; }
|
||||
|
||||
#if 0
|
||||
virtual void Serialize(IArchive& rArc)
|
||||
{
|
||||
IPropertyNew::Serialize(rArc);
|
||||
rArc << SERIAL("DefaultValue", mDefaultValue);
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void InitFromArchetype(IPropertyNew* pOther)
|
||||
{
|
||||
IPropertyNew::InitFromArchetype(pOther);
|
||||
mDefaultValue = static_cast<TTypedPropertyNew*>(pOther)->mDefaultValue;
|
||||
}
|
||||
|
||||
inline PropType* ValuePtr(void* pData) const
|
||||
{
|
||||
return (PropType*) RawValuePtr(pData);
|
||||
}
|
||||
|
||||
inline PropType& ValueRef(void* pData) const
|
||||
{
|
||||
return *ValuePtr(pData);
|
||||
}
|
||||
|
||||
inline PropType Value(void* pData) const
|
||||
{
|
||||
return *ValuePtr(pData);
|
||||
}
|
||||
|
||||
inline static EPropertyTypeNew StaticType() { return PropEnum; }
|
||||
};
|
||||
|
||||
template<typename PropType, EPropertyTypeNew PropEnum>
|
||||
class TNumericalPropertyNew : public TTypedPropertyNew<PropType, PropEnum>
|
||||
{
|
||||
friend class IPropertyNew;
|
||||
friend class CTemplateLoader;
|
||||
|
||||
protected:
|
||||
PropType mMinValue;
|
||||
PropType mMaxValue;
|
||||
|
||||
TNumericalPropertyNew()
|
||||
: TTypedPropertyNew()
|
||||
, mMinValue( -1 )
|
||||
, mMaxValue( -1 )
|
||||
{}
|
||||
|
||||
public:
|
||||
#if 0
|
||||
virtual void Serialize(IArchive& rArc)
|
||||
{
|
||||
TTypedPropertyNew::Serialize(rArc);
|
||||
rArc << SERIAL("Min", mMin)
|
||||
<< SERIAL("Max", mMax);
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void InitFromArchetype(IPropertyNew* pOther)
|
||||
{
|
||||
TTypedPropertyNew::InitFromArchetype(pOther);
|
||||
TNumericalPropertyNew* pCastOther = static_cast<TNumericalPropertyNew*>(pOther);
|
||||
mMinValue = pCastOther->mMinValue;
|
||||
mMaxValue = pCastOther->mMaxValue;
|
||||
}
|
||||
|
||||
virtual void PropertyValueChanged(void* pPropertyData)
|
||||
{
|
||||
IPropertyNew::PropertyValueChanged(pPropertyData);
|
||||
|
||||
if (mMinValue >= 0 && mMaxValue >= 0)
|
||||
{
|
||||
PropType& rValue = ValueRef(pPropertyData);
|
||||
rValue = Math::Clamp(mMinValue, mMaxValue, rValue);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Property casting with dynamic type checking */
|
||||
template<class PropertyClass>
|
||||
inline PropertyClass* TPropCast(IPropertyNew* pProperty)
|
||||
{
|
||||
if (pProperty && pProperty->Type() == PropertyClass::StaticType())
|
||||
{
|
||||
return static_cast<PropertyClass*>(pProperty);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // IPROPERTYNEW_H
|
|
@ -3,6 +3,7 @@
|
|||
#include <Common/Hash/CCRC32.h>
|
||||
#include <iostream>
|
||||
|
||||
#if 0
|
||||
// ************ IPropertyTemplate ************
|
||||
EGame IPropertyTemplate::Game() const
|
||||
{
|
||||
|
@ -250,75 +251,73 @@ void CStructTemplate::DetermineVersionPropertyCounts()
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// ************ GLOBAL FUNCTIONS ************
|
||||
TString PropEnumToPropString(EPropertyType Prop)
|
||||
TString PropEnumToPropString(EPropertyTypeNew Prop)
|
||||
{
|
||||
switch (Prop)
|
||||
{
|
||||
case eBoolProperty: return "bool";
|
||||
case eByteProperty: return "byte";
|
||||
case eShortProperty: return "short";
|
||||
case eLongProperty: return "long";
|
||||
case eEnumProperty: return "enum";
|
||||
case eBitfieldProperty: return "bitfield";
|
||||
case eFloatProperty: return "float";
|
||||
case eStringProperty: return "string";
|
||||
case eColorProperty: return "color";
|
||||
case eVector3Property: return "vector3f";
|
||||
case eSoundProperty: return "sound";
|
||||
case eAssetProperty: return "asset";
|
||||
case eStructProperty: return "struct";
|
||||
case eArrayProperty: return "array";
|
||||
case eCharacterProperty: return "character";
|
||||
case eMayaSplineProperty: return "MayaSpline";
|
||||
case eUnknownProperty: return "unknown";
|
||||
case EPropertyTypeNew::Bool: return "bool";
|
||||
case EPropertyTypeNew::Byte: return "byte";
|
||||
case EPropertyTypeNew::Short: return "short";
|
||||
case EPropertyTypeNew::Int: return "long";
|
||||
case EPropertyTypeNew::Enum: return "enum";
|
||||
case EPropertyTypeNew::Flags: return "bitfield";
|
||||
case EPropertyTypeNew::Float: return "float";
|
||||
case EPropertyTypeNew::String: return "string";
|
||||
case EPropertyTypeNew::Color: return "color";
|
||||
case EPropertyTypeNew::Vector: return "vector3f";
|
||||
case EPropertyTypeNew::Sound: return "sound";
|
||||
case EPropertyTypeNew::Asset: return "asset";
|
||||
case EPropertyTypeNew::Struct: return "struct";
|
||||
case EPropertyTypeNew::Array: return "array";
|
||||
case EPropertyTypeNew::AnimationSet: return "character";
|
||||
case EPropertyTypeNew::Spline: return "MayaSpline";
|
||||
|
||||
case eInvalidProperty:
|
||||
default:
|
||||
return "invalid";
|
||||
}
|
||||
}
|
||||
|
||||
EPropertyType PropStringToPropEnum(TString Prop)
|
||||
EPropertyTypeNew PropStringToPropEnum(TString Prop)
|
||||
{
|
||||
Prop = Prop.ToLower();
|
||||
if (Prop == "bool") return eBoolProperty;
|
||||
if (Prop == "byte") return eByteProperty;
|
||||
if (Prop == "short") return eShortProperty;
|
||||
if (Prop == "long") return eLongProperty;
|
||||
if (Prop == "enum") return eEnumProperty;
|
||||
if (Prop == "bitfield") return eBitfieldProperty;
|
||||
if (Prop == "float") return eFloatProperty;
|
||||
if (Prop == "string") return eStringProperty;
|
||||
if (Prop == "color") return eColorProperty;
|
||||
if (Prop == "vector3f") return eVector3Property;
|
||||
if (Prop == "sound") return eSoundProperty;
|
||||
if (Prop == "asset") return eAssetProperty;
|
||||
if (Prop == "struct") return eStructProperty;
|
||||
if (Prop == "array") return eArrayProperty;
|
||||
if (Prop == "character") return eCharacterProperty;
|
||||
if (Prop == "mayaspline") return eMayaSplineProperty;
|
||||
if (Prop == "unknown") return eUnknownProperty;
|
||||
return eInvalidProperty;
|
||||
if (Prop == "bool") return EPropertyTypeNew::Bool;
|
||||
if (Prop == "byte") return EPropertyTypeNew::Byte;
|
||||
if (Prop == "short") return EPropertyTypeNew::Short;
|
||||
if (Prop == "long") return EPropertyTypeNew::Int;
|
||||
if (Prop == "enum") return EPropertyTypeNew::Enum;
|
||||
if (Prop == "bitfield") return EPropertyTypeNew::Flags;
|
||||
if (Prop == "float") return EPropertyTypeNew::Float;
|
||||
if (Prop == "string") return EPropertyTypeNew::String;
|
||||
if (Prop == "color") return EPropertyTypeNew::Color;
|
||||
if (Prop == "vector3f") return EPropertyTypeNew::Vector;
|
||||
if (Prop == "sound") return EPropertyTypeNew::Sound;
|
||||
if (Prop == "asset") return EPropertyTypeNew::Asset;
|
||||
if (Prop == "struct") return EPropertyTypeNew::Struct;
|
||||
if (Prop == "array") return EPropertyTypeNew::Array;
|
||||
if (Prop == "character") return EPropertyTypeNew::AnimationSet;
|
||||
if (Prop == "mayaspline") return EPropertyTypeNew::Spline;
|
||||
return EPropertyTypeNew::Invalid;
|
||||
}
|
||||
|
||||
const char* HashablePropTypeName(EPropertyType Prop)
|
||||
const char* HashablePropTypeName(EPropertyTypeNew Prop)
|
||||
{
|
||||
// Variants that match Retro's internal type names for generating property IDs. case sensitive
|
||||
switch (Prop)
|
||||
{
|
||||
case eBoolProperty: return "bool";
|
||||
case eLongProperty: return "int";
|
||||
case eEnumProperty: return "enum";
|
||||
case eBitfieldProperty: return "Flags";
|
||||
case eFloatProperty: return "float";
|
||||
case eStringProperty: return "string";
|
||||
case eColorProperty: return "Color";
|
||||
case eVector3Property: return "Vector";
|
||||
case eSoundProperty: return "sound";
|
||||
case eAssetProperty: return "asset";
|
||||
case eMayaSplineProperty: return "spline";
|
||||
case EPropertyTypeNew::Bool: return "bool";
|
||||
case EPropertyTypeNew::Int: return "int";
|
||||
case EPropertyTypeNew::Enum: return "enum";
|
||||
case EPropertyTypeNew::Flags: return "Flags";
|
||||
case EPropertyTypeNew::Float: return "float";
|
||||
case EPropertyTypeNew::String: return "string";
|
||||
case EPropertyTypeNew::Color: return "Color";
|
||||
case EPropertyTypeNew::Vector: return "Vector";
|
||||
case EPropertyTypeNew::Sound: return "sound";
|
||||
case EPropertyTypeNew::Asset: return "asset";
|
||||
case EPropertyTypeNew::Spline: return "spline";
|
||||
|
||||
// All other types are either invalid or need a custom reimplementation because they can return multiple strings (like struct)
|
||||
default:
|
||||
|
@ -327,6 +326,7 @@ const char* HashablePropTypeName(EPropertyType Prop)
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// ************ DEBUG ************
|
||||
void CStructTemplate::DebugPrintProperties(TString base)
|
||||
{
|
||||
|
@ -343,3 +343,4 @@ void CStructTemplate::DebugPrintProperties(TString base)
|
|||
Log::Write(base + tmp->Name());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef IPROPERTYTEMPLATE
|
||||
#define IPROPERTYTEMPLATE
|
||||
|
||||
#if 0
|
||||
#include "EPropertyType.h"
|
||||
#include "IProperty.h"
|
||||
#include "IPropertyValue.h"
|
||||
|
@ -797,6 +798,7 @@ public:
|
|||
return (CPropertyStruct*) CStructTemplate::InstantiateProperty(pInstance, pArray);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // IPROPERTYTEMPLATE
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef IPROPERTYVALUE_H
|
||||
#define IPROPERTYVALUE_H
|
||||
|
||||
#if 0
|
||||
#include "EPropertyType.h"
|
||||
#include <Common/CAssetID.h>
|
||||
#include <Common/Log.h>
|
||||
|
@ -386,5 +387,6 @@ public:
|
|||
return new CUnknownValue(mValue);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // IPROPERTYVALUE_H
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef CANIMATIONPROPERTY_H
|
||||
#define CANIMATIONPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
class CAnimationProperty : public TTypedPropertyNew< int, EPropertyTypeNew::Animation >
|
||||
{
|
||||
friend class IPropertyNew;
|
||||
|
||||
protected:
|
||||
CAnimationProperty()
|
||||
: TTypedPropertyNew()
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual void SerializeValue(void* pData, IArchive& rArc) const
|
||||
{
|
||||
rArc.SerializeHexPrimitive( (u32&) ValueRef(pData) );
|
||||
}
|
||||
|
||||
virtual TString ValueAsString(void* pData) const
|
||||
{
|
||||
return TString::HexString( (u32) Value(pData) );
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CANIMATIONPROPERTY_H
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef CANIMATIONSETPROPERTY_H
|
||||
#define CANIMATIONSETPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
class CAnimationSetProperty : public TTypedPropertyNew< CAnimationParameters, EPropertyTypeNew::AnimationSet >
|
||||
{
|
||||
friend class IPropertyNew;
|
||||
|
||||
protected:
|
||||
CAnimationSetProperty()
|
||||
: TTypedPropertyNew()
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
Value(pData).Serialize(Arc);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CANIMATIONSETPROPERTY_H
|
|
@ -0,0 +1,176 @@
|
|||
#ifndef CARRAYPROPERTY_H
|
||||
#define CARRAYPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
struct SScriptArray
|
||||
{
|
||||
int Count;
|
||||
std::vector<char> Array;
|
||||
|
||||
SScriptArray()
|
||||
: Count(0)
|
||||
{}
|
||||
|
||||
inline bool operator==(const SScriptArray& rkOther) const
|
||||
{
|
||||
return( Count == rkOther.Count && Array == rkOther.Array );
|
||||
}
|
||||
};
|
||||
|
||||
/** You probably shouldn't use this on intrinsic classes; script only */
|
||||
/** @todo proper support of default values for arrays (this would be used for prefabs) */
|
||||
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.
|
||||
*/
|
||||
IPropertyNew* mpItemArchetype;
|
||||
|
||||
/** Internal functions */
|
||||
SScriptArray& _GetInternalArray(void* pData) const
|
||||
{
|
||||
return *( (SScriptArray*) RawValuePtr(pData) );
|
||||
}
|
||||
|
||||
u32 _InternalArrayCount(void* pPropertyData) const
|
||||
{
|
||||
std::vector<char>& rArray = _GetInternalArray(pPropertyData).Array;
|
||||
return rArray.size() / ItemSize();
|
||||
}
|
||||
|
||||
public:
|
||||
virtual u32 DataSize() const
|
||||
{
|
||||
return sizeof(SScriptArray);
|
||||
}
|
||||
|
||||
virtual u32 DataAlignment() const
|
||||
{
|
||||
return alignof(SScriptArray);
|
||||
}
|
||||
|
||||
virtual void Construct(void* pData) const
|
||||
{
|
||||
new(ValuePtr(pData)) SScriptArray;
|
||||
}
|
||||
|
||||
virtual void Destruct(void* pData) const
|
||||
{
|
||||
RevertToDefault(pData);
|
||||
TTypedPropertyNew::Destruct(pData);
|
||||
}
|
||||
|
||||
virtual bool MatchesDefault(void* pData) const
|
||||
{
|
||||
return ArrayCount(pData) == 0;
|
||||
}
|
||||
|
||||
virtual void RevertToDefault(void* pData) const
|
||||
{
|
||||
Resize(pData, 0);
|
||||
ValueRef(pData) = 0;
|
||||
}
|
||||
|
||||
virtual bool CanHaveDefault() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool IsPointerType() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void* GetChildDataPointer(void* pPropertyData) const
|
||||
{
|
||||
return _GetInternalArray(pPropertyData).Array.data();
|
||||
}
|
||||
|
||||
virtual void PropertyValueChanged(void* pPropertyData)
|
||||
{
|
||||
SScriptArray& rArray = _GetInternalArray(pPropertyData);
|
||||
rArray.Count = Math::Max(rArray.Count, 0);
|
||||
Resize(pPropertyData, rArray.Count);
|
||||
}
|
||||
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
u32 Count = ArrayCount(pData);
|
||||
Arc.SerializePrimitive(Count);
|
||||
|
||||
if (Arc.IsReader())
|
||||
Resize(pData, Count);
|
||||
|
||||
for (u32 ItemIdx = 0; ItemIdx < Count; ItemIdx++)
|
||||
{
|
||||
if (Arc.ParamBegin("ArrayElement"))
|
||||
{
|
||||
void* pItemData = ItemPointer(pData, ItemIdx);
|
||||
mpArchetype->SerializeValue(pItemData, Arc);
|
||||
Arc.ParamEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 ArrayCount(void* pPropertyData) const
|
||||
{
|
||||
return ValueRef(pPropertyData);
|
||||
}
|
||||
|
||||
void Resize(void* pPropertyData, u32 NewCount) const
|
||||
{
|
||||
u32 OldCount = _InternalArrayCount(pPropertyData);
|
||||
|
||||
if (OldCount != NewCount)
|
||||
{
|
||||
SScriptArray& rArray = _GetInternalArray(pPropertyData);
|
||||
|
||||
// Handle destruction of old elements
|
||||
if (OldCount > NewCount)
|
||||
{
|
||||
for (u32 ItemIdx = NewCount; ItemIdx < OldCount; ItemIdx++)
|
||||
{
|
||||
void* pItemPtr = ItemPointer(pPropertyData, ItemIdx);
|
||||
mpItemArchetype->Destruct(pItemPtr);
|
||||
}
|
||||
}
|
||||
|
||||
u32 NewSize = NewCount * ItemSize();
|
||||
rArray.Array.resize(NewSize);
|
||||
|
||||
// Handle construction of new elements
|
||||
if (NewCount > OldCount)
|
||||
{
|
||||
for (u32 ItemIdx = OldCount; ItemIdx < NewCount; ItemIdx++)
|
||||
{
|
||||
void* pItemPtr = ItemPointer(pPropertyData, ItemIdx);
|
||||
mpItemArchetype->Construct(pItemPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void* ItemPointer(void* pPropertyData, u32 ItemIndex) const
|
||||
{
|
||||
ASSERT(ArrayCount(pPropertyData) > ItemIndex);
|
||||
std::vector<char>& rArray = _GetInternalArray(pPropertyData).Array;
|
||||
u32 MyItemSize = ItemSize();
|
||||
ASSERT(rArray.size() >= (MyItemSize * (ItemIndex+1)));
|
||||
return rArray.data() + (MyItemSize * ItemIndex);
|
||||
}
|
||||
|
||||
u32 ItemSize() const
|
||||
{
|
||||
u32 ItemAlign = mpItemArchetype->DataAlignment();
|
||||
u32 ItemSize = ALIGN(mpItemArchetype->DataSize(), ItemAlign);
|
||||
return ItemSize;
|
||||
}
|
||||
|
||||
/** Accessors */
|
||||
IPropertyNew* ArchetypeProperty() const { return mpArchetype; }
|
||||
};
|
||||
|
||||
#endif // CARRAYPROPERTY_H
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef CASSETPROPERTY_H
|
||||
#define CASSETPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
#include "Core/Resource/CResTypeFilter.h"
|
||||
|
||||
class CAssetProperty : public TTypedPropertyNew<CAssetID, EPropertyTypeNew::Asset>
|
||||
{
|
||||
friend class CTemplateLoader;
|
||||
CResTypeFilter mTypeFilter;
|
||||
|
||||
public:
|
||||
#if 0
|
||||
virtual void Serialize(IArchive& rArc)
|
||||
{
|
||||
TTypedPropertyNew::Serialize(rArc);
|
||||
rArc << SERIAL("AcceptedTypes", mTypeFilter);
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
Arc.SerializePrimitive( ValueRef(pData) );
|
||||
}
|
||||
|
||||
virtual TString ValueAsString(void* pData) const
|
||||
{
|
||||
return Value(pData).ToString();
|
||||
}
|
||||
|
||||
void SetTypeFilter(const TStringList& rkExtensions)
|
||||
{
|
||||
mTypeFilter.SetAcceptedTypes(Game(), rkExtensions);
|
||||
}
|
||||
|
||||
const CResTypeFilter& GetTypeFilter() const
|
||||
{
|
||||
return mTypeFilter;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CASSETPROPERTY_H
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef CBOOLPROPERTY_H
|
||||
#define CBOOLPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
class CBoolProperty : public TTypedPropertyNew< bool, EPropertyTypeNew::Bool >
|
||||
{
|
||||
friend class IPropertyNew;
|
||||
|
||||
protected:
|
||||
CBoolProperty()
|
||||
: TTypedPropertyNew()
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
Arc.SerializePrimitive( ValueRef(pData) );
|
||||
}
|
||||
|
||||
virtual TString ValueAsString(void* pData)
|
||||
{
|
||||
return Value(pData) ? "true" : "false";
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CBOOLPROPERTY_H
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef CBYTEPROPERTY_H
|
||||
#define CBYTEPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
class CByteProperty : public TNumericalPropertyNew< char, EPropertyTypeNew::Byte >
|
||||
{
|
||||
friend class IPropertyNew;
|
||||
|
||||
protected:
|
||||
CByteProperty()
|
||||
: TNumericalPropertyNew()
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
Arc.SerializePrimitive( (u8&) ValueRef(pData) );
|
||||
}
|
||||
|
||||
virtual TString ValueAsString(void* pData)
|
||||
{
|
||||
return TString::FromInt32( (s32) Value(pData), 0, 10 );
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CBYTEPROPERTY_H
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef CCOLORPROPERTY_H
|
||||
#define CCOLORPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
class CColorProperty : public TTypedPropertyNew< CColor, EPropertyTypeNew::Color >
|
||||
{
|
||||
friend class IPropertyNew;
|
||||
|
||||
protected:
|
||||
CColorProperty()
|
||||
: TTypedPropertyNew()
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual void PostInitialize()
|
||||
{
|
||||
IPropertyNew* pR = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate);
|
||||
IPropertyNew* pG = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate);
|
||||
IPropertyNew* pB = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate);
|
||||
IPropertyNew* pA = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate);
|
||||
pR->SetName("R");
|
||||
pG->SetName("G");
|
||||
pB->SetName("B");
|
||||
pA->SetName("A");
|
||||
}
|
||||
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
Value(pData).Serialize(Arc);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CVECTORPROPERTY_H
|
|
@ -0,0 +1,124 @@
|
|||
#ifndef CENUMPROPERTY_H
|
||||
#define CENUMPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
/** 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
|
||||
* enum properties are stored as a hash of the name of the enum.
|
||||
*
|
||||
* In PWE, however, they are both implemented the same way under the hood.
|
||||
*/
|
||||
template<EPropertyTypeNew TypeEnum>
|
||||
class TEnumPropertyBase : public TTypedPropertyNew<int, TypeEnum>
|
||||
{
|
||||
friend class CTemplateLoader;
|
||||
struct SEnumValue
|
||||
{
|
||||
TString Name;
|
||||
u32 ID;
|
||||
|
||||
SEnumValue(const TString& rkInName, u32 InID)
|
||||
: Name(rkInName), ID(InID) {}
|
||||
|
||||
inline bool operator==(const SEnumValue& rkOther) const
|
||||
{
|
||||
return( Name == rkOther.Name && ID == rkOther.ID );
|
||||
}
|
||||
};
|
||||
std::vector<SEnumValue> mValues;
|
||||
|
||||
/** XML template file that this enum originated from; for archetypes */
|
||||
TString mSourceFile;
|
||||
|
||||
public:
|
||||
virtual const char* GetHashableTypeName() const
|
||||
{
|
||||
if (TypeEnum == EPropertyTypeNew::Enum)
|
||||
return "enum";
|
||||
else
|
||||
return "choice";
|
||||
}
|
||||
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
Arc.SerializePrimitive( (u32&) ValueRef(pData) );
|
||||
}
|
||||
|
||||
virtual TString GetTemplateFileName()
|
||||
{
|
||||
ASSERT(IsArchetype() || mpArchetype);
|
||||
return IsArchetype() ? mSourceFile : mpArchetype->GetTemplateFileName();
|
||||
}
|
||||
|
||||
inline u32 NumPossibleValues() const { return mValues.size(); }
|
||||
|
||||
u32 ValueIndex(u32 ID) const
|
||||
{
|
||||
for (u32 ValueIdx = 0; ValueIdx < mValues.size(); ValueIdx++)
|
||||
{
|
||||
if (mValues[ValueIdx].ID == ID)
|
||||
{
|
||||
return ValueIdx;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
u32 ValueID(u32 Index) const
|
||||
{
|
||||
ASSERT(Index >= 0 && Index < mValues.size());
|
||||
return mValues[Index].ID;
|
||||
}
|
||||
|
||||
TString ValueName(u32 Index) const
|
||||
{
|
||||
ASSERT(Index >= 0 && Index < mValues.size());
|
||||
return mValues[Index].Name;
|
||||
}
|
||||
|
||||
bool HasValidValue(void* pPropertyData)
|
||||
{
|
||||
int ID = ValueRef(pPropertyData);
|
||||
u32 Index = ValueIndex(ID);
|
||||
return Index >= 0 && Index < mValues.size();
|
||||
}
|
||||
};
|
||||
|
||||
typedef TEnumPropertyBase<EPropertyTypeNew::Choice> CChoiceProperty;
|
||||
typedef TEnumPropertyBase<EPropertyTypeNew::Enum> CEnumProperty;
|
||||
|
||||
// Specialization of TPropCast to allow interchangeable casting, as both types are the same thing
|
||||
template<>
|
||||
inline CEnumProperty* TPropCast(IPropertyNew* pProperty)
|
||||
{
|
||||
EPropertyTypeNew InType = pProperty->Type();
|
||||
|
||||
if (InType == EPropertyTypeNew::Enum || InType == EPropertyTypeNew::Choice)
|
||||
{
|
||||
return static_cast<CEnumProperty*>(pProperty);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
inline CChoiceProperty* TPropCast(IPropertyNew* pProperty)
|
||||
{
|
||||
if (pProperty)
|
||||
{
|
||||
EPropertyTypeNew InType = pProperty->Type();
|
||||
|
||||
if (InType == EPropertyTypeNew::Enum || InType == EPropertyTypeNew::Choice)
|
||||
{
|
||||
return static_cast<CChoiceProperty*>(pProperty);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif // CENUMPROPERTY_H
|
|
@ -0,0 +1,99 @@
|
|||
#ifndef CFLAGSPROPERTY_H
|
||||
#define CFLAGSPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
class CFlagsProperty : public TTypedPropertyNew<int, EPropertyTypeNew::Flags>
|
||||
{
|
||||
friend class CTemplateLoader;
|
||||
friend class IPropertyNew;
|
||||
|
||||
struct SBitFlag
|
||||
{
|
||||
TString Name;
|
||||
u32 Mask;
|
||||
|
||||
SBitFlag(const TString& rkInName, u32 InMask)
|
||||
: Name(rkInName), Mask(InMask)
|
||||
{}
|
||||
|
||||
bool operator==(const SBitFlag& rkOther) const
|
||||
{
|
||||
return( Name == rkOther.Name && Mask == rkOther.Mask );
|
||||
}
|
||||
|
||||
#if 0
|
||||
void Serialize(IArchive& rArc)
|
||||
{
|
||||
rArc << SERIAL("FlagName", Name)
|
||||
<< SERIAL_HEX("FlagMask", Mask);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
std::vector<SBitFlag> mBitFlags;
|
||||
u32 mAllFlags;
|
||||
|
||||
/** XML template file that this enum originated from; for archetypes */
|
||||
TString mSourceFile;
|
||||
|
||||
CFlagsProperty()
|
||||
: TTypedPropertyNew()
|
||||
, mAllFlags(0)
|
||||
{}
|
||||
|
||||
public:
|
||||
inline u32 NumFlags() const
|
||||
{
|
||||
return mBitFlags.size();
|
||||
}
|
||||
|
||||
inline TString FlagName(u32 Idx) const
|
||||
{
|
||||
ASSERT(Idx >= 0 && Idx < mBitFlags.size());
|
||||
return mBitFlags[Idx].Name;
|
||||
}
|
||||
|
||||
inline u32 FlagMask(u32 Idx) const
|
||||
{
|
||||
ASSERT(Idx >= 0 && Idx < mBitFlags.size());
|
||||
return mBitFlags[Idx].Mask;
|
||||
}
|
||||
|
||||
#if 0
|
||||
virtual void Serialize(IArchive& rArc)
|
||||
{
|
||||
TTypedPropertyNew::Serialize(rArc);
|
||||
rArc << SERIAL_CONTAINER("Flags", mFlags, "Flag");
|
||||
|
||||
// Initialize the "all flags" cache
|
||||
if (rArc.IsReader())
|
||||
{
|
||||
mAllFlags = 0;
|
||||
for (u32 FlagIdx = 0; FlagIdx < mFlags.size(); FlagIdx++)
|
||||
mAllFlags |= mFlags[FlagIdx].Mask;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void SerializeValue(void* pData, IArchive& rArc) const
|
||||
{
|
||||
rArc.SerializeHexPrimitive( (u32&) ValueRef(pData) );
|
||||
}
|
||||
|
||||
virtual TString GetTemplateFileName()
|
||||
{
|
||||
ASSERT(IsArchetype() || mpArchetype);
|
||||
return IsArchetype() ? mSourceFile : mpArchetype->GetTemplateFileName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether there are any unrecognized bits toggled on in the property value.
|
||||
* Returns the mask of any invalid bits. If all bits are valid, returns 0.
|
||||
*/
|
||||
u32 HasValidValue(void* pPropertyData)
|
||||
{
|
||||
return ValueRef(pPropertyData) & ~mAllFlags;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CFLAGSPROPERTY_H
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef CFLOATPROPERTY_H
|
||||
#define CFLOATPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
class CFloatProperty : public TNumericalPropertyNew< float, EPropertyTypeNew::Float >
|
||||
{
|
||||
friend class IPropertyNew;
|
||||
|
||||
protected:
|
||||
CFloatProperty()
|
||||
: TNumericalPropertyNew()
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
Arc.SerializePrimitive( (float&) ValueRef(pData) );
|
||||
}
|
||||
|
||||
virtual TString ValueAsString(void* pData)
|
||||
{
|
||||
return TString::FromFloat( Value(pData) );
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CFLOATPROPERTY_H
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef CGUIDPROPERTY_H
|
||||
#define CGUIDPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
class CGuidProperty : public TTypedPropertyNew< std::vector<char>, EPropertyTypeNew::Guid >
|
||||
{
|
||||
friend class IPropertyNew;
|
||||
|
||||
protected:
|
||||
CGuidProperty()
|
||||
: TTypedPropertyNew()
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
Arc.SerializeBulkData( ValueRef(pData) );
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CSPLINEPROPERTY_H
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef CINTPROPERTY_H
|
||||
#define CINTPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
class CIntProperty : public TNumericalPropertyNew< int, EPropertyTypeNew::Int >
|
||||
{
|
||||
friend class IPropertyNew;
|
||||
|
||||
protected:
|
||||
CIntProperty()
|
||||
: TNumericalPropertyNew()
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
Arc.SerializePrimitive( (u32&) ValueRef(pData) );
|
||||
}
|
||||
|
||||
virtual TString ValueAsString(void* pData)
|
||||
{
|
||||
return TString::FromInt32( Value(pData), 0, 10 );
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CINTPROPERTY_H
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef CPOINTERPROPERTY_H
|
||||
#define CPOINTERPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
class CPointerProperty : public TTypedPropertyNew<void*, EPropertyTypeNew::Pointer>
|
||||
{
|
||||
friend class CTemplateLoader;
|
||||
public:
|
||||
virtual bool IsPointerType() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void* GetChildDataPointer(void* pPropertyData) const
|
||||
{
|
||||
return ValueRef(pPropertyData);
|
||||
}
|
||||
|
||||
virtual void SerializeValue(void* pData, IArchive& rArc) const
|
||||
{
|
||||
// pointers are not serializable, this shouldn't happen
|
||||
ASSERT(false);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CPOINTERPROPERTY_H
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef CSEQUENCEPROPERTY_H
|
||||
#define CSEQUENCEPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
class CSequenceProperty : public TTypedPropertyNew< int, EPropertyTypeNew::Sequence >
|
||||
{
|
||||
friend class IPropertyNew;
|
||||
|
||||
protected:
|
||||
CSequenceProperty()
|
||||
: TTypedPropertyNew()
|
||||
{}
|
||||
|
||||
virtual void SerializeValue(void* pData, IArchive& rArc) const
|
||||
{}
|
||||
};
|
||||
|
||||
#endif // CSEQUENCEPROPERTY_H
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef CSHORTPROPERTY_H
|
||||
#define CSHORTPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
class CShortProperty : public TNumericalPropertyNew< short, EPropertyTypeNew::Short >
|
||||
{
|
||||
friend class IPropertyNew;
|
||||
|
||||
protected:
|
||||
CShortProperty()
|
||||
: TNumericalPropertyNew()
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
Arc.SerializePrimitive( (u16&) ValueRef(pData) );
|
||||
}
|
||||
|
||||
virtual TString ValueAsString(void* pData)
|
||||
{
|
||||
return TString::FromInt32( (s32) Value(pData), 0, 10 );
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CSHORTPROPERTY_H
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef CSOUNDPROPERTY_H
|
||||
#define CSOUNDPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
class CSoundProperty : public TTypedPropertyNew< int, EPropertyTypeNew::Sound >
|
||||
{
|
||||
friend class IPropertyNew;
|
||||
|
||||
protected:
|
||||
CSoundProperty()
|
||||
: TTypedPropertyNew()
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
Arc.SerializePrimitive( (u32&) ValueRef(pData) );
|
||||
}
|
||||
|
||||
virtual TString ValueAsString(void* pData)
|
||||
{
|
||||
return TString::FromInt32( Value(pData), 0, 10 );
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CSOUNDPROPERTY_H
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef CSPLINEPROPERTY_H
|
||||
#define CSPLINEPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
class CSplineProperty : public TTypedPropertyNew< std::vector<char>, EPropertyTypeNew::Spline >
|
||||
{
|
||||
friend class IPropertyNew;
|
||||
|
||||
protected:
|
||||
CSplineProperty()
|
||||
: TTypedPropertyNew()
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
Arc.SerializeBulkData( ValueRef(pData) );
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CSPLINEPROPERTY_H
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef CSTRINGPROPERTY_H
|
||||
#define CSTRINGPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
class CStringProperty : public TTypedPropertyNew< TString, EPropertyTypeNew::String >
|
||||
{
|
||||
friend class IPropertyNew;
|
||||
|
||||
protected:
|
||||
CStringProperty()
|
||||
: TTypedPropertyNew()
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
Arc.SerializePrimitive( ValueRef(pData) );
|
||||
}
|
||||
|
||||
virtual TString ValueAsString(void* pData) const
|
||||
{
|
||||
return Value(pData);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CSTRINGPROPERTY_H
|
|
@ -0,0 +1,146 @@
|
|||
#ifndef CSTRUCTPROPERTY_H
|
||||
#define CSTRUCTPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
class CStructPropertyNew : public IPropertyNew
|
||||
{
|
||||
friend class CTemplateLoader;
|
||||
|
||||
public:
|
||||
// Must be a valid type for TPropertyRef
|
||||
typedef void* ValueType;
|
||||
|
||||
protected:
|
||||
/** For archetypes, the filename of the template XML file. */
|
||||
TString mTemplateFileName;
|
||||
|
||||
public:
|
||||
virtual EPropertyTypeNew Type() const
|
||||
{
|
||||
return EPropertyTypeNew::Struct;
|
||||
}
|
||||
|
||||
virtual u32 DataSize() const
|
||||
{
|
||||
if (!mChildren.empty())
|
||||
{
|
||||
IPropertyNew* pLastChild = mChildren.back();
|
||||
return _GetOffset() + pLastChild->DataSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
virtual u32 DataAlignment() const
|
||||
{
|
||||
return (mChildren.empty() ? 1 : mChildren[0]->DataAlignment());
|
||||
}
|
||||
|
||||
virtual void Construct(void* pData) const
|
||||
{
|
||||
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
||||
{
|
||||
mChildren[ChildIdx]->Construct(pData);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Destruct(void* pData) const
|
||||
{
|
||||
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
||||
{
|
||||
mChildren[ChildIdx]->Destruct(pData);
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool MatchesDefault(void* pData) const
|
||||
{
|
||||
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
||||
{
|
||||
if (!mChildren[ChildIdx]->MatchesDefault(pData))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void RevertToDefault(void* pData) const
|
||||
{
|
||||
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
||||
{
|
||||
mChildren[ChildIdx]->RevertToDefault(pData);
|
||||
}
|
||||
}
|
||||
|
||||
virtual const char* HashableTypeName() const
|
||||
{
|
||||
ASSERT(IsArchetype() || mpArchetype != nullptr);
|
||||
|
||||
if (IsArchetype())
|
||||
return *mName;
|
||||
else
|
||||
return *mpArchetype->Name();
|
||||
}
|
||||
|
||||
#if 0
|
||||
virtual void Serialize(IArchive& rArc)
|
||||
{
|
||||
IPropertyNew::Serialize(rArc);
|
||||
|
||||
if (rArc.ParamBegin("SubProperties"))
|
||||
{
|
||||
u32 NumChildren;
|
||||
rArc.SerializeContainerSize(NumChildren, "Property");
|
||||
|
||||
if (rArc.IsReader())
|
||||
{
|
||||
mChildren.resize(NumChildren);
|
||||
}
|
||||
|
||||
for (u32 ChildIdx = 0; ChildIdx < NumChildren; ChildIdx++)
|
||||
{
|
||||
if (rArc.ParamBegin("Property"))
|
||||
{
|
||||
EPropertyTypeNew Type = (rArc.IsWriter() ? mChildren[ChildIdx]->Type() : EPropertyTypeNew::Invalid);
|
||||
rArc << SERIAL_AUTO(Type);
|
||||
|
||||
if (rArc.IsReader())
|
||||
{
|
||||
mChildren[ChildIdx] = Create(Type, this, mpMasterTemplate, mpScriptTemplate);
|
||||
}
|
||||
|
||||
mChildren[ChildIdx]->Serialize(rArc);
|
||||
rArc.ParamEnd();
|
||||
}
|
||||
}
|
||||
|
||||
rArc.ParamEnd();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
for (u32 ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
||||
{
|
||||
if (Arc.ParamBegin("Property"))
|
||||
{
|
||||
mChildren[ChildIdx]->SerializeValue(pData, Arc);
|
||||
Arc.ParamEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual TString GetTemplateFileName()
|
||||
{
|
||||
ASSERT(IsArchetype() || mpArchetype);
|
||||
return IsArchetype() ? mTemplateFileName : mpArchetype->GetTemplateFileName();
|
||||
}
|
||||
|
||||
inline static EPropertyTypeNew StaticType() { return EPropertyTypeNew::Struct; }
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef CVECTORPROPERTY_H
|
||||
#define CVECTORPROPERTY_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
|
||||
class CVectorProperty : public TTypedPropertyNew< CVector3f, EPropertyTypeNew::Vector >
|
||||
{
|
||||
friend class IPropertyNew;
|
||||
|
||||
protected:
|
||||
CVectorProperty()
|
||||
: TTypedPropertyNew()
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual void PostInitialize()
|
||||
{
|
||||
IPropertyNew* pX = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate);
|
||||
IPropertyNew* pY = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate);
|
||||
IPropertyNew* pZ = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate);
|
||||
pX->SetName("X");
|
||||
pY->SetName("Y");
|
||||
pZ->SetName("Z");
|
||||
}
|
||||
|
||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||
{
|
||||
ValueRef(pData).Serialize(Arc);
|
||||
}
|
||||
|
||||
virtual TString ValueAsString(void* pData) const
|
||||
{
|
||||
return Value(pData).ToString();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CVECTORPROPERTY_H
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef PROPERTIES_H
|
||||
#define PROPERTIES_H
|
||||
|
||||
#include "../IPropertyNew.h"
|
||||
#include "CAnimationProperty.h"
|
||||
#include "CAnimationSetProperty.h"
|
||||
#include "CArrayProperty.h"
|
||||
#include "CAssetProperty.h"
|
||||
#include "CBoolProperty.h"
|
||||
#include "CByteProperty.h"
|
||||
#include "CColorProperty.h"
|
||||
#include "CEnumProperty.h"
|
||||
#include "CFlagsProperty.h"
|
||||
#include "CFloatProperty.h"
|
||||
#include "CGuidProperty.h"
|
||||
#include "CIntProperty.h"
|
||||
#include "CPointerProperty.h"
|
||||
#include "CSequenceProperty.h"
|
||||
#include "CShortProperty.h"
|
||||
#include "CSoundProperty.h"
|
||||
#include "CSplineProperty.h"
|
||||
#include "CStringProperty.h"
|
||||
#include "CStructProperty.h"
|
||||
#include "CVectorProperty.h"
|
||||
#include "TPropertyRef.h"
|
||||
|
||||
#endif // PROPERTIES_H
|
|
@ -0,0 +1,113 @@
|
|||
#ifndef TPROPERTYREF_H
|
||||
#define TPROPERTYREF_H
|
||||
|
||||
#include "CAnimationProperty.h"
|
||||
#include "CAnimationSetProperty.h"
|
||||
#include "CArrayProperty.h"
|
||||
#include "CAssetProperty.h"
|
||||
#include "CBoolProperty.h"
|
||||
#include "CByteProperty.h"
|
||||
#include "CColorProperty.h"
|
||||
#include "CEnumProperty.h"
|
||||
#include "CFlagsProperty.h"
|
||||
#include "CFloatProperty.h"
|
||||
#include "CGuidProperty.h"
|
||||
#include "CIntProperty.h"
|
||||
#include "CPointerProperty.h"
|
||||
#include "CSequenceProperty.h"
|
||||
#include "CShortProperty.h"
|
||||
#include "CSoundProperty.h"
|
||||
#include "CSplineProperty.h"
|
||||
#include "CStringProperty.h"
|
||||
#include "CStructProperty.h"
|
||||
#include "CVectorProperty.h"
|
||||
|
||||
/** TPropertyRef: Embeds a reference to a property on a specific script object */
|
||||
template<class PropertyClass, typename ValueType = PropertyClass::ValueType>
|
||||
class TPropertyRef
|
||||
{
|
||||
/** Script object containing the property data being referenced */
|
||||
CScriptObject* mpObject;
|
||||
|
||||
/** Property being referenced */
|
||||
PropertyClass* mpProperty;
|
||||
|
||||
public:
|
||||
TPropertyRef()
|
||||
: mpObject(nullptr), mpProperty(nullptr)
|
||||
{}
|
||||
|
||||
TPropertyRef(CScriptObject* pInObject, IPropertyNew* pInProperty)
|
||||
: mpObject(pInObject), mpProperty( TPropCast<PropertyClass>(pInProperty) )
|
||||
{
|
||||
}
|
||||
|
||||
TPropertyRef(CScriptObject* pInObject, PropertyClass* pInProperty)
|
||||
: mpObject(pInObject), mpProperty(pInProperty)
|
||||
{
|
||||
}
|
||||
|
||||
/** 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 void Set(const ValueType& kIn) const { if (IsValid()) *((ValueType*) mpProperty->RawValuePtr( mpObject->PropertyData() )) = kIn; }
|
||||
inline bool IsValid() const { return mpObject != nullptr && mpProperty != nullptr; }
|
||||
|
||||
/** Inline operators */
|
||||
inline operator ValueType() const
|
||||
{
|
||||
return Get();
|
||||
}
|
||||
|
||||
inline bool operator==(IPropertyNew* pProperty) const
|
||||
{
|
||||
return mpProperty == pProperty;
|
||||
}
|
||||
|
||||
friend bool operator==(IPropertyNew* pLeft, const TPropertyRef& kRight)
|
||||
{
|
||||
return pLeft == kRight.Property();
|
||||
}
|
||||
};
|
||||
|
||||
/** Convenience typedefs */
|
||||
typedef TPropertyRef<CBoolProperty> CBoolRef;
|
||||
typedef TPropertyRef<CByteProperty> CByteRef;
|
||||
typedef TPropertyRef<CShortProperty> CShortRef;
|
||||
typedef TPropertyRef<CIntProperty> CIntRef;
|
||||
typedef TPropertyRef<CFloatProperty> CFloatRef;
|
||||
typedef TPropertyRef<CFlagsProperty> CFlagsRef;
|
||||
typedef TPropertyRef<CStringProperty> CStringRef;
|
||||
typedef TPropertyRef<CVectorProperty> CVectorRef;
|
||||
typedef TPropertyRef<CColorProperty> CColorRef;
|
||||
typedef TPropertyRef<CAssetProperty> CAssetRef;
|
||||
typedef TPropertyRef<CSoundProperty> CSoundRef;
|
||||
typedef TPropertyRef<CAnimationProperty> CAnimationRef;
|
||||
typedef TPropertyRef<CAnimationSetProperty> CAnimationSetRef;
|
||||
typedef TPropertyRef<CSequenceProperty> CSequenceRef;
|
||||
typedef TPropertyRef<CSplineProperty> CSplineRef;
|
||||
typedef TPropertyRef<CGuidProperty> CGuidRef;
|
||||
typedef TPropertyRef<CPointerProperty> CPointerRef;
|
||||
typedef TPropertyRef<CStructPropertyNew> CStructRef;
|
||||
typedef TPropertyRef<CArrayProperty> CArrayRef;
|
||||
|
||||
/** Special version for enums */
|
||||
template<typename ValueType>
|
||||
class TEnumRef : public TPropertyRef<CEnumProperty, ValueType>
|
||||
{
|
||||
public:
|
||||
TEnumRef()
|
||||
: TPropertyRef()
|
||||
{}
|
||||
|
||||
TEnumRef(CScriptObject* pInObject, IPropertyNew* pInProperty)
|
||||
: TPropertyRef(pInObject, pInProperty)
|
||||
{}
|
||||
|
||||
TEnumRef(CScriptObject* pInObject, CEnumProperty* pInProperty)
|
||||
: TPropertyRef(pInObject, pInProperty)
|
||||
{}
|
||||
};
|
||||
|
||||
#endif // TPROPERTYREF_H
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef TPROPERTYPROXY_H
|
||||
#define TPROPERTYPROXY_H
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
/**
|
||||
* Lightweight proxy class representing a property instance. Easy to read/modify
|
||||
* specific properties and efficient to pass around.
|
||||
*/
|
||||
template<class PropertyClass>
|
||||
class TPropertyProxy
|
||||
{
|
||||
typedef PropertyClass::ValueType ValueType;
|
||||
|
||||
/** Property data buffer */
|
||||
void* mpDataPtr;
|
||||
|
||||
/** Source property */
|
||||
PropertyClass* mpProperty;
|
||||
|
||||
public:
|
||||
TPropertyProxy()
|
||||
: mpDataPtr(nullptr)
|
||||
, mpProperty(nullptr)
|
||||
{}
|
||||
|
||||
TPropertyProxy(void* pDataPtr, PropertyClass* pProperty)
|
||||
: mpDataPtr(pDataPtr)
|
||||
, mpProperty(pProperty)
|
||||
{}
|
||||
|
||||
/** Returns whether this proxy points to a valid property instance */
|
||||
bool IsValid() const
|
||||
{
|
||||
return mpDataPtr != nullptr && mpProperty != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // TPROPERTYPROXY_H
|
|
@ -10,8 +10,11 @@ CScriptAttachNode::CScriptAttachNode(CScene *pScene, const SAttachment& rkAttach
|
|||
, mAttachType(rkAttachment.AttachType)
|
||||
, mLocatorName(rkAttachment.LocatorName)
|
||||
{
|
||||
CPropertyStruct *pBaseStruct = pParent->Instance()->Properties();
|
||||
mpAttachAssetProp = pBaseStruct->PropertyByIDString(rkAttachment.AttachProperty);
|
||||
CStructPropertyNew* pBaseStruct = pParent->Template()->Properties();
|
||||
|
||||
mpAttachAssetProp = pBaseStruct->ChildByIDString(rkAttachment.AttachProperty);
|
||||
mAttachAssetRef = CAssetRef(pParent->Instance(), mpAttachAssetProp);
|
||||
mAttachAnimSetRef = CAnimationSetRef(pParent->Instance(), mpAttachAssetProp);
|
||||
if (mpAttachAssetProp) AttachPropertyModified();
|
||||
|
||||
ParentDisplayAssetChanged(mpScriptNode->DisplayAsset());
|
||||
|
@ -21,12 +24,12 @@ void CScriptAttachNode::AttachPropertyModified()
|
|||
{
|
||||
if (mpAttachAssetProp)
|
||||
{
|
||||
if (mpAttachAssetProp->Type() == eAssetProperty)
|
||||
mpAttachAsset = gpResourceStore->LoadResource<CModel>( TPropCast<TAssetProperty>(mpAttachAssetProp)->Get() );
|
||||
else if (mpAttachAssetProp->Type() == eCharacterProperty)
|
||||
mpAttachAsset = TPropCast<TCharacterProperty>(mpAttachAssetProp)->Get().AnimSet();
|
||||
if (mAttachAssetRef.IsValid())
|
||||
mpAttachAsset = gpResourceStore->LoadResource<CModel>(mAttachAssetRef.Get());
|
||||
else if (mAttachAnimSetRef.IsValid())
|
||||
mpAttachAsset = mAttachAnimSetRef.Get().AnimSet();
|
||||
|
||||
CModel *pModel = Model();
|
||||
CModel* pModel = Model();
|
||||
|
||||
if (pModel && pModel->Type() == eModel)
|
||||
mLocalAABox = pModel->AABox();
|
||||
|
@ -37,11 +40,11 @@ void CScriptAttachNode::AttachPropertyModified()
|
|||
}
|
||||
}
|
||||
|
||||
void CScriptAttachNode::ParentDisplayAssetChanged(CResource *pNewDisplayAsset)
|
||||
void CScriptAttachNode::ParentDisplayAssetChanged(CResource* pNewDisplayAsset)
|
||||
{
|
||||
if (pNewDisplayAsset->Type() == eAnimSet)
|
||||
{
|
||||
CSkeleton *pSkel = mpScriptNode->ActiveSkeleton();
|
||||
CSkeleton* pSkel = mpScriptNode->ActiveSkeleton();
|
||||
mpLocator = pSkel->BoneByName(mLocatorName);
|
||||
}
|
||||
|
||||
|
@ -60,11 +63,8 @@ CModel* CScriptAttachNode::Model() const
|
|||
if (mpAttachAsset->Type() == eModel)
|
||||
return static_cast<CModel*>(mpAttachAsset.RawPointer());
|
||||
|
||||
if (mpAttachAsset->Type() == eAnimSet)
|
||||
{
|
||||
TCharacterProperty *pProp = TPropCast<TCharacterProperty>(mpAttachAssetProp);
|
||||
return pProp->Get().GetCurrentModel();
|
||||
}
|
||||
else if (mpAttachAsset->Type() == eAnimSet)
|
||||
return mAttachAnimSetRef.Get().GetCurrentModel();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
|
|
@ -2,20 +2,23 @@
|
|||
#define CSCRIPTATTACHNODE_H
|
||||
|
||||
#include "CSceneNode.h"
|
||||
#include "Core/Resource/Script/IProperty.h"
|
||||
#include "Core/Resource/Script/Property/Properties.h"
|
||||
#include "Core/Resource/Script/CScriptTemplate.h"
|
||||
|
||||
class CScriptNode;
|
||||
|
||||
class CScriptAttachNode : public CSceneNode
|
||||
{
|
||||
CScriptNode *mpScriptNode;
|
||||
CScriptNode* mpScriptNode;
|
||||
TResPtr<CResource> mpAttachAsset;
|
||||
IProperty *mpAttachAssetProp;
|
||||
|
||||
IPropertyNew* mpAttachAssetProp;
|
||||
CAssetRef mAttachAssetRef;
|
||||
CAnimationSetRef mAttachAnimSetRef;
|
||||
|
||||
EAttachType mAttachType;
|
||||
TString mLocatorName;
|
||||
CBone *mpLocator;
|
||||
CBone* mpLocator;
|
||||
|
||||
public:
|
||||
explicit CScriptAttachNode(CScene *pScene, const SAttachment& rkAttachment, CScriptNode *pParent);
|
||||
|
@ -30,7 +33,7 @@ public:
|
|||
void RayAABoxIntersectTest(CRayCollisionTester& rTester, const SViewInfo& rkViewInfo);
|
||||
SRayIntersection RayNodeIntersectTest(const CRay& rkRay, u32 AssetID, const SViewInfo& rkViewInfo);
|
||||
|
||||
inline IProperty* AttachProperty() const { return mpAttachAssetProp; }
|
||||
inline IPropertyNew* AttachProperty() const { return mpAttachAssetProp; }
|
||||
inline TString LocatorName() const { return mLocatorName; }
|
||||
|
||||
protected:
|
||||
|
|
|
@ -31,7 +31,7 @@ CScriptNode::CScriptNode(CScene *pScene, u32 NodeID, CSceneNode *pParent, CScrip
|
|||
CScriptTemplate *pTemp = Template();
|
||||
|
||||
// Determine transform
|
||||
mHasValidPosition = pTemp->HasPosition();
|
||||
mHasValidPosition = pTemp->PositionProperty() != nullptr;
|
||||
mPosition = mpInstance->Position();
|
||||
mRotation = CQuaternion::FromEuler(mpInstance->Rotation());
|
||||
mScale = mpInstance->Scale();
|
||||
|
@ -99,15 +99,13 @@ void CScriptNode::OnTransformed()
|
|||
{
|
||||
if (mpInstance)
|
||||
{
|
||||
CScriptTemplate *pTemplate = Template();
|
||||
|
||||
if (pTemplate->HasPosition() && LocalPosition() != mpInstance->Position())
|
||||
if (LocalPosition() != mpInstance->Position())
|
||||
mpInstance->SetPosition(LocalPosition());
|
||||
|
||||
if (pTemplate->HasRotation() && LocalRotation().ToEuler() != mpInstance->Rotation())
|
||||
if (LocalRotation().ToEuler() != mpInstance->Rotation())
|
||||
mpInstance->SetRotation(LocalRotation().ToEuler());
|
||||
|
||||
if (pTemplate->HasScale() && LocalScale() != mpInstance->Scale())
|
||||
if (LocalScale() != mpInstance->Scale())
|
||||
mpInstance->SetScale(LocalScale());
|
||||
}
|
||||
|
||||
|
@ -456,27 +454,29 @@ void CScriptNode::LinksModified()
|
|||
if (mpExtra) mpExtra->LinksModified();
|
||||
}
|
||||
|
||||
void CScriptNode::PropertyModified(IProperty *pProp)
|
||||
void CScriptNode::PropertyModified(IPropertyNew* pProp)
|
||||
{
|
||||
// Update volume
|
||||
if ( (pProp->Type() == eBoolProperty) || (pProp->Type() == eByteProperty) || (pProp->Type() == eShortProperty) ||
|
||||
(pProp->Type() == eLongProperty) || (pProp->Type() == eEnumProperty) )
|
||||
EPropertyTypeNew Type = pProp->Type();
|
||||
|
||||
if ( Type == EPropertyTypeNew::Bool || Type == EPropertyTypeNew::Byte || Type == EPropertyTypeNew::Short ||
|
||||
Type == EPropertyTypeNew::Int || Type == EPropertyTypeNew::Choice || Type == EPropertyTypeNew::Enum )
|
||||
{
|
||||
mpInstance->EvaluateVolume();
|
||||
UpdatePreviewVolume();
|
||||
}
|
||||
|
||||
// Update resources
|
||||
if (pProp->Type() == eCharacterProperty)
|
||||
else if (Type == EPropertyTypeNew::AnimationSet)
|
||||
{
|
||||
mpInstance->EvaluateDisplayAsset();
|
||||
SetDisplayAsset(mpInstance->DisplayAsset());
|
||||
}
|
||||
|
||||
else if (pProp->Type() == eAssetProperty)
|
||||
else if (Type == EPropertyTypeNew::Asset)
|
||||
{
|
||||
CAssetTemplate *pAssetTemp = static_cast<CAssetTemplate*>(pProp->Template());
|
||||
const CResTypeFilter& rkFilter = pAssetTemp->TypeFilter();
|
||||
CAssetProperty* pAssetProperty = TPropCast<CAssetProperty>(pProp);
|
||||
const CResTypeFilter& rkFilter = pAssetProperty->GetTypeFilter();
|
||||
|
||||
if (rkFilter.Accepts(eModel) || rkFilter.Accepts(eTexture) || rkFilter.Accepts(eAnimSet) || rkFilter.Accepts(eCharacter))
|
||||
{
|
||||
|
@ -491,40 +491,37 @@ void CScriptNode::PropertyModified(IProperty *pProp)
|
|||
}
|
||||
|
||||
// Update other editor properties
|
||||
if (mpInstance->IsEditorProperty(pProp))
|
||||
{
|
||||
CScriptTemplate *pTemplate = Template();
|
||||
CScriptTemplate *pTemplate = Template();
|
||||
|
||||
if (pTemplate->HasName())
|
||||
SetName("[" + mpInstance->Template()->Name() + "] " + mpInstance->InstanceName());
|
||||
if (pProp == pTemplate->NameProperty())
|
||||
SetName("[" + mpInstance->Template()->Name() + "] " + mpInstance->InstanceName());
|
||||
|
||||
if (pTemplate->HasPosition())
|
||||
mPosition = mpInstance->Position();
|
||||
else if (pProp == pTemplate->PositionProperty())
|
||||
mPosition = mpInstance->Position();
|
||||
|
||||
if (pTemplate->HasRotation())
|
||||
mRotation = CQuaternion::FromEuler(mpInstance->Rotation());
|
||||
else if (pProp == pTemplate->RotationProperty())
|
||||
mRotation = CQuaternion::FromEuler(mpInstance->Rotation());
|
||||
|
||||
if (pTemplate->HasScale())
|
||||
mScale = mpInstance->Scale();
|
||||
else if (pProp == pTemplate->ScaleProperty())
|
||||
mScale = mpInstance->Scale();
|
||||
|
||||
MarkTransformChanged();
|
||||
SetLightLayerIndex(mpLightParameters->LightLayerIndex());
|
||||
}
|
||||
MarkTransformChanged();
|
||||
SetLightLayerIndex(mpLightParameters->LightLayerIndex());
|
||||
|
||||
// Notify attachments
|
||||
for (u32 iAttach = 0; iAttach < mAttachments.size(); iAttach++)
|
||||
for (u32 AttachIdx = 0; AttachIdx < mAttachments.size(); AttachIdx++)
|
||||
{
|
||||
CScriptAttachNode *pAttach = mAttachments[iAttach];
|
||||
CScriptAttachNode* pAttachNode = mAttachments[AttachIdx];
|
||||
|
||||
if (pAttach->AttachProperty() == pProp)
|
||||
pAttach->AttachPropertyModified();
|
||||
if (pAttachNode->AttachProperty() == pProp)
|
||||
pAttachNode->AttachPropertyModified();
|
||||
}
|
||||
|
||||
// Notify script extra
|
||||
if (mpExtra) mpExtra->PropertyModified(pProp);
|
||||
|
||||
// Update game mode visibility
|
||||
if (pProp && pProp == mpInstance->ActiveProperty())
|
||||
if (pProp && pProp == pTemplate->ActiveProperty())
|
||||
TestGameModeVisibility();
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
CColor WireframeColor() const;
|
||||
|
||||
void LinksModified();
|
||||
void PropertyModified(IProperty *pProp);
|
||||
void PropertyModified(IPropertyNew* pProp);
|
||||
void UpdatePreviewVolume();
|
||||
void GeneratePosition();
|
||||
void TestGameModeVisibility();
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
CDamageableTriggerExtra::CDamageableTriggerExtra(CScriptObject *pInstance, CScene *pScene, CScriptNode *pParent)
|
||||
: CScriptExtra(pInstance, pScene, pParent)
|
||||
, mpRenderSideProp(nullptr)
|
||||
, mpMat(nullptr)
|
||||
{
|
||||
for (u32 iTex = 0; iTex < 3; iTex++)
|
||||
|
@ -15,21 +14,21 @@ CDamageableTriggerExtra::CDamageableTriggerExtra(CScriptObject *pInstance, CScen
|
|||
SetInheritance(true, false, false);
|
||||
CreateMaterial();
|
||||
|
||||
CPropertyStruct *pBaseStruct = pInstance->Properties();
|
||||
CStructPropertyNew* pProperties = pInstance->Template()->Properties();
|
||||
|
||||
// Fetch render side
|
||||
mpRenderSideProp = TPropCast<TEnumProperty>(pBaseStruct->PropertyByIndex(0x5));
|
||||
if (mpRenderSideProp) PropertyModified(mpRenderSideProp);
|
||||
mRenderSide = TEnumRef<ERenderSide>(pInstance, pProperties->ChildByIndex(5));
|
||||
if (mRenderSide.IsValid()) PropertyModified(mRenderSide.Property());
|
||||
|
||||
// Fetch scale
|
||||
mpSizeProp = TPropCast<TVector3Property>(pBaseStruct->PropertyByIndex(0x2));
|
||||
if (mpSizeProp) PropertyModified(mpSizeProp);
|
||||
mPlaneSize = CVectorRef(pInstance, pProperties->ChildByIndex(2));
|
||||
if (mPlaneSize.IsValid()) PropertyModified(mPlaneSize.Property());
|
||||
|
||||
// Fetch textures
|
||||
for (u32 iTex = 0; iTex < 3; iTex++)
|
||||
for (u32 TextureIdx = 0; TextureIdx < 3; TextureIdx++)
|
||||
{
|
||||
mpTextureProps[iTex] = TPropCast<TAssetProperty>(pBaseStruct->PropertyByIndex(0x6 + iTex));
|
||||
if (mpTextureProps[iTex]) PropertyModified(mpTextureProps[iTex]);
|
||||
mTextureAssets[TextureIdx] = CAssetRef(pInstance, pProperties->ChildByIndex(6 + TextureIdx));
|
||||
if (mTextureAssets[TextureIdx].IsValid()) PropertyModified(mTextureAssets[TextureIdx].Property());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,7 +79,7 @@ void CDamageableTriggerExtra::CreateMaterial()
|
|||
|
||||
void CDamageableTriggerExtra::UpdatePlaneTransform()
|
||||
{
|
||||
CVector3f Extent = mPlaneSize / 2.f;
|
||||
CVector3f Extent = mPlaneSize.Get() / 2.f;
|
||||
|
||||
switch (mRenderSide)
|
||||
{
|
||||
|
@ -92,7 +91,7 @@ void CDamageableTriggerExtra::UpdatePlaneTransform()
|
|||
mPosition = CVector3f(0.f, Extent.Y * Scalar, 0.f);
|
||||
mRotation = CQuaternion::FromEuler(CVector3f(90.f * Scalar, 0.f, 0.f));
|
||||
mScale = CVector3f(Extent.X, Extent.Z, 0.f);
|
||||
mCoordScale = mPlaneSize.XZ();
|
||||
mCoordScale = mPlaneSize.Get().XZ();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -104,7 +103,7 @@ void CDamageableTriggerExtra::UpdatePlaneTransform()
|
|||
mPosition = CVector3f(-Extent.X * Scalar, 0.f, 0.f);
|
||||
mRotation = CQuaternion::FromEuler(CVector3f(0.f, 90.f * Scalar, 0.f));
|
||||
mScale = CVector3f(Extent.Z, Extent.Y, 0.f);
|
||||
mCoordScale = -mPlaneSize.YZ();
|
||||
mCoordScale = -mPlaneSize.Get().YZ();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -117,7 +116,7 @@ void CDamageableTriggerExtra::UpdatePlaneTransform()
|
|||
mPosition = CVector3f(0.f, 0.f, Extent.Z * Scalar);
|
||||
mRotation = CQuaternion::FromEuler(CVector3f(0.f, RotAngle, 0.f));
|
||||
mScale = CVector3f(Extent.X, Extent.Y, 0.f);
|
||||
mCoordScale = -mPlaneSize.XY();
|
||||
mCoordScale = -mPlaneSize.Get().XY();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -176,36 +175,28 @@ CDamageableTriggerExtra::ERenderSide CDamageableTriggerExtra::TransformRenderSid
|
|||
|
||||
void CDamageableTriggerExtra::OnTransformed()
|
||||
{
|
||||
mPlaneSize = mpSizeProp->Get();
|
||||
UpdatePlaneTransform();
|
||||
}
|
||||
|
||||
void CDamageableTriggerExtra::PropertyModified(IProperty *pProperty)
|
||||
void CDamageableTriggerExtra::PropertyModified(IPropertyNew* pProperty)
|
||||
{
|
||||
if (pProperty == mpRenderSideProp)
|
||||
if (pProperty == mRenderSide || pProperty == mPlaneSize)
|
||||
{
|
||||
mRenderSide = TransformRenderSide( (ERenderSide) mpRenderSideProp->Get() );
|
||||
UpdatePlaneTransform();
|
||||
}
|
||||
|
||||
else if (pProperty == mpSizeProp)
|
||||
{
|
||||
mPlaneSize = mpSizeProp->Get();
|
||||
UpdatePlaneTransform();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
for (u32 iTex = 0; iTex < 3; iTex++)
|
||||
for (u32 TextureIdx = 0; TextureIdx < 3; TextureIdx++)
|
||||
{
|
||||
if (pProperty == mpTextureProps[iTex])
|
||||
if (pProperty == mTextureAssets[TextureIdx].Property())
|
||||
{
|
||||
mpTextures[iTex] = gpResourceStore->LoadResource<CTexture>( mpTextureProps[iTex]->Get() );
|
||||
mpTextures[TextureIdx] = gpResourceStore->LoadResource<CTexture>( mTextureAssets[TextureIdx].Get() );
|
||||
|
||||
if (mpTextures[iTex] && mpTextures[iTex]->Type() != eTexture)
|
||||
mpTextures[iTex] = nullptr;
|
||||
if (mpTextures[TextureIdx] && mpTextures[TextureIdx]->Type() != eTexture)
|
||||
mpTextures[TextureIdx] = nullptr;
|
||||
|
||||
mpMat->Pass(iTex)->SetTexture(mpTextures[iTex]);
|
||||
mpMat->Pass(TextureIdx)->SetTexture(mpTextures[TextureIdx]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,15 +17,12 @@ class CDamageableTriggerExtra : public CScriptExtra
|
|||
eDown = 0x20
|
||||
};
|
||||
|
||||
TVector3Property *mpSizeProp;
|
||||
TEnumProperty *mpRenderSideProp;
|
||||
TAssetProperty *mpTextureProps[3];
|
||||
CVectorRef mPlaneSize;
|
||||
TEnumRef<ERenderSide> mRenderSide;
|
||||
CAssetRef mTextureAssets[3];
|
||||
|
||||
CVector3f mPlaneSize;
|
||||
ERenderSide mRenderSide;
|
||||
TResPtr<CTexture> mpTextures[3];
|
||||
|
||||
CMaterial *mpMat;
|
||||
CMaterial* mpMat;
|
||||
CTexture* mpTextures[3];
|
||||
CVector2f mCoordScale;
|
||||
|
||||
float mCachedRayDistance;
|
||||
|
@ -38,7 +35,7 @@ public:
|
|||
ERenderSide RenderSideForDirection(const CVector3f& rkDir);
|
||||
ERenderSide TransformRenderSide(ERenderSide Side);
|
||||
void OnTransformed();
|
||||
void PropertyModified(IProperty *pProperty);
|
||||
void PropertyModified(IPropertyNew* pProperty);
|
||||
bool ShouldDrawNormalAssets();
|
||||
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& rkViewInfo);
|
||||
void Draw(FRenderOptions Options, int ComponentIndex, ERenderCommand Command, const SViewInfo& rkViewInfo);
|
||||
|
|
|
@ -1,35 +1,32 @@
|
|||
#include "CDoorExtra.h"
|
||||
#include "Core/Render/CRenderer.h"
|
||||
|
||||
CDoorExtra::CDoorExtra(CScriptObject *pInstance, CScene *pScene, CScriptNode *pParent)
|
||||
CDoorExtra::CDoorExtra(CScriptObject* pInstance, CScene* pScene, CScriptNode* pParent)
|
||||
: CScriptExtra(pInstance, pScene, pParent)
|
||||
, mpShieldModelProp(nullptr)
|
||||
, mpShieldColorProp(nullptr)
|
||||
, mpShieldModel(nullptr)
|
||||
{
|
||||
CPropertyStruct *pBaseStruct = pInstance->Properties();
|
||||
CStructPropertyNew* pProperties = pInstance->Template()->Properties();
|
||||
|
||||
mpShieldModelProp = TPropCast<TAssetProperty>(pBaseStruct->PropertyByID(0xB20CC271));
|
||||
if (mpShieldModelProp) PropertyModified(mpShieldModelProp);
|
||||
mShieldModelProp = CAssetRef(pInstance, pProperties->ChildByID(0xB20CC271));
|
||||
if (mShieldModelProp.IsValid()) PropertyModified(mShieldModelProp.Property());
|
||||
|
||||
if (mGame >= eEchoes)
|
||||
{
|
||||
mpShieldColorProp = TPropCast<TColorProperty>(pBaseStruct->PropertyByID(0x47B4E863));
|
||||
if (mpShieldColorProp) PropertyModified(mpShieldColorProp);
|
||||
mShieldColorProp = CColorRef(pInstance, pProperties->ChildByID(0x47B4E863));
|
||||
if (mShieldColorProp.IsValid()) PropertyModified(mShieldColorProp.Property());
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
mpDisabledProp = TPropCast<TBoolProperty>(pBaseStruct->PropertyByID(0xDEE730F5));
|
||||
if (mpDisabledProp) PropertyModified(mpDisabledProp);
|
||||
mDisabledProp = CBoolRef(pInstance, pProperties->ChildByID(0xDEE730F5));
|
||||
if (mDisabledProp.IsValid()) PropertyModified(mDisabledProp.Property());
|
||||
}
|
||||
}
|
||||
|
||||
void CDoorExtra::PropertyModified(IProperty *pProperty)
|
||||
void CDoorExtra::PropertyModified(IPropertyNew* pProperty)
|
||||
{
|
||||
if (pProperty == mpShieldModelProp)
|
||||
if (pProperty == mShieldModelProp)
|
||||
{
|
||||
mpShieldModel = gpResourceStore->LoadResource<CModel>( mpShieldModelProp->Get() );
|
||||
mpShieldModel = gpResourceStore->LoadResource<CModel>( mShieldModelProp.Get() );
|
||||
|
||||
if (mpShieldModel)
|
||||
mLocalAABox = mpShieldModel->AABox();
|
||||
|
@ -40,18 +37,13 @@ void CDoorExtra::PropertyModified(IProperty *pProperty)
|
|||
MarkTransformChanged();
|
||||
}
|
||||
|
||||
else if (pProperty == mpShieldColorProp)
|
||||
{
|
||||
mShieldColor = mpShieldColorProp->Get();
|
||||
}
|
||||
|
||||
else if (pProperty == mpDisabledProp)
|
||||
else if (pProperty == mDisabledProp)
|
||||
{
|
||||
// The Echoes demo doesn't have the shield color property. The color is
|
||||
// always cyan if the door is unlocked and always white if the door is locked.
|
||||
mShieldColor = CColor::skWhite;
|
||||
|
||||
if (!mpDisabledProp->Get())
|
||||
if (!mDisabledProp)
|
||||
mShieldColor = CColor::skCyan;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,16 +6,17 @@
|
|||
class CDoorExtra : public CScriptExtra
|
||||
{
|
||||
// Render colored door shield in MP2/3
|
||||
TAssetProperty *mpShieldModelProp;
|
||||
TColorProperty *mpShieldColorProp;
|
||||
TBoolProperty *mpDisabledProp;
|
||||
CAssetRef mShieldModelProp;
|
||||
CColorRef mShieldColorProp;
|
||||
CBoolRef mDisabledProp;
|
||||
|
||||
TResPtr<CModel> mpShieldModel;
|
||||
CColor mShieldColor;
|
||||
|
||||
public:
|
||||
explicit CDoorExtra(CScriptObject *pInstance, CScene *pScene, CScriptNode *pParent = 0);
|
||||
void PropertyModified(IProperty *pProperty);
|
||||
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& rkViewInfo);
|
||||
explicit CDoorExtra(CScriptObject* pInstance, CScene* pScene, CScriptNode* pParent = 0);
|
||||
void PropertyModified(IPropertyNew* pProperty);
|
||||
void AddToRenderer(CRenderer* pRenderer, const SViewInfo& rkViewInfo);
|
||||
void Draw(FRenderOptions Options, int ComponentIndex, ERenderCommand Command, const SViewInfo& rkViewInfo);
|
||||
void DrawSelection();
|
||||
void RayAABoxIntersectTest(CRayCollisionTester& rTester, const SViewInfo& rkViewInfo);
|
||||
|
|
|
@ -5,21 +5,21 @@ const CColor CPointOfInterestExtra::skImportantColor = CColor::Integral(0xFF,0x0
|
|||
|
||||
CPointOfInterestExtra::CPointOfInterestExtra(CScriptObject *pInstance, CScene *pScene, CScriptNode *pParent)
|
||||
: CScriptExtra(pInstance, pScene, pParent)
|
||||
, mpScanProperty(nullptr)
|
||||
, mpScanData(nullptr)
|
||||
{
|
||||
// Fetch scan data property
|
||||
CPropertyStruct *pBaseProp = pInstance->Properties();
|
||||
CStructPropertyNew* pProperties = pInstance->Template()->Properties();
|
||||
|
||||
if (mGame <= ePrime) mpScanProperty = TPropCast<TAssetProperty>(pBaseProp->PropertyByIDString("0x04:0x00"));
|
||||
else mpScanProperty = (TAssetProperty*) pBaseProp->PropertyByIDString("0xBDBEC295:0xB94E9BE7");
|
||||
if (mpScanProperty) PropertyModified(mpScanProperty);
|
||||
if (mGame <= ePrime) mScanProperty = CAssetRef(pInstance, pProperties->ChildByIDString("0x04:0x00"));
|
||||
else mScanProperty = CAssetRef(pInstance, pProperties->ChildByIDString("0xBDBEC295:0xB94E9BE7"));
|
||||
|
||||
PropertyModified(mScanProperty.Property());
|
||||
}
|
||||
|
||||
void CPointOfInterestExtra::PropertyModified(IProperty* pProperty)
|
||||
void CPointOfInterestExtra::PropertyModified(IPropertyNew* pProperty)
|
||||
{
|
||||
if (mpScanProperty == pProperty)
|
||||
mpScanData = gpResourceStore->LoadResource<CScan>( mpScanProperty->Get() );
|
||||
if (mScanProperty.Property() == pProperty)
|
||||
mpScanData = gpResourceStore->LoadResource<CScan>( mScanProperty.Get() );
|
||||
}
|
||||
|
||||
void CPointOfInterestExtra::ModifyTintColor(CColor& Color)
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
class CPointOfInterestExtra : public CScriptExtra
|
||||
{
|
||||
// Tint POI billboard orange/red depending on scan importance
|
||||
TAssetProperty *mpScanProperty;
|
||||
CAssetRef mScanProperty;
|
||||
TResPtr<CScan> mpScanData;
|
||||
|
||||
public:
|
||||
explicit CPointOfInterestExtra(CScriptObject *pInstance, CScene *pScene, CScriptNode *pParent = 0);
|
||||
void PropertyModified(IProperty* pProperty);
|
||||
void PropertyModified(IPropertyNew* pProperty);
|
||||
void ModifyTintColor(CColor& Color);
|
||||
CScan* GetScan() const { return mpScanData; }
|
||||
|
||||
|
|
|
@ -2,32 +2,32 @@
|
|||
#include "Core/Render/CDrawUtil.h"
|
||||
#include "Core/Render/CRenderer.h"
|
||||
|
||||
CRadiusSphereExtra::CRadiusSphereExtra(CScriptObject *pInstance, CScene *pScene, CScriptNode *pParent)
|
||||
CRadiusSphereExtra::CRadiusSphereExtra(CScriptObject* pInstance, CScene* pScene, CScriptNode* pParent)
|
||||
: CScriptExtra(pInstance, pScene, pParent)
|
||||
, mpRadius(nullptr)
|
||||
{
|
||||
mObjectType = pInstance->ObjectTypeID();
|
||||
CStructPropertyNew* pProperties = pInstance->Template()->Properties();
|
||||
|
||||
switch (mObjectType)
|
||||
{
|
||||
case 0x63: // Repulsor (MP1)
|
||||
mpRadius = TPropCast<TFloatProperty>(pInstance->Properties()->PropertyByID(0x3));
|
||||
mRadius = CFloatRef(pInstance, pProperties->ChildByID(3));
|
||||
break;
|
||||
|
||||
case 0x68: // RadialDamage (MP1)
|
||||
mpRadius = TPropCast<TFloatProperty>(pInstance->Properties()->PropertyByID(0x4));
|
||||
mRadius = CFloatRef(pInstance, pProperties->ChildByID(0x4));
|
||||
break;
|
||||
|
||||
case 0x5245504C: // "REPL" Repulsor (MP2/MP3)
|
||||
case 0x52414444: // "RADD" RadialDamage (MP2/MP3/DKCR)
|
||||
mpRadius = TPropCast<TFloatProperty>(pInstance->Properties()->PropertyByID(0x78C507EB));
|
||||
case FOURCC('REPL'): // Repulsor (MP2/MP3)
|
||||
case FOURCC('RADD'): // RadialDamage (MP2/MP3/DKCR)
|
||||
mRadius = CFloatRef(pInstance, pProperties->ChildByID(0x78C507EB));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CRadiusSphereExtra::AddToRenderer(CRenderer *pRenderer, const SViewInfo& rkViewInfo)
|
||||
void CRadiusSphereExtra::AddToRenderer(CRenderer* pRenderer, const SViewInfo& rkViewInfo)
|
||||
{
|
||||
if (!rkViewInfo.GameMode && (rkViewInfo.ShowFlags & eShowObjectGeometry) && mpRadius && mpParent->IsVisible() && mpParent->IsSelected())
|
||||
if (!rkViewInfo.GameMode && (rkViewInfo.ShowFlags & eShowObjectGeometry) && mRadius.IsValid() && mpParent->IsVisible() && mpParent->IsSelected())
|
||||
{
|
||||
CAABox BoundingBox = Bounds();
|
||||
|
||||
|
@ -42,7 +42,7 @@ void CRadiusSphereExtra::Draw(FRenderOptions /*Options*/, int /*ComponentIndex*/
|
|||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
CDrawUtil::DrawWireSphere(mpInstance->Position(), mpRadius->Get(), Color());
|
||||
CDrawUtil::DrawWireSphere(mpInstance->Position(), mRadius, Color());
|
||||
}
|
||||
|
||||
CColor CRadiusSphereExtra::Color() const
|
||||
|
@ -66,7 +66,7 @@ CColor CRadiusSphereExtra::Color() const
|
|||
|
||||
CAABox CRadiusSphereExtra::Bounds() const
|
||||
{
|
||||
CAABox Bounds = CAABox::skOne * 2.f * mpRadius->Get();
|
||||
CAABox Bounds = CAABox::skOne * 2.f * mRadius;
|
||||
Bounds += mpParent->AbsolutePosition();
|
||||
return Bounds;
|
||||
}
|
||||
|
|
|
@ -7,11 +7,11 @@ class CRadiusSphereExtra : public CScriptExtra
|
|||
{
|
||||
// Sphere visualization for objects that have a float radius property.
|
||||
u32 mObjectType;
|
||||
TFloatProperty *mpRadius;
|
||||
CFloatRef mRadius;
|
||||
|
||||
public:
|
||||
explicit CRadiusSphereExtra(CScriptObject *pInstance, CScene *pScene, CScriptNode *pParent = 0);
|
||||
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& rkViewInfo);
|
||||
explicit CRadiusSphereExtra(CScriptObject* pInstance, CScene* pScene, CScriptNode* pParent = 0);
|
||||
void AddToRenderer(CRenderer* pRenderer, const SViewInfo& rkViewInfo);
|
||||
void Draw(FRenderOptions Options, int ComponentIndex, ERenderCommand Command, const SViewInfo& rkViewInfo);
|
||||
CColor Color() const;
|
||||
CAABox Bounds() const;
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
#include "CSandwormExtra.h"
|
||||
|
||||
CSandwormExtra::CSandwormExtra(CScriptObject *pInstance, CScene *pScene, CScriptNode *pParent)
|
||||
CSandwormExtra::CSandwormExtra(CScriptObject* pInstance, CScene* pScene, CScriptNode* pParent)
|
||||
: CScriptExtra(pInstance, pScene, pParent)
|
||||
{
|
||||
// The back pincers need to be flipped 180 degrees
|
||||
for (u32 iAttach = 0; iAttach < pParent->NumAttachments(); iAttach++)
|
||||
for (u32 AttachIdx = 0; AttachIdx < pParent->NumAttachments(); AttachIdx++)
|
||||
{
|
||||
CScriptAttachNode *pAttach = pParent->Attachment(iAttach);
|
||||
CScriptAttachNode *pAttach = pParent->Attachment(AttachIdx);
|
||||
|
||||
if (pAttach->LocatorName() == "L_back_claw" || pAttach->LocatorName() == "R_back_claw")
|
||||
pAttach->SetRotation(CVector3f(0,0,180));
|
||||
}
|
||||
|
||||
// Get pincers scale
|
||||
mpPincersScaleProperty = TPropCast<TFloatProperty>(pInstance->PropertyByIDString("0x3DB583AE"));
|
||||
if (mpPincersScaleProperty) PropertyModified(mpPincersScaleProperty);
|
||||
mPincersScale = CFloatRef(pInstance, pInstance->Template()->Properties()->ChildByID(0x3DB583AE));
|
||||
if (mPincersScale.IsValid()) PropertyModified(mPincersScale.Property());
|
||||
}
|
||||
|
||||
void CSandwormExtra::PropertyModified(IProperty *pProp)
|
||||
void CSandwormExtra::PropertyModified(IPropertyNew* pProp)
|
||||
{
|
||||
if (pProp == mpPincersScaleProperty)
|
||||
if (pProp == mPincersScale)
|
||||
{
|
||||
for (u32 iAttach = 0; iAttach < mpScriptNode->NumAttachments(); iAttach++)
|
||||
for (u32 AttachIdx = 0; AttachIdx < mpScriptNode->NumAttachments(); AttachIdx++)
|
||||
{
|
||||
CScriptAttachNode *pAttach = mpScriptNode->Attachment(iAttach);
|
||||
pAttach->SetScale(CVector3f(mpPincersScaleProperty->Get()));
|
||||
CScriptAttachNode* pAttach = mpScriptNode->Attachment(AttachIdx);
|
||||
pAttach->SetScale( CVector3f(mPincersScale) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
class CSandwormExtra : public CScriptExtra
|
||||
{
|
||||
// Transform adjustments to Sandworm attachments.
|
||||
TFloatProperty *mpPincersScaleProperty;
|
||||
CFloatRef mPincersScale;
|
||||
|
||||
public:
|
||||
explicit CSandwormExtra(CScriptObject *pInstance, CScene *pScene, CScriptNode *pParent);
|
||||
void PropertyModified(IProperty *pProp);
|
||||
explicit CSandwormExtra(CScriptObject* pInstance, CScene* pScene, CScriptNode* pParent);
|
||||
void PropertyModified(IPropertyNew* pProp);
|
||||
};
|
||||
|
||||
#endif // CSANDWORMEXTRA_H
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
|
||||
// Virtual CScriptExtra functions
|
||||
virtual void InstanceTransformed() {}
|
||||
virtual void PropertyModified(IProperty* /*pProperty*/) {}
|
||||
virtual void PropertyModified(IPropertyNew* /*pProperty*/) {}
|
||||
virtual void DisplayAssetChanged(CResource* /*pNewDisplayAsset*/) {}
|
||||
virtual void LinksModified() {}
|
||||
virtual bool ShouldDrawNormalAssets() { return true; }
|
||||
|
|
|
@ -1,37 +1,33 @@
|
|||
#include "CSpacePirateExtra.h"
|
||||
|
||||
CSpacePirateExtra::CSpacePirateExtra(CScriptObject *pInstance, CScene *pScene, CScriptNode *pParent)
|
||||
CSpacePirateExtra::CSpacePirateExtra(CScriptObject* pInstance, CScene* pScene, CScriptNode* pParent)
|
||||
: CScriptExtra(pInstance, pScene ,pParent)
|
||||
, mpPowerVuln(nullptr)
|
||||
, mpWaveVuln(nullptr)
|
||||
, mpIceVuln(nullptr)
|
||||
, mpPlasmaVuln(nullptr)
|
||||
{
|
||||
CPropertyStruct *pBaseStruct = pInstance->Properties();
|
||||
CPropertyStruct *pVulns = (CPropertyStruct*) pBaseStruct->PropertyByIDString("0x04:0x10");
|
||||
CStructPropertyNew* pBaseStruct = pInstance->Template()->Properties();
|
||||
CStructPropertyNew* pVulnerabilities = TPropCast<CStructPropertyNew>(pBaseStruct->ChildByIDString("0x04:0x10"));
|
||||
|
||||
if (pVulns && pVulns->Type() == eStructProperty)
|
||||
if (pVulnerabilities)
|
||||
{
|
||||
mpPowerVuln = TPropCast<TEnumProperty>(pVulns->PropertyByID(0x0));
|
||||
mpWaveVuln = TPropCast<TEnumProperty>(pVulns->PropertyByID(0x2));
|
||||
mpIceVuln = TPropCast<TEnumProperty>(pVulns->PropertyByID(0x1));
|
||||
mpPlasmaVuln = TPropCast<TEnumProperty>(pVulns->PropertyByID(0x3));
|
||||
mPowerVulnerability = TEnumRef<EVulnerabilityTypeMP1>(pInstance, pVulnerabilities->ChildByID(0));
|
||||
mWaveVulnerability = TEnumRef<EVulnerabilityTypeMP1>(pInstance, pVulnerabilities->ChildByID(2));
|
||||
mIceVulnerability = TEnumRef<EVulnerabilityTypeMP1>(pInstance, pVulnerabilities->ChildByID(1));
|
||||
mPlasmaVulnerability = TEnumRef<EVulnerabilityTypeMP1>(pInstance, pVulnerabilities->ChildByID(3));
|
||||
}
|
||||
}
|
||||
|
||||
CColor CSpacePirateExtra::TevColor()
|
||||
{
|
||||
// Priority: Plasma -> Ice -> Power -> Wave
|
||||
if (mpPlasmaVuln && mpPlasmaVuln->Get() == 1)
|
||||
if (mPlasmaVulnerability.IsValid() && mPlasmaVulnerability.Get() == EVulnerabilityTypeMP1::Normal)
|
||||
return CColor::skRed;
|
||||
|
||||
if (mpIceVuln && mpIceVuln->Get() == 1)
|
||||
if (mIceVulnerability.IsValid() && mIceVulnerability.Get() == EVulnerabilityTypeMP1::Normal)
|
||||
return CColor::skWhite;
|
||||
|
||||
if (mpPowerVuln && mpPowerVuln->Get() == 1)
|
||||
if (mPowerVulnerability.IsValid() && mPowerVulnerability.Get() == EVulnerabilityTypeMP1::Normal)
|
||||
return CColor::skYellow;
|
||||
|
||||
if (mpWaveVuln && mpWaveVuln->Get() == 1)
|
||||
if (mWaveVulnerability.IsValid() && mWaveVulnerability.Get() == EVulnerabilityTypeMP1::Normal)
|
||||
return CColor::skPurple;
|
||||
|
||||
return CColor::skWhite;
|
||||
|
|
|
@ -4,13 +4,25 @@
|
|||
#include "CScriptExtra.h"
|
||||
#include "Core/Resource/Script/IProperty.h"
|
||||
|
||||
enum class EVulnerabilityTypeMP1
|
||||
{
|
||||
DoubleDamage,
|
||||
Normal,
|
||||
Reflect,
|
||||
Immune,
|
||||
PassThru,
|
||||
DirectDouble,
|
||||
DirectNormal,
|
||||
DirectImmune
|
||||
};
|
||||
|
||||
class CSpacePirateExtra : public CScriptExtra
|
||||
{
|
||||
// Render beam troopers with the correct color
|
||||
TEnumProperty *mpPowerVuln;
|
||||
TEnumProperty *mpWaveVuln;
|
||||
TEnumProperty *mpIceVuln;
|
||||
TEnumProperty *mpPlasmaVuln;
|
||||
TEnumRef<EVulnerabilityTypeMP1> mPowerVulnerability;
|
||||
TEnumRef<EVulnerabilityTypeMP1> mWaveVulnerability;
|
||||
TEnumRef<EVulnerabilityTypeMP1> mIceVulnerability;
|
||||
TEnumRef<EVulnerabilityTypeMP1> mPlasmaVulnerability;
|
||||
|
||||
public:
|
||||
explicit CSpacePirateExtra(CScriptObject *pInstance, CScene *pScene, CScriptNode *pParent = 0);
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
#include "Core/Resource/Script/CLink.h"
|
||||
#include "Core/Scene/CScene.h"
|
||||
|
||||
CSplinePathExtra::CSplinePathExtra(CScriptObject *pInstance, CScene *pScene, CScriptNode *pParent)
|
||||
CSplinePathExtra::CSplinePathExtra(CScriptObject* pInstance, CScene* pScene, CScriptNode* pParent)
|
||||
: CScriptExtra(pInstance, pScene, pParent)
|
||||
{
|
||||
mpPathColor = TPropCast<TColorProperty>(pInstance->Properties()->PropertyByID(0x00DD86E2));
|
||||
mPathColor = CColorRef(pInstance, pInstance->Template()->Properties()->ChildByID(0x00DD86E2));
|
||||
}
|
||||
|
||||
void CSplinePathExtra::PropertyModified(IProperty *pProperty)
|
||||
void CSplinePathExtra::PropertyModified(IPropertyNew* pProperty)
|
||||
{
|
||||
if (pProperty == mpPathColor)
|
||||
if (pProperty == mPathColor.Property())
|
||||
{
|
||||
for (auto it = mWaypoints.begin(); it != mWaypoints.end(); it++)
|
||||
(*it)->CheckColor();
|
||||
|
@ -23,7 +23,7 @@ void CSplinePathExtra::PostLoad()
|
|||
AddWaypoints();
|
||||
}
|
||||
|
||||
void CSplinePathExtra::FindAttachedWaypoints(std::set<CWaypointExtra*>& rChecked, CWaypointExtra *pWaypoint)
|
||||
void CSplinePathExtra::FindAttachedWaypoints(std::set<CWaypointExtra*>& rChecked, CWaypointExtra* pWaypoint)
|
||||
{
|
||||
if (rChecked.find(pWaypoint) != rChecked.end())
|
||||
return;
|
||||
|
@ -46,18 +46,18 @@ void CSplinePathExtra::AddWaypoints()
|
|||
|
||||
std::set<CWaypointExtra*> CheckedWaypoints;
|
||||
|
||||
for (u32 iLink = 0; iLink < mpInstance->NumLinks(eOutgoing); iLink++)
|
||||
for (u32 LinkIdx = 0; LinkIdx < mpInstance->NumLinks(eOutgoing); LinkIdx++)
|
||||
{
|
||||
CLink *pLink = mpInstance->Link(eOutgoing, iLink);
|
||||
CLink* pLink = mpInstance->Link(eOutgoing, LinkIdx);
|
||||
|
||||
if ( (pLink->State() == 0x49533030 && pLink->Message() == 0x41544348) || // InternalState00/Attach
|
||||
(pLink->State() == 0x4D4F5450 && pLink->Message() == 0x41544348) ) // MotionPath/Attach
|
||||
if ( (pLink->State() == FOURCC('IS00') && pLink->Message() == FOURCC('ATCH')) || // InternalState00/Attach
|
||||
(pLink->State() == FOURCC('MOTP') && pLink->Message() == FOURCC('ATCH')) ) // MotionPath/Attach
|
||||
{
|
||||
CScriptNode *pNode = mpScene->NodeForInstanceID(pLink->ReceiverID());
|
||||
CScriptNode* pNode = mpScene->NodeForInstanceID(pLink->ReceiverID());
|
||||
|
||||
if (pNode && pNode->Instance()->ObjectTypeID() == 0x57415950) // Waypoint
|
||||
if (pNode && pNode->Instance()->ObjectTypeID() == FOURCC('WAYP')) // Waypoint
|
||||
{
|
||||
CWaypointExtra *pWaypoint = static_cast<CWaypointExtra*>(pNode->Extra());
|
||||
CWaypointExtra* pWaypoint = static_cast<CWaypointExtra*>(pNode->Extra());
|
||||
FindAttachedWaypoints(CheckedWaypoints, pWaypoint);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,20 +11,20 @@ class CWaypointExtra;
|
|||
class CSplinePathExtra : public CScriptExtra
|
||||
{
|
||||
// Recolor waypoint paths to match the editor color parameter
|
||||
TColorProperty *mpPathColor;
|
||||
CColorRef mPathColor;
|
||||
std::list<CWaypointExtra*> mWaypoints;
|
||||
|
||||
public:
|
||||
explicit CSplinePathExtra(CScriptObject *pInstance, CScene *pScene, CScriptNode *pParent = 0);
|
||||
explicit CSplinePathExtra(CScriptObject* pInstance, CScene* pScene, CScriptNode* pParent = 0);
|
||||
~CSplinePathExtra() { ClearWaypoints(); }
|
||||
inline CColor PathColor() const { return (mpPathColor ? mpPathColor->Get() : CColor::skBlack); }
|
||||
inline CColor PathColor() const { return (mPathColor.IsValid() ? mPathColor.Get() : CColor::skBlack); }
|
||||
|
||||
void PostLoad();
|
||||
void PropertyModified(IProperty *pProperty);
|
||||
void PropertyModified(IPropertyNew* pProperty);
|
||||
|
||||
void FindAttachedWaypoints(std::set<CWaypointExtra*>& rChecked, CWaypointExtra *pWaypoint);
|
||||
void FindAttachedWaypoints(std::set<CWaypointExtra*>& rChecked, CWaypointExtra* pWaypoint);
|
||||
void AddWaypoints();
|
||||
void RemoveWaypoint(CWaypointExtra *pWaypoint);
|
||||
void RemoveWaypoint(CWaypointExtra* pWaypoint);
|
||||
void ClearWaypoints();
|
||||
};
|
||||
|
||||
|
|
|
@ -231,7 +231,8 @@ void CGeneratePropertyNamesDialog::ApplyChanges()
|
|||
pItem->setText(3, NewName);
|
||||
}
|
||||
|
||||
CTemplateWriter::SavePropertyList();
|
||||
//FIXME
|
||||
// CTemplateWriter::SavePropertyList();
|
||||
}
|
||||
|
||||
/** Check progress on name generation task and display results on the UI */
|
||||
|
|
|
@ -6,7 +6,7 @@ CPropertyNameValidator::CPropertyNameValidator(QObject* pParent)
|
|||
{}
|
||||
|
||||
/** Set the property to validate against */
|
||||
void CPropertyNameValidator::SetProperty(IPropertyTemplate* pProp)
|
||||
void CPropertyNameValidator::SetProperty(IPropertyNew* pProp)
|
||||
{
|
||||
mpProperty = pProp;
|
||||
emit changed();
|
||||
|
@ -19,10 +19,10 @@ QValidator::State CPropertyNameValidator::validate(QString& rInput, int&) const
|
|||
{
|
||||
CCRC32 Hash;
|
||||
Hash.Hash( rInput.toStdString().c_str() );
|
||||
Hash.Hash( mpProperty->GetTypeNameString() );
|
||||
Hash.Hash( mpProperty->HashableTypeName() );
|
||||
u32 PropertyID = Hash.Digest();
|
||||
|
||||
return ( PropertyID == mpProperty->PropertyID() ? QValidator::Acceptable : QValidator::Invalid );
|
||||
return ( PropertyID == mpProperty->ID() ? QValidator::Acceptable : QValidator::Invalid );
|
||||
}
|
||||
|
||||
return QValidator::Invalid;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define CPROPERTYNAMEVALIDATOR_H
|
||||
|
||||
#include <QValidator>
|
||||
#include <Core/Resource/Script/IPropertyTemplate.h>
|
||||
#include <Core/Resource/Script/Property/Properties.h>
|
||||
|
||||
/** QValidator subclass that checks if a property name is valid */
|
||||
class CPropertyNameValidator : public QValidator
|
||||
|
@ -10,13 +10,13 @@ class CPropertyNameValidator : public QValidator
|
|||
Q_OBJECT
|
||||
|
||||
/** The property being validated against */
|
||||
IPropertyTemplate* mpProperty;
|
||||
IPropertyNew* mpProperty;
|
||||
|
||||
public:
|
||||
CPropertyNameValidator(QObject* pParent = 0);
|
||||
|
||||
/** Set the property to validate against */
|
||||
void SetProperty(IPropertyTemplate* pProp);
|
||||
void SetProperty(IPropertyNew* pProp);
|
||||
|
||||
/** Perform validation */
|
||||
QValidator::State validate(QString& rInput, int& rPos) const;
|
||||
|
|
|
@ -49,7 +49,7 @@ void CPropertyDelegate::SetEditor(CWorldEditor *pEditor)
|
|||
QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionViewItem& /*rkOption*/, const QModelIndex& rkIndex) const
|
||||
{
|
||||
if (!mpModel) return nullptr;
|
||||
IProperty *pProp = mpModel->PropertyForIndex(rkIndex, false);
|
||||
IPropertyNew *pProp = mpModel->PropertyForIndex(rkIndex, false);
|
||||
QWidget *pOut = nullptr;
|
||||
|
||||
if (pProp)
|
||||
|
@ -57,7 +57,7 @@ QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionVie
|
|||
switch (pProp->Type())
|
||||
{
|
||||
|
||||
case eBoolProperty:
|
||||
case EPropertyTypeNew::Bool:
|
||||
{
|
||||
QCheckBox *pCheckBox = new QCheckBox(pParent);
|
||||
CONNECT_RELAY(pCheckBox, rkIndex, toggled(bool))
|
||||
|
@ -65,39 +65,39 @@ QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionVie
|
|||
break;
|
||||
}
|
||||
|
||||
case eShortProperty:
|
||||
case EPropertyTypeNew::Short:
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = new WIntegralSpinBox(pParent);
|
||||
pSpinBox->setMinimum(INT16_MIN);
|
||||
pSpinBox->setMaximum(INT16_MAX);
|
||||
pSpinBox->setSuffix(TO_QSTRING(pProp->Template()->Suffix()));
|
||||
pSpinBox->setSuffix(TO_QSTRING(pProp->Suffix()));
|
||||
CONNECT_RELAY(pSpinBox, rkIndex, valueChanged(int))
|
||||
pOut = pSpinBox;
|
||||
break;
|
||||
}
|
||||
|
||||
case eLongProperty:
|
||||
case EPropertyTypeNew::Int:
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = new WIntegralSpinBox(pParent);
|
||||
pSpinBox->setMinimum(INT32_MIN);
|
||||
pSpinBox->setMaximum(INT32_MAX);
|
||||
pSpinBox->setSuffix(TO_QSTRING(pProp->Template()->Suffix()));
|
||||
pSpinBox->setSuffix(TO_QSTRING(pProp->Suffix()));
|
||||
CONNECT_RELAY(pSpinBox, rkIndex, valueChanged(int))
|
||||
pOut = pSpinBox;
|
||||
break;
|
||||
}
|
||||
|
||||
case eFloatProperty:
|
||||
case EPropertyTypeNew::Float:
|
||||
{
|
||||
WDraggableSpinBox *pSpinBox = new WDraggableSpinBox(pParent);
|
||||
pSpinBox->setSingleStep(0.1);
|
||||
pSpinBox->setSuffix(TO_QSTRING(pProp->Template()->Suffix()));
|
||||
pSpinBox->setSuffix(TO_QSTRING(pProp->Suffix()));
|
||||
CONNECT_RELAY(pSpinBox, rkIndex, valueChanged(double))
|
||||
pOut = pSpinBox;
|
||||
break;
|
||||
}
|
||||
|
||||
case eColorProperty:
|
||||
case EPropertyTypeNew::Color:
|
||||
{
|
||||
WColorPicker *pColorPicker = new WColorPicker(pParent);
|
||||
CONNECT_RELAY(pColorPicker, rkIndex, ColorChanged(QColor))
|
||||
|
@ -105,7 +105,7 @@ QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionVie
|
|||
break;
|
||||
}
|
||||
|
||||
case eSoundProperty:
|
||||
case EPropertyTypeNew::Sound:
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = new WIntegralSpinBox(pParent);
|
||||
pSpinBox->setMinimum(-1);
|
||||
|
@ -115,7 +115,7 @@ QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionVie
|
|||
break;
|
||||
}
|
||||
|
||||
case eStringProperty:
|
||||
case EPropertyTypeNew::String:
|
||||
{
|
||||
QLineEdit *pLineEdit = new QLineEdit(pParent);
|
||||
CONNECT_RELAY(pLineEdit, rkIndex, textEdited(QString))
|
||||
|
@ -123,34 +123,34 @@ QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionVie
|
|||
break;
|
||||
}
|
||||
|
||||
case eEnumProperty:
|
||||
case EPropertyTypeNew::Enum:
|
||||
case EPropertyTypeNew::Choice:
|
||||
{
|
||||
QComboBox *pComboBox = new QComboBox(pParent);
|
||||
CEnumProperty* pEnum = TPropCast<CEnumProperty>(pProp);
|
||||
|
||||
CEnumTemplate *pTemp = static_cast<CEnumTemplate*>(pProp->Template());
|
||||
|
||||
for (u32 iEnum = 0; iEnum < pTemp->NumEnumerators(); iEnum++)
|
||||
pComboBox->addItem(TO_QSTRING(pTemp->EnumeratorName(iEnum)));
|
||||
for (u32 ValueIdx = 0; ValueIdx < pEnum->NumPossibleValues(); ValueIdx++)
|
||||
pComboBox->addItem(TO_QSTRING(pEnum->ValueName(ValueIdx)));
|
||||
|
||||
CONNECT_RELAY(pComboBox, rkIndex, currentIndexChanged(int))
|
||||
pOut = pComboBox;
|
||||
break;
|
||||
}
|
||||
|
||||
case eAssetProperty:
|
||||
case EPropertyTypeNew::Asset:
|
||||
{
|
||||
CResourceSelector *pSelector = new CResourceSelector(pParent);
|
||||
pSelector->SetFrameVisible(false);
|
||||
|
||||
CAssetTemplate *pTemp = static_cast<CAssetTemplate*>(pProp->Template());
|
||||
pSelector->SetTypeFilter(pTemp->TypeFilter());
|
||||
CAssetProperty *pAsset = TPropCast<CAssetProperty>(pProp);
|
||||
pSelector->SetTypeFilter(pAsset->GetTypeFilter());
|
||||
|
||||
CONNECT_RELAY(pSelector, rkIndex, ResourceChanged(CResourceEntry*))
|
||||
pOut = pSelector;
|
||||
break;
|
||||
}
|
||||
|
||||
case eArrayProperty:
|
||||
case EPropertyTypeNew::Array:
|
||||
{
|
||||
// No relay here, would prefer user to be sure of their change before it's reflected on the UI
|
||||
WIntegralSpinBox *pSpinBox = new WIntegralSpinBox(pParent);
|
||||
|
@ -163,41 +163,23 @@ QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionVie
|
|||
}
|
||||
}
|
||||
|
||||
// Check for sub-property of vector/color/character
|
||||
else if (rkIndex.internalId() & 0x1)
|
||||
// Check for sub-property of flgs/animation set
|
||||
else if (rkIndex.internalId() & 0x80000000)
|
||||
{
|
||||
pProp = mpModel->PropertyForIndex(rkIndex, true);
|
||||
EPropertyTypeNew Type = pProp->Type();
|
||||
|
||||
// Handle character
|
||||
if (pProp->Type() == eCharacterProperty)
|
||||
if (Type == EPropertyTypeNew::AnimationSet)
|
||||
pOut = CreateCharacterEditor(pParent, rkIndex);
|
||||
|
||||
// Handle bitfield
|
||||
else if (pProp->Type() == eBitfieldProperty)
|
||||
// Handle flags
|
||||
else if (Type == EPropertyTypeNew::Flags)
|
||||
{
|
||||
QCheckBox *pCheckBox = new QCheckBox(pParent);
|
||||
CONNECT_RELAY(pCheckBox, rkIndex, toggled(bool))
|
||||
pOut = pCheckBox;
|
||||
}
|
||||
|
||||
// Handle vector/color
|
||||
else
|
||||
{
|
||||
WDraggableSpinBox *pSpinBox = new WDraggableSpinBox(pParent);
|
||||
pSpinBox->setSingleStep(0.1);
|
||||
|
||||
// Limit to range of 0-1 on colors
|
||||
pProp = mpModel->PropertyForIndex(rkIndex, true);
|
||||
|
||||
if (pProp->Type() == eColorProperty)
|
||||
{
|
||||
pSpinBox->setMinimum(0.0);
|
||||
pSpinBox->setMaximum(1.0);
|
||||
}
|
||||
|
||||
CONNECT_RELAY(pSpinBox, rkIndex, valueChanged(double))
|
||||
pOut = pSpinBox;
|
||||
}
|
||||
}
|
||||
|
||||
if (pOut)
|
||||
|
@ -218,7 +200,8 @@ void CPropertyDelegate::setEditorData(QWidget *pEditor, const QModelIndex &rkInd
|
|||
if (pEditor)
|
||||
{
|
||||
// Set editor data for regular property
|
||||
IProperty *pProp = mpModel->PropertyForIndex(rkIndex, false);
|
||||
IPropertyNew *pProp = mpModel->PropertyForIndex(rkIndex, false);
|
||||
void* pData = mpModel->GetPropertyData();
|
||||
|
||||
if (pProp)
|
||||
{
|
||||
|
@ -227,102 +210,114 @@ void CPropertyDelegate::setEditorData(QWidget *pEditor, const QModelIndex &rkInd
|
|||
switch (pProp->Type())
|
||||
{
|
||||
|
||||
case eBoolProperty:
|
||||
case EPropertyTypeNew::Bool:
|
||||
{
|
||||
QCheckBox *pCheckBox = static_cast<QCheckBox*>(pEditor);
|
||||
TBoolProperty *pBool = static_cast<TBoolProperty*>(pProp);
|
||||
pCheckBox->setChecked(pBool->Get());
|
||||
CBoolProperty *pBool = TPropCast<CBoolProperty>(pProp);
|
||||
pCheckBox->setChecked( pBool->Value(pData) );
|
||||
break;
|
||||
}
|
||||
|
||||
case eShortProperty:
|
||||
case EPropertyTypeNew::Short:
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
|
||||
|
||||
if (!pSpinBox->hasFocus())
|
||||
{
|
||||
TShortProperty *pShort = static_cast<TShortProperty*>(pProp);
|
||||
pSpinBox->setValue(pShort->Get());
|
||||
CShortProperty *pShort = TPropCast<CShortProperty>(pProp);
|
||||
pSpinBox->setValue( pShort->Value(pData) );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case eLongProperty:
|
||||
case eSoundProperty:
|
||||
case EPropertyTypeNew::Int:
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
|
||||
|
||||
if (!pSpinBox->hasFocus())
|
||||
{
|
||||
TLongProperty *pLong = static_cast<TLongProperty*>(pProp);
|
||||
pSpinBox->setValue(pLong->Get());
|
||||
CIntProperty *pInt = TPropCast<CIntProperty>(pProp);
|
||||
pSpinBox->setValue( pInt->Value(pData) );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case eFloatProperty:
|
||||
case EPropertyTypeNew::Sound:
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
|
||||
|
||||
if (!pSpinBox->hasFocus())
|
||||
{
|
||||
CSoundProperty *pSound = TPropCast<CSoundProperty>(pProp);
|
||||
pSpinBox->setValue( pSound->Value(pData) );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EPropertyTypeNew::Float:
|
||||
{
|
||||
WDraggableSpinBox *pSpinBox = static_cast<WDraggableSpinBox*>(pEditor);
|
||||
|
||||
if (!pSpinBox->hasFocus())
|
||||
{
|
||||
TFloatProperty *pFloat = static_cast<TFloatProperty*>(pProp);
|
||||
pSpinBox->setValue(pFloat->Get());
|
||||
CFloatProperty *pFloat = TPropCast<CFloatProperty>(pProp);
|
||||
pSpinBox->setValue( pFloat->Value(pData) );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case eColorProperty:
|
||||
case EPropertyTypeNew::Color:
|
||||
{
|
||||
WColorPicker *pColorPicker = static_cast<WColorPicker*>(pEditor);
|
||||
TColorProperty *pColor = static_cast<TColorProperty*>(pProp);
|
||||
CColorProperty *pColor = TPropCast<CColorProperty>(pProp);
|
||||
|
||||
CColor Color = pColor->Get();
|
||||
CColor Color = pColor->Value(pData);
|
||||
pColorPicker->SetColor(TO_QCOLOR(Color));
|
||||
break;
|
||||
}
|
||||
|
||||
case eStringProperty:
|
||||
case EPropertyTypeNew::String:
|
||||
{
|
||||
QLineEdit *pLineEdit = static_cast<QLineEdit*>(pEditor);
|
||||
|
||||
if (!pLineEdit->hasFocus())
|
||||
{
|
||||
TStringProperty *pString = static_cast<TStringProperty*>(pProp);
|
||||
pLineEdit->setText(TO_QSTRING(pString->Get()));
|
||||
CStringProperty *pString = TPropCast<CStringProperty>(pProp);
|
||||
pLineEdit->setText( TO_QSTRING(pString->Value(pData)) );
|
||||
}
|
||||
|
||||
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());
|
||||
pComboBox->setCurrentIndex(pTemp->EnumeratorIndex(pEnum->Get()));
|
||||
CEnumProperty* pEnum = TPropCast<CEnumProperty>(pProp);
|
||||
pComboBox->setCurrentIndex( pEnum->ValueIndex( pEnum->Value(pData) ) );
|
||||
break;
|
||||
}
|
||||
|
||||
case eAssetProperty:
|
||||
case EPropertyTypeNew::Asset:
|
||||
{
|
||||
CResourceSelector *pSelector = static_cast<CResourceSelector*>(pEditor);
|
||||
TAssetProperty *pAsset = static_cast<TAssetProperty*>(pProp);
|
||||
pSelector->SetResource(pAsset->Get());
|
||||
CAssetProperty *pAsset = TPropCast<CAssetProperty>(pProp);
|
||||
pSelector->SetResource(pAsset->Value(pData));
|
||||
break;
|
||||
}
|
||||
|
||||
case eArrayProperty:
|
||||
case EPropertyTypeNew::Array:
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = static_cast<WIntegralSpinBox*>(pEditor);
|
||||
|
||||
if (!pSpinBox->hasFocus())
|
||||
{
|
||||
CArrayProperty *pArray = static_cast<CArrayProperty*>(pProp);
|
||||
pSpinBox->setValue(pArray->Count());
|
||||
pSpinBox->setValue( pArray->ArrayCount(pData) );
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -332,54 +327,22 @@ void CPropertyDelegate::setEditorData(QWidget *pEditor, const QModelIndex &rkInd
|
|||
}
|
||||
}
|
||||
|
||||
// Set editor data for character/bitfield/vector/color sub-property
|
||||
else if (rkIndex.internalId() & 0x1)
|
||||
// Set editor data for animation set/flags sub-property
|
||||
else if (rkIndex.internalId() & 0x80000000)
|
||||
{
|
||||
pProp = mpModel->PropertyForIndex(rkIndex, true);
|
||||
|
||||
if (pProp->Type() == eCharacterProperty)
|
||||
if (pProp->Type() == EPropertyTypeNew::AnimationSet)
|
||||
SetCharacterEditorData(pEditor, rkIndex);
|
||||
|
||||
else if (pProp->Type() == eBitfieldProperty)
|
||||
else if (pProp->Type() == EPropertyTypeNew::Flags)
|
||||
{
|
||||
QCheckBox *pCheckBox = static_cast<QCheckBox*>(pEditor);
|
||||
TBitfieldProperty *pBitfield = static_cast<TBitfieldProperty*>(pProp);
|
||||
u32 Mask = static_cast<CBitfieldTemplate*>(pBitfield->Template())->FlagMask(rkIndex.row());
|
||||
bool Set = (pBitfield->Get() & Mask) != 0;
|
||||
CFlagsProperty* pFlags = TPropCast<CFlagsProperty>(pProp);
|
||||
u32 Mask = pFlags->FlagMask(rkIndex.row());
|
||||
bool Set = (pFlags->Value(pData) & Mask) != 0;
|
||||
pCheckBox->setChecked(Set);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
WDraggableSpinBox *pSpinBox = static_cast<WDraggableSpinBox*>(pEditor);
|
||||
float Value;
|
||||
|
||||
if (!pSpinBox->hasFocus())
|
||||
{
|
||||
if (pProp->Type() == eVector3Property)
|
||||
{
|
||||
TVector3Property *pVector = static_cast<TVector3Property*>(pProp);
|
||||
CVector3f Vector = pVector->Get();
|
||||
|
||||
if (rkIndex.row() == 0) Value = Vector.X;
|
||||
if (rkIndex.row() == 1) Value = Vector.Y;
|
||||
if (rkIndex.row() == 2) Value = Vector.Z;
|
||||
}
|
||||
|
||||
else if (pProp->Type() == eColorProperty)
|
||||
{
|
||||
TColorProperty *pColor = static_cast<TColorProperty*>(pProp);
|
||||
CColor Color = pColor->Get();
|
||||
|
||||
if (rkIndex.row() == 0) Value = Color.R;
|
||||
if (rkIndex.row() == 1) Value = Color.G;
|
||||
if (rkIndex.row() == 2) Value = Color.B;
|
||||
if (rkIndex.row() == 3) Value = Color.A;
|
||||
}
|
||||
|
||||
pSpinBox->setValue((double) Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -391,20 +354,26 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
|
|||
if (!mpModel) return;
|
||||
if (!pEditor) return;
|
||||
|
||||
IProperty *pProp = mpModel->PropertyForIndex(rkIndex, false);
|
||||
IPropertyValue *pOldValue = nullptr;
|
||||
//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;
|
||||
|
||||
if (pProp)
|
||||
{
|
||||
IPropertyValue *pRawValue = pProp->RawValue();
|
||||
pOldValue = pRawValue ? pRawValue->Clone() : nullptr;
|
||||
|
||||
switch (pProp->Type())
|
||||
{
|
||||
|
||||
case eBoolProperty:
|
||||
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());
|
||||
break;
|
||||
|
@ -567,7 +536,7 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
|
|||
|
||||
else
|
||||
delete pOldValue;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
bool CPropertyDelegate::eventFilter(QObject *pObject, QEvent *pEvent)
|
||||
|
@ -589,7 +558,8 @@ 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
|
||||
{
|
||||
TCharacterProperty *pProp = static_cast<TCharacterProperty*>(mpModel->PropertyForIndex(rkIndex, true));
|
||||
//FIXME
|
||||
/* TCharacterProperty *pProp = static_cast<TCharacterProperty*>(mpModel->PropertyForIndex(rkIndex, true));
|
||||
CAnimationParameters Params = pProp->Get();
|
||||
|
||||
// Determine property type
|
||||
|
@ -632,13 +602,15 @@ QWidget* CPropertyDelegate::CreateCharacterEditor(QWidget *pParent, const QModel
|
|||
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);
|
||||
|
@ -659,12 +631,15 @@ void CPropertyDelegate::SetCharacterEditorData(QWidget *pEditor, const QModelInd
|
|||
u32 Value = Params.Unknown(UnkIndex);
|
||||
static_cast<WIntegralSpinBox*>(pEditor)->setValue(Value);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void CPropertyDelegate::SetCharacterModelData(QWidget *pEditor, const QModelIndex& rkIndex) const
|
||||
{
|
||||
TCharacterProperty *pProp = static_cast<TCharacterProperty*>(mpModel->PropertyForIndex(rkIndex, true));
|
||||
CAnimationParameters Params = pProp->Get();
|
||||
//FIXME
|
||||
/*
|
||||
CAnimationSetProperty* pAnimSet = TPropCast<CAnimationSetProperty>(mpModel->PropertyForIndex(rkIndex, true));
|
||||
CAnimationParameters Params = pAnimSet->Get();
|
||||
EPropertyType Type = DetermineCharacterPropType(Params.Version(), rkIndex);
|
||||
|
||||
if (Type == eAssetProperty)
|
||||
|
@ -693,27 +668,28 @@ void CPropertyDelegate::SetCharacterModelData(QWidget *pEditor, const QModelInde
|
|||
QModelIndex ParentIndex = rkIndex.parent();
|
||||
mpModel->dataChanged(mpModel->index(1, 1, ParentIndex), mpModel->index(mpModel->rowCount(ParentIndex) - 1, 1, ParentIndex));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
EPropertyType CPropertyDelegate::DetermineCharacterPropType(EGame Game, const QModelIndex& rkIndex) const
|
||||
EPropertyTypeNew CPropertyDelegate::DetermineCharacterPropType(EGame Game, const QModelIndex& rkIndex) const
|
||||
{
|
||||
if (Game <= eEchoes)
|
||||
{
|
||||
if (rkIndex.row() == 0) return eAssetProperty;
|
||||
else if (rkIndex.row() == 1) return eEnumProperty;
|
||||
else if (rkIndex.row() == 2) return eLongProperty;
|
||||
if (rkIndex.row() == 0) return EPropertyTypeNew::Asset;
|
||||
else if (rkIndex.row() == 1) return EPropertyTypeNew::Choice;
|
||||
else if (rkIndex.row() == 2) return EPropertyTypeNew::Int;
|
||||
}
|
||||
else if (Game <= eCorruption)
|
||||
{
|
||||
if (rkIndex.row() == 0) return eAssetProperty;
|
||||
else if (rkIndex.row() == 1) return eLongProperty;
|
||||
if (rkIndex.row() == 0) return EPropertyTypeNew::Asset;
|
||||
else if (rkIndex.row() == 1) return EPropertyTypeNew::Int;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rkIndex.row() == 0) return eAssetProperty;
|
||||
else if (rkIndex.row() <= 2) return eLongProperty;
|
||||
if (rkIndex.row() == 0) return EPropertyTypeNew::Asset;
|
||||
else if (rkIndex.row() <= 2) return EPropertyTypeNew::Int;
|
||||
}
|
||||
return eUnknownProperty;
|
||||
return EPropertyTypeNew::Invalid;
|
||||
}
|
||||
|
||||
// ************ PUBLIC SLOTS ************
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
QWidget* CreateCharacterEditor(QWidget *pParent, const QModelIndex& rkIndex) const;
|
||||
void SetCharacterEditorData(QWidget *pEditor, const QModelIndex& rkIndex) const;
|
||||
void SetCharacterModelData(QWidget *pEditor, const QModelIndex& rkIndex) const;
|
||||
EPropertyType DetermineCharacterPropType(EGame Game, const QModelIndex& rkIndex) const;
|
||||
EPropertyTypeNew DetermineCharacterPropType(EGame Game, const QModelIndex& rkIndex) const;
|
||||
|
||||
public slots:
|
||||
void WidgetEdited(QWidget *pWidget, const QModelIndex& rkIndex);
|
||||
|
|
|
@ -8,77 +8,111 @@
|
|||
|
||||
CPropertyModel::CPropertyModel(QObject *pParent /*= 0*/)
|
||||
: QAbstractItemModel(pParent)
|
||||
, mpBaseStruct(nullptr)
|
||||
, mpProject(nullptr)
|
||||
, mpRootProperty(nullptr)
|
||||
, mpPropertyData(nullptr)
|
||||
, mBoldModifiedProperties(true)
|
||||
, mShowNameValidity(false)
|
||||
{
|
||||
}
|
||||
|
||||
void CPropertyModel::SetBaseStruct(CPropertyStruct *pBaseStruct)
|
||||
int CPropertyModel::RecursiveBuildArrays(IPropertyNew* pProperty, int ParentID)
|
||||
{
|
||||
mProperties << SProperty();
|
||||
SProperty& Property = mProperties.back();
|
||||
Property.pProperty = pProperty;
|
||||
Property.ParentID = ParentID;
|
||||
|
||||
int MyID = mProperties.size() - 1;
|
||||
int RowNumber = (ParentID >= 0 ? mProperties[ParentID].ChildIDs.size() : 0);
|
||||
Property.Index = createIndex(RowNumber, 0, pProperty);
|
||||
|
||||
if (pProperty->Type() == EPropertyTypeNew::Array)
|
||||
{
|
||||
CArrayProperty* pArray = TPropCast<CArrayProperty>(pProperty);
|
||||
|
||||
for (u32 ElementIdx = 0; ElementIdx < pArray->ArrayCount(mpPropertyData); ElementIdx++)
|
||||
{
|
||||
int NewChildID = RecursiveBuildArrays( pArray->Archetype(), MyID );
|
||||
Property.ChildIDs.push_back(NewChildID);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u32 ChildIdx = 0; ChildIdx < pProperty->NumChildren(); ChildIdx++)
|
||||
{
|
||||
int NewChildID = RecursiveBuildArrays( pProperty->ChildByIndex(ChildIdx), MyID );
|
||||
Property.ChildIDs.push_back(NewChildID);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pProperty->IsArrayArchetype())
|
||||
{
|
||||
mPropertyToIDMap[pProperty] = MyID;
|
||||
}
|
||||
|
||||
return MyID;
|
||||
}
|
||||
|
||||
void CPropertyModel::ConfigureIntrinsic(CGameProject* pProject, IPropertyNew* pRootProperty, void* pPropertyData)
|
||||
{
|
||||
beginResetModel();
|
||||
mpBaseStruct = pBaseStruct;
|
||||
|
||||
mpProject = pProject;
|
||||
mpObject = nullptr;
|
||||
mpRootProperty = pRootProperty;
|
||||
mpPropertyData = pPropertyData;
|
||||
|
||||
mProperties.clear();
|
||||
mPropertyToIDMap.clear();
|
||||
|
||||
if (pRootProperty)
|
||||
RecursiveBuildArrays(pRootProperty, -1);
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
IProperty* CPropertyModel::PropertyForIndex(const QModelIndex& rkIndex, bool HandleFlaggedPointers) const
|
||||
void CPropertyModel::ConfigureScript(CGameProject* pProject, IPropertyNew* pRootProperty, CScriptObject* pObject)
|
||||
{
|
||||
if (!rkIndex.isValid()) return mpBaseStruct;
|
||||
ConfigureIntrinsic(pProject, pRootProperty, pObject);
|
||||
mpObject = pObject;
|
||||
}
|
||||
|
||||
if (rkIndex.internalId() & 0x1)
|
||||
IPropertyNew* CPropertyModel::PropertyForIndex(const QModelIndex& rkIndex, bool HandleFlaggedIndices) const
|
||||
{
|
||||
if (!rkIndex.isValid()) return mpRootProperty;
|
||||
|
||||
int Index = rkIndex.internalId();
|
||||
|
||||
if (Index & 0x80000000)
|
||||
{
|
||||
if (HandleFlaggedPointers)
|
||||
{
|
||||
void *pID = (void*) (rkIndex.internalId() & ~0x1);
|
||||
return static_cast<IProperty*>(pID);
|
||||
}
|
||||
if (HandleFlaggedIndices)
|
||||
Index &= ~0x80000000;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return static_cast<IProperty*>(rkIndex.internalPointer());
|
||||
return mProperties[Index].pProperty;
|
||||
}
|
||||
|
||||
QModelIndex CPropertyModel::IndexForProperty(IProperty *pProp) const
|
||||
QModelIndex CPropertyModel::IndexForProperty(IPropertyNew *pProp) const
|
||||
{
|
||||
if (pProp == mpBaseStruct) return QModelIndex();
|
||||
|
||||
QVector<u32> RowNumbers;
|
||||
IProperty *pChild = pProp;
|
||||
CPropertyStruct *pParent = pProp->Parent();
|
||||
|
||||
while (pParent)
|
||||
// Array archetype properties cannot be associated with a single index because the same IProperty
|
||||
// is used for every element of the array. So instead fetch the index for the array itself.
|
||||
if (pProp->IsArrayArchetype())
|
||||
{
|
||||
// Check for array with one sub-property
|
||||
CPropertyStruct *pGrandparent = pParent->Parent();
|
||||
if (pGrandparent && pGrandparent->Type() == eArrayProperty && pParent->Count() == 1)
|
||||
{
|
||||
pChild = pParent;
|
||||
pParent = pGrandparent;
|
||||
continue;
|
||||
}
|
||||
while (pProp && pProp->IsArrayArchetype())
|
||||
pProp = pProp->Parent();
|
||||
|
||||
// Find row index for this child property
|
||||
for (u32 iChild = 0; iChild < pParent->Count(); iChild++)
|
||||
{
|
||||
if (pParent->PropertyByIndex(iChild) == pChild)
|
||||
{
|
||||
RowNumbers << iChild;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pChild = pParent;
|
||||
pParent = pGrandparent;
|
||||
ASSERT(pProp != nullptr && pProp->Type() == EPropertyTypeNew::Array);
|
||||
}
|
||||
|
||||
// Find the corresponding QModelIndex in the same spot
|
||||
QModelIndex Index = QModelIndex();
|
||||
if (pProp == mpRootProperty) return QModelIndex();
|
||||
|
||||
for (int iChild = RowNumbers.size() - 1; iChild >= 0; iChild--)
|
||||
Index = index(RowNumbers[iChild], 0, Index);
|
||||
int ID = mPropertyToIDMap[pProp];
|
||||
ASSERT(ID >= 0);
|
||||
|
||||
return Index;
|
||||
return mProperties[ID].Index;
|
||||
}
|
||||
|
||||
int CPropertyModel::columnCount(const QModelIndex& /*rkParent*/) const
|
||||
|
@ -88,38 +122,30 @@ int CPropertyModel::columnCount(const QModelIndex& /*rkParent*/) const
|
|||
|
||||
int CPropertyModel::rowCount(const QModelIndex& rkParent) const
|
||||
{
|
||||
if (!mpBaseStruct) return 0;
|
||||
if (!rkParent.isValid()) return mpBaseStruct->Count();
|
||||
if (!mpRootProperty) return 0;
|
||||
if (!rkParent.isValid()) return mpRootProperty->NumChildren();
|
||||
if (rkParent.column() != 0) return 0;
|
||||
if (rkParent.internalId() & 0x1) return 0;
|
||||
if (rkParent.internalId() & 0x80000000) return 0;
|
||||
|
||||
IProperty *pProp = PropertyForIndex(rkParent, false);
|
||||
IPropertyNew *pProp = PropertyForIndex(rkParent, false);
|
||||
int ID = mPropertyToIDMap[pProp];
|
||||
|
||||
switch (pProp->Type())
|
||||
{
|
||||
case eStructProperty:
|
||||
case eArrayProperty:
|
||||
return static_cast<CPropertyStruct*>(pProp)->Count();
|
||||
case EPropertyTypeNew::Flags:
|
||||
return TPropCast<CFlagsProperty>(pProp)->NumFlags();
|
||||
|
||||
case eBitfieldProperty:
|
||||
return static_cast<CBitfieldTemplate*>(pProp->Template())->NumFlags();
|
||||
|
||||
case eVector3Property:
|
||||
return 3;
|
||||
|
||||
case eColorProperty:
|
||||
return 4;
|
||||
|
||||
case eCharacterProperty:
|
||||
case EPropertyTypeNew::AnimationSet:
|
||||
{
|
||||
CAnimationParameters Params = static_cast<TCharacterProperty*>(pProp)->Get();
|
||||
CAnimationParameters Params = TPropCast<CAnimationSetProperty>(pProp)->Value(mpPropertyData);
|
||||
|
||||
if (Params.Version() <= eEchoes) return 3;
|
||||
if (Params.Version() <= eCorruption) return 2;
|
||||
return 4;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
return mProperties[ID].ChildIDs.size();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,73 +168,29 @@ QVariant CPropertyModel::data(const QModelIndex& rkIndex, int Role) const
|
|||
{
|
||||
if (rkIndex.internalId() & 0x1)
|
||||
{
|
||||
IProperty *pProp = PropertyForIndex(rkIndex, true);
|
||||
IPropertyNew *pProp = PropertyForIndex(rkIndex, true);
|
||||
EPropertyTypeNew Type = pProp->Type();
|
||||
|
||||
if (pProp->Type() == eColorProperty)
|
||||
if (Type == EPropertyTypeNew::Flags)
|
||||
{
|
||||
if (rkIndex.column() == 0)
|
||||
{
|
||||
if (rkIndex.row() == 0) return "R";
|
||||
if (rkIndex.row() == 1) return "G";
|
||||
if (rkIndex.row() == 2) return "B";
|
||||
if (rkIndex.row() == 3) return "A";
|
||||
}
|
||||
|
||||
else if (rkIndex.column() == 1)
|
||||
{
|
||||
TStringList Strings = pProp->ToString().Split(" ,");
|
||||
|
||||
int i = 0;
|
||||
for (auto it = Strings.begin(); it != Strings.end(); it++)
|
||||
{
|
||||
if (i == rkIndex.row()) return TO_QSTRING(*it);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (pProp->Type() == eVector3Property)
|
||||
{
|
||||
if (rkIndex.column() == 0)
|
||||
{
|
||||
if (rkIndex.row() == 0) return "X";
|
||||
if (rkIndex.row() == 1) return "Y";
|
||||
if (rkIndex.row() == 2) return "Z";
|
||||
}
|
||||
|
||||
else if (rkIndex.column() == 1)
|
||||
{
|
||||
TStringList Strings = pProp->ToString().Split(" ,");
|
||||
|
||||
int i = 0;
|
||||
for (auto it = Strings.begin(); it != Strings.end(); it++)
|
||||
{
|
||||
if (i == rkIndex.row()) return TO_QSTRING(*it);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (pProp->Type() == eBitfieldProperty)
|
||||
{
|
||||
CBitfieldTemplate *pBitfield = static_cast<CBitfieldTemplate*>(pProp->Template());
|
||||
CFlagsProperty* pFlags = TPropCast<CFlagsProperty>(pProp);
|
||||
|
||||
if (rkIndex.column() == 0)
|
||||
return TO_QSTRING(pBitfield->FlagName(rkIndex.row()));
|
||||
return TO_QSTRING( pFlags->FlagName(rkIndex.row()) );
|
||||
|
||||
if (rkIndex.column() == 1)
|
||||
{
|
||||
if (Role == Qt::DisplayRole)
|
||||
return "";
|
||||
else
|
||||
return TO_QSTRING(TString::HexString(pBitfield->FlagMask(rkIndex.row())));
|
||||
return TO_QSTRING(TString::HexString( pFlags->FlagMask(rkIndex.row())));
|
||||
}
|
||||
}
|
||||
|
||||
else if (pProp->Type() == eCharacterProperty)
|
||||
else if (Type == EPropertyTypeNew::AnimationSet)
|
||||
{
|
||||
TCharacterProperty *pChar = static_cast<TCharacterProperty*>(pProp);
|
||||
CAnimationParameters Params = pChar->Get();
|
||||
CAnimationSetProperty* pAnimSet = TPropCast<CAnimationSetProperty>(pProp);
|
||||
CAnimationParameters Params = pAnimSet->Value(mpPropertyData);
|
||||
|
||||
// There are three different layouts for this property - one for MP1/2, one for MP3, and one for DKCR
|
||||
if (Params.Version() <= eEchoes)
|
||||
|
@ -255,28 +237,18 @@ QVariant CPropertyModel::data(const QModelIndex& rkIndex, int Role) const
|
|||
|
||||
else
|
||||
{
|
||||
IProperty *pProp = PropertyForIndex(rkIndex, false);
|
||||
IPropertyNew *pProp = PropertyForIndex(rkIndex, false);
|
||||
|
||||
if (rkIndex.column() == 0)
|
||||
{
|
||||
// Check for arrays
|
||||
IProperty *pParent = pProp->Parent();
|
||||
IPropertyNew *pParent = pProp->Parent();
|
||||
|
||||
if (pParent)
|
||||
if (pParent && pParent->Type() == EPropertyTypeNew::Array)
|
||||
{
|
||||
// For direct array sub-properties, display the element name instead of the property name (the property name is the array name)
|
||||
if (pProp->Type() == eStructProperty && pParent->Type() == eArrayProperty)
|
||||
{
|
||||
TString ElementName = static_cast<CArrayProperty*>(pParent)->ElementName();
|
||||
return QString("%1 %2").arg(TO_QSTRING(ElementName)).arg(rkIndex.row() + 1);
|
||||
}
|
||||
|
||||
// Check whether the parent struct is an array element with one sub-property
|
||||
if (pParent->Type() == eStructProperty && pParent->Parent() && pParent->Parent()->Type() == eArrayProperty)
|
||||
{
|
||||
if (static_cast<CPropertyStruct*>(pParent)->Count() == 1)
|
||||
return QString("%1 %2").arg(TO_QSTRING(pProp->Name())).arg(rkIndex.row() + 1);
|
||||
}
|
||||
// For direct array sub-properties, display the element index after the name
|
||||
TString ElementName = pParent->Name();
|
||||
return QString("%1 %2").arg( TO_QSTRING(ElementName) ).arg(rkIndex.row() + 1);
|
||||
}
|
||||
|
||||
// Display property name for everything else
|
||||
|
@ -288,19 +260,20 @@ QVariant CPropertyModel::data(const QModelIndex& rkIndex, int Role) const
|
|||
switch (pProp->Type())
|
||||
{
|
||||
// Enclose vector property text in parentheses
|
||||
case eVector3Property:
|
||||
return "(" + TO_QSTRING(pProp->ToString()) + ")";
|
||||
case EPropertyTypeNew::Vector:
|
||||
{
|
||||
CVector3f Value = TPropCast<CVectorProperty>(pProp)->Value(mpPropertyData);
|
||||
return TO_QSTRING("(" + Value.ToString() + ")");
|
||||
}
|
||||
|
||||
// Display the AGSC/sound name for sounds
|
||||
case eSoundProperty:
|
||||
case EPropertyTypeNew::Sound:
|
||||
{
|
||||
TSoundProperty *pSound = static_cast<TSoundProperty*>(pProp);
|
||||
u32 SoundID = pSound->Get();
|
||||
CSoundProperty* pSound = TPropCast<CSoundProperty>(pProp);
|
||||
u32 SoundID = pSound->Value(mpPropertyData);
|
||||
if (SoundID == -1) return "[None]";
|
||||
|
||||
CGameProject *pProj = pSound->Instance()->Area()->Entry()->Project();
|
||||
SSoundInfo SoundInfo = pProj->AudioManager()->GetSoundInfo(SoundID);
|
||||
|
||||
SSoundInfo SoundInfo = mpProject->AudioManager()->GetSoundInfo(SoundID);
|
||||
QString Out = QString::number(SoundID);
|
||||
|
||||
if (SoundInfo.DefineID == -1)
|
||||
|
@ -320,40 +293,47 @@ QVariant CPropertyModel::data(const QModelIndex& rkIndex, int Role) const
|
|||
}
|
||||
|
||||
// Display character name for characters
|
||||
case eCharacterProperty:
|
||||
return TO_QSTRING(static_cast<TCharacterProperty*>(pProp)->Get().GetCurrentCharacterName());
|
||||
case EPropertyTypeNew::AnimationSet:
|
||||
return TO_QSTRING(TPropCast<CAnimationSetProperty>(pProp)->Value(mpPropertyData).GetCurrentCharacterName());
|
||||
|
||||
// Display enumerator name for enums (but only on ToolTipRole)
|
||||
case eEnumProperty:
|
||||
case EPropertyTypeNew::Choice:
|
||||
case EPropertyTypeNew::Enum:
|
||||
if (Role == Qt::ToolTipRole)
|
||||
{
|
||||
TEnumProperty *pEnum = static_cast<TEnumProperty*>(pProp);
|
||||
CEnumTemplate *pTemp = static_cast<CEnumTemplate*>(pEnum->Template());
|
||||
return TO_QSTRING(pTemp->EnumeratorName( pTemp->EnumeratorIndex(pEnum->Get()) ));
|
||||
CEnumProperty *pEnum = TPropCast<CEnumProperty>(pProp);
|
||||
u32 ValueID = pEnum->Value(mpPropertyData);
|
||||
u32 ValueIndex = pEnum->ValueIndex(ValueID);
|
||||
return TO_QSTRING( pEnum->ValueName(ValueIndex) );
|
||||
}
|
||||
else return "";
|
||||
|
||||
// Display the element count for arrays
|
||||
case eArrayProperty:
|
||||
case EPropertyTypeNew::Array:
|
||||
{
|
||||
u32 Count = static_cast<CArrayProperty*>(pProp)->Count();
|
||||
u32 Count = TPropCast<CArrayProperty>(pProp)->Value(mpPropertyData);
|
||||
return QString("%1 element%2").arg(Count).arg(Count != 1 ? "s" : "");
|
||||
}
|
||||
|
||||
// Display "[MayaSpline]" for MayaSplines (todo: proper support)
|
||||
case eMayaSplineProperty:
|
||||
return "[MayaSpline]";
|
||||
// Display "[spline]" for splines (todo: proper support)
|
||||
case EPropertyTypeNew::Spline:
|
||||
return "[spline]";
|
||||
|
||||
// No display text on properties with persistent editors
|
||||
case eBoolProperty:
|
||||
case eAssetProperty:
|
||||
case eColorProperty:
|
||||
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)
|
||||
return "";
|
||||
// fall through
|
||||
// Display property value to string for everything else
|
||||
default:
|
||||
return TO_QSTRING(pProp->ToString() + pProp->Template()->Suffix());
|
||||
return TO_QSTRING(pProp->ValueAsString(mpPropertyData) + pProp->Suffix());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -364,23 +344,23 @@ QVariant CPropertyModel::data(const QModelIndex& rkIndex, int Role) const
|
|||
if (!(rkIndex.internalId() & 0x1))
|
||||
{
|
||||
// Add name
|
||||
IProperty *pProp = PropertyForIndex(rkIndex, false);
|
||||
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())));
|
||||
|
||||
// Add uncooked notification
|
||||
if (pProp->Template()->CookPreference() == eNeverCook)
|
||||
if (pProp->CookPreference() == ECookPreferenceNew::Never)
|
||||
{
|
||||
Text.prepend("<i>[uncooked]</i>");
|
||||
}
|
||||
|
||||
// Add description
|
||||
TString Desc = pProp->Template()->Description();
|
||||
TString Desc = pProp->Description();
|
||||
if (!Desc.IsEmpty()) Text += "<br/>" + TO_QSTRING(Desc);
|
||||
|
||||
// MayaSpline notification
|
||||
if (pProp->Type() == eMayaSplineProperty)
|
||||
Text += "<br/><i>(NOTE: MayaSpline properties are currently unsupported for editing)</i>";
|
||||
// Spline notification
|
||||
if (pProp->Type() == EPropertyTypeNew::Spline)
|
||||
Text += "<br/><i>(NOTE: Spline properties are currently unsupported for editing)</i>";
|
||||
|
||||
return Text;
|
||||
}
|
||||
|
@ -393,45 +373,12 @@ QVariant CPropertyModel::data(const QModelIndex& rkIndex, int Role) const
|
|||
|
||||
if (mBoldModifiedProperties)
|
||||
{
|
||||
IProperty *pProp = PropertyForIndex(rkIndex, true);
|
||||
IPropertyNew *pProp = PropertyForIndex(rkIndex, true);
|
||||
|
||||
if (!pProp->IsInArray())
|
||||
if (!pProp->IsArrayArchetype())
|
||||
{
|
||||
if (rkIndex.internalId() & 0x1)
|
||||
{
|
||||
if (pProp->Type() == eVector3Property)
|
||||
{
|
||||
TVector3Property *pVec = static_cast<TVector3Property*>(pProp);
|
||||
TVector3Template *pTemp = static_cast<TVector3Template*>(pProp->Template());
|
||||
|
||||
CVector3f Value = pVec->Get();
|
||||
CVector3f Default = pTemp->GetDefaultValue();
|
||||
|
||||
if (rkIndex.row() == 0) Bold = (Value.X != Default.X);
|
||||
if (rkIndex.row() == 1) Bold = (Value.Y != Default.Y);
|
||||
if (rkIndex.row() == 2) Bold = (Value.Z != Default.Z);
|
||||
}
|
||||
|
||||
else if (pProp->Type() == eColorProperty)
|
||||
{
|
||||
TColorProperty *pColor = static_cast<TColorProperty*>(pProp);
|
||||
TColorTemplate *pTemp = static_cast<TColorTemplate*>(pProp->Template());
|
||||
|
||||
CColor Value = pColor->Get();
|
||||
CColor Default = pTemp->GetDefaultValue();
|
||||
|
||||
if (rkIndex.row() == 0) Bold = (Value.R != Default.R);
|
||||
if (rkIndex.row() == 1) Bold = (Value.G != Default.G);
|
||||
if (rkIndex.row() == 2) Bold = (Value.B != Default.B);
|
||||
if (rkIndex.row() == 3) Bold = (Value.A != Default.A);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Bold = !pProp->MatchesDefault();
|
||||
}
|
||||
}
|
||||
Bold = !pProp->MatchesDefault(mpPropertyData);
|
||||
}
|
||||
}
|
||||
|
||||
Font.setBold(Bold);
|
||||
|
@ -445,17 +392,16 @@ QVariant CPropertyModel::data(const QModelIndex& rkIndex, int Role) const
|
|||
|
||||
if (Role == Qt::ForegroundRole)
|
||||
{
|
||||
if (mShowNameValidity && mpBaseStruct->Template()->Game() >= eEchoesDemo)
|
||||
if (mShowNameValidity && mpRootProperty->ScriptTemplate()->Game() >= eEchoesDemo)
|
||||
{
|
||||
IProperty *pProp = PropertyForIndex(rkIndex, true);
|
||||
IPropertyTemplate *pTemp = (pProp ? pProp->Template() : nullptr);
|
||||
IPropertyNew *pProp = PropertyForIndex(rkIndex, true);
|
||||
|
||||
// Don't highlight the name of the root property
|
||||
if (pTemp && pTemp->Parent() != nullptr)
|
||||
if (pProp && pProp->Parent() != nullptr && !pProp->IsArrayArchetype())
|
||||
{
|
||||
static const QColor skRightColor = QColor(128, 255, 128);
|
||||
static const QColor skWrongColor = QColor(255, 128, 128);
|
||||
return QBrush( pTemp->IsNameCorrect() ? skRightColor : skWrongColor );
|
||||
return QBrush( pProp->HasAccurateName() ? skRightColor : skWrongColor );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -470,33 +416,19 @@ QModelIndex CPropertyModel::index(int Row, int Column, const QModelIndex& rkPare
|
|||
return QModelIndex();
|
||||
|
||||
// Check property for children
|
||||
IProperty *pParent = (rkParent.isValid() ? PropertyForIndex(rkParent, false) : mpBaseStruct);
|
||||
IPropertyNew* pParent = (rkParent.isValid() ? PropertyForIndex(rkParent, false) : mpRootProperty);
|
||||
EPropertyTypeNew ParentType = pParent->Type();
|
||||
int ParentID = mPropertyToIDMap[pParent];
|
||||
|
||||
// Struct
|
||||
if (pParent->Type() == eStructProperty)
|
||||
if (ParentType == EPropertyTypeNew::Flags || ParentType == EPropertyTypeNew::AnimationSet)
|
||||
{
|
||||
IProperty *pProp = static_cast<CPropertyStruct*>(pParent)->PropertyByIndex(Row);
|
||||
return createIndex(Row, Column, pProp);
|
||||
return createIndex(Row, Column, ParentID | 0x80000000);
|
||||
}
|
||||
|
||||
// Array
|
||||
if (pParent->Type() == eArrayProperty)
|
||||
else
|
||||
{
|
||||
IProperty *pProp = static_cast<CArrayProperty*>(pParent)->PropertyByIndex(Row);
|
||||
|
||||
// If this array element only has one sub-property then let's just skip the redundant tree node and show the sub-property directly.
|
||||
CPropertyStruct *pStruct = static_cast<CPropertyStruct*>(pProp);
|
||||
if (pStruct->Count() == 1)
|
||||
pProp = pStruct->PropertyByIndex(0);
|
||||
|
||||
return createIndex(Row, Column, pProp);
|
||||
int ChildID = mProperties[ParentID].ChildIDs[Row];
|
||||
return createIndex(Row, Column, ChildID);
|
||||
}
|
||||
|
||||
// Other property
|
||||
if (pParent->Type() == eColorProperty || pParent->Type() == eVector3Property || pParent->Type() == eBitfieldProperty || pParent->Type() == eCharacterProperty)
|
||||
return createIndex(Row, Column, u64(pParent) | 0x1);
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex CPropertyModel::parent(const QModelIndex& rkChild) const
|
||||
|
@ -505,39 +437,14 @@ QModelIndex CPropertyModel::parent(const QModelIndex& rkChild) const
|
|||
if (!rkChild.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
// Find parent property
|
||||
IProperty *pParent;
|
||||
int ID = int(rkChild.internalId());
|
||||
|
||||
if (rkChild.internalId() & 0x1)
|
||||
pParent = PropertyForIndex(rkChild, true);
|
||||
if (ID & 0x80000000)
|
||||
ID &= ~0x80000000;
|
||||
else
|
||||
pParent = PropertyForIndex(rkChild, false)->Parent();
|
||||
ID = mProperties[ID].ParentID;
|
||||
|
||||
if (pParent == mpBaseStruct)
|
||||
return QModelIndex();
|
||||
|
||||
// Iterate over grandfather properties until we find the row
|
||||
CPropertyStruct *pGrandparent = pParent->Parent();
|
||||
|
||||
// Check for array with one sub-property
|
||||
if (pGrandparent->Type() == eArrayProperty)
|
||||
{
|
||||
CPropertyStruct *pStruct = static_cast<CPropertyStruct*>(pParent);
|
||||
|
||||
if (pStruct->Count() == 1)
|
||||
{
|
||||
pParent = pGrandparent;
|
||||
pGrandparent = pGrandparent->Parent();
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 iProp = 0; iProp < pGrandparent->Count(); iProp++)
|
||||
{
|
||||
if (pGrandparent->PropertyByIndex(iProp) == pParent)
|
||||
return createIndex(iProp, 0, pParent);
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
return mProperties[ID].Index;
|
||||
}
|
||||
|
||||
Qt::ItemFlags CPropertyModel::flags(const QModelIndex& rkIndex) const
|
||||
|
@ -546,7 +453,7 @@ Qt::ItemFlags CPropertyModel::flags(const QModelIndex& rkIndex) const
|
|||
else return (Qt::ItemIsEnabled | Qt::ItemIsEditable);
|
||||
}
|
||||
|
||||
void CPropertyModel::NotifyPropertyModified(class CScriptObject*, IProperty *pProp)
|
||||
void CPropertyModel::NotifyPropertyModified(class CScriptObject*, IPropertyNew* pProp)
|
||||
{
|
||||
NotifyPropertyModified(IndexForProperty(pProp));
|
||||
}
|
||||
|
@ -556,7 +463,7 @@ void CPropertyModel::NotifyPropertyModified(const QModelIndex& rkIndex)
|
|||
if (rowCount(rkIndex) != 0)
|
||||
emit dataChanged( index(0, 0, rkIndex), index(rowCount(rkIndex) - 1, 1, rkIndex));
|
||||
|
||||
if (rkIndex.internalId() & 0x1)
|
||||
if (rkIndex.internalId() & 0x80000000)
|
||||
{
|
||||
QModelIndex Parent = rkIndex.parent();
|
||||
QModelIndex Col0 = Parent.sibling(Parent.row(), 0);
|
||||
|
@ -573,7 +480,8 @@ void CPropertyModel::NotifyPropertyModified(const QModelIndex& rkIndex)
|
|||
|
||||
void CPropertyModel::ArrayAboutToBeResized(const QModelIndex& rkIndex, u32 NewSize)
|
||||
{
|
||||
QModelIndex Index = rkIndex.sibling(rkIndex.row(), 0);
|
||||
//FIXME
|
||||
/*QModelIndex Index = rkIndex.sibling(rkIndex.row(), 0);
|
||||
CArrayProperty *pArray = static_cast<CArrayProperty*>(PropertyForIndex(Index, false));
|
||||
|
||||
if (pArray && pArray->Type() == eArrayProperty)
|
||||
|
@ -587,12 +495,13 @@ void CPropertyModel::ArrayAboutToBeResized(const QModelIndex& rkIndex, u32 NewSi
|
|||
else
|
||||
beginRemoveRows(Index, NewSize, OldSize - 1);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void CPropertyModel::ArrayResized(const QModelIndex& rkIndex, u32 OldSize)
|
||||
{
|
||||
CArrayProperty *pArray = static_cast<CArrayProperty*>(PropertyForIndex(rkIndex, false));
|
||||
//FIXME
|
||||
/*CArrayProperty *pArray = static_cast<CArrayProperty*>(PropertyForIndex(rkIndex, false));
|
||||
u32 NewSize = pArray->Count();
|
||||
|
||||
if (NewSize != OldSize)
|
||||
|
@ -601,7 +510,7 @@ void CPropertyModel::ArrayResized(const QModelIndex& rkIndex, u32 OldSize)
|
|||
endInsertRows();
|
||||
else
|
||||
endRemoveRows();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void CPropertyModel::SetShowPropertyNameValidity(bool Enable)
|
||||
|
|
|
@ -1,24 +1,41 @@
|
|||
#ifndef CPROPERTYMODEL_H
|
||||
#define CPROPERTYMODEL_H
|
||||
|
||||
#include <Core/Resource/Script/Property/Properties.h>
|
||||
#include <QAbstractItemModel>
|
||||
#include <Core/Resource/Script/IProperty.h>
|
||||
#include <QFont>
|
||||
|
||||
class CPropertyModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
CPropertyStruct *mpBaseStruct;
|
||||
struct SProperty
|
||||
{
|
||||
IPropertyNew* pProperty;
|
||||
QModelIndex Index;
|
||||
int ParentID;
|
||||
std::vector<int> ChildIDs;
|
||||
};
|
||||
QVector<SProperty> mProperties;
|
||||
QMap<IPropertyNew*, int> mPropertyToIDMap;
|
||||
|
||||
CGameProject* mpProject;
|
||||
CScriptObject* mpObject; // may be null
|
||||
IPropertyNew* mpRootProperty;
|
||||
void* mpPropertyData;
|
||||
|
||||
bool mBoldModifiedProperties;
|
||||
bool mShowNameValidity;
|
||||
QFont mFont;
|
||||
|
||||
int RecursiveBuildArrays(IPropertyNew* pProperty, int ParentID);
|
||||
|
||||
public:
|
||||
CPropertyModel(QObject *pParent = 0);
|
||||
void SetBaseStruct(CPropertyStruct *pBaseStruct);
|
||||
IProperty* PropertyForIndex(const QModelIndex& rkIndex, bool HandleFlaggedPointers) const;
|
||||
QModelIndex IndexForProperty(IProperty *pProp) const;
|
||||
void ConfigureIntrinsic(CGameProject* pProject, IPropertyNew* pRootProperty, void* pPropertyData);
|
||||
void ConfigureScript(CGameProject* pProject, IPropertyNew* pRootProperty, CScriptObject* pObject);
|
||||
IPropertyNew* PropertyForIndex(const QModelIndex& rkIndex, bool HandleFlaggedIndices) const;
|
||||
QModelIndex IndexForProperty(IPropertyNew *pProp) const;
|
||||
|
||||
int columnCount(const QModelIndex& rkParent) const;
|
||||
int rowCount(const QModelIndex& rkParent) const;
|
||||
|
@ -36,9 +53,11 @@ public:
|
|||
|
||||
inline void SetFont(QFont Font) { mFont = Font; }
|
||||
inline void SetBoldModifiedProperties(bool Enable) { mBoldModifiedProperties = Enable; }
|
||||
inline void* GetPropertyData() const { return mpPropertyData; }
|
||||
inline CScriptObject* GetScriptObject() const { return mpObject; }
|
||||
|
||||
public slots:
|
||||
void NotifyPropertyModified(class CScriptObject *pInst, IProperty *pProp);
|
||||
void NotifyPropertyModified(class CScriptObject *pInst, IPropertyNew *pProp);
|
||||
void NotifyPropertyModified(const QModelIndex& rkIndex);
|
||||
|
||||
signals:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue