2019-12-27 09:26:59 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2018-04-12 16:57:51 -04:00
# include "ControlRigBlueprintUtils.h"
# include "Kismet2/BlueprintEditorUtils.h"
# include "Units/RigUnit.h"
# include "UObject/UObjectIterator.h"
# include "ControlRig.h"
2019-01-08 11:38:48 -05:00
# include "Graph/ControlRigGraphNode.h"
2018-04-12 16:57:51 -04:00
# include "ControlRigBlueprint.h"
2019-05-21 19:25:23 -04:00
# include "Kismet2/Kismet2NameValidators.h"
2018-04-12 16:57:51 -04:00
# define LOCTEXT_NAMESPACE "ControlRigBlueprintUtils"
2019-05-21 19:25:23 -04:00
FName FControlRigBlueprintUtils : : ValidateName ( UBlueprint * InBlueprint , const FString & InName )
{
2019-07-16 11:49:59 -04:00
DECLARE_SCOPE_HIERARCHICAL_COUNTER_FUNC ( )
2019-05-21 19:25:23 -04:00
FString Name = InName ;
if ( Name . StartsWith ( TEXT ( " RigUnit_ " ) ) )
{
2019-11-19 13:27:07 -05:00
Name . RightChopInline ( 8 , false ) ;
2019-05-21 19:25:23 -04:00
}
TSharedPtr < FKismetNameValidator > NameValidator ;
NameValidator = MakeShareable ( new FKismetNameValidator ( InBlueprint ) ) ;
// Clean up BaseName to not contain any invalid characters, which will mean we can never find a legal name no matter how many numbers we add
if ( NameValidator - > IsValid ( Name ) = = EValidatorResult : : ContainsInvalidCharacters )
{
for ( TCHAR & TestChar : Name )
{
for ( TCHAR BadChar : UE_BLUEPRINT_INVALID_NAME_CHARACTERS )
{
if ( TestChar = = BadChar )
{
TestChar = TEXT ( ' _ ' ) ;
break ;
}
}
}
}
if ( UClass * ParentClass = InBlueprint - > ParentClass )
{
2020-03-15 10:33:45 -04:00
FFieldVariant ExistingField = FindUFieldOrFProperty ( ParentClass , * Name ) ;
if ( ExistingField )
2019-05-21 19:25:23 -04:00
{
Name = FString : : Printf ( TEXT ( " %s_%d " ) , * Name , 0 ) ;
}
}
int32 Count = 0 ;
FString BaseName = Name ;
while ( NameValidator - > IsValid ( Name ) ! = EValidatorResult : : Ok )
{
// Calculate the number of digits in the number, adding 2 (1 extra to correctly count digits, another to account for the '_' that will be added to the name
int32 CountLength = Count > 0 ? ( int32 ) log ( ( double ) Count ) + 2 : 2 ;
// If the length of the final string will be too long, cut off the end so we can fit the number
if ( CountLength + BaseName . Len ( ) > NameValidator - > GetMaximumNameLength ( ) )
{
2019-11-19 13:27:07 -05:00
BaseName . LeftInline ( NameValidator - > GetMaximumNameLength ( ) - CountLength ) ;
2019-05-21 19:25:23 -04:00
}
Name = FString : : Printf ( TEXT ( " %s_%d " ) , * BaseName , Count ) ;
Count + + ;
}
return * Name ;
}
2020-01-22 17:58:55 -05:00
void FControlRigBlueprintUtils : : ForAllRigUnits ( TFunction < void ( UScriptStruct * ) > InFunction )
2018-04-12 16:57:51 -04:00
{
2019-07-16 11:49:59 -04:00
DECLARE_SCOPE_HIERARCHICAL_COUNTER_FUNC ( )
2018-04-12 16:57:51 -04:00
// Run over all unit types
for ( TObjectIterator < UStruct > StructIt ; StructIt ; + + StructIt )
{
2022-06-01 16:30:52 -04:00
if ( * StructIt )
2018-04-12 16:57:51 -04:00
{
2022-06-01 16:30:52 -04:00
if ( StructIt - > IsChildOf ( FRigUnit : : StaticStruct ( ) ) & & ! StructIt - > HasMetaData ( FRigVMStruct : : AbstractMetaName ) )
2020-01-22 17:58:55 -05:00
{
2022-06-01 16:30:52 -04:00
if ( UScriptStruct * ScriptStruct = Cast < UScriptStruct > ( * StructIt ) )
{
InFunction ( ScriptStruct ) ;
}
2020-01-22 17:58:55 -05:00
}
2018-04-12 16:57:51 -04:00
}
}
}
void FControlRigBlueprintUtils : : HandleReconstructAllNodes ( UBlueprint * InBlueprint )
{
2019-07-16 11:49:59 -04:00
DECLARE_SCOPE_HIERARCHICAL_COUNTER_FUNC ( )
2020-01-22 17:58:55 -05:00
return HandleRefreshAllNodes ( InBlueprint ) ;
2018-04-12 16:57:51 -04:00
}
void FControlRigBlueprintUtils : : HandleRefreshAllNodes ( UBlueprint * InBlueprint )
{
2019-07-16 11:49:59 -04:00
DECLARE_SCOPE_HIERARCHICAL_COUNTER_FUNC ( )
2023-02-03 20:52:25 -05:00
# ifdef WITH_EDITORONLY_DATA
// Avoid refreshing EdGraph nodes during cook
if ( GIsCookerLoadingPackage )
{
return ;
}
2020-06-23 18:40:00 -04:00
if ( UControlRigBlueprint * RigBlueprint = Cast < UControlRigBlueprint > ( InBlueprint ) )
2018-04-12 16:57:51 -04:00
{
2022-05-31 04:27:20 -04:00
if ( RigBlueprint - > GetDefaultModel ( ) = = nullptr )
2020-06-23 18:40:00 -04:00
{
return ;
}
2018-04-12 16:57:51 -04:00
TArray < UControlRigGraphNode * > AllNodes ;
2020-06-23 18:40:00 -04:00
FBlueprintEditorUtils : : GetAllNodesOfClass ( RigBlueprint , AllNodes ) ;
2018-04-12 16:57:51 -04:00
2020-09-24 00:43:27 -04:00
for ( UControlRigGraphNode * Node : AllNodes )
{
Node - > SetFlags ( RF_Transient ) ;
}
2018-04-12 16:57:51 -04:00
for ( UControlRigGraphNode * Node : AllNodes )
{
Node - > ReconstructNode ( ) ;
}
2020-09-24 00:43:27 -04:00
for ( UControlRigGraphNode * Node : AllNodes )
{
Node - > ClearFlags ( RF_Transient ) ;
}
2018-04-12 16:57:51 -04:00
}
2023-02-03 20:52:25 -05:00
# endif
2018-04-12 16:57:51 -04:00
}
void FControlRigBlueprintUtils : : RemoveMemberVariableIfNotUsed ( UBlueprint * Blueprint , const FName VarName , UControlRigGraphNode * ToBeDeleted )
{
2019-07-16 11:49:59 -04:00
DECLARE_SCOPE_HIERARCHICAL_COUNTER_FUNC ( )
2018-04-12 16:57:51 -04:00
if ( Blueprint - > IsA < UControlRigBlueprint > ( ) )
{
2020-01-22 17:58:55 -05:00
FBlueprintEditorUtils : : RemoveMemberVariable ( Blueprint , VarName ) ;
2018-04-12 16:57:51 -04:00
}
}
# undef LOCTEXT_NAMESPACE