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)
			{
				UWorld* World = SkelComp->GetWorld();
				check(World);

				BoneSelectActor = World->SpawnActor<ABoneSelectActor>(FVector(0), FRotator(0, 0, 0));
				check(BoneSelectActor.IsValid());
			}
		}
	}

	if (!BoneSelectActor.IsValid())
	{
		return;
	}

	// move the actor's position
	if (BoneSelectMode == BSM_JointTarget)
	{
		FName BoneName;
		int32 EffectorBoneIndex = SkelComp->GetBoneIndex(Node.EffectorSpaceBoneName);
		if (EffectorBoneIndex != INDEX_NONE)
		{
			BoneName = Node.EffectorSpaceBoneName;
		}
		else
		{
			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));
		}
	}
}
FVector UAnimGraphNode_TwoBoneIK::GetWidgetLocation(const USkeletalMeshComponent* SkelComp, FAnimNode_SkeletalControlBase* AnimNode)
{
	EBoneControlSpace Space;
	FName BoneName;
	FVector Location;
	 
	if (BoneSelectMode == BSM_EndEffector)
	{
		Space = Node.EffectorLocationSpace;
		Location = GetNodeValue(FString("EffectorLocation"), Node.EffectorLocation);
		BoneName = Node.EffectorSpaceBoneName;

	}
	else // BSM_JointTarget
	{
		Space = Node.JointTargetLocationSpace;

		if (Space == BCS_WorldSpace || Space == BCS_ComponentSpace)
		{
			return FVector::ZeroVector;
		}
		Location = GetNodeValue(FString("JointTargetLocation"), Node.JointTargetLocation);
		BoneName = Node.JointTargetSpaceBoneName;
	}

	return ConvertWidgetLocation(SkelComp, AnimNode->ForwardedPose, BoneName, Location, Space);
}
FVector UAnimGraphNode_Fabrik::GetWidgetLocation(const USkeletalMeshComponent* SkelComp, FAnimNode_SkeletalControlBase* AnimNode)
{
	FName& BoneName = Node.EffectorTransformBone.BoneName;
	FVector Location = Node.EffectorTransform.GetLocation();
	EBoneControlSpace Space = Node.EffectorTransformSpace;
	FVector WidgetLoc = ConvertWidgetLocation(SkelComp, AnimNode->ForwardedPose, BoneName, Location, Space);
	return WidgetLoc;
}
FVector FFabrikEditMode::GetWidgetLocation() const
{
	USkeletalMeshComponent* SkelComp = GetAnimPreviewScene().GetPreviewMeshComponent();

	FName& BoneName = GraphNode->Node.EffectorTransformBone.BoneName;
	FVector Location = GraphNode->Node.EffectorTransform.GetLocation();
	EBoneControlSpace Space = GraphNode->Node.EffectorTransformSpace;
	FVector WidgetLoc = ConvertWidgetLocation(SkelComp, RuntimeNode->ForwardedPose, BoneName, Location, Space);
	return WidgetLoc;
}
FVector UAnimGraphNode_ModifyBone::GetWidgetLocation(const USkeletalMeshComponent* SkelComp, FAnimNode_SkeletalControlBase* AnimNode)
{
	USkeleton* Skeleton = SkelComp->SkeletalMesh->Skeleton;
	FVector WidgetLoc = FVector::ZeroVector;

	// if the current widget mode is translate, then shows the widget according to translation space
	if (CurWidgetMode == FWidget::WM_Translate)
	{
		FCSPose<FCompactPose>& MeshBases = AnimNode->ForwardedPose;
		WidgetLoc = ConvertWidgetLocation(SkelComp, MeshBases, Node.BoneToModify.BoneName, GetNodeValue(FString("Translation"), Node.Translation), Node.TranslationSpace);

		if (MeshBases.GetPose().IsValid() && Node.TranslationMode == BMM_Additive)
		{
			if(Node.TranslationSpace == EBoneControlSpace::BCS_WorldSpace ||
				Node.TranslationSpace == EBoneControlSpace::BCS_ComponentSpace)
			{
				const FMeshPoseBoneIndex MeshBoneIndex(SkelComp->GetBoneIndex(Node.BoneToModify.BoneName));
				const FCompactPoseBoneIndex BoneIndex = MeshBases.GetPose().GetBoneContainer().MakeCompactPoseIndex(MeshBoneIndex);

				if (BoneIndex != INDEX_NONE)
				{
					const FTransform& BoneTM = MeshBases.GetComponentSpaceTransform(BoneIndex);
					WidgetLoc += BoneTM.GetLocation();
				}
			}
		}
	}
	else // if the current widget mode is not translate mode, then show the widget on the bone to modify
	{
		int32 MeshBoneIndex = SkelComp->GetBoneIndex(Node.BoneToModify.BoneName);

		if (MeshBoneIndex != INDEX_NONE)
		{
			const FTransform BoneTM = SkelComp->GetBoneTransform(MeshBoneIndex);
			WidgetLoc = BoneTM.GetLocation();
		}
	}
	
	return WidgetLoc;
}