Give FindOneWithInternalID the power to handle arrays of smart pointers.

Eliminate FindNoneWithInternalID, finish migration to FindNoDuplicateNames.
This commit is contained in:
2026-04-06 04:37:28 -04:00
parent 7aac8f194a
commit 8951065670
6 changed files with 38 additions and 65 deletions

View File

@@ -75,8 +75,9 @@ public:
// Check graph name uniqueness and legality
FName InternalID = WingUtils::CheckProposedName(Graph, WingOut::Stdout);
if (InternalID.IsNone()) return;
if (!WingUtils::FindNoneWithInternalID(InternalID, WingUtils::AllGraphs(BP), TEXT("Graph"), WingOut::Stdout))
return;
TSet<FName> Names;
if (!WingUtils::FindNoDuplicateName(Names, InternalID, TEXT("Graph"), WingOut::Stdout)) return;
if (!WingUtils::FindNoDuplicateNames(Names, WingUtils::AllGraphs(BP), TEXT("Graph"), WingOut::Stdout)) return;
// Parse and validate variables before making changes
WingVariables Vars;

View File

@@ -39,10 +39,9 @@ public:
FBPVariableDescription* Var = WingUtils::FindOneWithExternalID(Dispatcher, BP->NewVariables, TEXT("Dispatcher"), WingOut::Stdout);
if (!Var) return;
TObjectPtr<UEdGraph>* SigGraph = WingUtils::FindOneWithExternalID(Dispatcher, BP->DelegateSignatureGraphs, TEXT("Dispatcher Signature Graph"), WingOut::Stdout);
if (!SigGraph) return;
TObjectPtr<UEdGraph> Graph = WingUtils::FindOneWithExternalID(Dispatcher, BP->DelegateSignatureGraphs, TEXT("Dispatcher Signature Graph"), WingOut::Stdout);
if (!Graph) return;
UEdGraph* Graph = *SigGraph;
FName VarFName = Var->VarName;
// Remove the member variable (also destroys referencing nodes)

View File

@@ -274,12 +274,6 @@ FName WingUtils::GetFName(const FWingProperty &Prop)
return Prop.Prop->GetFName();
}
FName WingUtils::GetFName(const TSharedPtr<IPropertyHandle> &H)
{
return H->GetProperty()->GetFName();
}
// ============================================================
// Formatting other things
// ============================================================
@@ -385,21 +379,6 @@ bool WingUtils::CheckExactlyOneNamed(int Count, const TCHAR *Kind, FName Name, W
return CheckExactlyOneNamed(Count, Kind, ExternalizeID(Name), Errors);
}
bool WingUtils::CheckExactlyNoneNamed(int Count, const TCHAR *Kind, const FString &Name, WingOut Errors)
{
if (Count > 0)
{
Errors.Printf(TEXT("A %s named %s already exists."), Kind, *Name);
return false;
}
return true;
}
bool WingUtils::CheckExactlyNoneNamed(int Count, const TCHAR *Kind, FName Name, WingOut Errors)
{
return CheckExactlyNoneNamed(Count, Kind, ExternalizeID(Name), Errors);
}
bool WingUtils::CheckCanRename(UEdGraphNode* Node, const FString &Name, WingOut Errors)
{
if (!Node->bCanRenameNode)

View File

@@ -538,11 +538,11 @@ bool WingVariables::ModifyEditablePinBase(WingVariableList &List, UK2Node_Editab
{
for (Var &V : List.Variables)
{
TSharedPtr<FUserPinInfo> *Found =
TSharedPtr<FUserPinInfo> Found =
WingUtils::FindOneWithInternalID(V.Name, Node->UserDefinedPins, List.ListName, Errors);
if (!Found) return false;
(*Found)->PinType = V.Type;
if (V.DefaultSpecified) (*Found)->PinDefaultValue = V.DefaultValue;
Found->PinType = V.Type;
if (V.DefaultSpecified) Found->PinDefaultValue = V.DefaultValue;
}
return true;
}
@@ -736,13 +736,13 @@ bool WingVariables::RemoveGraph(WingOut Errors)
// Verify that all named variables exist before removing anything.
for (const Var& V : InputVariables.Variables)
{
TSharedPtr<FUserPinInfo>* Found =
TSharedPtr<FUserPinInfo> Found =
WingUtils::FindOneWithInternalID(V.Name, InputNode->UserDefinedPins, TEXT("input variable"), Errors);
if (!Found) return false;
}
for (const Var& V : OutputVariables.Variables)
{
TSharedPtr<FUserPinInfo>* Found =
TSharedPtr<FUserPinInfo> Found =
WingUtils::FindOneWithInternalID(V.Name, OutputNode->UserDefinedPins, TEXT("output variable"), Errors);
if (!Found) return false;
}
@@ -778,7 +778,7 @@ bool WingVariables::RemoveCustomEvent(WingOut Errors)
// Verify that all named parameters exist before removing anything.
for (const Var& V : InputVariables.Variables)
{
TSharedPtr<FUserPinInfo>* Found =
TSharedPtr<FUserPinInfo> Found =
WingUtils::FindOneWithInternalID(V.Name, CustomEvent->UserDefinedPins, TEXT("event parameter"), Errors);
if (!Found) return false;
}

View File

@@ -29,7 +29,6 @@ public:
FName PinCategory;
FName PinSubCategory;
FString PinSubCategoryObject;
// The following are only set for interfaces and Objects.
FName BroadCategory;
bool IsUserDefined = false;
};

View File

@@ -68,29 +68,43 @@ public:
static FName GetFName(const UWingComponentReference *Ref) { return Ref->VariableName; }
static FName GetFName(const UWidget *Widget) { return Widget->GetFName(); }
static FName GetFName(const WingVariables::Var &Var) { return Var.Name; }
static FName GetFName(const TSharedPtr<IPropertyHandle> &H);
////////////////////////////////////////////////////////
//
// When searching an array of structs, you want to
// return a pointer to one of the structs. When
// searching an array of pointers, you want to return
// one of the pointers. These helpers make it easy for
// the search templates below to do that.
// one of the pointers. When searching an array of
// smart pointers, you want to return one of the smart
// pointers. The AsPointerLike helper below makes it
// easy for the search templates below to do that.
//
////////////////////////////////////////////////////////
template<class T> static const T* EltAsPtr(const TArray<T> &A, const T &Elt) { return &Elt; }
template<class T> static T* EltAsPtr(TArray<T> &A, T &Elt) { return &Elt; }
template<class T> static T* EltAsPtr(const TArray<T*> &A, T* &Elt) { return Elt; }
template<class T> static T* EltAsPtr(TArray<T*> &A, T* &Elt) { return Elt; }
template<class T> static const T* EltAsPtr(const TArray<const T*> &A, const T* &Elt) { return Elt; }
template<class T> static const T* EltAsPtr(TArray<const T*> &A, const T* &Elt) { return Elt; }
template<class T> struct IsPointerLike : std::false_type {};
template<class T> struct IsPointerLike<T*> : std::true_type {};
template<class T> struct IsPointerLike<TSharedPtr<T>> : std::true_type {};
template<class T> struct IsPointerLike<TWeakObjectPtr<T>> : std::true_type {};
template<class T> struct IsPointerLike<TObjectPtr<T>> : std::true_type {};
template<class T> struct IsPointerLike<TStrongObjectPtr<T>> : std::true_type {};
template<class T>
static decltype(auto) AsPointerLike(T&& Elt)
{
if constexpr (IsPointerLike<std::remove_cvref_t<T>>::value)
{
return std::remove_cvref_t<T>(Elt);
}
else
{
return &Elt;
}
}
////////////////////////////////////////////////////////
//
// Search Templates. Search an array for an item with a
// given name. Works correctly no matter how a name is
// given name. Works correctly no matter how a name is
// expressed: eg, "A+B" finds the same results as
// "A&plus;B". Handles failure cases correctly: two
// items with the same name, no such item, and malformed
@@ -107,9 +121,9 @@ public:
template<typename ArrayType>
static auto FindOneWithInternalID(FName InternalID, ArrayType &&Array, const TCHAR *Kind, WingOut Errors)
{
decltype(EltAsPtr(Array, Array[0])) Result = nullptr;
decltype(AsPointerLike(Array[0])) Result = nullptr;
int Count = 0;
for (auto &Elt : Array) if (GetFName(Elt) == InternalID) { Count++; Result = EltAsPtr(Array, Elt); }
for (auto &Elt : Array) if (GetFName(Elt) == InternalID) { Count++; Result = AsPointerLike(Elt); }
if (!CheckExactlyOneNamed(Count, Kind, InternalID, Errors)) Result = nullptr;
return Result;
}
@@ -117,28 +131,12 @@ public:
template<typename ArrayType>
static auto FindOneWithExternalID(const FString &ExternalID, ArrayType &&Array, const TCHAR *Kind, WingOut Errors)
{
decltype(EltAsPtr(Array, Array[0])) Result = nullptr;
decltype(AsPointerLike(Array[0])) Result = nullptr;
FName InternalID = CheckInternalizeID(ExternalID, Errors);
if (!InternalID.IsNone()) Result = FindOneWithInternalID(InternalID, Array, Kind, Errors);
return Result;
}
template<typename ArrayType>
static bool FindNoneWithInternalID(FName InternalID, ArrayType &&Array, const TCHAR *Kind, WingOut Errors)
{
for (auto &Elt : Array) if (GetFName(Elt) == InternalID)
return CheckExactlyNoneNamed(1, Kind, InternalID, Errors);
return true;
}
template<typename ArrayType>
static bool FindNoneWithExternalID(const FString &ExternalID, ArrayType &&Array, const TCHAR *Kind, WingOut Errors)
{
FName InternalID = CheckInternalizeID(ExternalID, Errors);
if (InternalID.IsNone()) return false;
return FindNoneWithInternalID(InternalID, Array, Kind, Errors);
}
static bool FindNoDuplicateName(TSet<FName> &Collection, FName InternalID, const TCHAR *Kind, WingOut Errors)
{
if (Collection.Contains(InternalID))
@@ -276,9 +274,6 @@ public:
// ----- Common Error Reporting -----
static bool CheckExactlyOneNamed(int Count, const TCHAR *Kind, const FString &Name, WingOut Errors);
static bool CheckExactlyOneNamed(int Count, const TCHAR *Kind, FName Name, WingOut Errors);
static bool CheckExactlyNoneNamed(int Count, const TCHAR *Kind, const FString &Name, WingOut Errors);
static bool CheckExactlyNoneNamed(int Count, const TCHAR *Kind, FName Name, WingOut Errors);
static bool CheckCanRename(UEdGraphNode* Node, const FString &Name, WingOut Errors);
};