physxCAPI/physxCDLL/include/common/PxSerializer.h
2023-08-11 10:55:58 +08:00

264 lines
8.5 KiB
C++

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2023 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef PX_SERIALIZER_H
#define PX_SERIALIZER_H
/** \addtogroup extensions
@{
*/
#include "foundation/PxAssert.h"
#include "foundation/PxAllocatorCallback.h"
#include "foundation/PxFoundation.h"
#include "common/PxSerialFramework.h"
#include "common/PxCollection.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
/**
\brief Serialization interface class.
PxSerializer is used to extend serializable PxBase classes with serialization functionality. The
interface is structured such that per-class adapter instances can be used as opposed to per-object
adapter instances, avoiding per object allocations. Hence the methods take a reference to PxBase as a parameter.
The PxSerializer interface needs to be implemented for binary or RepX serialization to work on custom
types. If only RepX serialization is needed, some methods can be left empty, as they are only needed
for binary serialization.
A default implementation is available as a template adapter (PxSerializerDefaultAdapter).
@see PxSerializerDefaultAdapter, PX_NEW_SERIALIZER_ADAPTER, PxSerializationRegistry::registerSerializer
*/
class PxSerializer
{
public:
/**********************************************************************************************************************/
/** @name Basics needed for Binary- and RepX-Serialization
*/
//@{
/**
\brief Returns string name of dynamic type.
\return Class name of most derived type of this object.
*/
virtual const char* getConcreteTypeName() const = 0;
/**
\brief Adds required objects to the collection.
This method does not add the required objects recursively, e.g. objects required by required objects.
@see PxCollection, PxSerialization::complete
*/
virtual void requiresObjects(PxBase&, PxProcessPxBaseCallback&) const = 0;
/**
\brief Whether the object is subordinate.
A class is subordinate, if it can only be instantiated in the context of another class.
\return Whether the class is subordinate
@see PxSerialization::isSerializable
*/
virtual bool isSubordinate() const = 0;
//@}
/**********************************************************************************************************************/
/**********************************************************************************************************************/
/** @name Functionality needed for Binary Serialization only
*/
//@{
/**
\brief Exports object's extra data to stream.
*/
virtual void exportExtraData(PxBase&, PxSerializationContext&) const = 0;
/**
\brief Exports object's data to stream.
*/
virtual void exportData(PxBase&, PxSerializationContext&) const = 0;
/**
\brief Register references that the object maintains to other objects.
*/
virtual void registerReferences(PxBase& obj, PxSerializationContext& s) const = 0;
/**
\brief Returns size needed to create the class instance.
\return sizeof class instance.
*/
virtual size_t getClassSize() const = 0;
/**
\brief Create object at a given address, resolve references and import extra data.
\param address Location at which object is created. Address is increased by the size of the created object.
\param context Context for reading external data and resolving references.
\return Created PxBase pointer (needs to be identical to address before increment).
*/
virtual PxBase* createObject(PxU8*& address, PxDeserializationContext& context) const = 0;
//@}
/**********************************************************************************************************************/
virtual ~PxSerializer() {}
};
/**
\brief Default PxSerializer implementation.
*/
template<class T>
class PxSerializerDefaultAdapter : public PxSerializer
{
public:
/************************************************************************************************/
/** @name Basics needed for Binary- and RepX-Serialization
*/
//@{
PxSerializerDefaultAdapter(const char* name) : mTypeName(name){}
virtual const char* getConcreteTypeName() const
{
return mTypeName;
}
virtual void requiresObjects(PxBase& obj, PxProcessPxBaseCallback& c) const
{
T& t = static_cast<T&>(obj);
t.requiresObjects(c);
}
virtual bool isSubordinate() const
{
return false;
}
//@}
/************************************************************************************************/
/** @name Functionality needed for Binary Serialization only
*/
//@{
// object methods
virtual void exportExtraData(PxBase& obj, PxSerializationContext& s) const
{
T& t = static_cast<T&>(obj);
t.exportExtraData(s);
}
virtual void exportData(PxBase& obj, PxSerializationContext& s) const
{
PxAllocatorCallback& allocator = *PxGetAllocatorCallback();
T* copy = reinterpret_cast<T*>(allocator.allocate(sizeof(T), "TmpAllocExportData", __FILE__, __LINE__));
PxMemCopy(copy, &obj, sizeof(T));
copy->preExportDataReset();
s.writeData(copy, sizeof(T));
allocator.deallocate(copy);
}
virtual void registerReferences(PxBase& obj, PxSerializationContext& s) const
{
T& t = static_cast<T&>(obj);
s.registerReference(obj, PX_SERIAL_REF_KIND_PXBASE, size_t(&obj));
struct RequiresCallback : public PxProcessPxBaseCallback
{
RequiresCallback(PxSerializationContext& c) : context(c) {}
RequiresCallback& operator=(RequiresCallback&) { PX_ASSERT(0); return *this; }
void process(physx::PxBase& base)
{
context.registerReference(base, PX_SERIAL_REF_KIND_PXBASE, size_t(&base));
}
PxSerializationContext& context;
};
RequiresCallback callback(s);
t.requiresObjects(callback);
}
// class methods
virtual size_t getClassSize() const
{
return sizeof(T);
}
virtual PxBase* createObject(PxU8*& address, PxDeserializationContext& context) const
{
return T::createObject(address, context);
}
//@}
/************************************************************************************************/
private:
const char* mTypeName;
};
/**
\brief Preprocessor Macro to simplify adapter creation.
Note: that the allocator used for creation needs to match with the one used in PX_DELETE_SERIALIZER_ADAPTER.
*/
#define PX_NEW_SERIALIZER_ADAPTER(x) \
*new( PxGetAllocatorCallback()->allocate(sizeof(PxSerializerDefaultAdapter<x>), \
"PxSerializerDefaultAdapter", __FILE__, __LINE__ )) PxSerializerDefaultAdapter<x>(#x)
/**
\brief Preprocessor Macro to simplify adapter deletion.
*/
#define PX_DELETE_SERIALIZER_ADAPTER(x) \
{ PxSerializer* s = x; if (s) { s->~PxSerializer(); PxGetAllocatorCallback()->deallocate(s); } }
#if !PX_DOXYGEN
} // namespace physx
#endif
/** @} */
#endif