bool FStructureEditorUtils::CanHaveAMemberVariableOfType(const UBlueprintGeneratedStruct* Struct, const FEdGraphPinType& VarType, FString* OutMsg) { const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); if ((VarType.PinCategory == K2Schema->PC_Struct) && Struct) { if (const UScriptStruct* SubCategoryStruct = Cast<const UScriptStruct>(VarType.PinSubCategoryObject.Get())) { const EStructureError Result = IsStructureValid(SubCategoryStruct, Struct, OutMsg); if (EStructureError::Ok != Result) { return false; } } else { if (OutMsg) { *OutMsg = LOCTEXT("StructureIncorrectStructType", "Icorrect struct type in a structure member variable.").ToString(); } return false; } } else if ((VarType.PinCategory == K2Schema->PC_Exec) || (VarType.PinCategory == K2Schema->PC_Meta) || (VarType.PinCategory == K2Schema->PC_Wildcard)) { if (OutMsg) { *OutMsg = LOCTEXT("StructureIncorrectTypeCategory", "Icorrect type for a structure member variable.").ToString(); } return false; } return true; }
bool FStructureEditorUtils::CanHaveAMemberVariableOfType(const UUserDefinedStruct* Struct, const FEdGraphPinType& VarType, FString* OutMsg) { const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); if ((VarType.PinCategory == K2Schema->PC_Struct) && Struct) { if (const UScriptStruct* SubCategoryStruct = Cast<const UScriptStruct>(VarType.PinSubCategoryObject.Get())) { const EStructureError Result = IsStructureValid(SubCategoryStruct, Struct, OutMsg); if (EStructureError::Ok != Result) { return false; } } else { if (OutMsg) { *OutMsg = LOCTEXT("StructureIncorrectStructType", "Incorrect struct type in a structure member variable.").ToString(); } return false; } } else if ((VarType.PinCategory == K2Schema->PC_Exec) || (VarType.PinCategory == K2Schema->PC_Wildcard) || (VarType.PinCategory == K2Schema->PC_MCDelegate) || (VarType.PinCategory == K2Schema->PC_Delegate)) { if (OutMsg) { *OutMsg = LOCTEXT("StructureIncorrectTypeCategory", "Incorrect type for a structure member variable.").ToString(); } return false; } else { const auto PinSubCategoryClass = Cast<const UClass>(VarType.PinSubCategoryObject.Get()); if (PinSubCategoryClass && PinSubCategoryClass->IsChildOf(UBlueprint::StaticClass())) { if (OutMsg) { *OutMsg = LOCTEXT("StructureUseBlueprintReferences", "Struct cannot use any blueprint references").ToString(); } return false; } } return true; }
FStructureEditorUtils::EStructureError FStructureEditorUtils::IsStructureValid(const UScriptStruct* Struct, const UStruct* RecursionParent, FString* OutMsg) { check(Struct); if (Struct == RecursionParent) { if (OutMsg) { *OutMsg = FString::Printf(*LOCTEXT("StructureRecursion", "Recursion: Struct cannot have itself as a member variable. Struct '%s', recursive parent '%s'").ToString(), *Struct->GetFullName(), *RecursionParent->GetFullName()); } return EStructureError::Recursion; } const UScriptStruct* FallbackStruct = GetFallbackStruct(); if (Struct == FallbackStruct) { if (OutMsg) { *OutMsg = LOCTEXT("StructureUnknown", "Struct unknown (deleted?)").ToString(); } return EStructureError::FallbackStruct; } if (Struct->GetStructureSize() <= 0) { if (OutMsg) { *OutMsg = FString::Printf(*LOCTEXT("StructureSizeIsZero", "Struct '%s' is empty").ToString(), *Struct->GetFullName()); } return EStructureError::EmptyStructure; } if (const UUserDefinedStruct* UDStruct = Cast<const UUserDefinedStruct>(Struct)) { if (UDStruct->Status != EUserDefinedStructureStatus::UDSS_UpToDate) { if (OutMsg) { *OutMsg = FString::Printf(*LOCTEXT("StructureNotCompiled", "Struct '%s' is not compiled").ToString(), *Struct->GetFullName()); } return EStructureError::NotCompiled; } for (const UProperty* P = Struct->PropertyLink; P; P = P->PropertyLinkNext) { const UStructProperty* StructProp = Cast<const UStructProperty>(P); if (NULL == StructProp) { if (const UArrayProperty* ArrayProp = Cast<const UArrayProperty>(P)) { StructProp = Cast<const UStructProperty>(ArrayProp->Inner); } } if (StructProp) { if ((NULL == StructProp->Struct) || (FallbackStruct == StructProp->Struct)) { if (OutMsg) { *OutMsg = FString::Printf(*LOCTEXT("StructureUnknownProperty", "Struct unknown (deleted?). Parent '%s' Property: '%s'").ToString(), *Struct->GetFullName(), *StructProp->GetName()); } return EStructureError::FallbackStruct; } FString OutMsgInner; const EStructureError Result = IsStructureValid( StructProp->Struct, RecursionParent ? RecursionParent : Struct, OutMsg ? &OutMsgInner : NULL); if (EStructureError::Ok != Result) { if (OutMsg) { *OutMsg = FString::Printf(*LOCTEXT("StructurePropertyErrorTemplate", "Struct '%s' Property '%s' Error ( %s )").ToString(), *Struct->GetFullName(), *StructProp->GetName(), *OutMsgInner); } return Result; } } } } return EStructureError::Ok; }
FStructureEditorUtils::EStructureError FStructureEditorUtils::IsStructureValid(const UScriptStruct* Struct, const UStruct* RecursionParent, FString* OutMsg) { check(Struct); if (Struct == RecursionParent) { if (OutMsg) { *OutMsg = FString::Printf(*LOCTEXT("StructureRecursion", "Recursion: Struct cannot have itself as a member variable. Struct '%s', recursive parent '%s'").ToString(), *Struct->GetFullName(), *RecursionParent->GetFullName()); } return EStructureError::Recursion; } const UScriptStruct* FallbackStruct = GetFallbackStruct(); if (Struct == FallbackStruct) { if (OutMsg) { *OutMsg = LOCTEXT("StructureUnknown", "Struct unknown (deleted?)").ToString(); } return EStructureError::FallbackStruct; } if (const UBlueprintGeneratedStruct* BPGStruct = Cast<const UBlueprintGeneratedStruct>(Struct)) { static const FName BlueprintTypeName(TEXT("BlueprintType")); if (!Struct->GetBoolMetaData(BlueprintTypeName)) { if (OutMsg) { *OutMsg = FString::Printf(*LOCTEXT("StructureNotBlueprintType", "Struct '%s' is not BlueprintType").ToString(), *Struct->GetFullName()); } return EStructureError::NotBlueprintType; } if (BPGStruct->Status != EBlueprintStructureStatus::BSS_UpToDate) { if (OutMsg) { *OutMsg = FString::Printf(*LOCTEXT("StructureNotCompiled", "Struct '%s' is not compiled").ToString(), *Struct->GetFullName()); } return EStructureError::NotCompiled; } for (const UProperty * P = Struct->PropertyLink; P; P = P->PropertyLinkNext) { const UStructProperty* StructProp = Cast<const UStructProperty>(P); if (NULL == StructProp) { if (const UArrayProperty* ArrayProp = Cast<const UArrayProperty>(P)) { StructProp = Cast<const UStructProperty>(ArrayProp->Inner); } } if (StructProp) { if ((NULL == StructProp->Struct) || (FallbackStruct == StructProp->Struct)) { if (OutMsg) { *OutMsg = FString::Printf(*LOCTEXT("StructureUnknownProperty", "Struct unknown (deleted?). Parent '%s' Property: '%s").ToString(), *Struct->GetFullName(), *StructProp->GetName()); } return EStructureError::FallbackStruct; } const EStructureError Result = IsStructureValid(StructProp->Struct, RecursionParent ? RecursionParent : Struct, OutMsg); if (EStructureError::Ok != Result) { return Result; } } } } return EStructureError::Ok; }