From f90074adb6e78addc635667c97b2c8bd7ca0a2a3 Mon Sep 17 00:00:00 2001 From: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> Date: Wed, 27 Oct 2021 15:54:03 -0700 Subject: [PATCH] [profiler_capture_api] added utility for reflecting AZ::Interfaces through the BehaviorContext Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- .../AzCore/RTTI/BehaviorInterfaceProxy.h | 122 ++++++++++++++++++ .../AzCore/AzCore/azcore_files.cmake | 1 + 2 files changed, 123 insertions(+) create mode 100644 Code/Framework/AzCore/AzCore/RTTI/BehaviorInterfaceProxy.h diff --git a/Code/Framework/AzCore/AzCore/RTTI/BehaviorInterfaceProxy.h b/Code/Framework/AzCore/AzCore/RTTI/BehaviorInterfaceProxy.h new file mode 100644 index 0000000000..430524d3a2 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/RTTI/BehaviorInterfaceProxy.h @@ -0,0 +1,122 @@ +/* + * 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 + * + */ + +#include +#include +#include +#include +#include + +namespace AZ +{ + /** + * Utility class for reflecting an AZ::Interface through the BehaviorContext + * + * Example: + * + * class MyInterface + * { + * public: + * AZ_RTTI(MyInterface, "{BADDF000D-CDCD-CDCD-CDCD-BAAAADF0000D}"); + * virtual ~MyInterface() = default; + * + * virtual AZStd::string Foo() = 0; + * virtual void Bar(float x, float y) = 0; + * }; + * + * class MySystemProxy + * : public BehaviorInterfaceProxy + * { + * public: + * AZ_RTTI(MySystemProxy, "{CDCDCDCD-BAAD-BADD-F00D-CDCDCDCDCDCD}", BehaviorInterfaceProxy); + * }; + * + * void Reflect(AZ::ReflectContext* context) + * { + * if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) + * { + * behaviorContext->ConstantProperty("g_MySystem", MySystemProxy::GetInstance) + * ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + * ->Attribute(AZ::Script::Attributes::Module, "MyModule"); + * + * behaviorContext->Class("MySystemInterface") + * ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + * ->Attribute(AZ::Script::Attributes::Module, "MyModule") + * + * ->Method("Foo", MySystemProxy::WrapMethod<&MyInterface::Foo>()) + * ->Method("Bar", MySystemProxy::WrapMethod<&MyInterface::Bar>()); + * } + * } + */ + template + class BehaviorInterfaceProxy + { + public: + AZ_CLASS_ALLOCATOR(BehaviorInterfaceProxy, AZ::SystemAllocator, 0); + AZ_RTTI(BehaviorInterfaceProxy, "{E7CC8D27-4499-454E-A7DF-3F72FBECD30D}"); + + //! Accessor for use with ConstantProperty + static T* GetInstance() + { + T* interfacePtr = AZ::Interface::Get(); + AZ_Warning("BehaviorInterfaceProxy", interfacePtr, + "There is currently no global %s registered with an AZ Interface", + AzTypeInfo::Name() + ); + // Don't delete the global instance, it is not owned by the behavior context + return interfacePtr; + } + + //! Helper for attaching interface function via ClassBuilder::Method + template + static auto WrapMethod() + { + using FuncTraits = AZStd::function_traits>; + return FuncTraits::template expand_args::template WrapMethod(); + } + + BehaviorInterfaceProxy() = default; + virtual ~BehaviorInterfaceProxy() = default; + + //! Stores the instance which will use the provided shared_ptr deleter when the reference count hits zero + BehaviorInterfaceProxy(AZStd::shared_ptr sharedInstance) + : m_instance(AZStd::move(sharedInstance)) + { + } + + //! Stores the instance which will perform a no-op deleter when the reference count hits zero + BehaviorInterfaceProxy(T* rawIntance) + : m_instance(rawIntance, [](T*) {}) + { + } + + //! Returns if the m_instance shared pointer is non-nullptr + bool IsValid() const { return m_instance; } + + private: + template + struct MethodWrapper + { + template + static auto WrapMethod() + { + using return_type = AZStd::function_traits_get_result_t>; + return [](BehaviorInterfaceProxy* proxy, Args... params) -> return_type + { + if (proxy && proxy->IsValid()) + { + return AZStd::invoke(Method, proxy->m_instance, AZStd::forward(params)...); + } + return return_type(); + }; + } + }; + + AZStd::shared_ptr m_instance; + }; +} // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake index d4a26256bf..3cd702e588 100644 --- a/Code/Framework/AzCore/AzCore/azcore_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake @@ -456,6 +456,7 @@ set(FILES RTTI/BehaviorContext.h RTTI/BehaviorContextUtilities.h RTTI/BehaviorContextUtilities.cpp + RTTI/BehaviorInterfaceProxy.h RTTI/BehaviorObjectSignals.h RTTI/TypeSafeIntegral.h Script/ScriptAsset.cpp