From ce3dfdc397cb45676db236d628a6e527df190979 Mon Sep 17 00:00:00 2001 From: Aruki Date: Fri, 22 Jun 2018 15:24:04 -0600 Subject: [PATCH] Massive overhaul of property system done over the last few months. There is unfinished/broken stuff still, but it compiles now. --- src/.qmake.conf | 9 +- src/Common/Common.h | 6 +- src/Common/Common.pro | 3 +- src/Common/FileIO/CVectorOutStream.cpp | 55 +- src/Common/FileIO/CVectorOutStream.h | 7 +- src/Common/Flags.h | 30 +- src/Common/NBasics.h | 45 ++ src/Common/Serialization/CBasicBinaryReader.h | 11 + src/Common/Serialization/CBasicBinaryWriter.h | 2 + src/Common/Serialization/CBinaryReader.h | 2 + src/Common/Serialization/CBinaryWriter.h | 2 + src/Common/Serialization/CXMLReader.h | 13 + src/Common/Serialization/CXMLWriter.h | 11 + src/Common/Serialization/IArchive.h | 15 + src/Common/TString.cpp | 8 +- src/Common/TString.h | 41 +- src/Core/CAreaAttributes.cpp | 46 +- src/Core/CAreaAttributes.h | 8 +- src/Core/CLightParameters.h | 37 +- src/Core/Core.pro | 29 +- src/Core/GameProject/AssetNameGeneration.cpp | 15 +- src/Core/GameProject/CDependencyTree.cpp | 35 +- src/Core/GameProject/CDependencyTree.h | 4 +- .../Animation/CAnimationParameters.cpp | 19 + .../Resource/Animation/CAnimationParameters.h | 1 + src/Core/Resource/CResTypeFilter.h | 6 + src/Core/Resource/CResTypeInfo.cpp | 130 +++-- src/Core/Resource/CResTypeInfo.h | 3 +- src/Core/Resource/Cooker/CScriptCooker.cpp | 183 +++--- src/Core/Resource/Cooker/CScriptCooker.h | 6 +- src/Core/Resource/Cooker/CTemplateWriter.cpp | 7 +- src/Core/Resource/Cooker/CTemplateWriter.h | 2 + src/Core/Resource/EResType.h | 3 + src/Core/Resource/Factory/CScriptLoader.cpp | 353 ++++++------ src/Core/Resource/Factory/CScriptLoader.h | 17 +- src/Core/Resource/Factory/CTemplateLoader.cpp | 534 ++++++++++++------ src/Core/Resource/Factory/CTemplateLoader.h | 27 +- src/Core/Resource/Script/CMasterTemplate.cpp | 66 ++- src/Core/Resource/Script/CMasterTemplate.h | 17 +- src/Core/Resource/Script/CScriptObject.cpp | 59 +- src/Core/Resource/Script/CScriptObject.h | 59 +- src/Core/Resource/Script/CScriptTemplate.cpp | 119 ++-- src/Core/Resource/Script/CScriptTemplate.h | 45 +- src/Core/Resource/Script/EPropertyType.h | 10 +- src/Core/Resource/Script/IProperty.cpp | 2 + src/Core/Resource/Script/IProperty.h | 3 +- src/Core/Resource/Script/IPropertyNew.cpp | 364 ++++++++++++ src/Core/Resource/Script/IPropertyNew.h | 432 ++++++++++++++ .../Resource/Script/IPropertyTemplate.cpp | 101 ++-- src/Core/Resource/Script/IPropertyTemplate.h | 2 + src/Core/Resource/Script/IPropertyValue.h | 2 + .../Script/Property/CAnimationProperty.h | 27 + .../Script/Property/CAnimationSetProperty.h | 22 + .../Resource/Script/Property/CArrayProperty.h | 176 ++++++ .../Resource/Script/Property/CAssetProperty.h | 42 ++ .../Resource/Script/Property/CBoolProperty.h | 27 + .../Resource/Script/Property/CByteProperty.h | 27 + .../Resource/Script/Property/CColorProperty.h | 34 ++ .../Resource/Script/Property/CEnumProperty.h | 124 ++++ .../Resource/Script/Property/CFlagsProperty.h | 99 ++++ .../Resource/Script/Property/CFloatProperty.h | 27 + .../Resource/Script/Property/CGuidProperty.h | 22 + .../Resource/Script/Property/CIntProperty.h | 27 + .../Script/Property/CPointerProperty.h | 27 + .../Script/Property/CSequenceProperty.h | 19 + .../Resource/Script/Property/CShortProperty.h | 27 + .../Resource/Script/Property/CSoundProperty.h | 27 + .../Script/Property/CSplineProperty.h | 22 + .../Script/Property/CStringProperty.h | 27 + .../Script/Property/CStructProperty.h | 146 +++++ .../Script/Property/CVectorProperty.h | 37 ++ .../Resource/Script/Property/Properties.h | 27 + .../Resource/Script/Property/TPropertyRef.h | 113 ++++ src/Core/Resource/Script/TPropertyProxy.h | 39 ++ src/Core/Scene/CScriptAttachNode.cpp | 28 +- src/Core/Scene/CScriptAttachNode.h | 13 +- src/Core/Scene/CScriptNode.cpp | 61 +- src/Core/Scene/CScriptNode.h | 2 +- .../ScriptExtra/CDamageableTriggerExtra.cpp | 49 +- .../ScriptExtra/CDamageableTriggerExtra.h | 15 +- src/Core/ScriptExtra/CDoorExtra.cpp | 34 +- src/Core/ScriptExtra/CDoorExtra.h | 13 +- .../ScriptExtra/CPointOfInterestExtra.cpp | 16 +- src/Core/ScriptExtra/CPointOfInterestExtra.h | 4 +- src/Core/ScriptExtra/CRadiusSphereExtra.cpp | 22 +- src/Core/ScriptExtra/CRadiusSphereExtra.h | 6 +- src/Core/ScriptExtra/CSandwormExtra.cpp | 20 +- src/Core/ScriptExtra/CSandwormExtra.h | 6 +- src/Core/ScriptExtra/CScriptExtra.h | 2 +- src/Core/ScriptExtra/CSpacePirateExtra.cpp | 28 +- src/Core/ScriptExtra/CSpacePirateExtra.h | 20 +- src/Core/ScriptExtra/CSplinePathExtra.cpp | 24 +- src/Core/ScriptExtra/CSplinePathExtra.h | 12 +- src/Editor/CGeneratePropertyNamesDialog.cpp | 3 +- src/Editor/CPropertyNameValidator.cpp | 6 +- src/Editor/CPropertyNameValidator.h | 6 +- src/Editor/PropertyEdit/CPropertyDelegate.cpp | 240 ++++---- src/Editor/PropertyEdit/CPropertyDelegate.h | 2 +- src/Editor/PropertyEdit/CPropertyModel.cpp | 433 ++++++-------- src/Editor/PropertyEdit/CPropertyModel.h | 31 +- src/Editor/PropertyEdit/CPropertyView.cpp | 52 +- src/Editor/PropertyEdit/CPropertyView.h | 2 +- src/Editor/Undo/CCloneSelectionCommand.cpp | 2 +- src/Editor/Undo/CDeleteSelectionCommand.cpp | 6 +- .../Undo/CEditScriptPropertyCommand.cpp | 3 +- src/Editor/Undo/CEditScriptPropertyCommand.h | 71 ++- src/Editor/Undo/CResizeScriptArrayCommand.cpp | 7 +- src/Editor/Undo/CResizeScriptArrayCommand.h | 13 +- src/Editor/Undo/ObjReferences.h | 30 - src/Editor/WorldEditor/CInstancesModel.cpp | 6 +- src/Editor/WorldEditor/CInstancesModel.h | 2 +- .../WorldEditor/CTemplateEditDialog.cpp | 96 ++-- src/Editor/WorldEditor/CTemplateEditDialog.h | 15 +- src/Editor/WorldEditor/CWorldEditor.cpp | 34 +- src/Editor/WorldEditor/CWorldEditor.h | 4 +- src/Editor/WorldEditor/WEditorProperties.cpp | 6 +- src/Editor/WorldEditor/WEditorProperties.h | 2 +- src/Editor/main.cpp | 4 + src/Math/CVector3f.cpp | 5 + src/Math/CVector3f.h | 1 + templates/Properties.xml | 88 +-- templates/mp1/Script/CameraHint.xml | 97 +--- templates/mp1/Script/Magdolite.xml | 11 +- templates/mp1/Script/MetroidPrimeStage1.xml | 62 +- templates/mp1/Script/NewCameraShaker.xml | 71 +-- templates/mp1/Script/PathCamera.xml | 11 +- templates/mp1/Script/PlayerActor.xml | 10 +- templates/mp1/Script/PlayerHint.xml | 2 +- templates/mp1/Script/Ridley.xml | 28 +- templates/mp1/Script/RumbleEffect.xml | 7 +- templates/mp1/Script/ScriptBeam.xml | 21 +- templates/mp1/Script/SpecialFunction.xml | 7 +- templates/mp1/Script/SpindleCamera.xml | 32 +- templates/mp1/Script/Steam.xml | 14 +- templates/mp1/Script/Water.xml | 10 +- templates/mp1/Structs/BeamCombos.xml | 10 + templates/mp1/Structs/BoolFloat 1.xml | 7 + templates/mp1/Structs/BoolFloat 2.xml | 7 + templates/mp1/Structs/BoolFloat 3.xml | 7 + templates/mp1/Structs/BoolFloat 4.xml | 7 + templates/mp1/Structs/BoolFloat 5.xml | 7 + templates/mp1/Structs/BoolFloat 6.xml | 7 + templates/mp1/Structs/BoolFloat 7.xml | 7 + templates/mp1/Structs/BoolFloat 8.xml | 7 + templates/mp1/Structs/BoolVec3f 1.xml | 7 + templates/mp1/Structs/BoolVec3f 2.xml | 7 + templates/mp1/Structs/ChargedBeams.xml | 10 + templates/mp1/Structs/DamageVulnerability.xml | 20 +- templates/mp1/Structs/FluidUVMotion.xml | 10 + templates/mp1/Structs/LayerSwitch.xml | 7 + templates/mp1/Structs/LongBool.xml | 7 + .../mp1/Structs/MP1-CameraHintStruct.xml | 27 + templates/mp1/Structs/MP1-GuessStruct 1.xml | 7 + templates/mp1/Structs/MP1-GuessStruct 2.xml | 7 + templates/mp1/Structs/MP1-GuessStruct.xml | 7 + templates/mp1/Structs/MP1-MagdoliteStruct.xml | 11 + .../mp1/Structs/MP1-MassivePrimeStruct.xml | 54 ++ .../Structs/MP1-NewCameraShakerStruct 1.xml | 19 + .../Structs/MP1-NewCameraShakerStruct 2.xml | 19 + .../Structs/MP1-NewCameraShakerStruct 3.xml | 19 + .../mp1/Structs/MP1-PathCameraStruct.xml | 11 + .../mp1/Structs/MP1-PlayerActorStruct.xml | 10 + .../mp1/Structs/MP1-PlayerHintStruct.xml | 26 + templates/mp1/Structs/MP1-PrimeStruct1.xml | 19 + templates/mp1/Structs/MP1-PrimeStruct2.xml | 11 + templates/mp1/Structs/MP1-PrimeStruct3.xml | 14 + templates/mp1/Structs/MP1-PrimeStruct4.xml | 27 + templates/mp1/Structs/MP1-PrimeStruct5.xml | 13 + templates/mp1/Structs/MP1-PrimeStruct6.xml | 9 + templates/mp1/Structs/MP1-RidleyStruct1.xml | 22 + templates/mp1/Structs/MP1-RidleyStruct2.xml | 14 + .../mp1/Structs/MP1-RumbleEffectStruct.xml | 7 + .../mp1/Structs/MP1-ScriptBeamStruct.xml | 21 + .../mp1/Structs/MP1-SpindleCameraStruct.xml | 13 + 174 files changed, 4570 insertions(+), 2050 deletions(-) create mode 100644 src/Common/NBasics.h create mode 100644 src/Core/Resource/Script/IPropertyNew.cpp create mode 100644 src/Core/Resource/Script/IPropertyNew.h create mode 100644 src/Core/Resource/Script/Property/CAnimationProperty.h create mode 100644 src/Core/Resource/Script/Property/CAnimationSetProperty.h create mode 100644 src/Core/Resource/Script/Property/CArrayProperty.h create mode 100644 src/Core/Resource/Script/Property/CAssetProperty.h create mode 100644 src/Core/Resource/Script/Property/CBoolProperty.h create mode 100644 src/Core/Resource/Script/Property/CByteProperty.h create mode 100644 src/Core/Resource/Script/Property/CColorProperty.h create mode 100644 src/Core/Resource/Script/Property/CEnumProperty.h create mode 100644 src/Core/Resource/Script/Property/CFlagsProperty.h create mode 100644 src/Core/Resource/Script/Property/CFloatProperty.h create mode 100644 src/Core/Resource/Script/Property/CGuidProperty.h create mode 100644 src/Core/Resource/Script/Property/CIntProperty.h create mode 100644 src/Core/Resource/Script/Property/CPointerProperty.h create mode 100644 src/Core/Resource/Script/Property/CSequenceProperty.h create mode 100644 src/Core/Resource/Script/Property/CShortProperty.h create mode 100644 src/Core/Resource/Script/Property/CSoundProperty.h create mode 100644 src/Core/Resource/Script/Property/CSplineProperty.h create mode 100644 src/Core/Resource/Script/Property/CStringProperty.h create mode 100644 src/Core/Resource/Script/Property/CStructProperty.h create mode 100644 src/Core/Resource/Script/Property/CVectorProperty.h create mode 100644 src/Core/Resource/Script/Property/Properties.h create mode 100644 src/Core/Resource/Script/Property/TPropertyRef.h create mode 100644 src/Core/Resource/Script/TPropertyProxy.h create mode 100644 templates/mp1/Structs/BeamCombos.xml create mode 100644 templates/mp1/Structs/BoolFloat 1.xml create mode 100644 templates/mp1/Structs/BoolFloat 2.xml create mode 100644 templates/mp1/Structs/BoolFloat 3.xml create mode 100644 templates/mp1/Structs/BoolFloat 4.xml create mode 100644 templates/mp1/Structs/BoolFloat 5.xml create mode 100644 templates/mp1/Structs/BoolFloat 6.xml create mode 100644 templates/mp1/Structs/BoolFloat 7.xml create mode 100644 templates/mp1/Structs/BoolFloat 8.xml create mode 100644 templates/mp1/Structs/BoolVec3f 1.xml create mode 100644 templates/mp1/Structs/BoolVec3f 2.xml create mode 100644 templates/mp1/Structs/ChargedBeams.xml create mode 100644 templates/mp1/Structs/FluidUVMotion.xml create mode 100644 templates/mp1/Structs/LayerSwitch.xml create mode 100644 templates/mp1/Structs/LongBool.xml create mode 100644 templates/mp1/Structs/MP1-CameraHintStruct.xml create mode 100644 templates/mp1/Structs/MP1-GuessStruct 1.xml create mode 100644 templates/mp1/Structs/MP1-GuessStruct 2.xml create mode 100644 templates/mp1/Structs/MP1-GuessStruct.xml create mode 100644 templates/mp1/Structs/MP1-MagdoliteStruct.xml create mode 100644 templates/mp1/Structs/MP1-MassivePrimeStruct.xml create mode 100644 templates/mp1/Structs/MP1-NewCameraShakerStruct 1.xml create mode 100644 templates/mp1/Structs/MP1-NewCameraShakerStruct 2.xml create mode 100644 templates/mp1/Structs/MP1-NewCameraShakerStruct 3.xml create mode 100644 templates/mp1/Structs/MP1-PathCameraStruct.xml create mode 100644 templates/mp1/Structs/MP1-PlayerActorStruct.xml create mode 100644 templates/mp1/Structs/MP1-PlayerHintStruct.xml create mode 100644 templates/mp1/Structs/MP1-PrimeStruct1.xml create mode 100644 templates/mp1/Structs/MP1-PrimeStruct2.xml create mode 100644 templates/mp1/Structs/MP1-PrimeStruct3.xml create mode 100644 templates/mp1/Structs/MP1-PrimeStruct4.xml create mode 100644 templates/mp1/Structs/MP1-PrimeStruct5.xml create mode 100644 templates/mp1/Structs/MP1-PrimeStruct6.xml create mode 100644 templates/mp1/Structs/MP1-RidleyStruct1.xml create mode 100644 templates/mp1/Structs/MP1-RidleyStruct2.xml create mode 100644 templates/mp1/Structs/MP1-RumbleEffectStruct.xml create mode 100644 templates/mp1/Structs/MP1-ScriptBeamStruct.xml create mode 100644 templates/mp1/Structs/MP1-SpindleCameraStruct.xml diff --git a/src/.qmake.conf b/src/.qmake.conf index 39d68c4e..c4b541ca 100644 --- a/src/.qmake.conf +++ b/src/.qmake.conf @@ -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 diff --git a/src/Common/Common.h b/src/Common/Common.h index 28a96445..1ee11de9 100644 --- a/src/Common/Common.h +++ b/src/Common/Common.h @@ -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 diff --git a/src/Common/Common.pro b/src/Common/Common.pro index d8491d3e..a5a519e3 100644 --- a/src/Common/Common.pro +++ b/src/Common/Common.pro @@ -84,7 +84,8 @@ HEADERS += \ FileIO\CFileLock.h \ FileIO.h \ Common.h \ - Hash/CCRC32.h + Hash/CCRC32.h \ + NBasics.h # Source Files SOURCES += \ diff --git a/src/Common/FileIO/CVectorOutStream.cpp b/src/Common/FileIO/CVectorOutStream.cpp index e20cfc1f..fb95e0ca 100644 --- a/src/Common/FileIO/CVectorOutStream.cpp +++ b/src/Common/FileIO/CVectorOutStream.cpp @@ -1,10 +1,10 @@ #include "CVectorOutStream.h" +#include "Common/Common.h" CVectorOutStream::CVectorOutStream() : mpVector(new std::vector) , mOwnsVector(true) , mPos(0) - , mUsed(0) { mDataEndianness = IOUtil::eBigEndian; } @@ -13,7 +13,6 @@ CVectorOutStream::CVectorOutStream(IOUtil::EEndianness DataEndianness) : mpVector(new std::vector) , mOwnsVector(true) , mPos(0) - , mUsed(0) { mDataEndianness = DataEndianness; } @@ -22,7 +21,6 @@ CVectorOutStream::CVectorOutStream(u32 InitialSize, IOUtil::EEndianness DataEndi : mpVector(new std::vector(InitialSize)) , mOwnsVector(true) , mPos(0) - , mUsed(0) { mDataEndianness = DataEndianness; } @@ -31,7 +29,6 @@ CVectorOutStream::CVectorOutStream(std::vector *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 *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(); } diff --git a/src/Common/FileIO/CVectorOutStream.h b/src/Common/FileIO/CVectorOutStream.h index 26d505f7..846b0c1f 100644 --- a/src/Common/FileIO/CVectorOutStream.h +++ b/src/Common/FileIO/CVectorOutStream.h @@ -6,10 +6,11 @@ class CVectorOutStream : public IOutputStream { + static const u32 skAllocSize = 1024; // must be power of 2 + std::vector *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 *pVector); void *Data(); void *DataAtPosition(); - void Expand(u32 Amount); - void Shrink(); - void Reset(); void Clear(); }; diff --git a/src/Common/Flags.h b/src/Common/Flags.h index 90b96b5a..698bcd22 100644 --- a/src/Common/Flags.h +++ b/src/Common/Flags.h @@ -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 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 diff --git a/src/Common/NBasics.h b/src/Common/NBasics.h new file mode 100644 index 00000000..1f7c8192 --- /dev/null +++ b/src/Common/NBasics.h @@ -0,0 +1,45 @@ +#ifndef NBASICS_H +#define NBASICS_H + +#include "types.h" +#include + +namespace NBasics +{ + +/** Remove an element from a vector */ +template +bool VectorRemoveOne(std::vector& 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 +int VectorRemoveAll(std::vector& 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 diff --git a/src/Common/Serialization/CBasicBinaryReader.h b/src/Common/Serialization/CBasicBinaryReader.h index 6ebe724b..99b7011d 100644 --- a/src/Common/Serialization/CBasicBinaryReader.h +++ b/src/Common/Serialization/CBasicBinaryReader.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 diff --git a/src/Common/Serialization/CBasicBinaryWriter.h b/src/Common/Serialization/CBasicBinaryWriter.h index ebc86af3..5a97ee1a 100644 --- a/src/Common/Serialization/CBasicBinaryWriter.h +++ b/src/Common/Serialization/CBasicBinaryWriter.h @@ -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 diff --git a/src/Common/Serialization/CBinaryReader.h b/src/Common/Serialization/CBinaryReader.h index f224d1d8..d63c7dd3 100644 --- a/src/Common/Serialization/CBinaryReader.h +++ b/src/Common/Serialization/CBinaryReader.h @@ -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 diff --git a/src/Common/Serialization/CBinaryWriter.h b/src/Common/Serialization/CBinaryWriter.h index 675b6b63..b4cf4633 100644 --- a/src/Common/Serialization/CBinaryWriter.h +++ b/src/Common/Serialization/CBinaryWriter.h @@ -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 diff --git a/src/Common/Serialization/CXMLReader.h b/src/Common/Serialization/CXMLReader.h index 01921505..df287db7 100644 --- a/src/Common/Serialization/CXMLReader.h +++ b/src/Common/Serialization/CXMLReader.h @@ -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 diff --git a/src/Common/Serialization/CXMLWriter.h b/src/Common/Serialization/CXMLWriter.h index 21698ad7..a0fae7b1 100644 --- a/src/Common/Serialization/CXMLWriter.h +++ b/src/Common/Serialization/CXMLWriter.h @@ -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 diff --git a/src/Common/Serialization/IArchive.h b/src/Common/Serialization/IArchive.h index b7a871d3..2f78d93c 100644 --- a/src/Common/Serialization/IArchive.h +++ b/src/Common/Serialization/IArchive.h @@ -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& 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; } diff --git a/src/Common/TString.cpp b/src/Common/TString.cpp index 7c0ab6a5..490954f7 100644 --- a/src/Common/TString.cpp +++ b/src/Common/TString.cpp @@ -1,4 +1,5 @@ #include "TString.h" +#include "Hash/CCRC32.h" #include "Hash/CFNV1A.h" #include #include @@ -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(); diff --git a/src/Common/TString.h b/src/Common/TString.h index cb8b5bbb..d3802806 100644 --- a/src/Common/TString.h +++ b/src/Common/TString.h @@ -932,46 +932,7 @@ public: static _TString FromFloat(float Value, int MinDecimals = 1) { - // Initial float -> string conversion - std::basic_stringstream 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) diff --git a/src/Core/CAreaAttributes.cpp b/src/Core/CAreaAttributes.cpp index 21069c3e..89aa57b3 100644 --- a/src/Core/CAreaAttributes.cpp +++ b/src/Core/CAreaAttributes.cpp @@ -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(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( static_cast(pBaseStruct->PropertyByIndex(7))->Get() ); - case eEchoesDemo: - case eEchoes: - case eCorruptionProto: - case eCorruption: - case eReturns: - return gpResourceStore->LoadResource( static_cast(pBaseStruct->PropertyByID(0xD208C9FA))->Get() ); - default: - return nullptr; - } + return mOverrideSky.IsValid() ? gpResourceStore->LoadResource(mOverrideSky.Get()) : nullptr; } diff --git a/src/Core/CAreaAttributes.h b/src/Core/CAreaAttributes.h index 02890f20..86cec024 100644 --- a/src/Core/CAreaAttributes.h +++ b/src/Core/CAreaAttributes.h @@ -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 diff --git a/src/Core/CLightParameters.h b/src/Core/CLightParameters.h index a79153f8..ee4295cd 100644 --- a/src/Core/CLightParameters.h +++ b/src/Core/CLightParameters.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 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(mpStruct->PropertyByIndex(0x7)); - mpLightLayer = TPropCast(mpStruct->PropertyByIndex(0xD)); + mWorldLightingOptions = TEnumRef(InStruct.Object(), InStruct.Property()->ChildByIndex(0x7)); + mLightLayer = CIntRef(InStruct.Object(), InStruct.Property()->ChildByIndex(0xD)); } else { - mpWorldLightingOptions = TPropCast(mpStruct->PropertyByID(0x6B5E7509)); - mpLightLayer = TPropCast(mpStruct->PropertyByID(0x1F715FD3)); + mWorldLightingOptions = TEnumRef(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; } }; diff --git a/src/Core/Core.pro b/src/Core/Core.pro index 507db020..88fd99ff 100644 --- a/src/Core/Core.pro +++ b/src/Core/Core.pro @@ -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 diff --git a/src/Core/GameProject/AssetNameGeneration.cpp b/src/Core/GameProject/AssetNameGeneration.cpp index 025a6e5f..7a044200 100644 --- a/src/Core/GameProject/AssetNameGeneration.cpp +++ b/src/Core/GameProject/AssetNameGeneration.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(pInst->PropertyByIDString(ScanIDString)); + CAssetProperty *pScanProperty = TPropCast(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(pInst->Properties()->PropertyByID(StringPropID)); + CAssetProperty *pStringProperty = TPropCast(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(pInst->Properties()->PropertyByID(ModelPropID)); + CAssetProperty *pModelProperty = TPropCast(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()) diff --git a/src/Core/GameProject/CDependencyTree.cpp b/src/Core/GameProject/CDependencyTree.cpp index 44644800..69aed359 100644 --- a/src/Core/GameProject/CDependencyTree.cpp +++ b/src/Core/GameProject/CDependencyTree.cpp @@ -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(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(pProp)); - else if (Type == eSoundProperty) + else if (Type == EPropertyTypeNew::Sound) { - u32 SoundID = static_cast(pProp)->Get(); + u32 SoundID = TPropCast(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(pProp)->Get(); + CAssetID ID = TPropCast(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(pProp); - CAnimationParameters Params = pChar->Get(); + CAnimationParameters Params = TPropCast(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); diff --git a/src/Core/GameProject/CDependencyTree.h b/src/Core/GameProject/CDependencyTree.h index 2e3b8911..ade2088c 100644 --- a/src/Core/GameProject/CDependencyTree.h +++ b/src/Core/GameProject/CDependencyTree.h @@ -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. diff --git a/src/Core/Resource/Animation/CAnimationParameters.cpp b/src/Core/Resource/Animation/CAnimationParameters.cpp index 31ee155c..7a61ffab 100644 --- a/src/Core/Resource/Animation/CAnimationParameters.cpp +++ b/src/Core/Resource/Animation/CAnimationParameters.cpp @@ -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(); diff --git a/src/Core/Resource/Animation/CAnimationParameters.h b/src/Core/Resource/Animation/CAnimationParameters.h index 102c95fc..71e1086d 100644 --- a/src/Core/Resource/Animation/CAnimationParameters.h +++ b/src/Core/Resource/Animation/CAnimationParameters.h @@ -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); diff --git a/src/Core/Resource/CResTypeFilter.h b/src/Core/Resource/CResTypeFilter.h index 068313b4..52ae96b2 100644 --- a/src/Core/Resource/CResTypeFilter.h +++ b/src/Core/Resource/CResTypeFilter.h @@ -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(); diff --git a/src/Core/Resource/CResTypeInfo.cpp b/src/Core/Resource/CResTypeInfo.cpp index eec6dcbe..60c4c0be 100644 --- a/src/Core/Resource/CResTypeInfo.cpp +++ b/src/Core/Resource/CResTypeInfo.cpp @@ -4,9 +4,10 @@ std::unordered_map 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; } diff --git a/src/Core/Resource/CResTypeInfo.h b/src/Core/Resource/CResTypeInfo.h index b528f64f..c5b6191e 100644 --- a/src/Core/Resource/CResTypeInfo.h +++ b/src/Core/Resource/CResTypeInfo.h @@ -20,13 +20,14 @@ class CResTypeInfo EResType mType; TString mTypeName; std::vector 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 smTypeMap; // Private Methods - CResTypeInfo(EResType Type, const TString& rkTypeName); + CResTypeInfo(EResType Type, const TString& rkTypeName, const TString& rkRetroExtension); ~CResTypeInfo(); // Public Methods diff --git a/src/Core/Resource/Cooker/CScriptCooker.cpp b/src/Core/Resource/Cooker/CScriptCooker.cpp index 8b6d66cb..88d53740 100644 --- a/src/Core/Resource/Cooker/CScriptCooker.cpp +++ b/src/Core/Resource/Cooker/CScriptCooker.cpp @@ -1,118 +1,146 @@ #include "CScriptCooker.h" #include "Core/Resource/Script/CLink.h" +#include +#include +#include +#include -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(pProp); - rOut.WriteBool(pBoolCast->Get()); + CBoolProperty* pBool = TPropCast(pProperty); + rOut.WriteBool( pBool->Value(pData) ); break; } - case eByteProperty: + case EPropertyTypeNew::Byte: { - TByteProperty *pByteCast = static_cast(pProp); - rOut.WriteByte(pByteCast->Get()); + CByteProperty* pByte = TPropCast(pProperty); + rOut.WriteByte( pByte->Value(pData) ); break; } - case eShortProperty: + case EPropertyTypeNew::Short: { - TShortProperty *pShortCast = static_cast(pProp); - rOut.WriteShort(pShortCast->Get()); + CShortProperty* pShort = TPropCast(pProperty); + rOut.WriteShort( pShort->Value(pData) ); break; } - case eLongProperty: + case EPropertyTypeNew::Int: { - TLongProperty *pLongCast = static_cast(pProp); - rOut.WriteLong(pLongCast->Get()); + CIntProperty* pInt = TPropCast(pProperty); + rOut.WriteLong( pInt->Value(pData) ); break; } - case eEnumProperty: + case EPropertyTypeNew::Float: { - TEnumProperty *pEnumCast = static_cast(pProp); - rOut.WriteLong(pEnumCast->Get()); + CFloatProperty* pFloat = TPropCast(pProperty); + rOut.WriteFloat( pFloat->Value(pData) ); break; } - case eBitfieldProperty: + case EPropertyTypeNew::Choice: { - TBitfieldProperty *pBitfieldCast = static_cast(pProp); - rOut.WriteLong(pBitfieldCast->Get()); + CChoiceProperty* pChoice = TPropCast(pProperty); + rOut.WriteLong( pChoice->Value(pData) ); break; } - case eFloatProperty: + case EPropertyTypeNew::Enum: { - TFloatProperty *pFloatCast = static_cast(pProp); - rOut.WriteFloat(pFloatCast->Get()); + CEnumProperty* pEnum = TPropCast(pProperty); + rOut.WriteLong( pEnum->Value(pData) ); break; } - case eStringProperty: + case EPropertyTypeNew::Flags: { - TStringProperty *pStringCast = static_cast(pProp); - rOut.WriteString(pStringCast->Get()); + CFlagsProperty* pFlags = TPropCast(pProperty); + rOut.WriteLong( pFlags->Value(pData) ); break; } - case eVector3Property: + case EPropertyTypeNew::String: { - TVector3Property *pVectorCast = static_cast(pProp); - pVectorCast->Get().Write(rOut); + CStringProperty* pString = TPropCast(pProperty); + rOut.WriteString( pString->Value(pData) ); break; } - case eColorProperty: + case EPropertyTypeNew::Vector: { - TColorProperty *pColorCast = static_cast(pProp); - pColorCast->Get().Write(rOut, false); + CVectorProperty* pVector = TPropCast(pProperty); + pVector->ValueRef(pData).Write(rOut); break; } - case eSoundProperty: + case EPropertyTypeNew::Color: { - TSoundProperty *pSoundCast = static_cast(pProp); - rOut.WriteLong(pSoundCast->Get()); + CColorProperty* pColor = TPropCast(pProperty); + pColor->ValueRef(pData).Write(rOut); break; } - case eAssetProperty: + case EPropertyTypeNew::Asset: { - TAssetProperty *pAssetCast = static_cast(pProp); - pAssetCast->Get().Write(rOut); + CAssetProperty* pAsset = TPropCast(pProperty); + pAsset->ValueRef(pData).Write(rOut); break; } - case eCharacterProperty: + case EPropertyTypeNew::Sound: { - TCharacterProperty *pCharCast = static_cast(pProp); - pCharCast->Get().Write(rOut); + CSoundProperty* pSound = TPropCast(pProperty); + rOut.WriteLong( pSound->Value(pData) ); break; } - case eMayaSplineProperty: + case EPropertyTypeNew::Animation: { - TMayaSplineProperty *pSplineCast = static_cast(pProp); - std::vector Buffer = pSplineCast->Get(); - if (!Buffer.empty()) rOut.WriteBytes(Buffer.data(), Buffer.size()); + CAnimationProperty* pAnim = TPropCast(pProperty); + rOut.WriteLong( pAnim->Value(pData) ); + break; + } + case EPropertyTypeNew::AnimationSet: + { + CAnimationSetProperty* pAnimSet = TPropCast(pProperty); + pAnimSet->ValueRef(pData).Write(rOut); + break; + } + + case EPropertyTypeNew::Sequence: + { + // TODO + break; + } + + case EPropertyTypeNew::Spline: + { + CSplineProperty* pSpline = TPropCast(pProperty); + std::vector& 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(pProp); - CStructTemplate *pTemp = static_cast(pStruct->Template()); + CGuidProperty* pGuid = TPropCast(pProperty); + std::vector& rBuffer = pGuid->ValueRef(pData); - std::vector 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(pProperty); + std::vector 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(pProp); - rOut.WriteLong(pArray->Count()); + CArrayProperty* pArray = TPropCast(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]); } diff --git a/src/Core/Resource/Cooker/CScriptCooker.h b/src/Core/Resource/Cooker/CScriptCooker.h index c28a1bf2..a43c11f6 100644 --- a/src/Core/Resource/Cooker/CScriptCooker.h +++ b/src/Core/Resource/Cooker/CScriptCooker.h @@ -10,14 +10,18 @@ class CScriptCooker { EGame mGame; + CScriptObject* mpObject; + void* mpArrayItemData; std::vector 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) {} diff --git a/src/Core/Resource/Cooker/CTemplateWriter.cpp b/src/Core/Resource/Cooker/CTemplateWriter.cpp index 90ba206e..83f35888 100644 --- a/src/Core/Resource/Cooker/CTemplateWriter.cpp +++ b/src/Core/Resource/Cooker/CTemplateWriter.cpp @@ -1,9 +1,11 @@ #include "CTemplateWriter.h" #include "CAreaCooker.h" #include +#include #include +#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(pProp); + CStructTemplate *pChildStruct = static_cast(pProp); CStructTemplate *pSourceStruct = static_cast(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 diff --git a/src/Core/Resource/Cooker/CTemplateWriter.h b/src/Core/Resource/Cooker/CTemplateWriter.h index 156e343a..4af5da30 100644 --- a/src/Core/Resource/Cooker/CTemplateWriter.h +++ b/src/Core/Resource/Cooker/CTemplateWriter.h @@ -5,6 +5,7 @@ #include "Core/Resource/Script/CScriptTemplate.h" #include +#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 diff --git a/src/Core/Resource/EResType.h b/src/Core/Resource/EResType.h index 0ee52ed1..d8f54bbd 100644 --- a/src/Core/Resource/EResType.h +++ b/src/Core/Resource/EResType.h @@ -74,5 +74,8 @@ enum EResType eInvalidResType = -1 }; +// Defined in CResTypeInfo.cpp +void Serialize(IArchive& rArc, EResType& rType); + #endif // ERESTYPE diff --git a/src/Core/Resource/Factory/CScriptLoader.cpp b/src/Core/Resource/Factory/CScriptLoader.cpp index b71e87ef..8e9bfa38 100644 --- a/src/Core/Resource/Factory/CScriptLoader.cpp +++ b/src/Core/Resource/Factory/CScriptLoader.cpp @@ -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 #include #include +// 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(pProp); - pBoolCast->Set( (rSCLY.ReadByte() != 0) ); + CBoolProperty* pBool = TPropCast(pProp); + pBool->ValueRef(pData) = rSCLY.ReadBool(); break; } - case eByteProperty: + case EPropertyTypeNew::Byte: { - TByteProperty *pByteCast = static_cast(pProp); - pByteCast->Set(rSCLY.ReadByte()); + CByteProperty* pByte = TPropCast(pProp); + pByte->ValueRef(pData) = rSCLY.ReadByte(); break; } - case eShortProperty: + case EPropertyTypeNew::Short: { - TShortProperty *pShortCast = static_cast(pProp); - pShortCast->Set(rSCLY.ReadShort()); + CShortProperty* pShort = TPropCast(pProp); + pShort->ValueRef(pData) = rSCLY.ReadShort(); break; } - case eLongProperty: + case EPropertyTypeNew::Int: { - TLongProperty *pLongCast = static_cast(pProp); - pLongCast->Set(rSCLY.ReadLong()); + CIntProperty* pInt = TPropCast(pProp); + pInt->ValueRef(pData) = rSCLY.ReadLong(); break; } - case eBitfieldProperty: + case EPropertyTypeNew::Float: { - TBitfieldProperty *pBitfieldCast = static_cast(pProp); - pBitfieldCast->Set(rSCLY.ReadLong()); - - // Validate - u32 Mask = 0; - CBitfieldTemplate *pBitfieldTemp = static_cast(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(pProp); + pFloat->ValueRef(pData) = rSCLY.ReadFloat(); break; } - case eEnumProperty: + case EPropertyTypeNew::Choice: { - TEnumProperty *pEnumCast = static_cast(pProp); - CEnumTemplate *pEnumTemp = static_cast(pTemp); - u32 ID = rSCLY.ReadLong(); + CChoiceProperty* pChoice = TPropCast(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(pProp); - pFloatCast->Set(rSCLY.ReadFloat()); + CEnumProperty* pEnum = TPropCast(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(pProp); - pStringCast->Set(rSCLY.ReadString()); + CFlagsProperty* pFlags = TPropCast(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(pProp); - pVector3Cast->Set(CVector3f(rSCLY)); + CStringProperty* pString = TPropCast(pProp); + pString->ValueRef(pData) = rSCLY.ReadString(); break; } - case eColorProperty: + case EPropertyTypeNew::Vector: { - TColorProperty *pColorCast = static_cast(pProp); - pColorCast->Set(CColor(rSCLY)); + CVectorProperty* pVector = TPropCast(pProp); + pVector->ValueRef(pData) = CVector3f(rSCLY); break; } - case eSoundProperty: + case EPropertyTypeNew::Color: { - TSoundProperty *pSoundCast = static_cast(pProp); - pSoundCast->Set(rSCLY.ReadLong()); + CColorProperty* pColor = TPropCast(pProp); + pColor->ValueRef(pData) = CColor(rSCLY); break; } - case eAssetProperty: + case EPropertyTypeNew::Asset: { - TAssetProperty *pAssetCast = static_cast(pProp); + CAssetProperty* pAsset = TPropCast(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(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(pProp); + CSoundProperty* pSound = TPropCast(pProp); + pSound->ValueRef(pData) = rSCLY.ReadLong(); + break; + } + + case EPropertyTypeNew::Animation: + { + CAnimationProperty* pAnim = TPropCast(pProp); + pAnim->ValueRef(pData) = rSCLY.ReadLong(); + break; + } + + case EPropertyTypeNew::AnimationSet: + { + CAnimationSetProperty* pAnimSet = TPropCast(pProp); + pAnimSet->ValueRef(pData) = CAnimationParameters(rSCLY, mpMaster->Game()); + break; + } + + case EPropertyTypeNew::Sequence: + { + // TODO + break; + } + + case EPropertyTypeNew::Spline: + { + CSplineProperty* pSpline = TPropCast(pProp); + std::vector& Buffer = pSpline->ValueRef(pData); + Buffer.resize(Size); + rSCLY.ReadBytes(Buffer.data(), Buffer.size()); + break; + } + + case EPropertyTypeNew::Guid: + { + ASSERT(Size == 16); + CGuidProperty* pGuid = TPropCast(pProp); + pGuid->ValueRef(pData).resize(16); + rSCLY.ReadBytes(pGuid->ValueRef(pData).data(), 16); + break; + } + + case EPropertyTypeNew::Struct: + { + CStructPropertyNew* pStruct = TPropCast(pProp); if (mVersion < eEchoesDemo) - LoadStructMP1(rSCLY, pStructCast, static_cast(pStructCast->Template())); + LoadStructMP1(rSCLY, pStruct); else - LoadStructMP2(rSCLY, pStructCast, static_cast(pTemp)); + LoadStructMP2(rSCLY, pStruct); break; } - case eArrayProperty: + case EPropertyTypeNew::Array: { - CArrayProperty *pArrayCast = static_cast(pProp); + CArrayProperty *pArray = TPropCast(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(pArrayCast->PropertyByIndex(iElem)), pArrayCast->SubStructTemplate()); - else - LoadStructMP2(rSCLY, static_cast(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(pProp); - pAnimCast->Set(CAnimationParameters(rSCLY, mpMaster->Game())); - break; - } - - case eMayaSplineProperty: - { - TMayaSplineProperty *pSplineCast = static_cast(pProp); - std::vector Buffer(Size); - rSCLY.ReadBytes(Buffer.data(), Buffer.size()); - pSplineCast->Set(Buffer); - break; - } - - case eUnknownProperty: - { - TUnknownProperty *pUnknownCast = static_cast(pProp); - std::vector 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(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; diff --git a/src/Core/Resource/Factory/CScriptLoader.h b/src/Core/Resource/Factory/CScriptLoader.h index c2c53d7a..6af0a33d 100644 --- a/src/Core/Resource/Factory/CScriptLoader.h +++ b/src/Core/Resource/Factory/CScriptLoader.h @@ -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); diff --git a/src/Core/Resource/Factory/CTemplateLoader.cpp b/src/Core/Resource/Factory/CTemplateLoader.cpp index b6d0ec23..22ce2f6d 100644 --- a/src/Core/Resource/Factory/CTemplateLoader.cpp +++ b/src/Core/Resource/Factory/CTemplateLoader.cpp @@ -1,6 +1,7 @@ #include "CTemplateLoader.h" #include "CAreaLoader.h" #include "Core/Resource/Script/IPropertyTemplate.h" +#include "Core/Resource/Script/Property/Properties.h" #include #include @@ -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(pProp)->MemberName = (s8) LParam.ToInt32(10);\ + break;\ + \ + case EPropertyTypeNew::Short:\ + TPropCast(pProp)->MemberName = (s16) LParam.ToInt32(10);\ + break;\ + \ + case EPropertyTypeNew::Int:\ + TPropCast(pProp)->MemberName = (s32) LParam.ToInt32(10);\ + break;\ + \ + case EPropertyTypeNew::Float:\ + TPropCast(pProp)->MemberName = LParam.ToFloat();\ + break;\ + \ + +#define SET_MEMBER_CASES_NON_NUMERICAL(MemberName, Param, LParam) \ + case EPropertyTypeNew::Bool:\ + TPropCast(pProp)->MemberName = (LParam == "true");\ + break;\ + \ + case EPropertyTypeNew::Choice:\ + TPropCast(pProp)->MemberName = LParam.ToInt32( LParam.StartsWith("0x") ? 16 : 10 );\ + break;\ + \ + case EPropertyTypeNew::Enum:\ + TPropCast(pProp)->MemberName = LParam.ToInt32( LParam.StartsWith("0x") ? 16 : 10 );\ + break;\ + \ + case EPropertyTypeNew::Flags:\ + TPropCast(pProp)->MemberName = LParam.ToInt32( LParam.StartsWith("0x") ? 16 : 10 );\ + break;\ + \ + case EPropertyTypeNew::String:\ + TPropCast(pProp)->MemberName = Param;\ + break;\ + \ + case EPropertyTypeNew::Vector:\ + {\ + TStringList Components = Param.Split(", ");\ + if (Components.size() != 3) {\ + TPropCast(pProp)->MemberName = CVector3f::skInfinite;\ + break;\ + }\ + float* pPtr = &TPropCast(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(pProp)->MemberName = CColor::skTransparentBlack;\ + break;\ + }\ + float* pPtr = &TPropCast(pProp)->MemberName.R;\ + TPropCast(pProp)->MemberName.A = 1.0f;\ + for (auto it = Components.begin(); it != Components.end(); it++) {\ + *pPtr = it->ToFloat();\ + pPtr++;\ + }\ + break;\ + }\ + case EPropertyTypeNew::Asset:\ + TPropCast(pProp)->MemberName = CAssetID::FromString(Param);\ + break;\ + \ + case EPropertyTypeNew::Sound:\ + TPropCast(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(pProp); + CAssetProperty* pAsset = TPropCast(pProp); pAsset->SetTypeFilter(ExtensionsList); } } // Enum-specific parameters - else if (Type == eEnumProperty) + else if (Type == EPropertyTypeNew::Enum || Type == EPropertyTypeNew::Choice) { - CEnumTemplate *pEnum = static_cast(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(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(pProp); - - // Load template - if (!TemplateAttr.IsEmpty()) - LoadBitfieldTemplate(TemplateAttr, pBitfield); + CFlagsProperty* pFlags = TPropCast(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(pProp); + CStructPropertyNew* pStruct = nullptr; - // Load template or struct type - if (!TemplateAttr.IsEmpty()) - LoadStructTemplate(TemplateAttr, pStruct); + if (Type == EPropertyTypeNew::Struct) + { + pStruct = TPropCast(pProp); + } + else + { + CArrayProperty* pArray = TPropCast(pProp); - if (IsNewProperty && TemplateAttr.IsEmpty() && Type == eStructProperty) - pStruct->mIsSingleProperty = (TypeAttr == "single"); + if (pArray->mpArchetype != nullptr) + { + ASSERT(pArray->mpArchetype->Type() == EPropertyTypeNew::Struct); + pStruct = TPropCast(pArray->mpArchetype); + } + else + { + pArray->mpArchetype = IPropertyNew::Create(EPropertyTypeNew::Struct, pArray, mpMaster, pScript, false); + pStruct = TPropCast(pArray->mpArchetype); + pStruct->mFlags = EPropertyFlag::IsAtomic | EPropertyFlag::IsArrayArchetype; + } + pStruct = TPropCast(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( + 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( + 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( + 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("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( *TPropCast(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(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(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; } diff --git a/src/Core/Resource/Factory/CTemplateLoader.h b/src/Core/Resource/Factory/CTemplateLoader.h index 848b1782..a4423540 100644 --- a/src/Core/Resource/Factory/CTemplateLoader.h +++ b/src/Core/Resource/Factory/CTemplateLoader.h @@ -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 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 diff --git a/src/Core/Resource/Script/CMasterTemplate.cpp b/src/Core/Resource/Script/CMasterTemplate.cpp index a62fc291..a569b37a 100644 --- a/src/Core/Resource/Script/CMasterTemplate.cpp +++ b/src/Core/Resource/Script/CMasterTemplate.cpp @@ -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& rOutList) } } -const std::vector* CMasterTemplate::TemplatesWithMatchingID(IPropertyTemplate *pTemp) +const std::vector* 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); diff --git a/src/Core/Resource/Script/CMasterTemplate.h b/src/Core/Resource/Script/CMasterTemplate.h index 70128251..288e1feb 100644 --- a/src/Core/Resource/Script/CMasterTemplate.h +++ b/src/Core/Resource/Script/CMasterTemplate.h @@ -3,6 +3,7 @@ #include "CLink.h" #include "CScriptTemplate.h" +#include "Core/Resource/Script/Property/Properties.h" #include #include #include @@ -19,7 +20,9 @@ class CMasterTemplate bool mFullyLoaded; std::vector mGameVersions; - std::map mStructTemplates; + std::map mStructTemplates; + std::map mEnumTemplates; + std::map mFlagsTemplates; std::map mTemplates; std::map mStates; @@ -28,7 +31,7 @@ class CMasterTemplate struct SPropIDInfo { std::vector XMLList; // List of script/struct templates that use this ID - std::vector PropertyList; // List of all properties that use this ID + std::vector PropertyList; // List of all properties that use this ID }; static std::map smIDMap; static std::map 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& rOutList); - static const std::vector* TemplatesWithMatchingID(IPropertyTemplate *pTemp); + static const std::vector* TemplatesWithMatchingID(IPropertyNew *pTemp); }; #endif // CMASTERTEMPLATE_H diff --git a/src/Core/Resource/Script/CScriptObject.cpp b/src/Core/Resource/Script/CScriptObject.cpp index d1c5f01a..e73c9c2e 100644 --- a/src/Core/Resource/Script/CScriptObject.cpp +++ b/src/Core/Resource/Script/CScriptObject.cpp @@ -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()) ); } diff --git a/src/Core/Resource/Script/CScriptObject.h b/src/Core/Resource/Script/CScriptObject.h index fe5b57be..58dec217 100644 --- a/src/Core/Resource/Script/CScriptObject.h +++ b/src/Core/Resource/Script/CScriptObject.h @@ -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 mOutLinks; std::vector mInLinks; - CPropertyStruct *mpProperties; + std::vector 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 mpDisplayAsset; TResPtr 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 diff --git a/src/Core/Resource/Script/CScriptTemplate.cpp b/src/Core/Resource/Script/CScriptTemplate.cpp index 99d8160f..a087b619 100644 --- a/src/Core/Resource/Script/CScriptTemplate.cpp +++ b/src/Core/Resource/Script/CScriptTemplate.cpp @@ -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( mpProperties->ChildByIDString(mNameIDString) ); + if (!mPositionIDString.IsEmpty()) mpPositionProperty = TPropCast( mpProperties->ChildByIDString(mPositionIDString) ); + if (!mRotationIDString.IsEmpty()) mpRotationProperty = TPropCast( mpProperties->ChildByIDString(mRotationIDString) ); + if (!mScaleIDString.IsEmpty()) mpScaleProperty = TPropCast( mpProperties->ChildByIDString(mScaleIDString) ); + if (!mActiveIDString.IsEmpty()) mpActiveProperty = TPropCast( mpProperties->ChildByIDString(mActiveIDString) ); + if (!mLightParametersIDString.IsEmpty()) mpLightParametersProperty = TPropCast( mpProperties->ChildByIDString(mLightParametersIDString) ); } EGame CScriptTemplate::Game() const @@ -29,14 +44,14 @@ EGame CScriptTemplate::Game() const } // ************ PROPERTY FETCHING ************ -template -PropType TFetchProperty(CPropertyStruct *pProperties, const TIDString& rkID) +template +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(pProp); + return static_cast(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(pProp)->Get() ? 1 : 0); + case EPropertyTypeNew::Bool: + Val = TPropCast(pProp)->Value(pData) ? 1 : 0; break; - case eByteProperty: - Val = (int) static_cast(pProp)->Get(); + case EPropertyTypeNew::Byte: + Val = (int) TPropCast(pProp)->Value(pData); break; - case eShortProperty: - Val = (int) static_cast(pProp)->Get(); + case EPropertyTypeNew::Short: + Val = (int) TPropCast(pProp)->Value(pData); break; - case eLongProperty: - Val = (int) static_cast(pProp)->Get(); + case EPropertyTypeNew::Int: + Val = TPropCast(pProp)->Value(pData); break; - case eEnumProperty: - Val = (int) static_cast(pProp)->Get(); + case EPropertyTypeNew::Enum: + case EPropertyTypeNew::Choice: + Val = TPropCast(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(pProperties, mNameIDString); -} - -TVector3Property* CScriptTemplate::FindPosition(CPropertyStruct *pProperties) -{ - return TFetchProperty(pProperties, mPositionIDString); -} - -TVector3Property* CScriptTemplate::FindRotation(CPropertyStruct *pProperties) -{ - return TFetchProperty(pProperties, mRotationIDString); -} - -TVector3Property* CScriptTemplate::FindScale(CPropertyStruct *pProperties) -{ - return TFetchProperty(pProperties, mScaleIDString); -} - -TBoolProperty* CScriptTemplate::FindActive(CPropertyStruct *pProperties) -{ - return TFetchProperty(pProperties, mActiveIDString); -} - -CPropertyStruct* CScriptTemplate::FindLightParameters(CPropertyStruct *pProperties) -{ - return TFetchProperty(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(pProp); - pRes = pChar->Get().AnimSet(); + CAnimationSetProperty* pAnimSet = TPropCast(pProp); + CAnimationParameters Params = pAnimSet->Value(pPropertyData); + pRes = Params.AnimSet(); if (pRes) { u32 MaxNumChars = static_cast(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(pProp); - CResourceEntry *pEntry = gpResourceStore->FindEntry(pAsset->Get()); + ASSERT(pProp->Type() == EPropertyTypeNew::Asset); + CAssetProperty* pAsset = TPropCast(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(pProp); - pRes = gpResourceStore->LoadResource( pAsset->Get(), eDynamicCollision ); + CAssetProperty* pAsset = TPropCast(pProp); + pRes = gpResourceStore->LoadResource( pAsset->Value(pPropertyData), eDynamicCollision ); } } diff --git a/src/Core/Resource/Script/CScriptTemplate.h b/src/Core/Resource/Script/CScriptTemplate.h index 72e28789..28076d18 100644 --- a/src/Core/Resource/Script/CScriptTemplate.h +++ b/src/Core/Resource/Script/CScriptTemplate.h @@ -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 #include +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 mpProperties; std::list mObjectList; - TString mTemplateName; std::vector 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 mAssets; std::vector 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& 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& ObjectList() const; diff --git a/src/Core/Resource/Script/EPropertyType.h b/src/Core/Resource/Script/EPropertyType.h index 391f9a9e..0f86d1f9 100644 --- a/src/Core/Resource/Script/EPropertyType.h +++ b/src/Core/Resource/Script/EPropertyType.h @@ -1,6 +1,9 @@ #ifndef EPROPERTYTYPE #define EPROPERTYTYPE +#include "IPropertyNew.h" + +#if 0 #include 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 diff --git a/src/Core/Resource/Script/IProperty.cpp b/src/Core/Resource/Script/IProperty.cpp index 0fca29de..ba015407 100644 --- a/src/Core/Resource/Script/IProperty.cpp +++ b/src/Core/Resource/Script/IProperty.cpp @@ -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(Template())->ElementName(); } +#endif diff --git a/src/Core/Resource/Script/IProperty.h b/src/Core/Resource/Script/IProperty.h index 1756d726..18dc3988 100644 --- a/src/Core/Resource/Script/IProperty.h +++ b/src/Core/Resource/Script/IProperty.h @@ -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(pProp) : nullptr); } - +#endif #endif // IPROPERTY diff --git a/src/Core/Resource/Script/IPropertyNew.cpp b/src/Core/Resource/Script/IPropertyNew.cpp new file mode 100644 index 00000000..887eb407 --- /dev/null +++ b/src/Core/Resource/Script/IPropertyNew.cpp @@ -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(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; +} diff --git a/src/Core/Resource/Script/IPropertyNew.h b/src/Core/Resource/Script/IPropertyNew.h new file mode 100644 index 00000000..916ca63e --- /dev/null +++ b/src/Core/Resource/Script/IPropertyNew.h @@ -0,0 +1,432 @@ +#ifndef IPROPERTYNEW_H +#define IPROPERTYNEW_H + +#include "Core/Resource/Animation/CAnimationParameters.h" +#include +#include +#include + +#include + +/** 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 mSubInstances; + + /** Child properties; these appear underneath this property on the UI */ + std::vector 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 +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(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 +class TNumericalPropertyNew : public TTypedPropertyNew +{ + 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(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 +inline PropertyClass* TPropCast(IPropertyNew* pProperty) +{ + if (pProperty && pProperty->Type() == PropertyClass::StaticType()) + { + return static_cast(pProperty); + } + else + { + return nullptr; + } +} + +#endif // IPROPERTYNEW_H diff --git a/src/Core/Resource/Script/IPropertyTemplate.cpp b/src/Core/Resource/Script/IPropertyTemplate.cpp index 6cb6f59c..c890afea 100644 --- a/src/Core/Resource/Script/IPropertyTemplate.cpp +++ b/src/Core/Resource/Script/IPropertyTemplate.cpp @@ -3,6 +3,7 @@ #include #include +#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 diff --git a/src/Core/Resource/Script/IPropertyTemplate.h b/src/Core/Resource/Script/IPropertyTemplate.h index 8553b787..08a58cbb 100644 --- a/src/Core/Resource/Script/IPropertyTemplate.h +++ b/src/Core/Resource/Script/IPropertyTemplate.h @@ -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 diff --git a/src/Core/Resource/Script/IPropertyValue.h b/src/Core/Resource/Script/IPropertyValue.h index b49ef4cb..d9c83ecb 100644 --- a/src/Core/Resource/Script/IPropertyValue.h +++ b/src/Core/Resource/Script/IPropertyValue.h @@ -1,6 +1,7 @@ #ifndef IPROPERTYVALUE_H #define IPROPERTYVALUE_H +#if 0 #include "EPropertyType.h" #include #include @@ -386,5 +387,6 @@ public: return new CUnknownValue(mValue); } }; +#endif #endif // IPROPERTYVALUE_H diff --git a/src/Core/Resource/Script/Property/CAnimationProperty.h b/src/Core/Resource/Script/Property/CAnimationProperty.h new file mode 100644 index 00000000..7d13c230 --- /dev/null +++ b/src/Core/Resource/Script/Property/CAnimationProperty.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 diff --git a/src/Core/Resource/Script/Property/CAnimationSetProperty.h b/src/Core/Resource/Script/Property/CAnimationSetProperty.h new file mode 100644 index 00000000..3778a12d --- /dev/null +++ b/src/Core/Resource/Script/Property/CAnimationSetProperty.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 diff --git a/src/Core/Resource/Script/Property/CArrayProperty.h b/src/Core/Resource/Script/Property/CArrayProperty.h new file mode 100644 index 00000000..b01fa79e --- /dev/null +++ b/src/Core/Resource/Script/Property/CArrayProperty.h @@ -0,0 +1,176 @@ +#ifndef CARRAYPROPERTY_H +#define CARRAYPROPERTY_H + +#include "../IPropertyNew.h" + +struct SScriptArray +{ + int Count; + std::vector 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 +{ + friend class CTemplateLoader; + /** This class inherits from TTypedPropertyNew 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& 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& 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 diff --git a/src/Core/Resource/Script/Property/CAssetProperty.h b/src/Core/Resource/Script/Property/CAssetProperty.h new file mode 100644 index 00000000..1d73da96 --- /dev/null +++ b/src/Core/Resource/Script/Property/CAssetProperty.h @@ -0,0 +1,42 @@ +#ifndef CASSETPROPERTY_H +#define CASSETPROPERTY_H + +#include "../IPropertyNew.h" +#include "Core/Resource/CResTypeFilter.h" + +class CAssetProperty : public TTypedPropertyNew +{ + 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 diff --git a/src/Core/Resource/Script/Property/CBoolProperty.h b/src/Core/Resource/Script/Property/CBoolProperty.h new file mode 100644 index 00000000..98dd2379 --- /dev/null +++ b/src/Core/Resource/Script/Property/CBoolProperty.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 diff --git a/src/Core/Resource/Script/Property/CByteProperty.h b/src/Core/Resource/Script/Property/CByteProperty.h new file mode 100644 index 00000000..2f6403cc --- /dev/null +++ b/src/Core/Resource/Script/Property/CByteProperty.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 diff --git a/src/Core/Resource/Script/Property/CColorProperty.h b/src/Core/Resource/Script/Property/CColorProperty.h new file mode 100644 index 00000000..702976aa --- /dev/null +++ b/src/Core/Resource/Script/Property/CColorProperty.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 diff --git a/src/Core/Resource/Script/Property/CEnumProperty.h b/src/Core/Resource/Script/Property/CEnumProperty.h new file mode 100644 index 00000000..7d05eb26 --- /dev/null +++ b/src/Core/Resource/Script/Property/CEnumProperty.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 +class TEnumPropertyBase : public TTypedPropertyNew +{ + 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 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 CChoiceProperty; +typedef TEnumPropertyBase 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(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(pProperty); + } + } + + return nullptr; +} + +#endif // CENUMPROPERTY_H diff --git a/src/Core/Resource/Script/Property/CFlagsProperty.h b/src/Core/Resource/Script/Property/CFlagsProperty.h new file mode 100644 index 00000000..9a242bd6 --- /dev/null +++ b/src/Core/Resource/Script/Property/CFlagsProperty.h @@ -0,0 +1,99 @@ +#ifndef CFLAGSPROPERTY_H +#define CFLAGSPROPERTY_H + +#include "../IPropertyNew.h" + +class CFlagsProperty : public TTypedPropertyNew +{ + 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 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 diff --git a/src/Core/Resource/Script/Property/CFloatProperty.h b/src/Core/Resource/Script/Property/CFloatProperty.h new file mode 100644 index 00000000..2dd98bb5 --- /dev/null +++ b/src/Core/Resource/Script/Property/CFloatProperty.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 diff --git a/src/Core/Resource/Script/Property/CGuidProperty.h b/src/Core/Resource/Script/Property/CGuidProperty.h new file mode 100644 index 00000000..6931ba71 --- /dev/null +++ b/src/Core/Resource/Script/Property/CGuidProperty.h @@ -0,0 +1,22 @@ +#ifndef CGUIDPROPERTY_H +#define CGUIDPROPERTY_H + +#include "../IPropertyNew.h" + +class CGuidProperty : public TTypedPropertyNew< std::vector, EPropertyTypeNew::Guid > +{ + friend class IPropertyNew; + +protected: + CGuidProperty() + : TTypedPropertyNew() + {} + +public: + virtual void SerializeValue(void* pData, IArchive& Arc) const + { + Arc.SerializeBulkData( ValueRef(pData) ); + } +}; + +#endif // CSPLINEPROPERTY_H diff --git a/src/Core/Resource/Script/Property/CIntProperty.h b/src/Core/Resource/Script/Property/CIntProperty.h new file mode 100644 index 00000000..a26c7fe3 --- /dev/null +++ b/src/Core/Resource/Script/Property/CIntProperty.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 diff --git a/src/Core/Resource/Script/Property/CPointerProperty.h b/src/Core/Resource/Script/Property/CPointerProperty.h new file mode 100644 index 00000000..9718ea55 --- /dev/null +++ b/src/Core/Resource/Script/Property/CPointerProperty.h @@ -0,0 +1,27 @@ +#ifndef CPOINTERPROPERTY_H +#define CPOINTERPROPERTY_H + +#include "../IPropertyNew.h" + +class CPointerProperty : public TTypedPropertyNew +{ + 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 diff --git a/src/Core/Resource/Script/Property/CSequenceProperty.h b/src/Core/Resource/Script/Property/CSequenceProperty.h new file mode 100644 index 00000000..1377d4fc --- /dev/null +++ b/src/Core/Resource/Script/Property/CSequenceProperty.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 diff --git a/src/Core/Resource/Script/Property/CShortProperty.h b/src/Core/Resource/Script/Property/CShortProperty.h new file mode 100644 index 00000000..759f866b --- /dev/null +++ b/src/Core/Resource/Script/Property/CShortProperty.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 diff --git a/src/Core/Resource/Script/Property/CSoundProperty.h b/src/Core/Resource/Script/Property/CSoundProperty.h new file mode 100644 index 00000000..9c7aac53 --- /dev/null +++ b/src/Core/Resource/Script/Property/CSoundProperty.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 diff --git a/src/Core/Resource/Script/Property/CSplineProperty.h b/src/Core/Resource/Script/Property/CSplineProperty.h new file mode 100644 index 00000000..1aeb8e5b --- /dev/null +++ b/src/Core/Resource/Script/Property/CSplineProperty.h @@ -0,0 +1,22 @@ +#ifndef CSPLINEPROPERTY_H +#define CSPLINEPROPERTY_H + +#include "../IPropertyNew.h" + +class CSplineProperty : public TTypedPropertyNew< std::vector, EPropertyTypeNew::Spline > +{ + friend class IPropertyNew; + +protected: + CSplineProperty() + : TTypedPropertyNew() + {} + +public: + virtual void SerializeValue(void* pData, IArchive& Arc) const + { + Arc.SerializeBulkData( ValueRef(pData) ); + } +}; + +#endif // CSPLINEPROPERTY_H diff --git a/src/Core/Resource/Script/Property/CStringProperty.h b/src/Core/Resource/Script/Property/CStringProperty.h new file mode 100644 index 00000000..d1a0f763 --- /dev/null +++ b/src/Core/Resource/Script/Property/CStringProperty.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 diff --git a/src/Core/Resource/Script/Property/CStructProperty.h b/src/Core/Resource/Script/Property/CStructProperty.h new file mode 100644 index 00000000..0a80eeb5 --- /dev/null +++ b/src/Core/Resource/Script/Property/CStructProperty.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 diff --git a/src/Core/Resource/Script/Property/CVectorProperty.h b/src/Core/Resource/Script/Property/CVectorProperty.h new file mode 100644 index 00000000..04640f29 --- /dev/null +++ b/src/Core/Resource/Script/Property/CVectorProperty.h @@ -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 diff --git a/src/Core/Resource/Script/Property/Properties.h b/src/Core/Resource/Script/Property/Properties.h new file mode 100644 index 00000000..c7d770b2 --- /dev/null +++ b/src/Core/Resource/Script/Property/Properties.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 diff --git a/src/Core/Resource/Script/Property/TPropertyRef.h b/src/Core/Resource/Script/Property/TPropertyRef.h new file mode 100644 index 00000000..8719f2f4 --- /dev/null +++ b/src/Core/Resource/Script/Property/TPropertyRef.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 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(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 CBoolRef; +typedef TPropertyRef CByteRef; +typedef TPropertyRef CShortRef; +typedef TPropertyRef CIntRef; +typedef TPropertyRef CFloatRef; +typedef TPropertyRef CFlagsRef; +typedef TPropertyRef CStringRef; +typedef TPropertyRef CVectorRef; +typedef TPropertyRef CColorRef; +typedef TPropertyRef CAssetRef; +typedef TPropertyRef CSoundRef; +typedef TPropertyRef CAnimationRef; +typedef TPropertyRef CAnimationSetRef; +typedef TPropertyRef CSequenceRef; +typedef TPropertyRef CSplineRef; +typedef TPropertyRef CGuidRef; +typedef TPropertyRef CPointerRef; +typedef TPropertyRef CStructRef; +typedef TPropertyRef CArrayRef; + +/** Special version for enums */ +template +class TEnumRef : public TPropertyRef +{ +public: + TEnumRef() + : TPropertyRef() + {} + + TEnumRef(CScriptObject* pInObject, IPropertyNew* pInProperty) + : TPropertyRef(pInObject, pInProperty) + {} + + TEnumRef(CScriptObject* pInObject, CEnumProperty* pInProperty) + : TPropertyRef(pInObject, pInProperty) + {} +}; + +#endif // TPROPERTYREF_H diff --git a/src/Core/Resource/Script/TPropertyProxy.h b/src/Core/Resource/Script/TPropertyProxy.h new file mode 100644 index 00000000..b7d83b7f --- /dev/null +++ b/src/Core/Resource/Script/TPropertyProxy.h @@ -0,0 +1,39 @@ +#ifndef TPROPERTYPROXY_H +#define TPROPERTYPROXY_H + +#include + +/** + * Lightweight proxy class representing a property instance. Easy to read/modify + * specific properties and efficient to pass around. + */ +template +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 diff --git a/src/Core/Scene/CScriptAttachNode.cpp b/src/Core/Scene/CScriptAttachNode.cpp index d9b2542c..0f91c47e 100644 --- a/src/Core/Scene/CScriptAttachNode.cpp +++ b/src/Core/Scene/CScriptAttachNode.cpp @@ -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( TPropCast(mpAttachAssetProp)->Get() ); - else if (mpAttachAssetProp->Type() == eCharacterProperty) - mpAttachAsset = TPropCast(mpAttachAssetProp)->Get().AnimSet(); + if (mAttachAssetRef.IsValid()) + mpAttachAsset = gpResourceStore->LoadResource(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(mpAttachAsset.RawPointer()); - if (mpAttachAsset->Type() == eAnimSet) - { - TCharacterProperty *pProp = TPropCast(mpAttachAssetProp); - return pProp->Get().GetCurrentModel(); - } + else if (mpAttachAsset->Type() == eAnimSet) + return mAttachAnimSetRef.Get().GetCurrentModel(); } return nullptr; diff --git a/src/Core/Scene/CScriptAttachNode.h b/src/Core/Scene/CScriptAttachNode.h index 5888de5a..0b053c20 100644 --- a/src/Core/Scene/CScriptAttachNode.h +++ b/src/Core/Scene/CScriptAttachNode.h @@ -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 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: diff --git a/src/Core/Scene/CScriptNode.cpp b/src/Core/Scene/CScriptNode.cpp index ed5b7bcc..60029ae8 100644 --- a/src/Core/Scene/CScriptNode.cpp +++ b/src/Core/Scene/CScriptNode.cpp @@ -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(pProp->Template()); - const CResTypeFilter& rkFilter = pAssetTemp->TypeFilter(); + CAssetProperty* pAssetProperty = TPropCast(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(); } diff --git a/src/Core/Scene/CScriptNode.h b/src/Core/Scene/CScriptNode.h index 627a22e3..9462b7bf 100644 --- a/src/Core/Scene/CScriptNode.h +++ b/src/Core/Scene/CScriptNode.h @@ -49,7 +49,7 @@ public: CColor WireframeColor() const; void LinksModified(); - void PropertyModified(IProperty *pProp); + void PropertyModified(IPropertyNew* pProp); void UpdatePreviewVolume(); void GeneratePosition(); void TestGameModeVisibility(); diff --git a/src/Core/ScriptExtra/CDamageableTriggerExtra.cpp b/src/Core/ScriptExtra/CDamageableTriggerExtra.cpp index 93c1922f..62c3bafa 100644 --- a/src/Core/ScriptExtra/CDamageableTriggerExtra.cpp +++ b/src/Core/ScriptExtra/CDamageableTriggerExtra.cpp @@ -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(pBaseStruct->PropertyByIndex(0x5)); - if (mpRenderSideProp) PropertyModified(mpRenderSideProp); + mRenderSide = TEnumRef(pInstance, pProperties->ChildByIndex(5)); + if (mRenderSide.IsValid()) PropertyModified(mRenderSide.Property()); // Fetch scale - mpSizeProp = TPropCast(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(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( mpTextureProps[iTex]->Get() ); + mpTextures[TextureIdx] = gpResourceStore->LoadResource( 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; } } diff --git a/src/Core/ScriptExtra/CDamageableTriggerExtra.h b/src/Core/ScriptExtra/CDamageableTriggerExtra.h index f1b7b8db..e86b44b1 100644 --- a/src/Core/ScriptExtra/CDamageableTriggerExtra.h +++ b/src/Core/ScriptExtra/CDamageableTriggerExtra.h @@ -17,15 +17,12 @@ class CDamageableTriggerExtra : public CScriptExtra eDown = 0x20 }; - TVector3Property *mpSizeProp; - TEnumProperty *mpRenderSideProp; - TAssetProperty *mpTextureProps[3]; + CVectorRef mPlaneSize; + TEnumRef mRenderSide; + CAssetRef mTextureAssets[3]; - CVector3f mPlaneSize; - ERenderSide mRenderSide; - TResPtr 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); diff --git a/src/Core/ScriptExtra/CDoorExtra.cpp b/src/Core/ScriptExtra/CDoorExtra.cpp index 351b10d9..26d8d4a8 100644 --- a/src/Core/ScriptExtra/CDoorExtra.cpp +++ b/src/Core/ScriptExtra/CDoorExtra.cpp @@ -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(pBaseStruct->PropertyByID(0xB20CC271)); - if (mpShieldModelProp) PropertyModified(mpShieldModelProp); + mShieldModelProp = CAssetRef(pInstance, pProperties->ChildByID(0xB20CC271)); + if (mShieldModelProp.IsValid()) PropertyModified(mShieldModelProp.Property()); if (mGame >= eEchoes) { - mpShieldColorProp = TPropCast(pBaseStruct->PropertyByID(0x47B4E863)); - if (mpShieldColorProp) PropertyModified(mpShieldColorProp); + mShieldColorProp = CColorRef(pInstance, pProperties->ChildByID(0x47B4E863)); + if (mShieldColorProp.IsValid()) PropertyModified(mShieldColorProp.Property()); } else { - mpDisabledProp = TPropCast(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( mpShieldModelProp->Get() ); + mpShieldModel = gpResourceStore->LoadResource( 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; } } diff --git a/src/Core/ScriptExtra/CDoorExtra.h b/src/Core/ScriptExtra/CDoorExtra.h index b1e22a27..5bfe223d 100644 --- a/src/Core/ScriptExtra/CDoorExtra.h +++ b/src/Core/ScriptExtra/CDoorExtra.h @@ -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 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); diff --git a/src/Core/ScriptExtra/CPointOfInterestExtra.cpp b/src/Core/ScriptExtra/CPointOfInterestExtra.cpp index eb3df472..87723b67 100644 --- a/src/Core/ScriptExtra/CPointOfInterestExtra.cpp +++ b/src/Core/ScriptExtra/CPointOfInterestExtra.cpp @@ -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(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( mpScanProperty->Get() ); + if (mScanProperty.Property() == pProperty) + mpScanData = gpResourceStore->LoadResource( mScanProperty.Get() ); } void CPointOfInterestExtra::ModifyTintColor(CColor& Color) diff --git a/src/Core/ScriptExtra/CPointOfInterestExtra.h b/src/Core/ScriptExtra/CPointOfInterestExtra.h index 195a2a27..eb6ac554 100644 --- a/src/Core/ScriptExtra/CPointOfInterestExtra.h +++ b/src/Core/ScriptExtra/CPointOfInterestExtra.h @@ -8,12 +8,12 @@ class CPointOfInterestExtra : public CScriptExtra { // Tint POI billboard orange/red depending on scan importance - TAssetProperty *mpScanProperty; + CAssetRef mScanProperty; TResPtr 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; } diff --git a/src/Core/ScriptExtra/CRadiusSphereExtra.cpp b/src/Core/ScriptExtra/CRadiusSphereExtra.cpp index 4eeb7527..47f21996 100644 --- a/src/Core/ScriptExtra/CRadiusSphereExtra.cpp +++ b/src/Core/ScriptExtra/CRadiusSphereExtra.cpp @@ -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(pInstance->Properties()->PropertyByID(0x3)); + mRadius = CFloatRef(pInstance, pProperties->ChildByID(3)); break; case 0x68: // RadialDamage (MP1) - mpRadius = TPropCast(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(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; } diff --git a/src/Core/ScriptExtra/CRadiusSphereExtra.h b/src/Core/ScriptExtra/CRadiusSphereExtra.h index 6f5c9180..008fc3fc 100644 --- a/src/Core/ScriptExtra/CRadiusSphereExtra.h +++ b/src/Core/ScriptExtra/CRadiusSphereExtra.h @@ -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; diff --git a/src/Core/ScriptExtra/CSandwormExtra.cpp b/src/Core/ScriptExtra/CSandwormExtra.cpp index a053f54b..cdb79818 100644 --- a/src/Core/ScriptExtra/CSandwormExtra.cpp +++ b/src/Core/ScriptExtra/CSandwormExtra.cpp @@ -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(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) ); } } } diff --git a/src/Core/ScriptExtra/CSandwormExtra.h b/src/Core/ScriptExtra/CSandwormExtra.h index 2b65f64f..d2643666 100644 --- a/src/Core/ScriptExtra/CSandwormExtra.h +++ b/src/Core/ScriptExtra/CSandwormExtra.h @@ -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 diff --git a/src/Core/ScriptExtra/CScriptExtra.h b/src/Core/ScriptExtra/CScriptExtra.h index ec5812e0..0bdd812b 100644 --- a/src/Core/ScriptExtra/CScriptExtra.h +++ b/src/Core/ScriptExtra/CScriptExtra.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; } diff --git a/src/Core/ScriptExtra/CSpacePirateExtra.cpp b/src/Core/ScriptExtra/CSpacePirateExtra.cpp index cb3e135a..1a498824 100644 --- a/src/Core/ScriptExtra/CSpacePirateExtra.cpp +++ b/src/Core/ScriptExtra/CSpacePirateExtra.cpp @@ -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(pBaseStruct->ChildByIDString("0x04:0x10")); - if (pVulns && pVulns->Type() == eStructProperty) + if (pVulnerabilities) { - mpPowerVuln = TPropCast(pVulns->PropertyByID(0x0)); - mpWaveVuln = TPropCast(pVulns->PropertyByID(0x2)); - mpIceVuln = TPropCast(pVulns->PropertyByID(0x1)); - mpPlasmaVuln = TPropCast(pVulns->PropertyByID(0x3)); + mPowerVulnerability = TEnumRef(pInstance, pVulnerabilities->ChildByID(0)); + mWaveVulnerability = TEnumRef(pInstance, pVulnerabilities->ChildByID(2)); + mIceVulnerability = TEnumRef(pInstance, pVulnerabilities->ChildByID(1)); + mPlasmaVulnerability = TEnumRef(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; diff --git a/src/Core/ScriptExtra/CSpacePirateExtra.h b/src/Core/ScriptExtra/CSpacePirateExtra.h index e7dd1d2e..2e9c31e5 100644 --- a/src/Core/ScriptExtra/CSpacePirateExtra.h +++ b/src/Core/ScriptExtra/CSpacePirateExtra.h @@ -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 mPowerVulnerability; + TEnumRef mWaveVulnerability; + TEnumRef mIceVulnerability; + TEnumRef mPlasmaVulnerability; public: explicit CSpacePirateExtra(CScriptObject *pInstance, CScene *pScene, CScriptNode *pParent = 0); diff --git a/src/Core/ScriptExtra/CSplinePathExtra.cpp b/src/Core/ScriptExtra/CSplinePathExtra.cpp index 93721729..76c3bd21 100644 --- a/src/Core/ScriptExtra/CSplinePathExtra.cpp +++ b/src/Core/ScriptExtra/CSplinePathExtra.cpp @@ -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(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& rChecked, CWaypointExtra *pWaypoint) +void CSplinePathExtra::FindAttachedWaypoints(std::set& rChecked, CWaypointExtra* pWaypoint) { if (rChecked.find(pWaypoint) != rChecked.end()) return; @@ -46,18 +46,18 @@ void CSplinePathExtra::AddWaypoints() std::set 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(pNode->Extra()); + CWaypointExtra* pWaypoint = static_cast(pNode->Extra()); FindAttachedWaypoints(CheckedWaypoints, pWaypoint); } } diff --git a/src/Core/ScriptExtra/CSplinePathExtra.h b/src/Core/ScriptExtra/CSplinePathExtra.h index b4915260..58194af9 100644 --- a/src/Core/ScriptExtra/CSplinePathExtra.h +++ b/src/Core/ScriptExtra/CSplinePathExtra.h @@ -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 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& rChecked, CWaypointExtra *pWaypoint); + void FindAttachedWaypoints(std::set& rChecked, CWaypointExtra* pWaypoint); void AddWaypoints(); - void RemoveWaypoint(CWaypointExtra *pWaypoint); + void RemoveWaypoint(CWaypointExtra* pWaypoint); void ClearWaypoints(); }; diff --git a/src/Editor/CGeneratePropertyNamesDialog.cpp b/src/Editor/CGeneratePropertyNamesDialog.cpp index 2a598c2f..b9ce8bfe 100644 --- a/src/Editor/CGeneratePropertyNamesDialog.cpp +++ b/src/Editor/CGeneratePropertyNamesDialog.cpp @@ -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 */ diff --git a/src/Editor/CPropertyNameValidator.cpp b/src/Editor/CPropertyNameValidator.cpp index 28831eff..269b60b9 100644 --- a/src/Editor/CPropertyNameValidator.cpp +++ b/src/Editor/CPropertyNameValidator.cpp @@ -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; diff --git a/src/Editor/CPropertyNameValidator.h b/src/Editor/CPropertyNameValidator.h index a835afc6..e6a72bb2 100644 --- a/src/Editor/CPropertyNameValidator.h +++ b/src/Editor/CPropertyNameValidator.h @@ -2,7 +2,7 @@ #define CPROPERTYNAMEVALIDATOR_H #include -#include +#include /** 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; diff --git a/src/Editor/PropertyEdit/CPropertyDelegate.cpp b/src/Editor/PropertyEdit/CPropertyDelegate.cpp index ff9a99c6..0d2f6a8e 100644 --- a/src/Editor/PropertyEdit/CPropertyDelegate.cpp +++ b/src/Editor/PropertyEdit/CPropertyDelegate.cpp @@ -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(pProp); - CEnumTemplate *pTemp = static_cast(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(pProp->Template()); - pSelector->SetTypeFilter(pTemp->TypeFilter()); + CAssetProperty *pAsset = TPropCast(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(pEditor); - TBoolProperty *pBool = static_cast(pProp); - pCheckBox->setChecked(pBool->Get()); + CBoolProperty *pBool = TPropCast(pProp); + pCheckBox->setChecked( pBool->Value(pData) ); break; } - case eShortProperty: + case EPropertyTypeNew::Short: { WIntegralSpinBox *pSpinBox = static_cast(pEditor); if (!pSpinBox->hasFocus()) { - TShortProperty *pShort = static_cast(pProp); - pSpinBox->setValue(pShort->Get()); + CShortProperty *pShort = TPropCast(pProp); + pSpinBox->setValue( pShort->Value(pData) ); } break; } - case eLongProperty: - case eSoundProperty: + case EPropertyTypeNew::Int: { WIntegralSpinBox *pSpinBox = static_cast(pEditor); if (!pSpinBox->hasFocus()) { - TLongProperty *pLong = static_cast(pProp); - pSpinBox->setValue(pLong->Get()); + CIntProperty *pInt = TPropCast(pProp); + pSpinBox->setValue( pInt->Value(pData) ); } break; } - case eFloatProperty: + case EPropertyTypeNew::Sound: + { + WIntegralSpinBox *pSpinBox = static_cast(pEditor); + + if (!pSpinBox->hasFocus()) + { + CSoundProperty *pSound = TPropCast(pProp); + pSpinBox->setValue( pSound->Value(pData) ); + } + + break; + } + + case EPropertyTypeNew::Float: { WDraggableSpinBox *pSpinBox = static_cast(pEditor); if (!pSpinBox->hasFocus()) { - TFloatProperty *pFloat = static_cast(pProp); - pSpinBox->setValue(pFloat->Get()); + CFloatProperty *pFloat = TPropCast(pProp); + pSpinBox->setValue( pFloat->Value(pData) ); } break; } - case eColorProperty: + case EPropertyTypeNew::Color: { WColorPicker *pColorPicker = static_cast(pEditor); - TColorProperty *pColor = static_cast(pProp); + CColorProperty *pColor = TPropCast(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(pEditor); if (!pLineEdit->hasFocus()) { - TStringProperty *pString = static_cast(pProp); - pLineEdit->setText(TO_QSTRING(pString->Get())); + CStringProperty *pString = TPropCast(pProp); + pLineEdit->setText( TO_QSTRING(pString->Value(pData)) ); } break; } - case eEnumProperty: + case EPropertyTypeNew::Enum: + case EPropertyTypeNew::Choice: { QComboBox *pComboBox = static_cast(pEditor); - TEnumProperty *pEnum = static_cast(pProp); - CEnumTemplate *pTemp = static_cast(pProp->Template()); - pComboBox->setCurrentIndex(pTemp->EnumeratorIndex(pEnum->Get())); + CEnumProperty* pEnum = TPropCast(pProp); + pComboBox->setCurrentIndex( pEnum->ValueIndex( pEnum->Value(pData) ) ); break; } - case eAssetProperty: + case EPropertyTypeNew::Asset: { CResourceSelector *pSelector = static_cast(pEditor); - TAssetProperty *pAsset = static_cast(pProp); - pSelector->SetResource(pAsset->Get()); + CAssetProperty *pAsset = TPropCast(pProp); + pSelector->SetResource(pAsset->Value(pData)); break; } - case eArrayProperty: + case EPropertyTypeNew::Array: { WIntegralSpinBox *pSpinBox = static_cast(pEditor); if (!pSpinBox->hasFocus()) { CArrayProperty *pArray = static_cast(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(pEditor); - TBitfieldProperty *pBitfield = static_cast(pProp); - u32 Mask = static_cast(pBitfield->Template())->FlagMask(rkIndex.row()); - bool Set = (pBitfield->Get() & Mask) != 0; + CFlagsProperty* pFlags = TPropCast(pProp); + u32 Mask = pFlags->FlagMask(rkIndex.row()); + bool Set = (pFlags->Value(pData) & Mask) != 0; pCheckBox->setChecked(Set); } - - else - { - WDraggableSpinBox *pSpinBox = static_cast(pEditor); - float Value; - - if (!pSpinBox->hasFocus()) - { - if (pProp->Type() == eVector3Property) - { - TVector3Property *pVector = static_cast(pProp); - CVector3f Vector = pVector->Get(); - - if (rkIndex.row() == 0) Value = Vector.X; - if (rkIndex.row() == 1) Value = Vector.Y; - if (rkIndex.row() == 2) Value = Vector.Z; - } - - else if (pProp->Type() == eColorProperty) - { - TColorProperty *pColor = static_cast(pProp); - CColor Color = pColor->Get(); - - if (rkIndex.row() == 0) Value = Color.R; - if (rkIndex.row() == 1) Value = Color.G; - if (rkIndex.row() == 2) Value = Color.B; - if (rkIndex.row() == 3) Value = Color.A; - } - - pSpinBox->setValue((double) Value); - } - } } } @@ -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(pEditor); + bool NewValue = + pCommand = new TEditScriptPropertyCommand(pProp, mpModel->GetScriptObject(), mpEditor, pCheckBox->isChecked(), + bool NewValue = TEditScriptPropertyCommand(pProp, TBoolProperty *pBool = static_cast(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(mpModel->PropertyForIndex(rkIndex, true)); + //FIXME +/* TCharacterProperty *pProp = static_cast(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(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(pEditor)->setValue(Value); } + */ } void CPropertyDelegate::SetCharacterModelData(QWidget *pEditor, const QModelIndex& rkIndex) const { - TCharacterProperty *pProp = static_cast(mpModel->PropertyForIndex(rkIndex, true)); - CAnimationParameters Params = pProp->Get(); + //FIXME + /* + CAnimationSetProperty* pAnimSet = TPropCast(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 ************ diff --git a/src/Editor/PropertyEdit/CPropertyDelegate.h b/src/Editor/PropertyEdit/CPropertyDelegate.h index 95948a81..5fbae896 100644 --- a/src/Editor/PropertyEdit/CPropertyDelegate.h +++ b/src/Editor/PropertyEdit/CPropertyDelegate.h @@ -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); diff --git a/src/Editor/PropertyEdit/CPropertyModel.cpp b/src/Editor/PropertyEdit/CPropertyModel.cpp index 7eb5d8bc..021bbb90 100644 --- a/src/Editor/PropertyEdit/CPropertyModel.cpp +++ b/src/Editor/PropertyEdit/CPropertyModel.cpp @@ -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(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(pID); - } + if (HandleFlaggedIndices) + Index &= ~0x80000000; else return nullptr; } - return static_cast(rkIndex.internalPointer()); + return mProperties[Index].pProperty; } -QModelIndex CPropertyModel::IndexForProperty(IProperty *pProp) const +QModelIndex CPropertyModel::IndexForProperty(IPropertyNew *pProp) const { - if (pProp == mpBaseStruct) return QModelIndex(); - - QVector 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(pProp)->Count(); + case EPropertyTypeNew::Flags: + return TPropCast(pProp)->NumFlags(); - case eBitfieldProperty: - return static_cast(pProp->Template())->NumFlags(); - - case eVector3Property: - return 3; - - case eColorProperty: - return 4; - - case eCharacterProperty: + case EPropertyTypeNew::AnimationSet: { - CAnimationParameters Params = static_cast(pProp)->Get(); + CAnimationParameters Params = TPropCast(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(pProp->Template()); + CFlagsProperty* pFlags = TPropCast(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(pProp); - CAnimationParameters Params = pChar->Get(); + CAnimationSetProperty* pAnimSet = TPropCast(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(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(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(pProp)->Value(mpPropertyData); + return TO_QSTRING("(" + Value.ToString() + ")"); + } // Display the AGSC/sound name for sounds - case eSoundProperty: + case EPropertyTypeNew::Sound: { - TSoundProperty *pSound = static_cast(pProp); - u32 SoundID = pSound->Get(); + CSoundProperty* pSound = TPropCast(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(pProp)->Get().GetCurrentCharacterName()); + case EPropertyTypeNew::AnimationSet: + return TO_QSTRING(TPropCast(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(pProp); - CEnumTemplate *pTemp = static_cast(pEnum->Template()); - return TO_QSTRING(pTemp->EnumeratorName( pTemp->EnumeratorIndex(pEnum->Get()) )); + CEnumProperty *pEnum = TPropCast(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(pProp)->Count(); + u32 Count = TPropCast(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(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("%1 (%2)").arg(DisplayText).arg(TO_QSTRING(PropEnumToPropString(pProp->Type()))); // Add uncooked notification - if (pProp->Template()->CookPreference() == eNeverCook) + if (pProp->CookPreference() == ECookPreferenceNew::Never) { Text.prepend("[uncooked]"); } // Add description - TString Desc = pProp->Template()->Description(); + TString Desc = pProp->Description(); if (!Desc.IsEmpty()) Text += "
" + TO_QSTRING(Desc); - // MayaSpline notification - if (pProp->Type() == eMayaSplineProperty) - Text += "
(NOTE: MayaSpline properties are currently unsupported for editing)"; + // Spline notification + if (pProp->Type() == EPropertyTypeNew::Spline) + Text += "
(NOTE: Spline properties are currently unsupported for editing)"; 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(pProp); - TVector3Template *pTemp = static_cast(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(pProp); - TColorTemplate *pTemp = static_cast(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(pParent)->PropertyByIndex(Row); - return createIndex(Row, Column, pProp); + return createIndex(Row, Column, ParentID | 0x80000000); } - - // Array - if (pParent->Type() == eArrayProperty) + else { - IProperty *pProp = static_cast(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(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(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(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(PropertyForIndex(rkIndex, false)); + //FIXME + /*CArrayProperty *pArray = static_cast(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) diff --git a/src/Editor/PropertyEdit/CPropertyModel.h b/src/Editor/PropertyEdit/CPropertyModel.h index 4fa7686f..8f7e50b5 100644 --- a/src/Editor/PropertyEdit/CPropertyModel.h +++ b/src/Editor/PropertyEdit/CPropertyModel.h @@ -1,24 +1,41 @@ #ifndef CPROPERTYMODEL_H #define CPROPERTYMODEL_H +#include #include -#include #include class CPropertyModel : public QAbstractItemModel { Q_OBJECT - CPropertyStruct *mpBaseStruct; + struct SProperty + { + IPropertyNew* pProperty; + QModelIndex Index; + int ParentID; + std::vector ChildIDs; + }; + QVector mProperties; + QMap 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: diff --git a/src/Editor/PropertyEdit/CPropertyView.cpp b/src/Editor/PropertyEdit/CPropertyView.cpp index 3177d2db..c2869c27 100644 --- a/src/Editor/PropertyEdit/CPropertyView.cpp +++ b/src/Editor/PropertyEdit/CPropertyView.cpp @@ -88,12 +88,17 @@ void CPropertyView::SetInstance(CScriptObject *pObj) { mpObject = pObj; mpModel->SetBoldModifiedProperties(mpEditor ? (mpEditor->CurrentGame() > ePrime) : true); - mpModel->SetBaseStruct(pObj ? pObj->Properties() : nullptr); + + if (pObj) + mpModel->ConfigureScript(pObj->Area()->Entry()->Project(), pObj->Template()->Properties(), pObj); + else + mpModel->ConfigureScript(nullptr, nullptr, nullptr); + SetPersistentEditors(QModelIndex()); // Auto-expand EditorProperties QModelIndex Index = mpModel->index(0, 0, QModelIndex()); - IProperty *pProp = mpModel->PropertyForIndex(Index, false); + IPropertyNew *pProp = mpModel->PropertyForIndex(Index, false); if (pProp && pProp->ID() == 0x255A4580) expand(Index); } @@ -108,19 +113,19 @@ void CPropertyView::UpdateEditorProperties(const QModelIndex& rkParent) { QModelIndex Index0 = mpModel->index(iRow, 0, rkParent); QModelIndex Index1 = mpModel->index(iRow, 1, rkParent); - IProperty *pProp = mpModel->PropertyForIndex(Index0, false); + IPropertyNew *pProp = mpModel->PropertyForIndex(Index0, false); if (pProp) { // For structs, update sub-properties. - if (pProp->Type() == eStructProperty) + if (pProp->Type() == EPropertyTypeNew::Struct) { - CStructTemplate *pStruct = static_cast(pProp->Template()); + CStructPropertyNew *pStruct = TPropCast(pProp); - // As an optimization, in MP2+, we don't need to update unless this is a single struct or if + // As an optimization, in MP2+, we don't need to update unless this is an atomic struct or if // it's EditorProperties, because other structs never have editor properties in them. // In MP1 this isn't the case so we need to update every struct regardless - if ((Game <= ePrime) || (pStruct->IsSingleProperty() || pStruct->PropertyID() == 0x255A4580)) + if ((Game <= ePrime) || (pStruct->IsAtomic() || pStruct->ID() == 0x255A4580)) UpdateEditorProperties(Index0); else continue; @@ -148,34 +153,35 @@ void CPropertyView::SetPersistentEditors(const QModelIndex& rkParent) for (u32 iChild = 0; iChild < NumChildren; iChild++) { QModelIndex ChildIndex = mpModel->index(iChild, 1, rkParent); - IProperty *pProp = mpModel->PropertyForIndex(ChildIndex, false); - EPropertyType Type = (pProp ? pProp->Type() : eInvalidProperty); + IPropertyNew *pProp = mpModel->PropertyForIndex(ChildIndex, false); + EPropertyTypeNew Type = (pProp ? pProp->Type() : EPropertyTypeNew::Invalid); // Handle persistent editors under character properties - if (!pProp && ChildIndex.internalId() & 0x1) + if (!pProp && ChildIndex.internalId() & 0x80000000) { pProp = mpModel->PropertyForIndex(ChildIndex, true); - if (pProp->Type() == eCharacterProperty) + if (pProp->Type() == EPropertyTypeNew::AnimationSet) { - EGame Game = static_cast(pProp)->Get().Version(); + EGame Game = mpObject->Area()->Game(); Type = mpDelegate->DetermineCharacterPropType(Game, ChildIndex); } - if (pProp->Type() == eBitfieldProperty) - Type = eBoolProperty; + if (pProp->Type() == EPropertyTypeNew::Flags) + Type = EPropertyTypeNew::Bool; } switch (Type) { - case eBoolProperty: - case eEnumProperty: - case eColorProperty: - case eAssetProperty: + case EPropertyTypeNew::Bool: + case EPropertyTypeNew::Enum: + case EPropertyTypeNew::Choice: + case EPropertyTypeNew::Color: + case EPropertyTypeNew::Asset: openPersistentEditor(ChildIndex); break; - case eStructProperty: + case EPropertyTypeNew::Struct: setFirstColumnSpanned(iChild, rkParent, true); break; } @@ -202,9 +208,9 @@ void CPropertyView::ClosePersistentEditors(const QModelIndex& rkIndex) void CPropertyView::OnPropertyModified(const QModelIndex& rkIndex) { // Check for a character resource being changed. If that's the case we need to remake the persistent editors. - IProperty *pProp = mpModel->PropertyForIndex(rkIndex, true); + IPropertyNew *pProp = mpModel->PropertyForIndex(rkIndex, true); - if (pProp->Type() == eCharacterProperty /*&& rkIndex.internalId() & 0x1*/) + if (pProp->Type() == EPropertyTypeNew::AnimationSet /*&& rkIndex.internalId() & 0x1*/) { ClosePersistentEditors(rkIndex); SetPersistentEditors(rkIndex); @@ -217,7 +223,7 @@ void CPropertyView::CreateContextMenu(const QPoint& rkPos) if (Index.isValid() && Index.column() == 0) { - IProperty *pProp = mpModel->PropertyForIndex(Index, true); + IPropertyNew *pProp = mpModel->PropertyForIndex(Index, true); mpMenuProperty = pProp; QMenu Menu; @@ -239,6 +245,6 @@ void CPropertyView::ToggleShowNameValidity(bool ShouldShow) void CPropertyView::EditPropertyTemplate() { - CTemplateEditDialog Dialog(mpMenuProperty->Template(), mpEditor); + CTemplateEditDialog Dialog(mpMenuProperty, mpEditor); Dialog.exec(); } diff --git a/src/Editor/PropertyEdit/CPropertyView.h b/src/Editor/PropertyEdit/CPropertyView.h index bdec0967..57657d0b 100644 --- a/src/Editor/PropertyEdit/CPropertyView.h +++ b/src/Editor/PropertyEdit/CPropertyView.h @@ -15,7 +15,7 @@ class CPropertyView : public QTreeView CPropertyDelegate *mpDelegate; CScriptObject *mpObject; - IProperty *mpMenuProperty; + IPropertyNew *mpMenuProperty; QAction *mpShowNameValidityAction; QAction *mpEditTemplateAction; diff --git a/src/Editor/Undo/CCloneSelectionCommand.cpp b/src/Editor/Undo/CCloneSelectionCommand.cpp index c3343106..897f7abc 100644 --- a/src/Editor/Undo/CCloneSelectionCommand.cpp +++ b/src/Editor/Undo/CCloneSelectionCommand.cpp @@ -63,7 +63,7 @@ void CCloneSelectionCommand::redo() CScriptObject *pInstance = pScript->Instance(); CScriptObject *pCloneInst = mpEditor->ActiveArea()->SpawnInstance(pInstance->Template(), pInstance->Layer()); - pCloneInst->Properties()->Copy(pInstance->Properties()); + pCloneInst->CopyProperties(pInstance); pCloneInst->EvaluateProperties(); CScriptNode *pCloneNode = mpEditor->Scene()->CreateScriptNode(pCloneInst); diff --git a/src/Editor/Undo/CDeleteSelectionCommand.cpp b/src/Editor/Undo/CDeleteSelectionCommand.cpp index cb51b899..dc72a585 100644 --- a/src/Editor/Undo/CDeleteSelectionCommand.cpp +++ b/src/Editor/Undo/CDeleteSelectionCommand.cpp @@ -101,9 +101,9 @@ void CDeleteSelectionCommand::undo() rNode.pArea->AddInstanceToArea(pInstance); rNode.pLayer->AddInstance(pInstance, rNode.LayerIndex); - if (!pInstance->PositionProperty()) pNode->SetPosition(rNode.Position); - if (!pInstance->RotationProperty()) pNode->SetRotation(rNode.Rotation); - if (!pInstance->ScaleProperty()) pNode->SetScale(rNode.Scale); + pNode->SetPosition(rNode.Position); + pNode->SetRotation(rNode.Rotation); + pNode->SetScale(rNode.Scale); NewNodes << pNode; NewInstanceIDs << pInstance->InstanceID(); diff --git a/src/Editor/Undo/CEditScriptPropertyCommand.cpp b/src/Editor/Undo/CEditScriptPropertyCommand.cpp index b1b12f08..3a80b74c 100644 --- a/src/Editor/Undo/CEditScriptPropertyCommand.cpp +++ b/src/Editor/Undo/CEditScriptPropertyCommand.cpp @@ -1,7 +1,7 @@ #include "CEditScriptPropertyCommand.h" #include "EUndoCommand.h" -CEditScriptPropertyCommand::CEditScriptPropertyCommand(IProperty *pProp, CWorldEditor *pEditor, IPropertyValue *pOldValue, bool IsDone, const QString& rkCommandName /*= "Edit Property"*/) +/*CEditScriptPropertyCommand::CEditScriptPropertyCommand(IProperty *pProp, CWorldEditor *pEditor, IPropertyValue *pOldValue, bool IsDone, const QString& rkCommandName /*= "Edit Property") : IUndoCommand(rkCommandName) , mpProp(pProp) , mpEditor(pEditor) @@ -53,3 +53,4 @@ void CEditScriptPropertyCommand::redo() pProp->RawValue()->Copy(mpNewValue); mpEditor->OnPropertyModified(pProp); } +*/ diff --git a/src/Editor/Undo/CEditScriptPropertyCommand.h b/src/Editor/Undo/CEditScriptPropertyCommand.h index 63efad5c..8cf3ea19 100644 --- a/src/Editor/Undo/CEditScriptPropertyCommand.h +++ b/src/Editor/Undo/CEditScriptPropertyCommand.h @@ -3,10 +3,77 @@ #include "IUndoCommand.h" #include "ObjReferences.h" +#include "EUndoCommand.h" #include "Editor/PropertyEdit/CPropertyModel.h" #include "Editor/WorldEditor/CWorldEditor.h" -class CEditScriptPropertyCommand : public IUndoCommand +template +class TEditScriptPropertyCommand : public IUndoCommand +{ + typedef typename PropertyClass::ValueType ValueType; + + CWorldEditor *mpEditor; + CInstancePtr mpInstance; + PropertyClass* mpProperty; + ValueType mOldValue; + ValueType mNewValue; + bool mCommandEnded; + +public: + TEditScriptPropertyCommand(PropertyClass* pProp, CScriptObject* pInstance, CWorldEditor* pEditor, ValueType NewValue, bool IsDone, const QString& rkCommandName = "Edit Property") + : IUndoCommand(rkCommandName) + , mpEditor(pEditor) + , mpInstance(pInstance) + , mpProperty(pProp) + , mOldValue(pProp->Value(pInstance->PropertyData())) + , mNewValue(NewValue) + , mCommandEnded(IsDone) + {} + + int id() const + { + return eEditScriptPropertyCmd; + } + + bool mergeWith(const QUndoCommand *pkOther) + { + if (!mCommandEnded) + { + TEditScriptPropertyCommand* pkCmd = dynamic_cast(pkOther); + + if (pkCmd && pkCmd->mpProperty == mpProperty && pkCmd->mpInstance == mpInstance) + { + mNewValue = pkCmd->mNewValue; + mCommandEnded = pkCmd->mCommandEnded; + return true; + } + } + + return false; + } + + void undo() + { + void* pData = mpInstance->PropertyData(); + mpProperty->ValueRef(pData) = mOldValue; + mpEditor->OnPropertyModified(mpProperty); + mCommandEnded = true; + } + + void redo() + { + void* pData = mpInstance->PropertyData(); + mpProperty->ValueRef(pData) = mNewValue; + mpEditor->OnPropertyModified(mpProperty); + } + + bool AffectsCleanState() const + { + return true; + } +}; + +/*class CEditScriptPropertyCommand : public IUndoCommand { CWorldEditor *mpEditor; CPropertyPtr mpProp; @@ -22,6 +89,6 @@ public: void undo(); void redo(); bool AffectsCleanState() const { return true; } -}; +};*/ #endif // CEDITSCRIPTPROPERTYCOMMAND_H diff --git a/src/Editor/Undo/CResizeScriptArrayCommand.cpp b/src/Editor/Undo/CResizeScriptArrayCommand.cpp index d36b2e06..2d0e5a38 100644 --- a/src/Editor/Undo/CResizeScriptArrayCommand.cpp +++ b/src/Editor/Undo/CResizeScriptArrayCommand.cpp @@ -1,6 +1,6 @@ #include "CResizeScriptArrayCommand.h" - -CResizeScriptArrayCommand::CResizeScriptArrayCommand(IProperty *pProp, CWorldEditor *pEditor, CPropertyModel *pModel, int NewSize) +/* +CResizeScriptArrayCommand::CResizeScriptArrayCommand(IPropertyNew *pProp, CWorldEditor *pEditor, CPropertyModel *pModel, int NewSize) : IUndoCommand("Edit Property") , mpEditor(pEditor) , mpArray(pProp) @@ -23,7 +23,7 @@ CResizeScriptArrayCommand::CResizeScriptArrayCommand(IProperty *pProp, CWorldEdi CResizeScriptArrayCommand::~CResizeScriptArrayCommand() { - foreach (IProperty *pProp, mDeletedProperties) + foreach (IPropertyNew *pProp, mDeletedProperties) delete pProp; } @@ -69,3 +69,4 @@ void CResizeScriptArrayCommand::redo() mpModel->ArrayResized(Index, (u32) mOldSize); } } +*/ diff --git a/src/Editor/Undo/CResizeScriptArrayCommand.h b/src/Editor/Undo/CResizeScriptArrayCommand.h index a5b89ec3..06efcdc2 100644 --- a/src/Editor/Undo/CResizeScriptArrayCommand.h +++ b/src/Editor/Undo/CResizeScriptArrayCommand.h @@ -8,11 +8,12 @@ #include // todo: make this more general... it shouldn't be relying on a CPropertyModel pointer -class CResizeScriptArrayCommand : public IUndoCommand +//FIXME +/*class CResizeScriptArrayCommand : public IUndoCommand { - CWorldEditor *mpEditor; - CPropertyPtr mpArray; - QVector mDeletedProperties; + CWorldEditor* mpEditor; + IPropertyNew* mpArray; + QVector mDeletedProperties; CPropertyModel *mpModel; int mOldSize; @@ -20,11 +21,11 @@ class CResizeScriptArrayCommand : public IUndoCommand bool mNewSizeLarger; public: - CResizeScriptArrayCommand(IProperty *pProp, CWorldEditor *pEditor, CPropertyModel *pModel, int NewSize); + CResizeScriptArrayCommand(IPropertyNew *pProp, CWorldEditor *pEditor, CPropertyModel *pModel, int NewSize); ~CResizeScriptArrayCommand(); void undo(); void redo(); bool AffectsCleanState() const { return true; } -}; +};*/ #endif // CRESIZESCRIPTARRAYCOMMAND_H diff --git a/src/Editor/Undo/ObjReferences.h b/src/Editor/Undo/ObjReferences.h index e862562d..fd3ee307 100644 --- a/src/Editor/Undo/ObjReferences.h +++ b/src/Editor/Undo/ObjReferences.h @@ -111,35 +111,6 @@ public: } }; -class CPropertyPtr -{ - CInstancePtr mpInstance; - TIDString mPropertyID; - bool mValid; - -public: - CPropertyPtr() { SetProperty(nullptr); } - CPropertyPtr(IProperty *pProp) { SetProperty(pProp); } - - inline void SetProperty(IProperty *pProp) - { - mpInstance = pProp ? pProp->Instance() : nullptr; - mPropertyID = pProp ? pProp->IDString(true) : ""; - mValid = pProp ? true : false; - } - - inline CInstancePtr InstancePtr() const { return mpInstance; } - inline TIDString PropertyID() const { return mPropertyID; } - inline IProperty* operator* () const { return mValid ? mpInstance->PropertyByIDString(mPropertyID) : nullptr; } - inline IProperty* operator->() const { return mValid ? mpInstance->PropertyByIDString(mPropertyID) : nullptr; } - inline CPropertyPtr& operator=(IProperty *pProp) { SetProperty(pProp); return *this; } - - inline bool operator==(const CPropertyPtr& rkOther) const - { - return (mpInstance == rkOther.mpInstance && mPropertyID == rkOther.mPropertyID); - } -}; - class CLinkPtr { CInstancePtr mpInstance; @@ -170,7 +141,6 @@ public: DEFINE_PTR_LIST_CLASS(CNodePtrList, CNodePtr, CSceneNode*) DEFINE_PTR_LIST_CLASS(CInstancePtrList, CInstancePtr, CScriptObject*) -DEFINE_PTR_LIST_CLASS(CPropertyPtrList, CPropertyPtr, IProperty*) DEFINE_PTR_LIST_CLASS(CLinkPtrList, CLinkPtr, CLink*) #endif // OBJREFERENCES diff --git a/src/Editor/WorldEditor/CInstancesModel.cpp b/src/Editor/WorldEditor/CInstancesModel.cpp index 75483e9b..4f3a5867 100644 --- a/src/Editor/WorldEditor/CInstancesModel.cpp +++ b/src/Editor/WorldEditor/CInstancesModel.cpp @@ -44,7 +44,7 @@ CInstancesModel::CInstancesModel(CWorldEditor *pEditor, QObject *pParent) connect(mpEditor, SIGNAL(NodeSpawned(CSceneNode*)), this, SLOT(NodeCreated(CSceneNode*))); connect(mpEditor, SIGNAL(NodeAboutToBeDeleted(CSceneNode*)), this, SLOT(NodeAboutToBeDeleted(CSceneNode*))); connect(mpEditor, SIGNAL(NodeDeleted()), this, SLOT(NodeDeleted())); - connect(mpEditor, SIGNAL(PropertyModified(CScriptObject*,IProperty*)), this, SLOT(PropertyModified(CScriptObject*,IProperty*))); + connect(mpEditor, SIGNAL(PropertyModified(CScriptObject*,IPropertyNew*)), this, SLOT(PropertyModified(CScriptObject*,IPropertyNew*))); connect(mpEditor, SIGNAL(InstancesLayerAboutToChange()), this, SLOT(InstancesLayerPreChange())); connect(mpEditor, SIGNAL(InstancesLayerChanged(QList)), this, SLOT(InstancesLayerPostChange(QList))); } @@ -474,9 +474,9 @@ void CInstancesModel::NodeDeleted() } } -void CInstancesModel::PropertyModified(CScriptObject *pInst, IProperty *pProp) +void CInstancesModel::PropertyModified(CScriptObject *pInst, IPropertyNew *pProp) { - if (pInst->InstanceNameProperty() == pProp) + if (pProp->Name() == "Name") { QModelIndex ScriptRoot = index(0, 0, QModelIndex()); diff --git a/src/Editor/WorldEditor/CInstancesModel.h b/src/Editor/WorldEditor/CInstancesModel.h index 270143cf..8e2a9346 100644 --- a/src/Editor/WorldEditor/CInstancesModel.h +++ b/src/Editor/WorldEditor/CInstancesModel.h @@ -67,7 +67,7 @@ public slots: void NodeAboutToBeDeleted(CSceneNode *pNode); void NodeDeleted(); - void PropertyModified(CScriptObject *pInst, IProperty *pProp); + void PropertyModified(CScriptObject *pInst, IPropertyNew *pProp); void InstancesLayerPreChange(); void InstancesLayerPostChange(const QList& rkInstanceList); diff --git a/src/Editor/WorldEditor/CTemplateEditDialog.cpp b/src/Editor/WorldEditor/CTemplateEditDialog.cpp index edf6da37..bb22884b 100644 --- a/src/Editor/WorldEditor/CTemplateEditDialog.cpp +++ b/src/Editor/WorldEditor/CTemplateEditDialog.cpp @@ -6,22 +6,22 @@ #include #include -CTemplateEditDialog::CTemplateEditDialog(IPropertyTemplate *pTemplate, QWidget *pParent) +CTemplateEditDialog::CTemplateEditDialog(IPropertyNew *pProperty, QWidget *pParent) : QDialog(pParent) , mpUI(new Ui::CTemplateEditDialog) , mpValidator(new CPropertyNameValidator(this)) - , mpTemplate(pTemplate) - , mGame(pTemplate->Game()) - , mOriginalName(pTemplate->Name()) - , mOriginalDescription(pTemplate->Description()) + , mpProperty(pProperty) + , mGame(pProperty->Game()) + , mOriginalName(pProperty->Name()) + , mOriginalDescription(pProperty->Description()) , mOriginalNameWasValid(true) { mpUI->setupUi(this); - mpUI->IDDisplayLabel->setText(TO_QSTRING(pTemplate->IDString(false))); - mpUI->PathDisplayLabel->setText(TO_QSTRING(pTemplate->IDString(true))); - mpUI->NameLineEdit->setText(TO_QSTRING(pTemplate->Name())); - mpUI->DescriptionTextEdit->setPlainText(TO_QSTRING(pTemplate->Description())); + mpUI->IDDisplayLabel->setText(TO_QSTRING(pProperty->IDString(false))); + mpUI->PathDisplayLabel->setText(TO_QSTRING(pProperty->IDString(true))); + mpUI->NameLineEdit->setText(TO_QSTRING(pProperty->Name())); + mpUI->DescriptionTextEdit->setPlainText(TO_QSTRING(pProperty->Description())); if (mGame <= ePrime) { @@ -35,7 +35,7 @@ CTemplateEditDialog::CTemplateEditDialog(IPropertyTemplate *pTemplate, QWidget * { CTemplateLoader::LoadAllGames(); std::vector TemplateList; - CMasterTemplate::XMLsUsingID(pTemplate->PropertyID(), TemplateList); + CMasterTemplate::XMLsUsingID(pProperty->ID(), TemplateList); for (u32 iTemp = 0; iTemp < TemplateList.size(); iTemp++) mpUI->TemplatesListWidget->addItem(TO_QSTRING(TemplateList[iTemp])); @@ -43,38 +43,15 @@ CTemplateEditDialog::CTemplateEditDialog(IPropertyTemplate *pTemplate, QWidget * mpUI->ValidityLabel->SetValidityText("Hash match! Property name is likely correct.", "Hash mismatch! Property name is likely wrong."); connect(mpUI->NameLineEdit, SIGNAL( SoftValidityChanged(bool) ), mpUI->ValidityLabel, SLOT( SetValid(bool) ) ); - mpValidator->SetProperty(pTemplate); + mpValidator->SetProperty(pProperty); mpUI->NameLineEdit->SetSoftValidator(mpValidator); mOriginalNameWasValid = mpUI->NameLineEdit->IsInputValid(); } - TString Source; - - if (mpTemplate->Type() == eStructProperty || mpTemplate->Type() == eArrayProperty) - Source = static_cast(mpTemplate)->SourceFile(); - else if (mpTemplate->Type() == eEnumProperty) - Source = static_cast(mpTemplate)->SourceFile(); - else if (mpTemplate->Type() == eBitfieldProperty) - Source = static_cast(mpTemplate)->SourceFile(); + TString Source = mpProperty->GetTemplateFileName(); if (Source.IsEmpty()) - { - CStructTemplate *pParent = mpTemplate->Parent(); - while (pParent) - { - Source = pParent->SourceFile(); - if (!Source.IsEmpty()) break; - pParent = pParent->Parent(); - } - } - - if (Source.IsEmpty()) - { - if (mpTemplate->ScriptTemplate()) - Source = mpTemplate->ScriptTemplate()->SourceFile(); - if (Source.IsEmpty()) - Source = "None"; - } + Source = "None"; mpUI->SourceFileDisplayLabel->setText(TO_QSTRING(Source)); @@ -100,7 +77,7 @@ void CTemplateEditDialog::ApplyChanges() return; } - FindEquivalentProperties(mpTemplate); + FindEquivalentProperties(mpProperty); bool NeedsListResave = false; bool RenameAll = mpUI->RenameAllCheckBox->isChecked(); @@ -111,12 +88,12 @@ void CTemplateEditDialog::ApplyChanges() if (mOriginalName != NewName) { // Rename properties - if (RenameAll && (mGame >= eEchoesDemo || mpTemplate->IsFromStructTemplate())) + if (RenameAll && (mGame >= eEchoesDemo || mpProperty->Archetype() != nullptr)) { - CMasterTemplate::RenameProperty(mpTemplate, NewName); + CMasterTemplate::RenameProperty(mpProperty, NewName); // Add modified templates to pending resave list - const std::vector *pList = CMasterTemplate::TemplatesWithMatchingID(mpTemplate); + const std::vector *pList = CMasterTemplate::TemplatesWithMatchingID(mpProperty); if (pList) { @@ -125,7 +102,7 @@ void CTemplateEditDialog::ApplyChanges() } } - mpTemplate->SetName(NewName); // If mpTemplate has an overridden name then CMasterTemplate::RenameProperty won't touch it + mpProperty->SetName(NewName); // If mpTemplate has an overridden name then CMasterTemplate::RenameProperty won't touch it if (RenameAll && mGame >= eEchoesDemo) NeedsListResave = true; @@ -135,28 +112,30 @@ void CTemplateEditDialog::ApplyChanges() UpdateDescription(NewDescription); // Resave templates - foreach (CScriptTemplate *pScript, mScriptTemplatesToResave) + //FIXME +/* foreach (CScriptTemplate *pScript, mScriptTemplatesToResave) CTemplateWriter::SaveScriptTemplate(pScript); foreach (CStructTemplate *pStruct, mStructTemplatesToResave) CTemplateWriter::SaveStructTemplate(pStruct); if (NeedsListResave) - CTemplateWriter::SavePropertyList(); + CTemplateWriter::SavePropertyList();*/ close(); } // ************ PROTECTED ************ -void CTemplateEditDialog::AddTemplate(IPropertyTemplate *pTemp) +void CTemplateEditDialog::AddTemplate(IPropertyNew* pProp) { - if (pTemp->IsFromStructTemplate()) + //FIXME +/* if (pProp->Archetype() != nullptr) { - TString Source = pTemp->FindStructSource(); + TString Source = pProp->GetTemplateFileName(); if (!Source.IsEmpty()) { - CStructTemplate *pStruct = pTemp->MasterTemplate()->StructAtSource(Source); + CStructTemplate *pStruct = pProp->MasterTemplate()->StructAtSource(Source); if (!mStructTemplatesToResave.contains(pStruct)) mStructTemplatesToResave << pStruct; @@ -165,7 +144,7 @@ void CTemplateEditDialog::AddTemplate(IPropertyTemplate *pTemp) else { - CScriptTemplate *pScript = pTemp->ScriptTemplate(); + CScriptTemplate *pScript = pProp->ScriptTemplate(); if (pScript) { @@ -175,22 +154,23 @@ void CTemplateEditDialog::AddTemplate(IPropertyTemplate *pTemp) else { - Log::Error("Can't determine where property " + pTemp->IDString(true) + " comes from"); + Log::Error("Can't determine where property " + pProp->IDString(true) + " comes from"); } - } + }*/ } void CTemplateEditDialog::UpdateDescription(const TString& rkNewDesc) { - mpTemplate->SetDescription(rkNewDesc); - AddTemplate(mpTemplate); + //FIXME +/* mpProperty->SetDescription(rkNewDesc); + AddTemplate(mpProperty); // Update all copies of this property in memory with the new description - TString SourceFile = mpTemplate->FindStructSource(); + TString SourceFile = mpProperty->FindStructSource(); if (!SourceFile.IsEmpty()) { - const std::vector *pkTemplates = CMasterTemplate::TemplatesWithMatchingID(mpTemplate); + const std::vector *pkTemplates = CMasterTemplate::TemplatesWithMatchingID(mpProperty); if (pkTemplates) { @@ -209,11 +189,13 @@ void CTemplateEditDialog::UpdateDescription(const TString& rkNewDesc) { pTemp->SetDescription(rkNewDesc); AddTemplate(pTemp); - } + }*/ } -void CTemplateEditDialog::FindEquivalentProperties(IPropertyTemplate *pTemp) +void CTemplateEditDialog::FindEquivalentProperties(IPropertyNew *pTemp) { + //FIXME + /* if (mGame <= ePrime) return; // Find the equivalent version of this property in other games. @@ -275,5 +257,5 @@ void CTemplateEditDialog::FindEquivalentProperties(IPropertyTemplate *pTemp) mEquivalentProperties << pNewTemp; } } - } + }*/ } diff --git a/src/Editor/WorldEditor/CTemplateEditDialog.h b/src/Editor/WorldEditor/CTemplateEditDialog.h index 771879cc..241b4c44 100644 --- a/src/Editor/WorldEditor/CTemplateEditDialog.h +++ b/src/Editor/WorldEditor/CTemplateEditDialog.h @@ -16,7 +16,7 @@ class CTemplateEditDialog : public QDialog Ui::CTemplateEditDialog* mpUI; CPropertyNameValidator* mpValidator; - IPropertyTemplate *mpTemplate; + IPropertyNew *mpProperty; EGame mGame; TString mOriginalName; @@ -24,21 +24,22 @@ class CTemplateEditDialog : public QDialog bool mOriginalNameWasValid; // These members help track what templates need to be updated and resaved after the user clicks OK - QVector mScriptTemplatesToResave; - QVector mStructTemplatesToResave; - QVector mEquivalentProperties; + //FIXME +// QVector mScriptTemplatesToResave; +// QVector mStructTemplatesToResave; +// QVector mEquivalentProperties; public: - CTemplateEditDialog(IPropertyTemplate *pTemplate, QWidget *pParent = 0); + CTemplateEditDialog(IPropertyNew* pProperty, QWidget *pParent = 0); ~CTemplateEditDialog(); public slots: void ApplyChanges(); protected: - void AddTemplate(IPropertyTemplate *pTemp); + void AddTemplate(IPropertyNew* pProperty); void UpdateDescription(const TString& rkNewDesc); - void FindEquivalentProperties(IPropertyTemplate *pTemp); + void FindEquivalentProperties(IPropertyNew *pTemp); }; #endif // CTEMPLATEEDITDIALOG_H diff --git a/src/Editor/WorldEditor/CWorldEditor.cpp b/src/Editor/WorldEditor/CWorldEditor.cpp index 44710548..f77925ca 100644 --- a/src/Editor/WorldEditor/CWorldEditor.cpp +++ b/src/Editor/WorldEditor/CWorldEditor.cpp @@ -569,36 +569,30 @@ void CWorldEditor::OnLinksModified(const QList& rkInstances) emit InstanceLinksModified(rkInstances); } -void CWorldEditor::OnPropertyModified(IProperty *pProp) +void CWorldEditor::OnPropertyModified(IPropertyNew *pProp) { - bool EditorProperty = false; - if (!mpSelection->IsEmpty() && mpSelection->Front()->NodeType() == eScriptNode) { CScriptNode *pScript = static_cast(mpSelection->Front()); pScript->PropertyModified(pProp); - // Check editor property - if (pScript->Instance()->IsEditorProperty(pProp)) - EditorProperty = true; - // If this is an editor property, update other parts of the UI to reflect the new value. - if (EditorProperty) + if ( pScript->Instance()->IsEditorProperty(pProp) ) { UpdateStatusBar(); UpdateSelectionUI(); } // If this is a model/character, then we'll treat this as a modified selection. This is to make sure the selection bounds updates. - if (pProp->Type() == eAssetProperty) + if (pProp->Type() == EPropertyTypeNew::Asset) { - CAssetTemplate *pAsset = static_cast(pProp->Template()); - const CResTypeFilter& rkFilter = pAsset->TypeFilter(); + CAssetProperty *pAsset = TPropCast(pProp); + const CResTypeFilter& rkFilter = pAsset->GetTypeFilter(); if (rkFilter.Accepts(eModel) || rkFilter.Accepts(eAnimSet) || rkFilter.Accepts(eCharacter)) SelectionModified(); } - else if (pProp->Type() == eCharacterProperty) + else if (pProp->Type() == EPropertyTypeNew::AnimationSet) SelectionModified(); // Emit signal so other widgets can react to the property change @@ -615,11 +609,10 @@ void CWorldEditor::SetSelectionActive(bool Active) { if (It->NodeType() == eScriptNode) { - CScriptNode *pScript = static_cast(*It); - CScriptObject *pInst = pScript->Instance(); - IProperty *pActive = pInst->ActiveProperty(); + CScriptNode* pScript = static_cast(*It); + CScriptObject* pInst = pScript->Instance(); - if (pActive) + if (pInst->IsActive()) Objects << pInst; } } @@ -628,13 +621,13 @@ void CWorldEditor::SetSelectionActive(bool Active) { mUndoStack.beginMacro("Toggle Active"); - foreach (CScriptObject *pInst, Objects) + /*foreach (CScriptObject *pInst, Objects) { IProperty *pActive = pInst->ActiveProperty(); IPropertyValue *pOld = pActive->RawValue()->Clone(); pInst->SetActive(Active); mUndoStack.push(new CEditScriptPropertyCommand(pActive, this, pOld, true)); - } + }*/ mUndoStack.endMacro(); } @@ -644,11 +637,10 @@ void CWorldEditor::SetSelectionInstanceNames(const QString& rkNewName, bool IsDo { // todo: this only supports one node at a time because a macro prevents us from merging undo commands // this is fine right now because this function is only ever called with a selection of one node, but probably want to fix in the future - if (mpSelection->Size() == 1 && mpSelection->Front()->NodeType() == eScriptNode) + /*if (mpSelection->Size() == 1 && mpSelection->Front()->NodeType() == eScriptNode) { CScriptNode *pNode = static_cast(mpSelection->Front()); CScriptObject *pInst = pNode->Instance(); - IProperty *pName = pInst->InstanceNameProperty(); if (pName) { @@ -657,7 +649,7 @@ void CWorldEditor::SetSelectionInstanceNames(const QString& rkNewName, bool IsDo pInst->SetName(NewName); mUndoStack.push(new CEditScriptPropertyCommand(pName, this, pOld, IsDone, "Edit Instance Name")); } - } + }*/ } void CWorldEditor::SetSelectionLayer(CScriptLayer *pLayer) diff --git a/src/Editor/WorldEditor/CWorldEditor.h b/src/Editor/WorldEditor/CWorldEditor.h index eb730461..766bd9c0 100644 --- a/src/Editor/WorldEditor/CWorldEditor.h +++ b/src/Editor/WorldEditor/CWorldEditor.h @@ -122,7 +122,7 @@ public slots: void OnActiveProjectChanged(CGameProject *pProj); void OnLinksModified(const QList& rkInstances); - void OnPropertyModified(IProperty *pProp); + void OnPropertyModified(IPropertyNew *pProp); void SetSelectionActive(bool Active); void SetSelectionInstanceNames(const QString& rkNewName, bool IsDone); void SetSelectionLayer(CScriptLayer *pLayer); @@ -187,7 +187,7 @@ signals: void InstancesLayerAboutToChange(); void InstancesLayerChanged(const QList& rkInstanceList); void InstanceLinksModified(const QList& rkInstances); - void PropertyModified(CScriptObject *pInst, IProperty *pProp); + void PropertyModified(CScriptObject *pInst, IPropertyNew *pProp); }; #endif // CWORLDEDITOR_H diff --git a/src/Editor/WorldEditor/WEditorProperties.cpp b/src/Editor/WorldEditor/WEditorProperties.cpp index c13a4b93..3a416d66 100644 --- a/src/Editor/WorldEditor/WEditorProperties.cpp +++ b/src/Editor/WorldEditor/WEditorProperties.cpp @@ -139,7 +139,7 @@ void WEditorProperties::OnSelectionModified() SetLayerComboBox(); } -void WEditorProperties::OnPropertyModified(CScriptObject *pInstance, IProperty *pProp) +void WEditorProperties::OnPropertyModified(CScriptObject *pInstance, IPropertyNew *pProp) { if (!mpInstanceNameLineEdit->hasFocus()) { @@ -174,11 +174,11 @@ void WEditorProperties::UpdatePropertyValues() CScriptObject *pInst = pScript->Instance(); mpActiveCheckBox->setChecked(pInst->IsActive()); - mpActiveCheckBox->setEnabled(pInst->ActiveProperty() != nullptr); + mpActiveCheckBox->setEnabled(pInst->HasActive()); mpInstanceNameLineEdit->blockSignals(true); mpInstanceNameLineEdit->setText(TO_QSTRING(pInst->InstanceName())); - mpInstanceNameLineEdit->setEnabled(pInst->InstanceNameProperty() != nullptr); + mpInstanceNameLineEdit->setEnabled(pInst->HasInstanceName()); mpInstanceNameLineEdit->blockSignals(false); } diff --git a/src/Editor/WorldEditor/WEditorProperties.h b/src/Editor/WorldEditor/WEditorProperties.h index e21ba9b2..a6f56184 100644 --- a/src/Editor/WorldEditor/WEditorProperties.h +++ b/src/Editor/WorldEditor/WEditorProperties.h @@ -39,7 +39,7 @@ public: public slots: void OnSelectionModified(); - void OnPropertyModified(CScriptObject *pInst, IProperty *pProp); + void OnPropertyModified(CScriptObject *pInst, IPropertyNew *pProp); void OnInstancesLayerChanged(const QList& rkNodeList); void OnLayersModified(); void UpdatePropertyValues(); diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index d1568cc8..12d83bcb 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -3,6 +3,7 @@ #include "UICommon.h" #include #include +#include #include #include @@ -54,6 +55,7 @@ int main(int argc, char *argv[]) DarkPalette.setColor(QPalette::HighlightedText, Qt::white); qApp->setPalette(DarkPalette); + // Init log bool Initialized = Log::InitLog("primeworldeditor.log"); if (!Initialized) QMessageBox::warning(0, "Error", "Couldn't open log file. Logging will not work for this session."); @@ -71,6 +73,8 @@ int main(int argc, char *argv[]) // Load templates CTemplateLoader::LoadGameList(); + CTemplateLoader::LoadAllGames(); + //CTemplateWriter::SaveAllTemplates(); // Execute application App.InitEditor(); diff --git a/src/Math/CVector3f.cpp b/src/Math/CVector3f.cpp index f7695849..af81c46e 100644 --- a/src/Math/CVector3f.cpp +++ b/src/Math/CVector3f.cpp @@ -41,6 +41,11 @@ void CVector3f::Serialize(IArchive& rArc) rArc << SERIAL_AUTO(X) << SERIAL_AUTO(Y) << SERIAL_AUTO(Z); } +TString CVector3f::ToString() const +{ + return TString::Format("%f.1, %f.1, %f.1", X, Y, Z); +} + // ************ SWIZZLE ************ CVector2f CVector3f::XY() { diff --git a/src/Math/CVector3f.h b/src/Math/CVector3f.h index f242b8f0..acfa9bbf 100644 --- a/src/Math/CVector3f.h +++ b/src/Math/CVector3f.h @@ -22,6 +22,7 @@ public: CVector3f(IInputStream& rInput); void Write(IOutputStream& rOutput) const; void Serialize(IArchive& rArc); + TString ToString() const; // Swizzle CVector2f XY(); diff --git a/templates/Properties.xml b/templates/Properties.xml index 45ba8d20..3bd0fb9a 100644 --- a/templates/Properties.xml +++ b/templates/Properties.xml @@ -149,7 +149,7 @@ - + @@ -420,7 +420,7 @@ - + @@ -856,7 +856,7 @@ - + @@ -1744,7 +1744,7 @@ - + @@ -1873,7 +1873,7 @@ - + @@ -2164,7 +2164,7 @@ - + @@ -2176,7 +2176,7 @@ - + @@ -2833,7 +2833,7 @@ - + @@ -2972,7 +2972,7 @@ - + @@ -3006,7 +3006,7 @@ - + @@ -3238,7 +3238,7 @@ - + @@ -3264,7 +3264,7 @@ - + @@ -3286,7 +3286,7 @@ - + @@ -3432,7 +3432,7 @@ - + @@ -3551,7 +3551,7 @@ - + @@ -4175,7 +4175,7 @@ - + @@ -4279,7 +4279,7 @@ - + @@ -4586,7 +4586,7 @@ - + @@ -4933,7 +4933,7 @@ - + @@ -4958,7 +4958,7 @@ - + @@ -5388,7 +5388,7 @@ - + @@ -5526,7 +5526,7 @@ - + @@ -5750,7 +5750,7 @@ - + @@ -6251,7 +6251,7 @@ - + @@ -6635,7 +6635,7 @@ - + @@ -6650,7 +6650,7 @@ - + @@ -7206,7 +7206,7 @@ - + @@ -7280,7 +7280,7 @@ - + @@ -7763,7 +7763,7 @@ - + @@ -7883,9 +7883,9 @@ - + - + @@ -8041,7 +8041,7 @@ - + @@ -8260,7 +8260,7 @@ - + @@ -8440,7 +8440,7 @@ - + @@ -8987,7 +8987,7 @@ - + @@ -8996,7 +8996,7 @@ - + @@ -9124,7 +9124,7 @@ - + @@ -9243,7 +9243,7 @@ - + @@ -9462,7 +9462,7 @@ - + @@ -9651,7 +9651,7 @@ - + @@ -9913,7 +9913,7 @@ - + @@ -10036,7 +10036,7 @@ - + @@ -10090,7 +10090,7 @@ - + @@ -10405,7 +10405,7 @@ - + diff --git a/templates/mp1/Script/CameraHint.xml b/templates/mp1/Script/CameraHint.xml index 5f1048e0..9998381a 100644 --- a/templates/mp1/Script/CameraHint.xml +++ b/templates/mp1/Script/CameraHint.xml @@ -8,95 +8,20 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - + diff --git a/templates/mp1/Script/Magdolite.xml b/templates/mp1/Script/Magdolite.xml index 6c978388..adbb8d47 100644 --- a/templates/mp1/Script/Magdolite.xml +++ b/templates/mp1/Script/Magdolite.xml @@ -20,16 +20,7 @@ - - - - - - - - - - + diff --git a/templates/mp1/Script/MetroidPrimeStage1.xml b/templates/mp1/Script/MetroidPrimeStage1.xml index 60c3b4fe..fd8541df 100644 --- a/templates/mp1/Script/MetroidPrimeStage1.xml +++ b/templates/mp1/Script/MetroidPrimeStage1.xml @@ -17,65 +17,13 @@ - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/templates/mp1/Script/NewCameraShaker.xml b/templates/mp1/Script/NewCameraShaker.xml index e973f694..e4894c8b 100644 --- a/templates/mp1/Script/NewCameraShaker.xml +++ b/templates/mp1/Script/NewCameraShaker.xml @@ -5,72 +5,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + diff --git a/templates/mp1/Script/PathCamera.xml b/templates/mp1/Script/PathCamera.xml index 6604033b..9d2b4966 100644 --- a/templates/mp1/Script/PathCamera.xml +++ b/templates/mp1/Script/PathCamera.xml @@ -6,16 +6,7 @@ - - - - - - - - - - + diff --git a/templates/mp1/Script/PlayerActor.xml b/templates/mp1/Script/PlayerActor.xml index d950d4b2..a16727e0 100644 --- a/templates/mp1/Script/PlayerActor.xml +++ b/templates/mp1/Script/PlayerActor.xml @@ -19,15 +19,7 @@ - - - - - - - - - + diff --git a/templates/mp1/Script/PlayerHint.xml b/templates/mp1/Script/PlayerHint.xml index 4d16381f..3653b236 100644 --- a/templates/mp1/Script/PlayerHint.xml +++ b/templates/mp1/Script/PlayerHint.xml @@ -6,7 +6,7 @@ - + diff --git a/templates/mp1/Script/Ridley.xml b/templates/mp1/Script/Ridley.xml index 66fa8105..3c55da85 100644 --- a/templates/mp1/Script/Ridley.xml +++ b/templates/mp1/Script/Ridley.xml @@ -27,37 +27,17 @@ - - - - - - - - - - - - - - - - - - - - - + - + - + - + diff --git a/templates/mp1/Script/RumbleEffect.xml b/templates/mp1/Script/RumbleEffect.xml index 2ed5ec73..eec06409 100644 --- a/templates/mp1/Script/RumbleEffect.xml +++ b/templates/mp1/Script/RumbleEffect.xml @@ -7,12 +7,7 @@ - - - - - - + diff --git a/templates/mp1/Script/ScriptBeam.xml b/templates/mp1/Script/ScriptBeam.xml index 5354c34f..b94d8096 100644 --- a/templates/mp1/Script/ScriptBeam.xml +++ b/templates/mp1/Script/ScriptBeam.xml @@ -7,26 +7,7 @@ - - - - - - - - - - - - - - - - - - - - + diff --git a/templates/mp1/Script/SpecialFunction.xml b/templates/mp1/Script/SpecialFunction.xml index 979f954e..40dcebba 100644 --- a/templates/mp1/Script/SpecialFunction.xml +++ b/templates/mp1/Script/SpecialFunction.xml @@ -46,12 +46,7 @@ - - - - - - + diff --git a/templates/mp1/Script/SpindleCamera.xml b/templates/mp1/Script/SpindleCamera.xml index 0431e0c1..1025dd13 100644 --- a/templates/mp1/Script/SpindleCamera.xml +++ b/templates/mp1/Script/SpindleCamera.xml @@ -6,26 +6,26 @@ - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/templates/mp1/Script/Steam.xml b/templates/mp1/Script/Steam.xml index 22f9de2c..a8424eb7 100644 --- a/templates/mp1/Script/Steam.xml +++ b/templates/mp1/Script/Steam.xml @@ -10,18 +10,8 @@ - - - - - - - - - - - - + + diff --git a/templates/mp1/Script/Water.xml b/templates/mp1/Script/Water.xml index 5703a1f7..1187637c 100644 --- a/templates/mp1/Script/Water.xml +++ b/templates/mp1/Script/Water.xml @@ -24,15 +24,7 @@ - - - - - - - - - + diff --git a/templates/mp1/Structs/BeamCombos.xml b/templates/mp1/Structs/BeamCombos.xml new file mode 100644 index 00000000..a3ec653a --- /dev/null +++ b/templates/mp1/Structs/BeamCombos.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/templates/mp1/Structs/BoolFloat 1.xml b/templates/mp1/Structs/BoolFloat 1.xml new file mode 100644 index 00000000..83927340 --- /dev/null +++ b/templates/mp1/Structs/BoolFloat 1.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/templates/mp1/Structs/BoolFloat 2.xml b/templates/mp1/Structs/BoolFloat 2.xml new file mode 100644 index 00000000..9b3d0cea --- /dev/null +++ b/templates/mp1/Structs/BoolFloat 2.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/templates/mp1/Structs/BoolFloat 3.xml b/templates/mp1/Structs/BoolFloat 3.xml new file mode 100644 index 00000000..463dd9e7 --- /dev/null +++ b/templates/mp1/Structs/BoolFloat 3.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/templates/mp1/Structs/BoolFloat 4.xml b/templates/mp1/Structs/BoolFloat 4.xml new file mode 100644 index 00000000..843b1793 --- /dev/null +++ b/templates/mp1/Structs/BoolFloat 4.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/templates/mp1/Structs/BoolFloat 5.xml b/templates/mp1/Structs/BoolFloat 5.xml new file mode 100644 index 00000000..57b89be0 --- /dev/null +++ b/templates/mp1/Structs/BoolFloat 5.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/templates/mp1/Structs/BoolFloat 6.xml b/templates/mp1/Structs/BoolFloat 6.xml new file mode 100644 index 00000000..0865785b --- /dev/null +++ b/templates/mp1/Structs/BoolFloat 6.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/templates/mp1/Structs/BoolFloat 7.xml b/templates/mp1/Structs/BoolFloat 7.xml new file mode 100644 index 00000000..fccd431d --- /dev/null +++ b/templates/mp1/Structs/BoolFloat 7.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/templates/mp1/Structs/BoolFloat 8.xml b/templates/mp1/Structs/BoolFloat 8.xml new file mode 100644 index 00000000..1255d25e --- /dev/null +++ b/templates/mp1/Structs/BoolFloat 8.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/templates/mp1/Structs/BoolVec3f 1.xml b/templates/mp1/Structs/BoolVec3f 1.xml new file mode 100644 index 00000000..e67b84a0 --- /dev/null +++ b/templates/mp1/Structs/BoolVec3f 1.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/templates/mp1/Structs/BoolVec3f 2.xml b/templates/mp1/Structs/BoolVec3f 2.xml new file mode 100644 index 00000000..0010251c --- /dev/null +++ b/templates/mp1/Structs/BoolVec3f 2.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/templates/mp1/Structs/ChargedBeams.xml b/templates/mp1/Structs/ChargedBeams.xml new file mode 100644 index 00000000..2a2d36ca --- /dev/null +++ b/templates/mp1/Structs/ChargedBeams.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/templates/mp1/Structs/DamageVulnerability.xml b/templates/mp1/Structs/DamageVulnerability.xml index e2a5f547..90918d5e 100644 --- a/templates/mp1/Structs/DamageVulnerability.xml +++ b/templates/mp1/Structs/DamageVulnerability.xml @@ -17,23 +17,7 @@ - - - - - - - - - - - - - - - - - - + + diff --git a/templates/mp1/Structs/FluidUVMotion.xml b/templates/mp1/Structs/FluidUVMotion.xml new file mode 100644 index 00000000..37921c57 --- /dev/null +++ b/templates/mp1/Structs/FluidUVMotion.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/templates/mp1/Structs/LayerSwitch.xml b/templates/mp1/Structs/LayerSwitch.xml new file mode 100644 index 00000000..8b0d25f1 --- /dev/null +++ b/templates/mp1/Structs/LayerSwitch.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/templates/mp1/Structs/LongBool.xml b/templates/mp1/Structs/LongBool.xml new file mode 100644 index 00000000..0905297f --- /dev/null +++ b/templates/mp1/Structs/LongBool.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/templates/mp1/Structs/MP1-CameraHintStruct.xml b/templates/mp1/Structs/MP1-CameraHintStruct.xml new file mode 100644 index 00000000..562a5740 --- /dev/null +++ b/templates/mp1/Structs/MP1-CameraHintStruct.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/mp1/Structs/MP1-GuessStruct 1.xml b/templates/mp1/Structs/MP1-GuessStruct 1.xml new file mode 100644 index 00000000..bb122245 --- /dev/null +++ b/templates/mp1/Structs/MP1-GuessStruct 1.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/templates/mp1/Structs/MP1-GuessStruct 2.xml b/templates/mp1/Structs/MP1-GuessStruct 2.xml new file mode 100644 index 00000000..0a494f91 --- /dev/null +++ b/templates/mp1/Structs/MP1-GuessStruct 2.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/templates/mp1/Structs/MP1-GuessStruct.xml b/templates/mp1/Structs/MP1-GuessStruct.xml new file mode 100644 index 00000000..a664e20a --- /dev/null +++ b/templates/mp1/Structs/MP1-GuessStruct.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/templates/mp1/Structs/MP1-MagdoliteStruct.xml b/templates/mp1/Structs/MP1-MagdoliteStruct.xml new file mode 100644 index 00000000..88660f64 --- /dev/null +++ b/templates/mp1/Structs/MP1-MagdoliteStruct.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/templates/mp1/Structs/MP1-MassivePrimeStruct.xml b/templates/mp1/Structs/MP1-MassivePrimeStruct.xml new file mode 100644 index 00000000..326976e1 --- /dev/null +++ b/templates/mp1/Structs/MP1-MassivePrimeStruct.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/mp1/Structs/MP1-NewCameraShakerStruct 1.xml b/templates/mp1/Structs/MP1-NewCameraShakerStruct 1.xml new file mode 100644 index 00000000..9e134d4d --- /dev/null +++ b/templates/mp1/Structs/MP1-NewCameraShakerStruct 1.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/templates/mp1/Structs/MP1-NewCameraShakerStruct 2.xml b/templates/mp1/Structs/MP1-NewCameraShakerStruct 2.xml new file mode 100644 index 00000000..94f633a2 --- /dev/null +++ b/templates/mp1/Structs/MP1-NewCameraShakerStruct 2.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/templates/mp1/Structs/MP1-NewCameraShakerStruct 3.xml b/templates/mp1/Structs/MP1-NewCameraShakerStruct 3.xml new file mode 100644 index 00000000..197ca3c6 --- /dev/null +++ b/templates/mp1/Structs/MP1-NewCameraShakerStruct 3.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/templates/mp1/Structs/MP1-PathCameraStruct.xml b/templates/mp1/Structs/MP1-PathCameraStruct.xml new file mode 100644 index 00000000..3b6ea8a0 --- /dev/null +++ b/templates/mp1/Structs/MP1-PathCameraStruct.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/templates/mp1/Structs/MP1-PlayerActorStruct.xml b/templates/mp1/Structs/MP1-PlayerActorStruct.xml new file mode 100644 index 00000000..921aac74 --- /dev/null +++ b/templates/mp1/Structs/MP1-PlayerActorStruct.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/templates/mp1/Structs/MP1-PlayerHintStruct.xml b/templates/mp1/Structs/MP1-PlayerHintStruct.xml new file mode 100644 index 00000000..ce4ba468 --- /dev/null +++ b/templates/mp1/Structs/MP1-PlayerHintStruct.xml @@ -0,0 +1,26 @@ + + + + + + Inverts morph ball controls? + + + + + Affects Spider Ball controls in some situations. + + + + + + + + + + + + On state Play, send a Play message to the target object. + + + diff --git a/templates/mp1/Structs/MP1-PrimeStruct1.xml b/templates/mp1/Structs/MP1-PrimeStruct1.xml new file mode 100644 index 00000000..e9111c08 --- /dev/null +++ b/templates/mp1/Structs/MP1-PrimeStruct1.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/templates/mp1/Structs/MP1-PrimeStruct2.xml b/templates/mp1/Structs/MP1-PrimeStruct2.xml new file mode 100644 index 00000000..d93e9440 --- /dev/null +++ b/templates/mp1/Structs/MP1-PrimeStruct2.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/templates/mp1/Structs/MP1-PrimeStruct3.xml b/templates/mp1/Structs/MP1-PrimeStruct3.xml new file mode 100644 index 00000000..6052af26 --- /dev/null +++ b/templates/mp1/Structs/MP1-PrimeStruct3.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/templates/mp1/Structs/MP1-PrimeStruct4.xml b/templates/mp1/Structs/MP1-PrimeStruct4.xml new file mode 100644 index 00000000..3869552d --- /dev/null +++ b/templates/mp1/Structs/MP1-PrimeStruct4.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/mp1/Structs/MP1-PrimeStruct5.xml b/templates/mp1/Structs/MP1-PrimeStruct5.xml new file mode 100644 index 00000000..b92c1fb4 --- /dev/null +++ b/templates/mp1/Structs/MP1-PrimeStruct5.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/templates/mp1/Structs/MP1-PrimeStruct6.xml b/templates/mp1/Structs/MP1-PrimeStruct6.xml new file mode 100644 index 00000000..322bdef3 --- /dev/null +++ b/templates/mp1/Structs/MP1-PrimeStruct6.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/templates/mp1/Structs/MP1-RidleyStruct1.xml b/templates/mp1/Structs/MP1-RidleyStruct1.xml new file mode 100644 index 00000000..5fce3f21 --- /dev/null +++ b/templates/mp1/Structs/MP1-RidleyStruct1.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/mp1/Structs/MP1-RidleyStruct2.xml b/templates/mp1/Structs/MP1-RidleyStruct2.xml new file mode 100644 index 00000000..c3e1ff42 --- /dev/null +++ b/templates/mp1/Structs/MP1-RidleyStruct2.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/templates/mp1/Structs/MP1-RumbleEffectStruct.xml b/templates/mp1/Structs/MP1-RumbleEffectStruct.xml new file mode 100644 index 00000000..f7dc3e76 --- /dev/null +++ b/templates/mp1/Structs/MP1-RumbleEffectStruct.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/templates/mp1/Structs/MP1-ScriptBeamStruct.xml b/templates/mp1/Structs/MP1-ScriptBeamStruct.xml new file mode 100644 index 00000000..fcd39121 --- /dev/null +++ b/templates/mp1/Structs/MP1-ScriptBeamStruct.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/mp1/Structs/MP1-SpindleCameraStruct.xml b/templates/mp1/Structs/MP1-SpindleCameraStruct.xml new file mode 100644 index 00000000..b7658a1e --- /dev/null +++ b/templates/mp1/Structs/MP1-SpindleCameraStruct.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + +