Merge pull request #932 from aws-lumberyard-dev/carlitosan-beta-fixes

SC support for unordered_set, version upgrade improvements and bug fixes
This commit is contained in:
carlitosan
2021-05-25 17:39:06 -07:00
committed by GitHub
38 changed files with 518 additions and 415 deletions
@@ -1020,29 +1020,60 @@ namespace AZ
}
};
/// OnDemand reflection for AZStd::set
template<class t_Key, class t_Hasher, class t_EqualKey, class t_Allocator>
class Iterator_VM<AZStd::unordered_set<t_Key, t_Hasher, t_EqualKey, t_Allocator>>
{
public:
using ContainerType = AZStd::unordered_set<t_Key, t_Hasher, t_EqualKey, t_Allocator>;
using IteratorType = typename ContainerType::iterator;
Iterator_VM(ContainerType& container)
: m_iterator(container.begin())
, m_end(container.end())
{}
const t_Key& GetKeyUnchecked() const
{
return *m_iterator;
}
bool IsNotAtEnd() const
{
return m_iterator != m_end;
}
t_Key& ModValueUnchecked()
{
return *m_iterator;
}
void Next()
{
++m_iterator;
}
private:
IteratorType m_iterator;
IteratorType m_end;
};
/// OnDemand reflection for AZStd::unordered_set
template<class Key, class Hasher, class EqualKey, class Allocator>
struct OnDemandReflection< AZStd::unordered_set<Key, Hasher, EqualKey, Allocator> >
{
using ContainerType = AZStd::unordered_set<Key, Hasher, EqualKey, Allocator>;
using KeyListType = AZStd::vector<Key, Allocator>;
static AZ::Outcome<void, void> Erase(ContainerType& thisMap, Key& key)
using ValueIteratorType = Iterator_VM<ContainerType>;
static bool EraseCheck_VM(ContainerType& thisSet, Key& key)
{
const auto result = thisMap.erase(key);
if (result)
{
return AZ::Success();
}
else
{
return AZ::Failure();
}
return thisSet.erase(key) != 0;
}
static void Insert(ContainerType& thisSet, Key& key)
static ContainerType& ErasePost_VM(ContainerType& thisSet, [[maybe_unused]] Key&)
{
thisSet.insert(key);
return thisSet;
}
static KeyListType GetKeys(ContainerType& thisSet)
@@ -1055,6 +1086,17 @@ namespace AZ
return keys;
}
static ContainerType& Insert(ContainerType& thisSet, Key& key)
{
thisSet.insert(key);
return thisSet;
}
static ValueIteratorType Iterate_VM(ContainerType& thisContainer)
{
return ValueIteratorType(thisContainer);
}
static void Swap(ContainerType& thisSet, ContainerType& otherSet)
{
thisSet.swap(otherSet);
@@ -1064,33 +1106,68 @@ namespace AZ
{
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(context))
{
BranchOnResultInfo emptyBranchInfo;
emptyBranchInfo.m_returnResultInBranches = true;
emptyBranchInfo.m_trueToolTip = "The container is empty";
emptyBranchInfo.m_falseToolTip = "The container is not empty";
auto ContainsTransparent = [](const ContainerType& containerType, typename ContainerType::key_type& key)->bool
{
return containerType.contains(key);
};
ExplicitOverloadInfo explicitOverloadInfo;
behaviorContext->Class<ContainerType>()
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::ListOnly)
->Attribute(AZ::ScriptCanvasAttributes::PrettyName, ScriptCanvasOnDemandReflection::OnDemandPrettyName<ContainerType>::Get(*behaviorContext))
->Attribute(AZ::Script::Attributes::ToolTip, ScriptCanvasOnDemandReflection::OnDemandToolTip<ContainerType>::Get(*behaviorContext))
->Attribute(AZ::Script::Attributes::Category, ScriptCanvasOnDemandReflection::OnDemandCategoryName<ContainerType>::Get(*behaviorContext))
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::ScriptOwn)
->Method("BucketCount", static_cast<typename ContainerType::size_type(ContainerType::*)() const>(&ContainerType::bucket_count))
->Method("Erase", &Erase)
->Method("Empty", [](ContainerType& thisSet)->bool { return thisSet.empty(); })
->Method("Empty", static_cast<bool(ContainerType::*)() const>(&ContainerType::empty), { { { "Container", "The container to check if it is empty", nullptr, {} } } })
->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Is Empty", "Containers"))
->Attribute(AZ::ScriptCanvasAttributes::BranchOnResult, emptyBranchInfo)
->Method("EraseCheck_VM", &EraseCheck_VM)
->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Method("Erase", &ErasePost_VM)
->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent)
->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Erase", "Containers"))
->Attribute(AZ::ScriptCanvasAttributes::CheckedOperation, CheckedOperationInfo("EraseCheck_VM", {}, "Out", "Key Not Found", true))
->Attribute(AZ::ScriptCanvasAttributes::OverloadArgumentGroup, AZ::OverloadArgumentGroupInfo({ "ContainerGroup", "" }, { "ContainerGroup" }))
->Method("contains", ContainsTransparent)
->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Has Key", "Containers"))
->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent)
->Method("Insert", &Insert)
->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent)
->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Insert", "Containers"))
->Attribute(AZ::ScriptCanvasAttributes::OverloadArgumentGroup, AZ::OverloadArgumentGroupInfo({ "ContainerGroup", "", "" }, { "ContainerGroup" }))
->Method(k_sizeName, [](ContainerType* thisPtr) { return aznumeric_cast<int>(thisPtr->size()); })
->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Length)
->Method("GetKeys", &GetKeys)
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
->Method("GetSize", [](ContainerType& thisPtr) { return aznumeric_cast<int>(thisPtr.size()); })
->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Get Size", "Containers"))
->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent)
->Method("Reserve", static_cast<void(ContainerType::*)(typename ContainerType::size_type)>(&ContainerType::reserve))
->Method("Swap", &Swap)
->Method("Clear", [](ContainerType& thisContainer)->ContainerType& { thisContainer.clear(); return thisContainer; })
->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent)
->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Clear All Elements", "Containers"))
->Attribute(AZ::ScriptCanvasAttributes::OverloadArgumentGroup, AZ::OverloadArgumentGroupInfo({ "ContainerGroup" }, { "ContainerGroup" }))
->Method(k_iteratorConstructorName, &Iterate_VM)
;
behaviorContext->Class<ValueIteratorType>()
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::ListOnly)
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::ScriptOwn)
->Method(k_iteratorGetKeyName, &ValueIteratorType::GetKeyUnchecked)
->Method(k_iteratorModValueName, &ValueIteratorType::ModValueUnchecked)
->Method(k_iteratorIsNotAtEndName, &ValueIteratorType::IsNotAtEnd)
->Method(k_iteratorNextName, &ValueIteratorType::Next)
;
}
}
};
template <>
@@ -165,7 +165,7 @@ namespace AZ
if (HasResult() != overload->HasResult())
{
AZ_Error("Reflection", false, "Overload failure, all methods must have the same result, or none at all");
AZ_Error("Reflection", false, "Overload failure, all methods must have the same result, or none at all: %s", m_name.c_str());
return false;
}
@@ -176,7 +176,7 @@ namespace AZ
if (!(methodResult->m_typeId == overloadResult->m_typeId && methodResult->m_traits == overloadResult->m_traits))
{
AZ_Error("Reflection", false, "Overload failure, all methods must have the same result, or none at all");
AZ_Error("Reflection", false, "Overload failure, all methods must have the same result, or none at all: %s", m_name.c_str());
return false;
}
}
@@ -575,7 +575,7 @@ namespace AZ
}
else
{
AZ_Error("BehaviorContext", false, "safety check declared for method %s but it was not found in the class");
AZ_Error("BehaviorContext", false, "Method: %s, declared safety check: %s, but it was not found in class: %s", method.m_name.c_str(), m_name.c_str(), checkedOperationInfo.m_safetyCheckName.c_str());
}
}
}
@@ -34,10 +34,17 @@ namespace BehaviorContextUtilitiesCPP
using argument_type = const BehaviorParameter*;
using result_type = size_t;
result_type operator()(const argument_type& value) const
{
result_type result = AZStd::hash<Uuid>()(value->m_typeId);
AZStd::hash_combine(result, CleanTraits(value->m_traits));
return result;
{
if (value)
{
result_type result = AZStd::hash<Uuid>()(value->m_typeId);
AZStd::hash_combine(result, CleanTraits(value->m_traits));
return result;
}
else
{
return 0;
}
}
};
@@ -45,7 +52,11 @@ namespace BehaviorContextUtilitiesCPP
{
bool operator()(const BehaviorParameter* left, const BehaviorParameter* right) const
{
return left->m_typeId == right->m_typeId && CleanTraits(left->m_traits) == CleanTraits(right->m_traits);
return (left == nullptr && right == nullptr)
|| (left != nullptr
&& right != nullptr
&& left->m_typeId == right->m_typeId
&& CleanTraits(left->m_traits) == CleanTraits(right->m_traits));
}
};
@@ -137,7 +148,7 @@ namespace AZ
for (size_t argIndex = 0, argSentinel = overload.GetNumArguments(); argIndex < argSentinel; ++argIndex)
{
auto overloadedArgIter = variance.m_input.find(argIndex);
if (overloadedArgIter != variance.m_input.end())
if (overloadedArgIter != variance.m_input.end() && overloadedArgIter->second[overloadIndex])
{
// if this doesn't work try the type name
overloadName += ReplaceCppArtifacts(overloadedArgIter->second[overloadIndex]->m_name);
@@ -185,16 +196,24 @@ namespace AZ
{
auto argument = overloads[overloadIndex].first->GetArgument(0);
const bool isThisPointer
= (argument->m_traits & AZ::BehaviorParameter::Traits::TR_THIS_PTR) != 0
|| AZ::FindAttribute(AZ::Script::Attributes::TreatAsMemberFunction, overloads[overloadIndex].first->m_attributes);
if (argument)
{
const bool isThisPointer
= (argument->m_traits & AZ::BehaviorParameter::Traits::TR_THIS_PTR) != 0
|| AZ::FindAttribute(AZ::Script::Attributes::TreatAsMemberFunction, overloads[overloadIndex].first->m_attributes);
oneArgIsThisPointer = oneArgIsThisPointer || isThisPointer;
oneArgIsThisPointer = oneArgIsThisPointer || isThisPointer;
}
types.insert(argument);
stripedArgs.emplace_back(argument);
}
if (types.size() == overloads.size())
{
variance.m_unambiguousInput.insert(0);
}
if (types.size() > 1 && (onThis == VariantOnThis::Yes || !oneArgIsThisPointer))
{
variance.m_input.insert(AZStd::make_pair(0, stripedArgs));
@@ -210,11 +229,15 @@ namespace AZ
for (size_t overloadIndex = 0, overloadSentinel = overloads.size(); overloadIndex < overloadSentinel; ++overloadIndex)
{
auto argument = overloads[overloadIndex].first->GetArgument(argIndex);
types.insert(argument);
stripedArgs.emplace_back(argument);
}
if (types.size() == overloads.size())
{
variance.m_unambiguousInput.insert(0);
}
if (types.size() > 1)
{
variance.m_input.insert(AZStd::make_pair(argIndex, stripedArgs));
@@ -27,6 +27,8 @@ namespace AZ
struct OverloadVariance
{
AZStd::unordered_map<size_t, AZStd::vector<const BehaviorParameter*>> m_input;
// the indices of inputs that make selection of overload unambiguous
AZStd::unordered_set<size_t> m_unambiguousInput;
AZStd::vector<const BehaviorParameter*> m_output;
};
@@ -83,7 +83,7 @@ namespace AzToolsFramework
protected:
QWidget* GetFirstInTabOrder() override;
QWidget* GetLastInTabOrder() override;
void UpdateTabOrder() override;
void UpdateTabOrder() override;
void onChildComboBoxValueChange(int comboBoxIndex) override;
@@ -93,7 +93,7 @@ namespace AzToolsFramework
void addElementImpl(const AZStd::pair<T, AZStd::string>& genericValue);
QLabel* m_warningLabel = nullptr;
QLabel* m_warningLabel = nullptr;
DHQComboBox* m_pComboBox;
AZStd::vector<AZStd::pair<T, AZStd::string>> m_values;
AZ::AttributeFunction <void(const T&)>* m_postChangeNotifyCB{};
@@ -131,6 +131,11 @@ namespace AzToolsFramework
template<typename T>
AzToolsFramework::PropertyHandlerBase* RegisterGenericComboBoxHandler()
{
if (!AzToolsFramework::PropertyTypeRegistrationMessages::Bus::FindFirstHandler())
{
return nullptr;
}
auto propertyHandler = aznew GenericComboBoxHandler<T>();
AzToolsFramework::PropertyTypeRegistrationMessages::Bus::Broadcast(&AzToolsFramework::PropertyTypeRegistrationMessages::RegisterPropertyType, propertyHandler);
return propertyHandler;