266 lines
8.3 KiB
C
266 lines
8.3 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-2019 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 "common/PxSerialFramework.h"
|
||
|
#include "common/PxCollection.h"
|
||
|
#include "PxFoundation.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 = PxGetFoundation().getAllocatorCallback();
|
||
|
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( PxGetFoundation().getAllocatorCallback().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(); PxGetFoundation().getAllocatorCallback().deallocate(s); } }
|
||
|
|
||
|
#if !PX_DOXYGEN
|
||
|
} // namespace physx
|
||
|
#endif
|
||
|
|
||
|
/** @} */
|
||
|
#endif
|