/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #pragma once #include #include #include #include #include #include #include #include #include #include namespace AZStd { /** * Intrusive ptr for EMotionFX-owned objects (uses EMotionFX's internal ref-counting MCore::Destroy()). */ template<> struct IntrusivePtrCountPolicy { static AZ_FORCE_INLINE void add_ref(MCore::MemoryObject* ptr) { ptr->IncreaseReferenceCount(); } static AZ_FORCE_INLINE void release(MCore::MemoryObject* ptr) { MCore::Destroy(ptr); // Calls DecreaseReferenceCount. } }; } namespace EMotionFX { namespace Integration { /** * System allocator to be used for all EMotionFX and EMotionFXAnimation gem persistent allocations. */ class EMotionFXAllocator : public AZ::SimpleSchemaAllocator> { public: AZ_TYPE_INFO(EMotionFXAllocator, "{00AEC34F-4A00-4ECB-BC9C-7221E76337D6}"); using Base = AZ::SimpleSchemaAllocator>; using Descriptor = Base::Descriptor; EMotionFXAllocator() : Base("EMotion FX System Allocator", "EMotion FX general memory allocator") { } }; /** * Intrusive ptr for EMotionFX-owned objects. * Uses EMotionFX's internal ref-counting. */ template class EMotionFXPtr { public: /// Use only to initialize a new EMotionFXPtr<> given an EMotionFX SDK object not currently owned by an EMotionFXPtr<>. /// This is generally only appropriate for use when an EMotionFX object has just been constructed. static EMotionFXPtr MakeFromNew(ObjectType* object) { AZ_Assert(object, "CreateFromNew called with invalid object."); AZ_Assert(object && object->GetReferenceCount() == 1, "Newly constructed EMotion FX objects are expected to have a referene count initialized to 1."); // EMotionFX initializes objects with a ref count already at 1. So for newly-constructed objects that we're // managing through smart pointers, it's not necessary to increment ref count during initial acquisition. EMotionFXPtr ptr; ptr.m_ptr = object; return ptr; } AZ_FORCE_INLINE explicit EMotionFXPtr(ObjectType* object = nullptr) { *this = object; } AZ_FORCE_INLINE EMotionFXPtr(const EMotionFXPtr& rhs) { *this = rhs; } AZ_FORCE_INLINE ~EMotionFXPtr() { if (m_ptr) { MCore::Destroy(m_ptr); // Calls DecreaseReferenceCount. } } AZ_FORCE_INLINE void reset(ObjectType* object = nullptr) { *this = object; } AZ_FORCE_INLINE void operator=(ObjectType* object) { if (m_ptr) { MCore::Destroy(m_ptr); // Calls DecreaseReferenceCount. m_ptr = nullptr; } m_ptr = object; if (m_ptr) { m_ptr->IncreaseReferenceCount(); } } AZ_FORCE_INLINE void operator=(const EMotionFXPtr& rhs) { reset(rhs ? rhs.get() : nullptr); } AZ_FORCE_INLINE ObjectType* operator ->() const { AZ_Assert(m_ptr, "Attempting to dereference a null EMotion FX object pointer."); return m_ptr; } AZ_FORCE_INLINE ObjectType* get() const { return m_ptr; } AZ_FORCE_INLINE operator bool() const { return m_ptr != nullptr; } AZ_FORCE_INLINE bool operator==(const EMotionFXPtr& rhs) const { return (m_ptr == rhs.m_ptr); } AZ_FORCE_INLINE bool operator==(const ObjectType* rhs) const { return (m_ptr == rhs); } AZ_FORCE_INLINE bool operator!=(const EMotionFXPtr& rhs) const { return !(m_ptr == rhs.m_ptr); } AZ_FORCE_INLINE bool operator!=(const ObjectType* rhs) const { return !(m_ptr == rhs); } private: ObjectType* m_ptr = nullptr; }; /** * EMotionFX memory hooks */ AZ_FORCE_INLINE void* EMotionFXAlloc(size_t numBytes, AZ::u16 categoryID, AZ::u16 blockID, const char* filename, AZ::u32 lineNr) { (void)categoryID; (void)blockID; (void)lineNr; return AZ::AllocatorInstance::Get().Allocate(numBytes, 8, 0, "EMotionFX", filename, lineNr); } AZ_FORCE_INLINE void* EMotionFXRealloc(void* memory, size_t numBytes, AZ::u16 categoryID, AZ::u16 blockID, const char* filename, AZ::u32 lineNr) { (void)categoryID; (void)blockID; (void)filename; (void)lineNr; return AZ::AllocatorInstance::Get().ReAllocate(memory, numBytes, 8); } AZ_FORCE_INLINE void EMotionFXFree(void* memory) { AZ::AllocatorInstance::Get().DeAllocate(memory); } } //namespace Integration } // namespace EMotionFX