CallProcessorBinder.inl 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/std/typetraits/is_base_of.h>
  9. namespace AZ
  10. {
  11. namespace SceneAPI
  12. {
  13. namespace Events
  14. {
  15. template<typename Class, typename ContextType>
  16. void CallProcessorBinder::BindToCall(ProcessingResult(Class::*Func)(ContextType& context) const, TypeMatch typeMatch)
  17. {
  18. static_assert((AZStd::is_base_of<CallProcessorBinder, Class>::value),
  19. "CallProcessorBinder can only bind to classes derived from it.");
  20. static_assert((AZStd::is_base_of<ICallContext, ContextType>::value),
  21. "Only arguments derived from ICallContext are accepted by CallProcessorBinder");
  22. if (typeMatch == TypeMatch::Exact)
  23. {
  24. using Binder = ConstFunctionBindingTemplate<Class, ContextType>;
  25. m_bindings.emplace_back(AZStd::make_unique<Binder>(Func));
  26. }
  27. else
  28. {
  29. using Binder = ConstDerivedFunctionBindingTemplate<Class, ContextType>;
  30. m_bindings.emplace_back(AZStd::make_unique<Binder>(Func));
  31. }
  32. }
  33. template<typename Class, typename ContextType>
  34. void CallProcessorBinder::BindToCall(ProcessingResult(Class::*Func)(ContextType& context), TypeMatch typeMatch)
  35. {
  36. static_assert((AZStd::is_base_of<CallProcessorBinder, Class>::value),
  37. "CallProcessorBinder can only bind to classes derived from it.");
  38. static_assert((AZStd::is_base_of<ICallContext, ContextType>::value),
  39. "Only arguments derived from ICallContext are accepted by CallProcessorBinder");
  40. if (typeMatch == TypeMatch::Exact)
  41. {
  42. using Binder = FunctionBindingTemplate<Class, ContextType>;
  43. m_bindings.emplace_back(AZStd::make_unique<Binder>(Func));
  44. }
  45. else
  46. {
  47. using Binder = DerivedFunctionBindingTemplate<Class, ContextType>;
  48. m_bindings.emplace_back(AZStd::make_unique<Binder>(Func));
  49. }
  50. }
  51. // FunctionBinding
  52. template<typename Class, typename ContextType, typename Function>
  53. ProcessingResult CallProcessorBinder::FunctionBinding::Call(CallProcessorBinder* thisPtr, ICallContext* context, Function function)
  54. {
  55. ContextType* arg = azrtti_cast<ContextType*>(context);
  56. if (arg)
  57. {
  58. // As the compiler can't "see" the target Class for conversion the safety checks in azrtti_cast
  59. // throw a false positive. Instead of using azrtti_cast directly, so address look up here
  60. // and use a standard reinterpret_cast.
  61. void* address = thisPtr->RTTI_AddressOf(Class::TYPEINFO_Uuid());
  62. AZ_Assert(address, "Unable to case CallProcessorBinder to %s.", Class::TYPEINFO_Name());
  63. return (reinterpret_cast<Class*>(address)->*(function))(*arg);
  64. }
  65. else
  66. {
  67. AZ_Assert(arg, "CallProcessorBinder failed to cast context for unknown reasons.");
  68. return ProcessingResult::Failure;
  69. }
  70. }
  71. // ConstFunctionBindingTemplate
  72. template<typename Class, typename ContextType>
  73. CallProcessorBinder::ConstFunctionBindingTemplate<Class, ContextType>::ConstFunctionBindingTemplate(Function function)
  74. : m_function(function)
  75. {
  76. }
  77. template<typename Class, typename ContextType>
  78. ProcessingResult CallProcessorBinder::ConstFunctionBindingTemplate<Class, ContextType>::Process(
  79. CallProcessorBinder* thisPtr, ICallContext* context)
  80. {
  81. if (context && context->RTTI_GetType() == ContextType::TYPEINFO_Uuid())
  82. {
  83. return Call<Class, ContextType, Function>(thisPtr, context, m_function);
  84. }
  85. return ProcessingResult::Ignored;
  86. }
  87. //FunctionBindingTemplate
  88. template<typename Class, typename ContextType>
  89. CallProcessorBinder::FunctionBindingTemplate<Class, ContextType>::FunctionBindingTemplate(Function function)
  90. : m_function(function)
  91. {
  92. }
  93. template<typename Class, typename ContextType>
  94. ProcessingResult CallProcessorBinder::FunctionBindingTemplate<Class, ContextType>::Process(
  95. CallProcessorBinder* thisPtr, ICallContext* context)
  96. {
  97. if (context && context->RTTI_GetType() == ContextType::TYPEINFO_Uuid())
  98. {
  99. return Call<Class, ContextType, Function>(thisPtr, context, m_function);
  100. }
  101. return ProcessingResult::Ignored;
  102. }
  103. // ConstDerivedFunctionBindingTemplate
  104. template<typename Class, typename ContextType>
  105. CallProcessorBinder::ConstDerivedFunctionBindingTemplate<Class, ContextType>::ConstDerivedFunctionBindingTemplate(Function function)
  106. : m_function(function)
  107. {
  108. }
  109. template<typename Class, typename ContextType>
  110. ProcessingResult CallProcessorBinder::ConstDerivedFunctionBindingTemplate<Class, ContextType>::Process(
  111. CallProcessorBinder* thisPtr, ICallContext* context)
  112. {
  113. if (context && context->RTTI_IsTypeOf(ContextType::TYPEINFO_Uuid()))
  114. {
  115. return Call<Class, ContextType, Function>(thisPtr, context, m_function);
  116. }
  117. return ProcessingResult::Ignored;
  118. }
  119. //DerivedFunctionBindingTemplate
  120. template<typename Class, typename ContextType>
  121. CallProcessorBinder::DerivedFunctionBindingTemplate<Class, ContextType>::DerivedFunctionBindingTemplate(Function function)
  122. : m_function(function)
  123. {
  124. }
  125. template<typename Class, typename ContextType>
  126. ProcessingResult CallProcessorBinder::DerivedFunctionBindingTemplate<Class, ContextType>::Process(
  127. CallProcessorBinder* thisPtr, ICallContext* context)
  128. {
  129. if (context && context->RTTI_IsTypeOf(ContextType::TYPEINFO_Uuid()))
  130. {
  131. return Call<Class, ContextType, Function>(thisPtr, context, m_function);
  132. }
  133. return ProcessingResult::Ignored;
  134. }
  135. } // namespace Events
  136. } // namespace SceneAPI
  137. } // namespace AZ