diff --git a/Engine/source/T3D/convexShape.cpp b/Engine/source/T3D/convexShape.cpp index 90bb2bc040..92ad9219df 100644 --- a/Engine/source/T3D/convexShape.cpp +++ b/Engine/source/T3D/convexShape.cpp @@ -2159,3 +2159,119 @@ void ConvexShape::Geometry::generate(const Vector< PlaneF > &planes, const Vecto faces.push_back( newFace ); } } + +static StringTableEntry surfacesCustomNodeName = StringTable->insert("Surfaces"); +static StringTableEntry surfaceNodeName = StringTable->insert("Surface"); +static StringTableEntry surfaceQuatName = StringTable->insert("Rotation"); +static StringTableEntry surfacePositionName = StringTable->insert("Position"); + +void ConvexShape::onTamlCustomWrite(TamlCustomNodes& customNodes) +{ + // Debug Profiling. + PROFILE_SCOPE(ConvexShape_OnTamlCustomWrite); + + // Call parent. + Parent::onTamlCustomWrite(customNodes); + + if (mSurfaces.size() > 0) + { + // Add cell custom node. + TamlCustomNode* pCustomCellNodes = customNodes.addNode(surfacesCustomNodeName); + + // Iterate explicit frames. + for (Vector::iterator surfaceItr = mSurfaces.begin(); surfaceItr != mSurfaces.end(); ++surfaceItr) + { + QuatF quat(*surfaceItr); + Point3F pos = surfaceItr->getPosition(); + // Add cell alias. + TamlCustomNode* pNode = pCustomCellNodes->addNode(surfaceNodeName); + + AngAxisF axis(quat); + + // Add cell properties. + pNode->addField(surfaceQuatName, axis); + pNode->addField(surfacePositionName, pos); + } + } +} + +void ConvexShape::onTamlCustomRead(const TamlCustomNodes& customNodes) +{ + // Debug Profiling. + PROFILE_SCOPE(ConvexShape_OnTamlCustomRead); + + // Call parent. + Parent::onTamlCustomRead(customNodes); + + // Find cell custom node. + const TamlCustomNode* pCustomCellNodes = customNodes.findNode(surfacesCustomNodeName); + + // Continue if we have explicit cells. + if (pCustomCellNodes != NULL) + { + mSurfaces.clear(); + + // Fetch children cell nodes. + const TamlCustomNodeVector& cellNodes = pCustomCellNodes->getChildren(); + + // Iterate cells. + for (TamlCustomNodeVector::const_iterator cellNodeItr = cellNodes.begin(); cellNodeItr != cellNodes.end(); ++cellNodeItr) + { + // Fetch cell node. + TamlCustomNode* pCellNode = *cellNodeItr; + + // Fetch node name. + StringTableEntry nodeName = pCellNode->getNodeName(); + + // Is this a valid alias? + if (nodeName != surfaceNodeName) + { + // No, so warn. + Con::warnf("ConvexShape::onTamlCustomRead() - Encountered an unknown custom name of '%s'. Only '%s' is valid.", nodeName, surfaceNodeName); + continue; + } + + QuatF quat; + Point3F pos; + + // Fetch fields. + const TamlCustomFieldVector& fields = pCellNode->getFields(); + + // Iterate property fields. + for (TamlCustomFieldVector::const_iterator fieldItr = fields.begin(); fieldItr != fields.end(); ++fieldItr) + { + // Fetch field. + const TamlCustomField* pField = *fieldItr; + + // Fetch field name. + StringTableEntry fieldName = pField->getFieldName(); + + // Check common fields. + if (fieldName == surfaceQuatName) + { + AngAxisF axis; + pField->getFieldValue(axis); + quat = QuatF(axis); + } + else if (fieldName == surfacePositionName) + { + pField->getFieldValue(pos); + } + else + { + // Unknown name so warn. + Con::warnf("MeshRoad::onTamlCustomRead() - Encountered an unknown custom field name of '%s'.", fieldName); + continue; + } + } + + MatrixF surface; + quat.setMatrix(&surface); + surface.setPosition(pos); + + mSurfaces.push_back(surface); + } + _updateGeometry(true); + setMaskBits(UpdateMask); + } +} diff --git a/Engine/source/T3D/convexShape.h b/Engine/source/T3D/convexShape.h index 3bbd2e6579..66e5804afa 100644 --- a/Engine/source/T3D/convexShape.h +++ b/Engine/source/T3D/convexShape.h @@ -199,6 +199,12 @@ class ConvexShape : public SceneObject virtual void writeFields(Stream &stream, U32 tabStop); virtual bool writeField( StringTableEntry fieldname, const char *value ); + /// Called during the writing of the object to allow custom properties to be written. + virtual void onTamlCustomWrite(TamlCustomNodes& customNodes); + + /// Called during the reading of the object to allow custom properties to be read. + virtual void onTamlCustomRead(const TamlCustomNodes& customNodes); + // NetObject virtual U32 packUpdate( NetConnection *conn, U32 mask, BitStream *stream ); virtual void unpackUpdate( NetConnection *conn, BitStream *stream ); diff --git a/Engine/source/assets/assetBase.h b/Engine/source/assets/assetBase.h index f127c83ccf..d5421d6e50 100644 --- a/Engine/source/assets/assetBase.h +++ b/Engine/source/assets/assetBase.h @@ -120,23 +120,23 @@ class AssetBase : public SimObject protected: static bool setAssetName(void *obj, const char *array, const char *data) { static_cast(obj)->setAssetName(data); return false; } static const char* getAssetName(void* obj, const char* data) { return static_cast(obj)->getAssetName(); } - static bool writeAssetName(void* obj, StringTableEntry pFieldName) { return static_cast(obj)->getAssetName() != StringTable->EmptyString(); } + static bool writeAssetName(void* obj, const char* idx, StringTableEntry pFieldName) { return static_cast(obj)->getAssetName() != StringTable->EmptyString(); } static bool setAssetDescription(void *obj, const char *array, const char *data) { static_cast(obj)->setAssetDescription(data); return false; } static const char* getAssetDescription(void* obj, const char* data) { return static_cast(obj)->getAssetDescription(); } - static bool writeAssetDescription(void* obj, StringTableEntry pFieldName) { return static_cast(obj)->getAssetDescription() != StringTable->EmptyString(); } + static bool writeAssetDescription(void* obj, const char* idx, StringTableEntry pFieldName) { return static_cast(obj)->getAssetDescription() != StringTable->EmptyString(); } static bool setAssetCategory(void *obj, const char *array, const char *data) { static_cast(obj)->setAssetCategory(data); return false; } static const char* getAssetCategory(void* obj, const char* data) { return static_cast(obj)->getAssetCategory(); } - static bool writeAssetCategory(void* obj, StringTableEntry pFieldName) { return static_cast(obj)->getAssetCategory() != StringTable->EmptyString(); } + static bool writeAssetCategory(void* obj, const char* idx, StringTableEntry pFieldName) { return static_cast(obj)->getAssetCategory() != StringTable->EmptyString(); } static bool setAssetAutoUnload(void *obj, const char *array, const char *data) { static_cast(obj)->setAssetAutoUnload(dAtob(data)); return false; } static const char* getAssetAutoUnload(void* obj, const char* data) { return Con::getBoolArg(static_cast(obj)->getAssetAutoUnload()); } - static bool writeAssetAutoUnload(void* obj, StringTableEntry pFieldName) { return static_cast(obj)->getAssetAutoUnload() == false; } + static bool writeAssetAutoUnload(void* obj, const char* idx, StringTableEntry pFieldName) { return static_cast(obj)->getAssetAutoUnload() == false; } static bool setAssetInternal(void *obj, const char *array, const char *data) { static_cast(obj)->setAssetInternal(dAtob(data)); return false; } static const char* getAssetInternal(void* obj, const char* data) { return Con::getBoolArg(static_cast(obj)->getAssetInternal()); } - static bool writeAssetInternal(void* obj, StringTableEntry pFieldName) { return static_cast(obj)->getAssetInternal() == true; } + static bool writeAssetInternal(void* obj, const char* idx, StringTableEntry pFieldName) { return static_cast(obj)->getAssetInternal() == true; } static const char* getAssetPrivate(void* obj, const char* data) { return Con::getBoolArg(static_cast(obj)->getAssetPrivate()); } diff --git a/Engine/source/assets/assetQuery.h b/Engine/source/assets/assetQuery.h index 86a7f744f8..1bd66c8aa0 100644 --- a/Engine/source/assets/assetQuery.h +++ b/Engine/source/assets/assetQuery.h @@ -57,7 +57,7 @@ class AssetQuery : public SimObject virtual void onTamlCustomRead( const TamlCustomNodes& customNodes ); static const char* getCount(void* obj, const char* data) { return Con::getIntArg(static_cast(obj)->mAssetList.size()); } - static bool writeCount( void* obj, StringTableEntry pFieldName ) { return false; } + static bool writeCount( void* obj, const char* idx, StringTableEntry pFieldName ) { return false; } public: AssetQuery() {} diff --git a/Engine/source/console/consoleObject.h b/Engine/source/console/consoleObject.h index 784e294ff6..92228c65a6 100644 --- a/Engine/source/console/consoleObject.h +++ b/Engine/source/console/consoleObject.h @@ -450,7 +450,7 @@ class AbstractClassRep : public ConsoleBaseType typedef const char *(*GetDataNotify)( void *obj, const char *data ); /// This is a function pointer typedef to support optional writing for fields. - typedef bool(*WriteDataNotify)(void* obj, StringTableEntry pFieldName); + typedef bool(*WriteDataNotify)(void* obj, const char* idx, StringTableEntry fieldName); /// These are special field type values used to mark /// groups and arrays in the field list. @@ -531,7 +531,7 @@ class AbstractClassRep : public ConsoleBaseType TypeValidator *validator; ///< Validator, if any. SetDataNotify setDataFn; ///< Set data notify Fn GetDataNotify getDataFn; ///< Get data notify Fn - WriteDataNotify writeDataFn; ///< Function to determine whether data should be written or not. + WriteDataNotify writeDataFn; ///< Function to determine whether data should be written or not. bool doNotSubstitute; bool keepClearSubsOnly; @@ -757,7 +757,7 @@ template< typename T > EnginePropertyTable& ConcreteAbstractClassRep< T >::smPro //------------------------------------------------------------------------------ // Forward declaration of this function so it can be used in the class const char *defaultProtectedGetFn( void *obj, const char *data ); -bool defaultProtectedWriteFn(void* obj, StringTableEntry pFieldName); +bool defaultProtectedWriteFn(void* obj, const char* idx, StringTableEntry fieldName); //============================================================================= // ConsoleObject. @@ -1334,7 +1334,7 @@ inline const char *emptyStringProtectedGetFn( void *obj, const char *data ) return ""; } -inline bool defaultProtectedWriteFn(void* obj, StringTableEntry pFieldName) +inline bool defaultProtectedWriteFn(void* obj, const char* idx, StringTableEntry fieldName) { return true; } @@ -1344,7 +1344,7 @@ inline bool defaultProtectedNotSetFn(void* obj, const char *array, const char* d return false; } -inline bool defaultProtectedNotWriteFn(void* obj, StringTableEntry pFieldName) +inline bool defaultProtectedNotWriteFn(void* obj, const char* idx, StringTableEntry fieldName) { return false; } diff --git a/Engine/source/console/simObject.cpp b/Engine/source/console/simObject.cpp index ea0da309c1..e8cf1d2af5 100644 --- a/Engine/source/console/simObject.cpp +++ b/Engine/source/console/simObject.cpp @@ -153,26 +153,32 @@ void SimObject::initPersistFields() addGroup( "Ungrouped" ); addProtectedField( "name", TypeName, Offset(mObjectName, SimObject), &setProtectedName, &defaultProtectedGetFn, + &PublicStringMemberWriteFn, "Optional global name of this object." ); endGroup( "Ungrouped" ); addGroup( "Object" ); - addField( "internalName", TypeString, Offset(mInternalName, SimObject), + addField( "internalName", TypeString, Offset(mInternalName, SimObject), + &PublicStringMemberWriteFn, "Optional name that may be used to lookup this object within a SimSet."); - addProtectedField( "parentGroup", TYPEID< SimObject >(), Offset(mGroup, SimObject), &setProtectedParent, &defaultProtectedGetFn, + addProtectedField( "parentGroup", TYPEID< SimObject >(), Offset(mGroup, SimObject), &setProtectedParent, &defaultProtectedGetFn, + &PublicMemberWriteFn, "Group hierarchy parent of the object." ); addProtectedField( "class", TypeString, Offset(mClassName, SimObject), &setClass, &defaultProtectedGetFn, + &PublicStringMemberWriteFn, "Script class of object." ); addProtectedField( "superClass", TypeString, Offset(mSuperClassName, SimObject), &setSuperClass, &defaultProtectedGetFn, + &PublicStringMemberWriteFn, "Script super-class of object." ); // For legacy support addProtectedField( "className", TypeString, Offset(mClassName, SimObject), &setClass, &defaultProtectedGetFn, + &PublicStringMemberWriteFn, "Script class of object.", AbstractClassRep::FIELD_HideInInspectors ); endGroup( "Object" ); @@ -180,10 +186,10 @@ void SimObject::initPersistFields() addGroup( "Editing" ); addProtectedField( "hidden", TypeBool, NULL, - &_setHidden, &_getHidden, + &_setHidden, &_getHidden, &DefaultBoolWriteFn, "Whether the object is visible." ); addProtectedField( "locked", TypeBool, NULL, - &_setLocked, &_getLocked, + &_setLocked, &_getLocked, &DefaultBoolWriteFn, "Whether the object can be edited." ); endGroup( "Editing" ); @@ -191,14 +197,15 @@ void SimObject::initPersistFields() addGroup( "Persistence" ); addProtectedField( "canSave", TypeBool, Offset( mFlags, SimObject ), - &_setCanSave, &_getCanSave, + &_setCanSave, &_getCanSave, &PublicConstMethodWriteFn, "Whether the object can be saved out. If false, the object is purely transient in nature." ); - addField( "canSaveDynamicFields", TypeBool, Offset(mCanSaveFieldDictionary, SimObject), + addField( "canSaveDynamicFields", TypeBool, Offset(mCanSaveFieldDictionary, SimObject), + &PublicMemberWriteFn, "True if dynamic fields (added at runtime) should be saved. Defaults to true." ); addProtectedField( "persistentId", TypePID, Offset( mPersistentId, SimObject ), - &_setPersistentID, &defaultProtectedGetFn, + &_setPersistentID, &defaultProtectedGetFn, &PublicMemberWriteFn, "The universally unique identifier for the object." ); endGroup( "Persistence" ); diff --git a/Engine/source/console/simObject.h b/Engine/source/console/simObject.h index 102689b417..fe0894f6a8 100644 --- a/Engine/source/console/simObject.h +++ b/Engine/source/console/simObject.h @@ -1074,4 +1074,74 @@ class SimObjectPtr : public WeakRefPtr< T > } }; +inline bool DefaultNonEmptyStringWriteFn(void *obj, const char* idx, StringTableEntry fieldName) +{ + const char* value = static_cast(obj)->getDataField(fieldName, idx); + return value != NULL && dStricmp(value, "") != 0; +} + +template +bool DefaultValueWriteFn(void* obj, const char* idx, StringTableEntry fieldName) +{ + const char* value = static_cast(obj)->getDataField(fieldName, idx); + return dStricmp(value, defaultValue) != 0; +} + +template +bool DefaultFloatWriteFn(void* obj, const char* idx, StringTableEntry fieldName) +{ + const char* value = static_cast(obj)->getDataField(fieldName, idx); + return dAtof(value) != dAtof(defaultValue); +} + +template +bool DefaultIntWriteFn(void* obj, const char* idx, StringTableEntry fieldName) +{ + const char* value = static_cast(obj)->getDataField(fieldName, idx); + return dAtoi(value) != defaultValue; +} + +template +bool DefaultUintWriteFn(void* obj, const char* idx, StringTableEntry fieldName) +{ + const char* value = static_cast(obj)->getDataField(fieldName, idx); + return dAtoui(value) != defaultValue; +} + +template +bool DefaultBoolWriteFn(void* obj, const char* idx, StringTableEntry fieldName) +{ + const char* value = static_cast(obj)->getDataField(fieldName, idx); + return dAtob(value) != defaultValue; +} + +template +bool PublicMemberWriteFn(void* obj, const char* idx, StringTableEntry fieldName) +{ + C* instance = static_cast(obj); + return instance->*field != defaultValue; +} + +template +bool PublicStringMemberWriteFn(void* obj, const char* idx, StringTableEntry fieldName) +{ + C* instance = static_cast(obj); + return instance->*field != NULL && dStricmp(instance->*field, StringTable->insert(defaultValue)) != 0; +} + +template +bool PublicMethodWriteFn(void* obj, const char* idx, StringTableEntry fieldName) +{ + C* instance = static_cast(obj); + return (instance->*method)() != defaultValue; +} + +template +bool PublicConstMethodWriteFn(void* obj, const char* idx, StringTableEntry fieldName) +{ + C* instance = static_cast(obj); + return (instance->*method)() != defaultValue; +} + + #endif // _SIMOBJECT_H_ diff --git a/Engine/source/environment/basicClouds.cpp b/Engine/source/environment/basicClouds.cpp index 0352c4e1ac..767e784748 100644 --- a/Engine/source/environment/basicClouds.cpp +++ b/Engine/source/environment/basicClouds.cpp @@ -165,31 +165,79 @@ void BasicClouds::onRemove() Parent::onRemove(); } +bool BasicCloudsHeightWriteFn(void* obj, const char* idx, StringTableEntry fieldName) +{ + BasicClouds* cloud = static_cast(obj); + F32 defVal; + U32 i = dAtoi(idx); + switch (i) + { + case 0: + defVal = 4.0f; + break; + case 1: + defVal = 3.0f; + break; + case 2: + defVal = 2.0f; + break; + default: + defVal = 0.0f; + } + if (dAtof(cloud->getDataField(fieldName, idx)) == defVal) + return false; + return true; +} + +bool BasicCloudsTexSpeedWriteFn(void* obj, const char* idx, StringTableEntry fieldName) +{ + BasicClouds* cloud = static_cast(obj); + F32 defVal; + U32 i = dAtoi(idx); + switch (i) + { + case 0: + defVal = 0.0005f; + break; + case 1: + defVal = 0.001f; + break; + case 2: + defVal = 0.0003f; + break; + default: + defVal = 0.0f; + } + if (dAtof(cloud->getDataField(fieldName, idx)) == defVal) + return false; + return true; +} + void BasicClouds::initPersistFields() { addGroup( "BasicClouds" ); addArray( "Layers", TEX_COUNT ); - addField( "layerEnabled", TypeBool, Offset( mLayerEnabled, BasicClouds ), TEX_COUNT, + addField( "layerEnabled", TypeBool, Offset( mLayerEnabled, BasicClouds ), &DefaultBoolWriteFn, TEX_COUNT, "Enable or disable rendering of this layer." ); addField( "texture", TypeImageFilename, Offset( mTexName, BasicClouds ), TEX_COUNT, "Texture for this layer." ); - addField( "texScale", TypeF32, Offset( mTexScale, BasicClouds ), TEX_COUNT, + addField( "texScale", TypeF32, Offset( mTexScale, BasicClouds ), &DefaultValueWriteFn<"1.0">, TEX_COUNT, "Texture repeat for this layer." ); - addField( "texDirection", TypePoint2F, Offset( mTexDirection, BasicClouds ), TEX_COUNT, + addField( "texDirection", TypePoint2F, Offset( mTexDirection, BasicClouds ), &DefaultValueWriteFn<"1 0">, TEX_COUNT, "Texture scroll direction for this layer, relative to the world axis." ); - addField( "texSpeed", TypeF32, Offset( mTexSpeed, BasicClouds ), TEX_COUNT, + addField( "texSpeed", TypeF32, Offset( mTexSpeed, BasicClouds ), &BasicCloudsTexSpeedWriteFn, TEX_COUNT, "Texture scroll speed for this layer." ); - addField( "texOffset", TypePoint2F, Offset( mTexOffset, BasicClouds ), TEX_COUNT, + addField( "texOffset", TypePoint2F, Offset( mTexOffset, BasicClouds ), &DefaultValueWriteFn<"0.5 0.5">, TEX_COUNT, "UV offset for this layer." ); - addField( "height", TypeF32, Offset( mHeight, BasicClouds ), TEX_COUNT, + addField( "height", TypeF32, Offset( mHeight, BasicClouds ), &BasicCloudsHeightWriteFn, TEX_COUNT, "Abstract number which controls the curvature and height of the dome mesh" ); endArray( "Layers" ); diff --git a/Engine/source/environment/decalRoad.cpp b/Engine/source/environment/decalRoad.cpp index 668bfcaaed..b24b2a1fe3 100644 --- a/Engine/source/environment/decalRoad.cpp +++ b/Engine/source/environment/decalRoad.cpp @@ -1708,6 +1708,117 @@ bool DecalRoad::ptSetTextureLength( void *object, const char *index, const char return false; } +static StringTableEntry nodesCustomNodeName = StringTable->insert("Nodes"); +static StringTableEntry nodeNodeName = StringTable->insert("Node"); +static StringTableEntry nodePointName = StringTable->insert("Point"); +static StringTableEntry nodeWidthName = StringTable->insert("Width"); + +void DecalRoad::onTamlCustomWrite(TamlCustomNodes& customNodes) +{ + // Debug Profiling. + PROFILE_SCOPE(DecalRoad_OnTamlCustomWrite); + + // Call parent. + Parent::onTamlCustomWrite(customNodes); + + if (mNodes.size() > 0) + { + // Add cell custom node. + TamlCustomNode* pCustomCellNodes = customNodes.addNode(nodesCustomNodeName); + + // Iterate explicit frames. + for (RoadNodeVector::iterator nodeItr = mNodes.begin(); nodeItr != mNodes.end(); ++nodeItr) + { + // Add cell alias. + TamlCustomNode* pNode = pCustomCellNodes->addNode(nodeNodeName); + + // Add cell properties. + pNode->addField(nodePointName, nodeItr->point); + pNode->addField(nodeWidthName, nodeItr->width); + } + } +} + +void DecalRoad::onTamlCustomRead(const TamlCustomNodes& customNodes) +{ + // Debug Profiling. + PROFILE_SCOPE(DecalRoad_OnTamlCustomRead); + + // Call parent. + Parent::onTamlCustomRead(customNodes); + + // Find cell custom node. + const TamlCustomNode* pCustomCellNodes = customNodes.findNode(nodesCustomNodeName); + + // Continue if we have explicit cells. + if (pCustomCellNodes != NULL) + { + // Fetch children cell nodes. + const TamlCustomNodeVector& cellNodes = pCustomCellNodes->getChildren(); + + // Iterate cells. + for (TamlCustomNodeVector::const_iterator cellNodeItr = cellNodes.begin(); cellNodeItr != cellNodes.end(); ++cellNodeItr) + { + // Fetch cell node. + TamlCustomNode* pCellNode = *cellNodeItr; + + // Fetch node name. + StringTableEntry nodeName = pCellNode->getNodeName(); + + // Is this a valid alias? + if (nodeName != nodeNodeName) + { + // No, so warn. + Con::warnf("DecalRoad::onTamlCustomRead() - Encountered an unknown custom name of '%s'. Only '%s' is valid.", nodeName, nodeNodeName); + continue; + } + + F32 depth; + VectorF normal; + Point3F point; + F32 width; + + // Fetch fields. + const TamlCustomFieldVector& fields = pCellNode->getFields(); + + // Iterate property fields. + for (TamlCustomFieldVector::const_iterator fieldItr = fields.begin(); fieldItr != fields.end(); ++fieldItr) + { + // Fetch field. + const TamlCustomField* pField = *fieldItr; + + // Fetch field name. + StringTableEntry fieldName = pField->getFieldName(); + + // Check common fields. + if (fieldName == nodePointName) + { + pField->getFieldValue(point); + } + else if (fieldName == nodeWidthName) + { + pField->getFieldValue(width); + } + else + { + // Unknown name so warn. + Con::warnf("DecalRoad::onTamlCustomRead() - Encountered an unknown custom field name of '%s'.", fieldName); + continue; + } + } + + // Is cell height valid? + if (width <= 0) + { + // No, so warn. + Con::warnf("DecalRoad::onTamlCustomRead() - Width height of '%d' is invalid or was not set.", width); + continue; + } + + _addNode(point, width); + } + } +} // ConsoleMethods diff --git a/Engine/source/environment/decalRoad.h b/Engine/source/environment/decalRoad.h index 7b0987d273..a85017095a 100644 --- a/Engine/source/environment/decalRoad.h +++ b/Engine/source/environment/decalRoad.h @@ -166,6 +166,12 @@ class DecalRoad : public SceneObject void onStaticModified(const char* slotName, const char*newValue = NULL); void writeFields(Stream &stream, U32 tabStop); bool writeField( StringTableEntry fieldname, const char *value ); + + /// Called during the writing of the object to allow custom properties to be written. + virtual void onTamlCustomWrite(TamlCustomNodes& customNodes); + + /// Called during the reading of the object to allow custom properties to be read. + virtual void onTamlCustomRead(const TamlCustomNodes& customNodes); // NetObject U32 packUpdate(NetConnection *, U32, BitStream *); diff --git a/Engine/source/environment/meshRoad.cpp b/Engine/source/environment/meshRoad.cpp index cf15ef9aba..e15e592215 100644 --- a/Engine/source/environment/meshRoad.cpp +++ b/Engine/source/environment/meshRoad.cpp @@ -56,6 +56,7 @@ #include "T3D/physics/physicsBody.h" #include "T3D/physics/physicsCollision.h" #include "environment/nodeListManager.h" +#include "persistence/taml/tamlCustom.h" #ifdef TORQUE_AFX_ENABLED #include "afx/ce/afxZodiacMgr.h" #endif @@ -3482,6 +3483,138 @@ void MeshRoad::regenerate() setMaskBits( RegenMask ); } +static StringTableEntry nodesCustomNodeName = StringTable->insert("Nodes"); +static StringTableEntry nodeNodeName = StringTable->insert("Node"); +static StringTableEntry nodeDepthName = StringTable->insert("Depth"); +static StringTableEntry nodeNormalName = StringTable->insert("Normal"); +static StringTableEntry nodePointName = StringTable->insert("Point"); +static StringTableEntry nodeWidthName = StringTable->insert("Width"); + +void MeshRoad::onTamlCustomWrite(TamlCustomNodes& customNodes) +{ + // Debug Profiling. + PROFILE_SCOPE(MeshRoad_OnTamlCustomWrite); + + // Call parent. + Parent::onTamlCustomWrite(customNodes); + + if (mNodes.size() > 0) + { + // Add cell custom node. + TamlCustomNode* pCustomCellNodes = customNodes.addNode(nodesCustomNodeName); + + // Iterate explicit frames. + for (MeshRoadNodeVector::iterator nodeItr = mNodes.begin(); nodeItr != mNodes.end(); ++nodeItr) + { + // Add cell alias. + TamlCustomNode* pNode = pCustomCellNodes->addNode(nodeNodeName); + + // Add cell properties. + pNode->addField(nodeDepthName, nodeItr->depth); + pNode->addField(nodeNormalName, nodeItr->normal); + pNode->addField(nodePointName, nodeItr->point); + pNode->addField(nodeWidthName, nodeItr->width); + } + } +} + +void MeshRoad::onTamlCustomRead(const TamlCustomNodes& customNodes) +{ + // Debug Profiling. + PROFILE_SCOPE(MeshRoad_OnTamlCustomRead); + + // Call parent. + Parent::onTamlCustomRead(customNodes); + + // Find cell custom node. + const TamlCustomNode* pCustomCellNodes = customNodes.findNode(nodesCustomNodeName); + + // Continue if we have explicit cells. + if (pCustomCellNodes != NULL) + { + // Fetch children cell nodes. + const TamlCustomNodeVector& cellNodes = pCustomCellNodes->getChildren(); + + // Iterate cells. + for (TamlCustomNodeVector::const_iterator cellNodeItr = cellNodes.begin(); cellNodeItr != cellNodes.end(); ++cellNodeItr) + { + // Fetch cell node. + TamlCustomNode* pCellNode = *cellNodeItr; + + // Fetch node name. + StringTableEntry nodeName = pCellNode->getNodeName(); + + // Is this a valid alias? + if (nodeName != nodeNodeName) + { + // No, so warn. + Con::warnf("MeshRoad::onTamlCustomRead() - Encountered an unknown custom name of '%s'. Only '%s' is valid.", nodeName, nodeNodeName); + continue; + } + + F32 depth; + VectorF normal; + Point3F point; + F32 width; + + // Fetch fields. + const TamlCustomFieldVector& fields = pCellNode->getFields(); + + // Iterate property fields. + for (TamlCustomFieldVector::const_iterator fieldItr = fields.begin(); fieldItr != fields.end(); ++fieldItr) + { + // Fetch field. + const TamlCustomField* pField = *fieldItr; + + // Fetch field name. + StringTableEntry fieldName = pField->getFieldName(); + + // Check common fields. + if (fieldName == nodeDepthName) + { + pField->getFieldValue(depth); + } + else if (fieldName == nodeNormalName) + { + pField->getFieldValue(normal); + } + else if (fieldName == nodePointName) + { + pField->getFieldValue(point); + } + else if (fieldName == nodeWidthName) + { + pField->getFieldValue(width); + } + else + { + // Unknown name so warn. + Con::warnf("MeshRoad::onTamlCustomRead() - Encountered an unknown custom field name of '%s'.", fieldName); + continue; + } + } + + // Is cell width valid? + if (depth <= 0) + { + // No, so warn. + Con::warnf("MeshRoad::onTamlCustomRead() - Depth of '%d' is invalid or was not set.", depth); + continue; + } + + // Is cell height valid? + if (width <= 0) + { + // No, so warn. + Con::warnf("MeshRoad::onTamlCustomRead() - Width height of '%d' is invalid or was not set.", width); + continue; + } + + _addNode(point, width, depth, normal); + } + } +} + //------------------------------------------------------------------------- // Console Methods //------------------------------------------------------------------------- diff --git a/Engine/source/environment/meshRoad.h b/Engine/source/environment/meshRoad.h index b817d6b8da..a817d355c4 100644 --- a/Engine/source/environment/meshRoad.h +++ b/Engine/source/environment/meshRoad.h @@ -522,6 +522,12 @@ class MeshRoad : public SceneObject void writeFields(Stream &stream, U32 tabStop); bool writeField( StringTableEntry fieldname, const char *value ); + /// Called during the writing of the object to allow custom properties to be written. + virtual void onTamlCustomWrite(TamlCustomNodes& customNodes); + + /// Called during the reading of the object to allow custom properties to be read. + virtual void onTamlCustomRead(const TamlCustomNodes& customNodes); + // NetObject U32 packUpdate(NetConnection *, U32, BitStream *); void unpackUpdate(NetConnection *, BitStream *); diff --git a/Engine/source/environment/river.cpp b/Engine/source/environment/river.cpp index 9606584f75..013824a474 100644 --- a/Engine/source/environment/river.cpp +++ b/Engine/source/environment/river.cpp @@ -2499,6 +2499,139 @@ void River::setMaxDivisionSize( F32 meters ) setMaskBits( RiverMask | RegenMask ); } +static StringTableEntry nodesCustomNodeName = StringTable->insert("Nodes"); +static StringTableEntry nodeNodeName = StringTable->insert("Node"); +static StringTableEntry nodeDepthName = StringTable->insert("Depth"); +static StringTableEntry nodeNormalName = StringTable->insert("Normal"); +static StringTableEntry nodePointName = StringTable->insert("Point"); +static StringTableEntry nodeWidthName = StringTable->insert("Width"); + +void River::onTamlCustomWrite(TamlCustomNodes& customNodes) +{ + // Debug Profiling. + PROFILE_SCOPE(River_OnTamlCustomWrite); + + // Call parent. + Parent::onTamlCustomWrite(customNodes); + + if (mNodes.size() > 0) + { + // Add cell custom node. + TamlCustomNode* pCustomCellNodes = customNodes.addNode(nodesCustomNodeName); + + // Iterate explicit frames. + for (RiverNodeVector::iterator nodeItr = mNodes.begin(); nodeItr != mNodes.end(); ++nodeItr) + { + // Add cell alias. + TamlCustomNode* pNode = pCustomCellNodes->addNode(nodeNodeName); + + // Add cell properties. + pNode->addField(nodeDepthName, nodeItr->depth); + pNode->addField(nodeNormalName, nodeItr->normal); + pNode->addField(nodePointName, nodeItr->point); + pNode->addField(nodeWidthName, nodeItr->width); + } + } +} + +void River::onTamlCustomRead(const TamlCustomNodes& customNodes) +{ + // Debug Profiling. + PROFILE_SCOPE(River_OnTamlCustomRead); + + // Call parent. + Parent::onTamlCustomRead(customNodes); + + // Find cell custom node. + const TamlCustomNode* pCustomCellNodes = customNodes.findNode(nodesCustomNodeName); + + // Continue if we have explicit cells. + if (pCustomCellNodes != NULL) + { + // Fetch children cell nodes. + const TamlCustomNodeVector& cellNodes = pCustomCellNodes->getChildren(); + + // Iterate cells. + for (TamlCustomNodeVector::const_iterator cellNodeItr = cellNodes.begin(); cellNodeItr != cellNodes.end(); ++cellNodeItr) + { + // Fetch cell node. + TamlCustomNode* pCellNode = *cellNodeItr; + + // Fetch node name. + StringTableEntry nodeName = pCellNode->getNodeName(); + + // Is this a valid alias? + if (nodeName != nodeNodeName) + { + // No, so warn. + Con::warnf("River::onTamlCustomRead() - Encountered an unknown custom name of '%s'. Only '%s' is valid.", nodeName, nodeNodeName); + continue; + } + + F32 depth; + VectorF normal; + Point3F point; + F32 width; + + // Fetch fields. + const TamlCustomFieldVector& fields = pCellNode->getFields(); + + // Iterate property fields. + for (TamlCustomFieldVector::const_iterator fieldItr = fields.begin(); fieldItr != fields.end(); ++fieldItr) + { + // Fetch field. + const TamlCustomField* pField = *fieldItr; + + // Fetch field name. + StringTableEntry fieldName = pField->getFieldName(); + + // Check common fields. + if (fieldName == nodeDepthName) + { + pField->getFieldValue(depth); + } + else if (fieldName == nodeNormalName) + { + pField->getFieldValue(normal); + } + else if (fieldName == nodePointName) + { + pField->getFieldValue(point); + } + else if (fieldName == nodeWidthName) + { + pField->getFieldValue(width); + } + else + { + // Unknown name so warn. + Con::warnf("River::onTamlCustomRead() - Encountered an unknown custom field name of '%s'.", fieldName); + continue; + } + } + + // Is cell width valid? + if (depth <= 0) + { + // No, so warn. + Con::warnf("River::onTamlCustomRead() - Depth of '%d' is invalid or was not set.", depth); + continue; + } + + // Is cell height valid? + if (width <= 0) + { + // No, so warn. + Con::warnf("River::onTamlCustomRead() - Width height of '%d' is invalid or was not set.", width); + continue; + } + + + _addNode(point, width, depth, normal); + } + } +} + //------------------------------------------------------------------------- // Console Methods //------------------------------------------------------------------------- diff --git a/Engine/source/environment/river.h b/Engine/source/environment/river.h index f912179558..efe6fb3826 100644 --- a/Engine/source/environment/river.h +++ b/Engine/source/environment/river.h @@ -394,6 +394,12 @@ class River : public WaterObject void writeFields(Stream &stream, U32 tabStop); bool writeField( StringTableEntry fieldname, const char *value ); + /// Called during the writing of the object to allow custom properties to be written. + virtual void onTamlCustomWrite(TamlCustomNodes& customNodes); + + /// Called during the reading of the object to allow custom properties to be read. + virtual void onTamlCustomRead(const TamlCustomNodes& customNodes); + // NetObject U32 packUpdate(NetConnection *, U32, BitStream *); void unpackUpdate(NetConnection *, BitStream *); diff --git a/Engine/source/module/moduleDefinition.h b/Engine/source/module/moduleDefinition.h index f26c2ae2ce..b891c04813 100644 --- a/Engine/source/module/moduleDefinition.h +++ b/Engine/source/module/moduleDefinition.h @@ -203,33 +203,33 @@ class ModuleDefinition : public SimSet static bool setModuleId(void* obj, const char* index, const char* data) { static_cast(obj)->setModuleId( data ); return false; } static bool setVersionId(void* obj, const char* index, const char* data) { static_cast(obj)->setVersionId((U32)dAtoi(data)); return false; } static bool setBuildId(void* obj, const char* index, const char* data) { static_cast(obj)->setBuildId((U32)dAtoi(data)); return false; } - static bool writeBuildId( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->getBuildId() != 0; } + static bool writeBuildId( void* obj, const char* idx, StringTableEntry pFieldName ) { return static_cast(obj)->getBuildId() != 0; } static bool setEnabled(void* obj, const char* index, const char* data) { static_cast(obj)->setEnabled(dAtob(data)); return false; } - static bool writeEnabled( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->getEnabled() == false; } + static bool writeEnabled( void* obj, const char* idx, StringTableEntry pFieldName ) { return static_cast(obj)->getEnabled() == false; } static bool setSynchronized(void* obj, const char* index, const char* data) { static_cast(obj)->setSynchronized(dAtob(data)); return false; } - static bool writeSynchronized( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->getSynchronized() == true; } + static bool writeSynchronized( void* obj, const char* idx, StringTableEntry pFieldName ) { return static_cast(obj)->getSynchronized() == true; } static bool setDeprecated(void* obj, const char* index, const char* data) { static_cast(obj)->setDeprecated(dAtob(data)); return false; } - static bool writeDeprecated( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->getDeprecated() == true; } - static bool writeCriticalMerge( void* obj, StringTableEntry pFieldName ){ return static_cast(obj)->getCriticalMerge() == true; } + static bool writeDeprecated( void* obj, const char* idx, StringTableEntry pFieldName ) { return static_cast(obj)->getDeprecated() == true; } + static bool writeCriticalMerge( void* obj, const char* idx, StringTableEntry pFieldName ){ return static_cast(obj)->getCriticalMerge() == true; } static bool setOverrideExistingObjects(void* obj, const char* index, const char* data) { static_cast(obj)->setOverrideExistingObjects(dAtob(data)); return false; } - static bool writeOverrideExistingObjects(void* obj, StringTableEntry pFieldName) { return static_cast(obj)->getOverrideExistingObjects() == true; } + static bool writeOverrideExistingObjects(void* obj, const char* idx, StringTableEntry pFieldName) { return static_cast(obj)->getOverrideExistingObjects() == true; } static bool setModuleDescription(void* obj, const char* index, const char* data) { static_cast(obj)->setModuleDescription(data); return false; } - static bool writeModuleDescription( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->getModuleDescription() != StringTable->EmptyString(); } + static bool writeModuleDescription( void* obj, const char* idx, StringTableEntry pFieldName ) { return static_cast(obj)->getModuleDescription() != StringTable->EmptyString(); } static bool setAuthor(void* obj, const char* index, const char* data) { static_cast(obj)->setAuthor(data); return false; } - static bool writeAuthor(void* obj, StringTableEntry pFieldName) { return static_cast(obj)->getAuthor() != StringTable->EmptyString(); } + static bool writeAuthor(void* obj, const char* idx, StringTableEntry pFieldName) { return static_cast(obj)->getAuthor() != StringTable->EmptyString(); } static bool setModuleGroup(void* obj, const char* index, const char* data) { static_cast(obj)->setModuleGroup(data); return false; } static bool setModuleType(void* obj, const char* index, const char* data) { static_cast(obj)->setModuleType(data); return false; } - static bool writeModuleType(void* obj, StringTableEntry pFieldName) { return static_cast(obj)->getModuleType() != StringTable->EmptyString(); } + static bool writeModuleType(void* obj, const char* idx, StringTableEntry pFieldName) { return static_cast(obj)->getModuleType() != StringTable->EmptyString(); } static bool setScriptFile(void* obj, const char* index, const char* data) { static_cast(obj)->setScriptFile(data); return false; } - static bool writeScriptFile(void* obj, StringTableEntry pFieldName) { return static_cast(obj)->getScriptFile() != StringTable->EmptyString(); } + static bool writeScriptFile(void* obj, const char* idx, StringTableEntry pFieldName) { return static_cast(obj)->getScriptFile() != StringTable->EmptyString(); } static bool setCreateFunction(void* obj, const char* index, const char* data) { static_cast(obj)->setCreateFunction(data); return false; } - static bool writeCreateFunction(void* obj, StringTableEntry pFieldName) { return static_cast(obj)->getCreateFunction() != StringTable->EmptyString(); } + static bool writeCreateFunction(void* obj, const char* idx, StringTableEntry pFieldName) { return static_cast(obj)->getCreateFunction() != StringTable->EmptyString(); } static bool setDestroyFunction(void* obj, const char* index, const char* data) { static_cast(obj)->setDestroyFunction(data); return false; } - static bool writeDestroyFunction(void* obj, StringTableEntry pFieldName) { return static_cast(obj)->getDestroyFunction() != StringTable->EmptyString(); } + static bool writeDestroyFunction(void* obj, const char* idx, StringTableEntry pFieldName) { return static_cast(obj)->getDestroyFunction() != StringTable->EmptyString(); } /// Asset manifest. static bool setAssetTagsManifest(void* obj, const char* index, const char* data) { static_cast(obj)->setAssetTagsManifest(data); return false; } - static bool writeAssetTagsManifest(void* obj, StringTableEntry pFieldName) { return static_cast(obj)->getAssetTagsManifest() != StringTable->EmptyString(); } + static bool writeAssetTagsManifest(void* obj, const char* idx, StringTableEntry pFieldName) { return static_cast(obj)->getAssetTagsManifest() != StringTable->EmptyString(); } static const char* getScopeSet(void* obj, const char* data) { return Con::getIntArg(static_cast(obj)->getScopeSet()); } static bool setDependencies(void* obj, const char* index, const char* data) @@ -328,7 +328,7 @@ class ModuleDefinition : public SimSet return pReturnBuffer; } - static bool writeDependencies( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->getDependencies().size() > 0; } + static bool writeDependencies( void* obj, const char* idx, StringTableEntry pFieldName ) { return static_cast(obj)->getDependencies().size() > 0; } static const char* getSignature(void* obj, const char* data) { return static_cast(obj)->getSignature(); } }; diff --git a/Engine/source/persistence/taml/taml.cpp b/Engine/source/persistence/taml/taml.cpp index b8390a70ca..a41df43a8e 100644 --- a/Engine/source/persistence/taml/taml.cpp +++ b/Engine/source/persistence/taml/taml.cpp @@ -689,7 +689,7 @@ ImplementEnumType(_TamlFormatMode, // For now, we only deal with non-array fields. if (elementCount == 1 && pField->setDataFn != NULL && - (!getWriteDefaults() && pField->writeDataFn(pSimObject, fieldName) == false)) + (!getWriteDefaults() && pField->writeDataFn(pSimObject, NULL, fieldName) == false)) continue; // Iterate elements.