bool FStructureEditorUtils::AddVariable(UBlueprint* Blueprint, FName StructName, const FEdGraphPinType& VarType)
{
	if (NULL != Blueprint)
	{
		const FScopedTransaction Transaction( LOCTEXT("AddVariable", "Add Variable") );
		Blueprint->Modify();

		FBPStructureDescription* StructureDesc = Blueprint->UserDefinedStructures.FindByPredicate(FFindByNameHelper(StructName));
		if (StructureDesc)
		{
			FString ErrorMessage;
			if (!CanHaveAMemberVariableOfType(StructureDesc->CompiledStruct, VarType, &ErrorMessage))
			{
				UE_LOG(LogBlueprint, Warning, TEXT("%s"), *ErrorMessage);
				return false;
			}

			const FName VarName = FMemberVariableNameHelper::Generate(StructureDesc->CompiledStruct, FString());
			check(NULL == StructureDesc->Fields.FindByPredicate(FFindByNameHelper(VarName)));
			const FString DisplayName = VarName.ToString();
			check(IsUniqueVariableDisplayName(Blueprint, StructName, DisplayName));

			FBPVariableDescription NewVar;
			NewVar.VarName = VarName;
			NewVar.FriendlyName = DisplayName;
			NewVar.VarType = VarType;
			NewVar.VarGuid = FGuid::NewGuid();
			StructureDesc->Fields.Add(NewVar);

			OnStructureChanged(*StructureDesc, Blueprint);
			return true;
		}
	}
	return false;
}
bool FStructureEditorUtils::RenameVariable(UUserDefinedStruct* Struct, FGuid VarGuid, const FString& NewDisplayNameStr)
{
    if (Struct)
    {
        auto VarDesc = GetVarDescByGuid(Struct, VarGuid);
        if (VarDesc
                && !NewDisplayNameStr.IsEmpty()
                && FName(*NewDisplayNameStr).IsValidXName(INVALID_OBJECTNAME_CHARACTERS)
                && IsUniqueVariableDisplayName(Struct, NewDisplayNameStr))
        {
            const FScopedTransaction Transaction(LOCTEXT("RenameVariable", "Rename Variable"));
            ModifyStructData(Struct);

            VarDesc->FriendlyName = NewDisplayNameStr;
            //>>> TEMPORARY it's more important to prevent changes in structs instances, than to have consistent names
            if (GetGuidFromPropertyName(VarDesc->VarName).IsValid())
                //<<< TEMPORARY
            {
                const FName NewName = FMemberVariableNameHelper::Generate(Struct, NewDisplayNameStr, VarGuid);
                check(NULL == GetVarDesc(Struct).FindByPredicate(FFindByNameHelper<FStructVariableDescription>(NewName)))
                VarDesc->VarName = NewName;
            }
            OnStructureChanged(Struct);
            return true;
        }
    }
    return false;
}
bool FStructureEditorUtils::AddVariable(UUserDefinedStruct* Struct, const FEdGraphPinType& VarType)
{
    if (Struct)
    {
        const FScopedTransaction Transaction( LOCTEXT("AddVariable", "Add Variable") );
        ModifyStructData(Struct);

        FString ErrorMessage;
        if (!CanHaveAMemberVariableOfType(Struct, VarType, &ErrorMessage))
        {
            UE_LOG(LogBlueprint, Warning, TEXT("%s"), *ErrorMessage);
            return false;
        }

        const FGuid Guid = FGuid::NewGuid();
        FString DisplayName;
        const FName VarName = FMemberVariableNameHelper::Generate(Struct, FString(), Guid, &DisplayName);
        check(NULL == GetVarDesc(Struct).FindByPredicate(FStructureEditorUtils::FFindByNameHelper<FStructVariableDescription>(VarName)));
        check(IsUniqueVariableDisplayName(Struct, DisplayName));

        FStructVariableDescription NewVar;
        NewVar.VarName = VarName;
        NewVar.FriendlyName = DisplayName;
        NewVar.SetPinType(VarType);
        NewVar.VarGuid = Guid;
        NewVar.bDontEditoOnInstance = false;
        NewVar.bInvalidMember = false;
        GetVarDesc(Struct).Add(NewVar);

        OnStructureChanged(Struct);
        return true;
    }
    return false;
}
bool FStructureEditorUtils::RenameVariable(UBlueprint* Blueprint, FName StructName, FGuid VarGuid, const FString& NewDisplayNameStr)
{
	if (NULL != Blueprint)
	{
		const FScopedTransaction Transaction( LOCTEXT("RenameVariable", "Rename Variable") );
		Blueprint->Modify();

		FBPStructureDescription* StructureDesc = Blueprint->UserDefinedStructures.FindByPredicate(FFindByNameHelper(StructName));
		if (StructureDesc)
		{
			const FName NewNameBase(*NewDisplayNameStr);
			if (NewNameBase.IsValidXName(INVALID_OBJECTNAME_CHARACTERS) &&
				IsUniqueVariableDisplayName(Blueprint, StructName, NewDisplayNameStr))
			{
				const FName NewName = FMemberVariableNameHelper::Generate(StructureDesc->CompiledStruct, NewDisplayNameStr);
				if (NULL == StructureDesc->Fields.FindByPredicate(FFindByNameHelper(NewName)))
				{
					FBPVariableDescription* VarDesc = StructureDesc->Fields.FindByPredicate(FFindByGuidHelper(VarGuid));
					if (VarDesc)
					{
						VarDesc->FriendlyName = NewDisplayNameStr;
						VarDesc->VarName = NewName;
						OnStructureChanged(*StructureDesc, Blueprint);
						return true;
					}
				}
			}
		}
	}
	return false;
}