Removes ComparisonFunctions.h from Gems/ScriptCanvas

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
This commit is contained in:
Esteban Papp
2022-01-06 13:27:54 -08:00
parent 8f4e547b9e
commit ff0a5b6c0d
8 changed files with 0 additions and 396 deletions
@@ -1,387 +0,0 @@
/*
* 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
#if defined(EXPRESSION_TEMPLATES_ENABLED)
#include <ScriptCanvas/Core/Core.h>
#include <ScriptCanvas/Core/Datum.h>
#include <AzCore/std/containers/array.h>
#include <AzCore/std/containers/map.h>
#include <AzCore/RTTI/AttributeReader.h>
#include <AzCore/Component/ComponentApplicationBus.h>
namespace ScriptCanvas
{
namespace Nodes
{
namespace Comparison
{
enum class OperatorType : AZ::u32
{
Equal,
NotEqual,
Less,
Greater,
LessEqual,
GreaterEqual
};
template<typename NumberType1, typename NumberType2, typename = void>
struct CompareAction
{
// Compares two primitive types each other
//! \return true if a comparison occurred between both types and stores the result of the comparison in the @result parameter
inline static bool CompareNumber(bool& result, OperatorType operatorType, NumberType1 leftNumber, NumberType2 rightNumber)
{
switch (operatorType)
{
case OperatorType::Equal:
result = leftNumber == rightNumber;
return true;
case OperatorType::NotEqual:
result = leftNumber != rightNumber;
return true;
case OperatorType::Less:
result = leftNumber < rightNumber;
return true;
case OperatorType::Greater:
result = leftNumber > rightNumber;
return true;
case OperatorType::LessEqual:
result = leftNumber <= rightNumber;
return true;
case OperatorType::GreaterEqual:
result = leftNumber >= rightNumber;
return true;
default:
return false;
}
}
};
//! Attempts to cast the second object parameter to a primitive type and compare it against the supplied primitive parameter
//! \return true if a comparison occurred between both types and stores the result of the comparison in the @result parameter
template<typename NumberType, typename = AZStd::enable_if_t<AZStd::is_arithmetic<NumberType>::value>>
inline bool CompareNumberToBehaviorParameter(bool& result, OperatorType operatorType, NumberType leftNumber, AZ::BehaviorValueParameter& rhs)
{
if(CanCastToValue<NumberType>(rhs))
{
NumberType convertedParam{};
return CastToValue(convertedParam, rhs) && CompareAction<NumberType, NumberType>::CompareNumber(result, operatorType, leftNumber, convertedParam);
}
return false;
}
//! Attempts to cast the supplied object parameters to a primitive type and compare them
//! \return true if a comparison occurred between both types and stores the result of the comparison in the @result parameter
inline bool ComparePrimitive(bool& result, OperatorType operatorType, const Datum& lhs, const Datum& rhs)
{
auto leftParam = lhs.Get();
auto rightParam = rhs.Get();
if (CanCastToValue<bool>(leftParam))
{
bool convertedParam{};
return CastToValue(convertedParam, leftParam) && CompareNumberToBehaviorParameter(result, operatorType, convertedParam, rightParam);
}
else if (CanCastToValue<double>(leftParam))
{
double convertedParam{};
return CastToValue(convertedParam, leftParam) && CompareNumberToBehaviorParameter(result,operatorType, convertedParam, rightParam);
}
else if (CanCastToValue<float>(leftParam))
{
float convertedParam{};
return CastToValue(convertedParam, leftParam) && CompareNumberToBehaviorParameter(result, operatorType, convertedParam, rightParam);
}
else if (CanCastToValue<AZ::u64>(leftParam))
{
AZ::u64 convertedParam{};
return CastToValue(convertedParam, leftParam) && CompareNumberToBehaviorParameter(result, operatorType, convertedParam, rightParam);
}
else if (CanCastToValue<AZ::s64>(leftParam))
{
AZ::s64 convertedParam{};
return CastToValue(convertedParam, leftParam) && CompareNumberToBehaviorParameter(result, operatorType, convertedParam, rightParam);
}
else if (CanCastToValue<unsigned long>(leftParam))
{
unsigned long convertedParam{};
return CastToValue(convertedParam, leftParam) && CompareNumberToBehaviorParameter(result, operatorType, convertedParam, rightParam);
}
else if (CanCastToValue<long>(leftParam))
{
long convertedParam{};
return CastToValue(convertedParam, leftParam) && CompareNumberToBehaviorParameter(result, operatorType, convertedParam, rightParam);
}
else if (CanCastToValue<AZ::u32>(leftParam))
{
AZ::u32 convertedParam{};
return CastToValue(convertedParam, leftParam) && CompareNumberToBehaviorParameter(result, operatorType, convertedParam, rightParam);
}
else if (CanCastToValue<AZ::s32>(leftParam))
{
AZ::s32 convertedParam{};
return CastToValue(convertedParam, leftParam) && CompareNumberToBehaviorParameter(result, operatorType, convertedParam, rightParam);
}
else if (CanCastToValue<AZ::u16>(leftParam))
{
AZ::u16 convertedParam{};
return CastToValue(convertedParam, leftParam) && CompareNumberToBehaviorParameter(result, operatorType, convertedParam, rightParam);
}
else if (CanCastToValue<AZ::s16>(leftParam))
{
AZ::s16 convertedParam{};
return CastToValue(convertedParam, leftParam) && CompareNumberToBehaviorParameter(result, operatorType, convertedParam, rightParam);
}
else if (CanCastToValue<AZ::u8>(leftParam))
{
AZ::u8 convertedParam{};
return CastToValue(convertedParam, leftParam) && CompareNumberToBehaviorParameter(result, operatorType, convertedParam, rightParam);
}
else if (CanCastToValue<AZ::s8>(leftParam))
{
AZ::s8 convertedParam{};
return CastToValue(convertedParam, leftParam) && CompareNumberToBehaviorParameter(result, operatorType, convertedParam, rightParam);
}
else if (CanCastToValue<char>(leftParam))
{
char convertedParam{};
return CastToValue(convertedParam, leftParam) && CompareNumberToBehaviorParameter(result, operatorType, convertedParam, rightParam);
}
return false;
}
/**
For the record, this is amazing. But, we can't go dumpster diving through behavior context for the right method to call. If there is a proper evaluation to make, we make the ability for people to
expose to behavior context the correct operations they want used in ScriptCanvas. No matter which route we chose, we should do it at edit time, rather than compile time.
*/
//! Returns a multimap of methods which match the operatorType prioritized by the by least number of type conversions needed for both parameters to invoke the method
inline AZStd::multimap<size_t, AZ::BehaviorMethod*> FindOperatorMethod(AZ::Script::Attributes::OperatorType operatorLookupType, AZ::BehaviorValueParameter& leftParameter, AZ::BehaviorValueParameter& rightParameter)
{
AZStd::multimap<size_t, AZ::BehaviorMethod*> methodMap;
AZ::BehaviorContext* behaviorContext{};
AZ::ComponentApplicationBus::BroadcastResult(behaviorContext, &AZ::ComponentApplicationRequests::GetBehaviorContext);
if (!behaviorContext)
{
return methodMap;
}
auto behaviorClassIt = behaviorContext->m_typeToClassMap.find(leftParameter.m_typeId);
if (behaviorClassIt != behaviorContext->m_typeToClassMap.end())
{
AZ::BehaviorClass* behaviorClass = behaviorClassIt->second;
for (auto& methodPair : behaviorClass->m_methods)
{
AZ::BehaviorMethod* method = methodPair.second;
if (auto* operatorAttr = FindAttribute(AZ::Script::Attributes::Operator, method->m_attributes))
{
// read the operator type
AZ::AttributeReader operatorAttrReader(nullptr, operatorAttr);
AZ::Script::Attributes::OperatorType operatorType;
operatorAttrReader.Read<decltype(operatorType)>(operatorType);
if (operatorType == operatorLookupType
&& method->HasResult() && method->GetResult()->m_typeId == azrtti_typeid<bool>() && method->GetNumArguments() == 2)
{
if (behaviorClass->m_typeId == method->GetArgument(0)->m_typeId && rightParameter.m_typeId == method->GetArgument(1)->m_typeId)
{
methodMap.emplace(0, method);
}
else if (behaviorClass->m_typeId == method->GetArgument(0)->m_typeId && rightParameter.m_azRtti && rightParameter.m_azRtti->IsTypeOf(method->GetArgument(1)->m_typeId))
{
methodMap.emplace(1, method);
}
else if (behaviorClass->m_azRtti && behaviorClass->m_azRtti->IsTypeOf(method->GetArgument(0)->m_typeId) && rightParameter.m_typeId == method->GetArgument(1)->m_typeId)
{
methodMap.emplace(1, method);
}
else if (behaviorClass->m_azRtti && behaviorClass->m_azRtti->IsTypeOf(method->GetArgument(0)->m_typeId) && rightParameter.m_azRtti && rightParameter.m_azRtti->IsTypeOf(method->GetArgument(1)->m_typeId))
{
methodMap.emplace(2, method);
}
}
}
}
}
return methodMap;
}
inline bool InvokeMethod(AZ::BehaviorMethod* method, AZ::BehaviorValueParameter& resultParam, AZStd::array<AZStd::reference_wrapper<AZ::BehaviorValueParameter>, 2> parameters)
{
AZStd::array<void*,2> argAddresses;
AZStd::array<AZ::BehaviorValueParameter, 2> methodArgs;
for (size_t i = 0; i < methodArgs.size(); ++i)
{
methodArgs[i].Set(*method->GetArgument(i));
argAddresses[i] = parameters[i].get().GetValueAddress();
if (methodArgs[i].m_traits & AZ::BehaviorParameter::TR_POINTER)
{
methodArgs[i].m_value = &argAddresses[i];
}
else
{
methodArgs[i].m_value = argAddresses[i];
}
}
return method->Call(methodArgs.data(), static_cast<unsigned int>(methodArgs.size()), &resultParam);
}
//! Compares two object types to each other
//! \return true if a comparison occurred between both types and stores the result of the comparison in the @result parameter
inline bool CompareObjects(bool& result, OperatorType operatorType, const Datum& lhs, const Datum& rhs)
{
auto leftParameter = lhs.Get();
auto rightParameter = rhs.Get();
AZ::BehaviorValueParameter resultParameter(&result);
AZStd::multimap<size_t, AZ::BehaviorMethod*> methodMap{};
switch (operatorType)
{
case OperatorType::Equal:
methodMap = FindOperatorMethod(AZ::Script::Attributes::OperatorType::Equal, leftParameter, rightParameter);
if (!methodMap.empty())
{
if (InvokeMethod(methodMap.begin()->second, resultParameter, { { AZStd::reference_wrapper<AZ::BehaviorValueParameter>(leftParameter), AZStd::reference_wrapper<AZ::BehaviorValueParameter>(rightParameter)} }))
{
return true;
}
}
else
{
methodMap = FindOperatorMethod(AZ::Script::Attributes::OperatorType::Equal, rightParameter, leftParameter);
if (!methodMap.empty())
{
if (InvokeMethod(methodMap.begin()->second, resultParameter, { { AZStd::reference_wrapper<AZ::BehaviorValueParameter>(rightParameter), AZStd::reference_wrapper<AZ::BehaviorValueParameter>(leftParameter) } }))
{
return true;
}
}
}
break;
case OperatorType::NotEqual:
methodMap = FindOperatorMethod(AZ::Script::Attributes::OperatorType::Equal, leftParameter, rightParameter);
if (!methodMap.empty())
{
if (InvokeMethod(methodMap.begin()->second, resultParameter, { { AZStd::reference_wrapper<AZ::BehaviorValueParameter>(leftParameter), AZStd::reference_wrapper<AZ::BehaviorValueParameter>(rightParameter) } }))
{
result = !result;
return true;
}
}
else
{
methodMap = FindOperatorMethod(AZ::Script::Attributes::OperatorType::Equal, rightParameter, leftParameter);
if (!methodMap.empty())
{
if (InvokeMethod(methodMap.begin()->second, resultParameter, { { AZStd::reference_wrapper<AZ::BehaviorValueParameter>(rightParameter), AZStd::reference_wrapper<AZ::BehaviorValueParameter>(leftParameter) } }))
{
result = !result;
return true;
}
}
}
break;
case OperatorType::Less:
methodMap = FindOperatorMethod(AZ::Script::Attributes::OperatorType::LessThan, leftParameter, rightParameter);
if (!methodMap.empty())
{
if (InvokeMethod(methodMap.begin()->second, resultParameter, { { AZStd::reference_wrapper<AZ::BehaviorValueParameter>(leftParameter), AZStd::reference_wrapper<AZ::BehaviorValueParameter>(rightParameter) } }))
{
return true;
}
}
break;
case OperatorType::Greater:
methodMap = FindOperatorMethod(AZ::Script::Attributes::OperatorType::LessThan, leftParameter, rightParameter);
if (!methodMap.empty())
{
if (InvokeMethod(methodMap.begin()->second, resultParameter, { { AZStd::reference_wrapper<AZ::BehaviorValueParameter>(rightParameter), AZStd::reference_wrapper<AZ::BehaviorValueParameter>(leftParameter) } }))
{
return true;
}
}
break;
case OperatorType::LessEqual:
methodMap = FindOperatorMethod(AZ::Script::Attributes::OperatorType::LessEqualThan, leftParameter, rightParameter);
if (!methodMap.empty())
{
if (InvokeMethod(methodMap.begin()->second, resultParameter, { { AZStd::reference_wrapper<AZ::BehaviorValueParameter>(leftParameter), AZStd::reference_wrapper<AZ::BehaviorValueParameter>(rightParameter) } }))
{
return true;
}
}
else
{
methodMap = FindOperatorMethod(AZ::Script::Attributes::OperatorType::LessThan, leftParameter, rightParameter);
if (!methodMap.empty())
{
if (InvokeMethod(methodMap.begin()->second, resultParameter, { { AZStd::reference_wrapper<AZ::BehaviorValueParameter>(rightParameter), AZStd::reference_wrapper<AZ::BehaviorValueParameter>(leftParameter) } }))
{
result = !result;
return true;
}
}
}
break;
case OperatorType::GreaterEqual:
methodMap = FindOperatorMethod(AZ::Script::Attributes::OperatorType::LessEqualThan, leftParameter, rightParameter);
if (!methodMap.empty())
{
if (InvokeMethod(methodMap.begin()->second, resultParameter, { { AZStd::reference_wrapper<AZ::BehaviorValueParameter>(rightParameter), AZStd::reference_wrapper<AZ::BehaviorValueParameter>(leftParameter) } }))
{
return true;
}
}
else
{
methodMap = FindOperatorMethod(AZ::Script::Attributes::OperatorType::LessThan, leftParameter, rightParameter);
if (!methodMap.empty())
{
if (InvokeMethod(methodMap.begin()->second, resultParameter, { { AZStd::reference_wrapper<AZ::BehaviorValueParameter>(leftParameter), AZStd::reference_wrapper<AZ::BehaviorValueParameter>(rightParameter) } }))
{
result = !result;
return true;
}
}
}
break;
default:
break;
}
return false;
}
template<OperatorType operatorType>
struct ComparisonOperator
{
bool operator()(const Datum& lhs, const Datum& rhs) const
{
// If both types sides are primitive types then perform a special case primitive value compare
bool result{};
if (ComparePrimitive(result, operatorType, lhs, rhs) || CompareObjects(result, operatorType, lhs, rhs))
{
return result;
}
return false;
}
};
}
}
}
#endif // EXPRESSION_TEMPLATES_ENABLED
@@ -8,10 +8,8 @@
#pragma once
#include "ComparisonFunctions.h"
#include <Libraries/Core/BinaryOperator.h>
namespace ScriptCanvas
{
namespace Nodes
@@ -8,7 +8,6 @@
#pragma once
#include "ComparisonFunctions.h"
#include <Libraries/Core/BinaryOperator.h>
namespace ScriptCanvas
@@ -8,8 +8,6 @@
#pragma once
#include "ComparisonFunctions.h"
#include <Libraries/Core/BinaryOperator.h>
namespace ScriptCanvas
@@ -8,7 +8,6 @@
#pragma once
#include "ComparisonFunctions.h"
#include <Libraries/Core/BinaryOperator.h>
namespace ScriptCanvas
@@ -8,7 +8,6 @@
#pragma once
#include "ComparisonFunctions.h"
#include <Libraries/Core/BinaryOperator.h>
namespace ScriptCanvas
@@ -8,7 +8,6 @@
#pragma once
#include "ComparisonFunctions.h"
#include <Libraries/Core/BinaryOperator.h>
namespace ScriptCanvas
@@ -230,7 +230,6 @@ set(FILES
Include/ScriptCanvas/Libraries/Math/Vector3Nodes.h
Include/ScriptCanvas/Libraries/Math/Vector4Nodes.h
Include/ScriptCanvas/Libraries/Comparison/Comparison.h
Include/ScriptCanvas/Libraries/Comparison/ComparisonFunctions.h
Include/ScriptCanvas/Libraries/Comparison/EqualTo.h
Include/ScriptCanvas/Libraries/Comparison/NotEqualTo.h
Include/ScriptCanvas/Libraries/Comparison/Less.h