2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
# include "AnimGraphPrivatePCH.h"
2014-04-24 08:49:31 -04:00
# include "AnimGraphNode_TwoBoneIK.h"
2014-11-14 05:00:37 -05:00
# include "DebugRenderSceneProxy.h"
2014-03-14 14:13:41 -04:00
2014-09-22 09:45:11 -04:00
// for customization details
# include "../../PropertyEditor/Public/PropertyHandle.h"
# include "../../PropertyEditor/Public/DetailLayoutBuilder.h"
# include "../../PropertyEditor/Public/DetailCategoryBuilder.h"
# include "../../PropertyEditor/Public/DetailWidgetRow.h"
# include "../../PropertyEditor/Public/IDetailPropertyRow.h"
# define LOCTEXT_NAMESPACE "A3Nodes"
/////////////////////////////////////////////////////
// FTwoBoneIKDelegate
class FTwoBoneIKDelegate : public TSharedFromThis < FTwoBoneIKDelegate >
{
public :
void UpdateLocationSpace ( class IDetailLayoutBuilder * DetailBuilder )
{
if ( DetailBuilder )
{
DetailBuilder - > ForceRefreshDetails ( ) ;
}
}
} ;
2014-11-14 05:00:37 -05:00
TSharedPtr < FTwoBoneIKDelegate > UAnimGraphNode_TwoBoneIK : : TwoBoneIKDelegate = NULL ;
2014-03-14 14:13:41 -04:00
/////////////////////////////////////////////////////
// UAnimGraphNode_TwoBoneIK
2014-04-23 18:30:37 -04:00
2014-10-14 10:29:11 -04:00
UAnimGraphNode_TwoBoneIK : : UAnimGraphNode_TwoBoneIK ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
{
2014-11-14 05:00:37 -05:00
BoneSelectMode = BSM_EndEffector ;
2014-03-14 14:13:41 -04:00
}
2014-04-23 18:30:37 -04:00
FText UAnimGraphNode_TwoBoneIK : : GetControllerDescription ( ) const
2014-03-14 14:13:41 -04:00
{
2014-04-23 18:30:37 -04:00
return LOCTEXT ( " TwoBoneIK " , " Two Bone IK " ) ;
2014-03-14 14:13:41 -04:00
}
2014-09-03 18:14:09 -04:00
FText UAnimGraphNode_TwoBoneIK : : GetTooltipText ( ) const
2014-03-14 14:13:41 -04:00
{
2014-09-03 18:14:09 -04:00
return LOCTEXT ( " AnimGraphNode_TwoBoneIK_Tooltip " , " The Two Bone IK control applies an inverse kinematic (IK) solver to a 3 - joint chain , such as the limbs of a character . " ) ;
2014-03-14 14:13:41 -04:00
}
2014-04-23 18:30:37 -04:00
FText UAnimGraphNode_TwoBoneIK : : GetNodeTitle ( ENodeTitleType : : Type TitleType ) const
2014-03-14 14:13:41 -04:00
{
2014-09-16 15:01:38 -04:00
if ( ( TitleType = = ENodeTitleType : : ListView | | TitleType = = ENodeTitleType : : MenuTitle ) & & ( Node . IKBone . BoneName = = NAME_None ) )
2014-09-04 11:25:05 -04:00
{
return GetControllerDescription ( ) ;
}
2014-09-24 14:15:13 -04:00
// @TODO: the bone can be altered in the property editor, so we have to
// choose to mark this dirty when that happens for this to properly work
2015-04-02 11:16:23 -04:00
else //if (!CachedNodeTitles.IsTitleCached(TitleType, this))
2014-09-04 11:25:05 -04:00
{
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " ControllerDescription " ) , GetControllerDescription ( ) ) ;
Args . Add ( TEXT ( " BoneName " ) , FText : : FromName ( Node . IKBone . BoneName ) ) ;
2014-04-23 18:30:37 -04:00
2014-09-04 11:25:05 -04:00
// FText::Format() is slow, so we cache this to save on performance
2014-09-16 15:01:38 -04:00
if ( TitleType = = ENodeTitleType : : ListView | | TitleType = = ENodeTitleType : : MenuTitle )
2014-08-21 18:50:33 -04:00
{
2015-04-02 11:16:23 -04:00
CachedNodeTitles . SetCachedTitle ( TitleType , FText : : Format ( LOCTEXT ( " AnimGraphNode_IKBone_ListTitle " , " {ControllerDescription} - Bone: {BoneName} " ) , Args ) , this ) ;
2014-09-04 11:25:05 -04:00
}
else
{
2015-04-02 11:16:23 -04:00
CachedNodeTitles . SetCachedTitle ( TitleType , FText : : Format ( LOCTEXT ( " AnimGraphNode_IKBone_Title " , " {ControllerDescription} \n Bone: {BoneName} " ) , Args ) , this ) ;
2014-08-21 18:50:33 -04:00
}
2014-04-23 18:30:37 -04:00
}
2014-09-04 11:25:05 -04:00
return CachedNodeTitles [ TitleType ] ;
2014-04-23 18:30:37 -04:00
}
2014-03-14 14:13:41 -04:00
void UAnimGraphNode_TwoBoneIK : : Draw ( FPrimitiveDrawInterface * PDI , USkeletalMeshComponent * SkelMeshComp ) const
{
2014-09-22 09:45:11 -04:00
if ( SkelMeshComp & & SkelMeshComp - > SkeletalMesh & & SkelMeshComp - > SkeletalMesh - > Skeleton )
2014-03-14 14:13:41 -04:00
{
2014-11-14 05:00:37 -05:00
USkeleton * Skeleton = SkelMeshComp - > SkeletalMesh - > Skeleton ;
2014-03-14 14:13:41 -04:00
2014-09-22 09:45:11 -04:00
DrawTargetLocation ( PDI , SkelMeshComp , Skeleton , Node . EffectorLocationSpace , Node . EffectorSpaceBoneName , Node . EffectorLocation , FColor ( 255 , 128 , 128 ) , FColor ( 180 , 128 , 128 ) ) ;
DrawTargetLocation ( PDI , SkelMeshComp , Skeleton , Node . JointTargetLocationSpace , Node . JointTargetSpaceBoneName , Node . JointTargetLocation , FColor ( 128 , 255 , 128 ) , FColor ( 128 , 180 , 128 ) ) ;
2014-03-14 14:13:41 -04:00
}
}
2014-11-14 05:00:37 -05:00
void UAnimGraphNode_TwoBoneIK : : DrawTargetLocation ( FPrimitiveDrawInterface * PDI , USkeletalMeshComponent * SkelComp , USkeleton * Skeleton , EBoneControlSpace SpaceBase , FName SpaceBoneName , const FVector & TargetLocation , const FColor & TargetColor , const FColor & BoneColor ) const
2014-03-14 14:13:41 -04:00
{
const bool bInBoneSpace = ( SpaceBase = = BCS_ParentBoneSpace ) | | ( SpaceBase = = BCS_BoneSpace ) ;
const int32 SpaceBoneIndex = bInBoneSpace ? Skeleton - > GetReferenceSkeleton ( ) . FindBoneIndex ( SpaceBoneName ) : INDEX_NONE ;
// Transform EffectorLocation from EffectorLocationSpace to ComponentSpace.
FTransform TargetTransform = FTransform ( TargetLocation ) ;
FTransform CSTransform ;
2014-11-14 05:00:37 -05:00
ConvertToComponentSpaceTransform ( SkelComp , TargetTransform , CSTransform , SpaceBoneIndex , SpaceBase ) ;
2014-03-14 14:13:41 -04:00
FTransform WorldTransform = CSTransform * SkelComp - > ComponentToWorld ;
2014-11-14 05:00:37 -05:00
#if 0 // @TODO : remove this code because this doesn't show correct target location
2014-03-14 14:13:41 -04:00
DrawCoordinateSystem ( PDI , WorldTransform . GetLocation ( ) , WorldTransform . GetRotation ( ) . Rotator ( ) , 20.f , SDPG_Foreground ) ;
DrawWireDiamond ( PDI , WorldTransform . ToMatrixWithScale ( ) , 2.f , TargetColor , SDPG_Foreground ) ;
2014-11-14 05:00:37 -05:00
# endif
2014-03-14 14:13:41 -04:00
if ( bInBoneSpace )
{
2014-11-14 05:00:37 -05:00
ConvertToComponentSpaceTransform ( SkelComp , FTransform : : Identity , CSTransform , SpaceBoneIndex , SpaceBase ) ;
2014-03-14 14:13:41 -04:00
WorldTransform = CSTransform * SkelComp - > ComponentToWorld ;
DrawCoordinateSystem ( PDI , WorldTransform . GetLocation ( ) , WorldTransform . GetRotation ( ) . Rotator ( ) , 20.f , SDPG_Foreground ) ;
DrawWireDiamond ( PDI , WorldTransform . ToMatrixWithScale ( ) , 2.f , BoneColor , SDPG_Foreground ) ;
}
}
2014-11-14 05:00:37 -05:00
void UAnimGraphNode_TwoBoneIK : : CopyNodeDataTo ( FAnimNode_Base * AnimNode )
2014-03-14 14:13:41 -04:00
{
2014-11-14 05:00:37 -05:00
FAnimNode_TwoBoneIK * TwoBoneIK = static_cast < FAnimNode_TwoBoneIK * > ( AnimNode ) ;
// copies Pin values from the internal node to get data which are not compiled yet
2015-02-18 03:59:11 -05:00
TwoBoneIK - > EffectorLocation = GetNodeValue ( FString ( " EffectorLocation " ) , Node . EffectorLocation ) ;
TwoBoneIK - > JointTargetLocation = GetNodeValue ( FString ( " JointTargetLocation " ) , Node . JointTargetLocation ) ;
2014-11-14 05:00:37 -05:00
}
void UAnimGraphNode_TwoBoneIK : : CopyNodeDataFrom ( const FAnimNode_Base * InNewAnimNode )
{
const FAnimNode_TwoBoneIK * TwoBoneIK = static_cast < const FAnimNode_TwoBoneIK * > ( InNewAnimNode ) ;
2015-02-18 03:59:11 -05:00
if ( BoneSelectMode = = BSM_EndEffector )
{
SetNodeValue ( FString ( " EffectorLocation " ) , Node . EffectorLocation , TwoBoneIK - > EffectorLocation ) ;
}
else
{
SetNodeValue ( FString ( " JointTargetLocation " ) , Node . JointTargetLocation , TwoBoneIK - > JointTargetLocation ) ;
}
2014-11-14 05:00:37 -05:00
}
FVector UAnimGraphNode_TwoBoneIK : : GetWidgetLocation ( const USkeletalMeshComponent * SkelComp , FAnimNode_SkeletalControlBase * AnimNode )
{
EBoneControlSpace Space ;
FName BoneName ;
FVector Location ;
if ( BoneSelectMode = = BSM_EndEffector )
2014-03-14 14:13:41 -04:00
{
2014-11-14 05:00:37 -05:00
Space = Node . EffectorLocationSpace ;
2015-02-18 03:59:11 -05:00
Location = GetNodeValue ( FString ( " EffectorLocation " ) , Node . EffectorLocation ) ;
2014-11-14 05:00:37 -05:00
BoneName = Node . EffectorSpaceBoneName ;
2014-03-14 14:13:41 -04:00
2014-11-14 05:00:37 -05:00
}
else // BSM_JointTarget
{
Space = Node . JointTargetLocationSpace ;
2014-03-14 14:13:41 -04:00
2014-11-14 05:00:37 -05:00
if ( Space = = BCS_WorldSpace | | Space = = BCS_ComponentSpace )
2014-03-14 14:13:41 -04:00
{
2014-11-14 05:00:37 -05:00
return FVector : : ZeroVector ;
}
2015-02-18 03:59:11 -05:00
Location = GetNodeValue ( FString ( " JointTargetLocation " ) , Node . JointTargetLocation ) ;
2014-11-14 05:00:37 -05:00
BoneName = Node . JointTargetSpaceBoneName ;
}
return ConvertWidgetLocation ( SkelComp , AnimNode - > ForwardedPose , BoneName , Location , Space ) ;
}
2014-11-14 10:55:42 -05:00
int32 UAnimGraphNode_TwoBoneIK : : GetWidgetMode ( const USkeletalMeshComponent * SkelComp )
2014-11-14 05:00:37 -05:00
{
int32 BoneIndex = SkelComp - > GetBoneIndex ( Node . IKBone . BoneName ) ;
// Two bone IK node uses only Translate
if ( BoneIndex ! = INDEX_NONE )
{
return FWidget : : WM_Translate ;
}
return FWidget : : WM_None ;
}
void UAnimGraphNode_TwoBoneIK : : MoveSelectActorLocation ( const USkeletalMeshComponent * SkelComp , FAnimNode_SkeletalControlBase * AnimNode )
{
USkeleton * Skeleton = SkelComp - > SkeletalMesh - > Skeleton ;
// create a bone select actor
if ( ! BoneSelectActor . IsValid ( ) )
{
if ( Node . JointTargetLocationSpace = = EBoneControlSpace : : BCS_BoneSpace | |
Node . JointTargetLocationSpace = = EBoneControlSpace : : BCS_ParentBoneSpace )
{
int32 JointTargetIndex = Skeleton - > GetReferenceSkeleton ( ) . FindBoneIndex ( Node . JointTargetSpaceBoneName ) ;
if ( JointTargetIndex ! = INDEX_NONE )
2014-03-14 14:13:41 -04:00
{
2014-11-14 05:00:37 -05:00
UWorld * World = SkelComp - > GetWorld ( ) ;
check ( World ) ;
BoneSelectActor = World - > SpawnActor < ABoneSelectActor > ( FVector ( 0 ) , FRotator ( 0 , 0 , 0 ) ) ;
check ( BoneSelectActor . IsValid ( ) ) ;
2014-03-14 14:13:41 -04:00
}
}
2014-11-14 05:00:37 -05:00
}
2014-03-14 14:13:41 -04:00
2014-11-14 05:00:37 -05:00
if ( ! BoneSelectActor . IsValid ( ) )
{
return ;
}
2014-03-14 14:13:41 -04:00
2014-11-14 05:00:37 -05:00
// move the actor's position
if ( BoneSelectMode = = BSM_JointTarget )
{
FName BoneName ;
int32 EffectorBoneIndex = SkelComp - > GetBoneIndex ( Node . EffectorSpaceBoneName ) ;
if ( EffectorBoneIndex ! = INDEX_NONE )
2014-03-14 14:13:41 -04:00
{
2014-11-14 05:00:37 -05:00
BoneName = Node . EffectorSpaceBoneName ;
2014-03-14 14:13:41 -04:00
}
else
{
2014-11-14 05:00:37 -05:00
BoneName = Node . IKBone . BoneName ;
}
FVector ActorLocation = ConvertWidgetLocation ( SkelComp , AnimNode - > ForwardedPose , BoneName , Node . EffectorLocation , Node . EffectorLocationSpace ) ;
BoneSelectActor - > SetActorLocation ( ActorLocation + FVector ( 0 , 10 , 0 ) ) ;
}
else if ( BoneSelectMode = = BSM_EndEffector )
{
int32 JointTargetIndex = SkelComp - > GetBoneIndex ( Node . JointTargetSpaceBoneName ) ;
if ( JointTargetIndex ! = INDEX_NONE )
{
FVector ActorLocation = ConvertWidgetLocation ( SkelComp , AnimNode - > ForwardedPose , Node . JointTargetSpaceBoneName , Node . JointTargetLocation , Node . JointTargetLocationSpace ) ;
BoneSelectActor - > SetActorLocation ( ActorLocation + FVector ( 0 , 10 , 0 ) ) ;
2014-03-14 14:13:41 -04:00
}
}
}
2014-04-23 18:30:37 -04:00
2014-11-14 05:00:37 -05:00
FName UAnimGraphNode_TwoBoneIK : : FindSelectedBone ( )
{
FName SelectedBone ;
// should return mesh bone index
if ( BoneSelectMode = = BSM_EndEffector )
{
if ( Node . EffectorLocationSpace = = EBoneControlSpace : : BCS_BoneSpace | |
Node . EffectorLocationSpace = = EBoneControlSpace : : BCS_ParentBoneSpace )
{
SelectedBone = Node . EffectorSpaceBoneName ;
}
else
{
SelectedBone = Node . IKBone . BoneName ;
}
}
else if ( BoneSelectMode = = BSM_JointTarget )
{
SelectedBone = Node . JointTargetSpaceBoneName ;
}
return SelectedBone ;
}
bool UAnimGraphNode_TwoBoneIK : : IsActorClicked ( HActor * ActorHitProxy )
{
ABoneSelectActor * BoneActor = Cast < ABoneSelectActor > ( ActorHitProxy - > Actor ) ;
if ( BoneActor )
{
return true ;
}
return false ;
}
void UAnimGraphNode_TwoBoneIK : : ProcessActorClick ( HActor * ActorHitProxy )
{
// toggle bone selection mode
if ( BoneSelectMode = = BSM_EndEffector )
{
BoneSelectMode = BSM_JointTarget ;
}
else
{
BoneSelectMode = BSM_EndEffector ;
}
}
void UAnimGraphNode_TwoBoneIK : : DoTranslation ( const USkeletalMeshComponent * SkelComp , FVector & Drag , FAnimNode_Base * InOutAnimNode )
{
FAnimNode_TwoBoneIK * TwoBoneIK = static_cast < FAnimNode_TwoBoneIK * > ( InOutAnimNode ) ;
if ( BoneSelectMode = = BSM_EndEffector )
{
FVector Offset = ConvertCSVectorToBoneSpace ( SkelComp , Drag , TwoBoneIK - > ForwardedPose , FindSelectedBone ( ) , Node . EffectorLocationSpace ) ;
TwoBoneIK - > EffectorLocation + = Offset ;
Node . EffectorLocation = TwoBoneIK - > EffectorLocation ;
}
else if ( BoneSelectMode = = BSM_JointTarget )
{
FVector Offset = ConvertCSVectorToBoneSpace ( SkelComp , Drag , TwoBoneIK - > ForwardedPose , FindSelectedBone ( ) , Node . JointTargetLocationSpace ) ;
TwoBoneIK - > JointTargetLocation + = Offset ;
Node . JointTargetLocation = TwoBoneIK - > JointTargetLocation ;
}
}
void UAnimGraphNode_TwoBoneIK : : DeselectActor ( USkeletalMeshComponent * SkelComp )
{
if ( BoneSelectActor ! = NULL )
{
if ( SkelComp - > GetWorld ( ) - > DestroyActor ( BoneSelectActor . Get ( ) ) )
{
BoneSelectActor = NULL ;
}
}
}
2014-09-22 09:45:11 -04:00
void UAnimGraphNode_TwoBoneIK : : CustomizeDetails ( class IDetailLayoutBuilder & DetailBuilder )
{
// initialize just once
if ( ! TwoBoneIKDelegate . IsValid ( ) )
{
TwoBoneIKDelegate = MakeShareable ( new FTwoBoneIKDelegate ( ) ) ;
}
EBoneControlSpace Space = Node . EffectorLocationSpace ;
2014-11-14 05:00:37 -05:00
const FString TakeRotationPropName = FString : : Printf ( TEXT ( " Node.%s " ) , GET_MEMBER_NAME_STRING_CHECKED ( FAnimNode_TwoBoneIK , bTakeRotationFromEffectorSpace ) ) ;
const FString MaintainEffectorPropName = FString : : Printf ( TEXT ( " Node.%s " ) , GET_MEMBER_NAME_STRING_CHECKED ( FAnimNode_TwoBoneIK , bMaintainEffectorRelRot ) ) ;
const FString EffectorBoneName = FString : : Printf ( TEXT ( " Node.%s " ) , GET_MEMBER_NAME_STRING_CHECKED ( FAnimNode_TwoBoneIK , EffectorSpaceBoneName ) ) ;
const FString EffectorLocationPropName = FString : : Printf ( TEXT ( " Node.%s " ) , GET_MEMBER_NAME_STRING_CHECKED ( FAnimNode_TwoBoneIK , EffectorLocation ) ) ;
2014-09-22 09:45:11 -04:00
if ( Space = = BCS_BoneSpace | | Space = = BCS_ParentBoneSpace )
{
IDetailCategoryBuilder & IKCategory = DetailBuilder . EditCategory ( " IK " ) ;
IDetailCategoryBuilder & EffectorCategory = DetailBuilder . EditCategory ( " EndEffector " ) ;
TSharedPtr < IPropertyHandle > PropertyHandle ;
2014-11-14 05:00:37 -05:00
PropertyHandle = DetailBuilder . GetProperty ( * TakeRotationPropName , GetClass ( ) ) ;
2014-09-22 09:45:11 -04:00
EffectorCategory . AddProperty ( PropertyHandle ) ;
2014-11-14 05:00:37 -05:00
PropertyHandle = DetailBuilder . GetProperty ( * MaintainEffectorPropName , GetClass ( ) ) ;
2014-09-22 09:45:11 -04:00
EffectorCategory . AddProperty ( PropertyHandle ) ;
2014-11-14 05:00:37 -05:00
PropertyHandle = DetailBuilder . GetProperty ( * EffectorBoneName , GetClass ( ) ) ;
2014-09-22 09:45:11 -04:00
EffectorCategory . AddProperty ( PropertyHandle ) ;
}
else // hide all properties in EndEffector category
{
2014-11-14 05:00:37 -05:00
TSharedPtr < IPropertyHandle > PropertyHandle = DetailBuilder . GetProperty ( * EffectorLocationPropName , GetClass ( ) ) ;
2014-09-22 09:45:11 -04:00
DetailBuilder . HideProperty ( PropertyHandle ) ;
2014-11-14 05:00:37 -05:00
PropertyHandle = DetailBuilder . GetProperty ( * TakeRotationPropName , GetClass ( ) ) ;
2014-09-22 09:45:11 -04:00
DetailBuilder . HideProperty ( PropertyHandle ) ;
2014-11-14 05:00:37 -05:00
PropertyHandle = DetailBuilder . GetProperty ( * MaintainEffectorPropName , GetClass ( ) ) ;
2014-09-22 09:45:11 -04:00
DetailBuilder . HideProperty ( PropertyHandle ) ;
2014-11-14 05:00:37 -05:00
PropertyHandle = DetailBuilder . GetProperty ( * EffectorBoneName , GetClass ( ) ) ;
2014-09-22 09:45:11 -04:00
DetailBuilder . HideProperty ( PropertyHandle ) ;
}
Space = Node . JointTargetLocationSpace ;
2014-11-14 05:00:37 -05:00
bool bPinVisibilityChanged = false ;
const FString JointTargetSpaceBoneName = FString : : Printf ( TEXT ( " Node.%s " ) , GET_MEMBER_NAME_STRING_CHECKED ( FAnimNode_TwoBoneIK , JointTargetSpaceBoneName ) ) ;
const FString JointTargetLocation = FString : : Printf ( TEXT ( " Node.%s " ) , GET_MEMBER_NAME_STRING_CHECKED ( FAnimNode_TwoBoneIK , JointTargetLocation ) ) ;
2014-09-22 09:45:11 -04:00
if ( Space = = BCS_BoneSpace | | Space = = BCS_ParentBoneSpace )
{
IDetailCategoryBuilder & IKCategory = DetailBuilder . EditCategory ( " IK " ) ;
IDetailCategoryBuilder & EffectorCategory = DetailBuilder . EditCategory ( " JointTarget " ) ;
TSharedPtr < IPropertyHandle > PropertyHandle ;
2014-11-14 05:00:37 -05:00
PropertyHandle = DetailBuilder . GetProperty ( * JointTargetSpaceBoneName , GetClass ( ) ) ;
2014-09-22 09:45:11 -04:00
EffectorCategory . AddProperty ( PropertyHandle ) ;
2014-11-14 05:00:37 -05:00
bPinVisibilityChanged = SetPinsVisibility ( true ) ;
2014-09-22 09:45:11 -04:00
}
else // hide all properties in JointTarget category except for JointTargetLocationSpace
{
2014-11-14 05:00:37 -05:00
TSharedPtr < IPropertyHandle > PropertyHandle = DetailBuilder . GetProperty ( * JointTargetLocation , GetClass ( ) ) ;
2014-09-22 09:45:11 -04:00
DetailBuilder . HideProperty ( PropertyHandle ) ;
2014-11-14 05:00:37 -05:00
PropertyHandle = DetailBuilder . GetProperty ( * JointTargetSpaceBoneName , GetClass ( ) ) ;
2014-09-22 09:45:11 -04:00
DetailBuilder . HideProperty ( PropertyHandle ) ;
2014-11-14 05:00:37 -05:00
bPinVisibilityChanged = SetPinsVisibility ( false ) ;
2014-09-22 09:45:11 -04:00
}
2014-11-14 05:00:37 -05:00
const FString EffectorLocationSpace = FString : : Printf ( TEXT ( " Node.%s " ) , GET_MEMBER_NAME_STRING_CHECKED ( FAnimNode_TwoBoneIK , EffectorLocationSpace ) ) ;
const FString JointTargetLocationSpace = FString : : Printf ( TEXT ( " Node.%s " ) , GET_MEMBER_NAME_STRING_CHECKED ( FAnimNode_TwoBoneIK , JointTargetLocationSpace ) ) ;
2014-09-22 09:45:11 -04:00
// refresh UIs when bone space is changed
2014-11-14 05:00:37 -05:00
TSharedRef < IPropertyHandle > EffectorLocHandle = DetailBuilder . GetProperty ( * EffectorLocationSpace , GetClass ( ) ) ;
2014-09-22 09:45:11 -04:00
if ( EffectorLocHandle - > IsValidHandle ( ) )
{
FSimpleDelegate UpdateEffectorSpaceDelegate = FSimpleDelegate : : CreateSP ( TwoBoneIKDelegate . Get ( ) , & FTwoBoneIKDelegate : : UpdateLocationSpace , & DetailBuilder ) ;
EffectorLocHandle - > SetOnPropertyValueChanged ( UpdateEffectorSpaceDelegate ) ;
}
2014-11-14 05:00:37 -05:00
TSharedRef < IPropertyHandle > JointTragetLocHandle = DetailBuilder . GetProperty ( * JointTargetLocationSpace , GetClass ( ) ) ;
2014-09-22 09:45:11 -04:00
if ( JointTragetLocHandle - > IsValidHandle ( ) )
{
FSimpleDelegate UpdateJointSpaceDelegate = FSimpleDelegate : : CreateSP ( TwoBoneIKDelegate . Get ( ) , & FTwoBoneIKDelegate : : UpdateLocationSpace , & DetailBuilder ) ;
JointTragetLocHandle - > SetOnPropertyValueChanged ( UpdateJointSpaceDelegate ) ;
}
// reconstruct node for showing/hiding Pins
2014-11-14 05:00:37 -05:00
if ( bPinVisibilityChanged )
2014-09-22 09:45:11 -04:00
{
2014-11-14 05:00:37 -05:00
ReconstructNode ( ) ;
2014-09-22 09:45:11 -04:00
}
}
2014-04-23 18:30:37 -04:00
2014-11-14 05:00:37 -05:00
bool UAnimGraphNode_TwoBoneIK : : SetPinsVisibility ( bool bShow )
{
bool bChanged = false ;
for ( FOptionalPinFromProperty & Pin : ShowPinForProperties )
{
if ( Pin . PropertyName = = GET_MEMBER_NAME_CHECKED ( FAnimNode_TwoBoneIK , JointTargetLocation ) )
{
PreEditChange ( NULL ) ;
if ( Pin . bShowPin ! = bShow )
{
Pin . bShowPin = bShow ;
bChanged = true ;
}
break ;
}
}
return bChanged ;
}
2014-04-23 18:30:37 -04:00
# undef LOCTEXT_NAMESPACE