/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #include namespace AZ { namespace SceneAPI { namespace Events { template void CallProcessorBinder::BindToCall(ProcessingResult(Class::*Func)(ContextType& context) const, TypeMatch typeMatch) { static_assert((AZStd::is_base_of::value), "CallProcessorBinder can only bind to classes derived from it."); static_assert((AZStd::is_base_of::value), "Only arguments derived from ICallContext are accepted by CallProcessorBinder"); if (typeMatch == TypeMatch::Exact) { using Binder = ConstFunctionBindingTemplate; m_bindings.emplace_back(AZStd::make_unique(Func)); } else { using Binder = ConstDerivedFunctionBindingTemplate; m_bindings.emplace_back(AZStd::make_unique(Func)); } } template void CallProcessorBinder::BindToCall(ProcessingResult(Class::*Func)(ContextType& context), TypeMatch typeMatch) { static_assert((AZStd::is_base_of::value), "CallProcessorBinder can only bind to classes derived from it."); static_assert((AZStd::is_base_of::value), "Only arguments derived from ICallContext are accepted by CallProcessorBinder"); if (typeMatch == TypeMatch::Exact) { using Binder = FunctionBindingTemplate; m_bindings.emplace_back(AZStd::make_unique(Func)); } else { using Binder = DerivedFunctionBindingTemplate; m_bindings.emplace_back(AZStd::make_unique(Func)); } } // FunctionBinding template ProcessingResult CallProcessorBinder::FunctionBinding::Call(CallProcessorBinder* thisPtr, ICallContext* context, Function function) { ContextType* arg = azrtti_cast(context); if (arg) { // As the compiler can't "see" the target Class for conversion the safety checks in azrtti_cast // throw a false positive. Instead of using azrtti_cast directly, so address look up here // and use a standard reinterpret_cast. void* address = thisPtr->RTTI_AddressOf(Class::TYPEINFO_Uuid()); AZ_Assert(address, "Unable to case CallProcessorBinder to %s.", Class::TYPEINFO_Name()); return (reinterpret_cast(address)->*(function))(*arg); } else { AZ_Assert(arg, "CallProcessorBinder failed to cast context for unknown reasons."); return ProcessingResult::Failure; } } // ConstFunctionBindingTemplate template CallProcessorBinder::ConstFunctionBindingTemplate::ConstFunctionBindingTemplate(Function function) : m_function(function) { } template ProcessingResult CallProcessorBinder::ConstFunctionBindingTemplate::Process( CallProcessorBinder* thisPtr, ICallContext* context) { if (context && context->RTTI_GetType() == ContextType::TYPEINFO_Uuid()) { return Call(thisPtr, context, m_function); } return ProcessingResult::Ignored; } //FunctionBindingTemplate template CallProcessorBinder::FunctionBindingTemplate::FunctionBindingTemplate(Function function) : m_function(function) { } template ProcessingResult CallProcessorBinder::FunctionBindingTemplate::Process( CallProcessorBinder* thisPtr, ICallContext* context) { if (context && context->RTTI_GetType() == ContextType::TYPEINFO_Uuid()) { return Call(thisPtr, context, m_function); } return ProcessingResult::Ignored; } // ConstDerivedFunctionBindingTemplate template CallProcessorBinder::ConstDerivedFunctionBindingTemplate::ConstDerivedFunctionBindingTemplate(Function function) : m_function(function) { } template ProcessingResult CallProcessorBinder::ConstDerivedFunctionBindingTemplate::Process( CallProcessorBinder* thisPtr, ICallContext* context) { if (context && context->RTTI_IsTypeOf(ContextType::TYPEINFO_Uuid())) { return Call(thisPtr, context, m_function); } return ProcessingResult::Ignored; } //DerivedFunctionBindingTemplate template CallProcessorBinder::DerivedFunctionBindingTemplate::DerivedFunctionBindingTemplate(Function function) : m_function(function) { } template ProcessingResult CallProcessorBinder::DerivedFunctionBindingTemplate::Process( CallProcessorBinder* thisPtr, ICallContext* context) { if (context && context->RTTI_IsTypeOf(ContextType::TYPEINFO_Uuid())) { return Call(thisPtr, context, m_function); } return ProcessingResult::Ignored; } } // namespace Events } // namespace SceneAPI } // namespace AZ