[ue4] Added bone follower component, fixed up SkeletonComponent::SetBoneWorldPosition

This commit is contained in:
badlogic 2016-12-13 14:54:17 +01:00
parent 3b21f24027
commit 8287e90298
10 changed files with 135 additions and 7 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,29 @@
#include "SpinePluginPrivatePCH.h"
USpineBoneFollowerComponent::USpineBoneFollowerComponent () {
bWantsBeginPlay = true;
PrimaryComponentTick.bCanEverTick = true;
bTickInEditor = true;
bAutoActivate = true;
}
void USpineBoneFollowerComponent::BeginPlay () {
Super::BeginPlay();
}
void USpineBoneFollowerComponent::TickComponent ( float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction ) {
Super::TickComponent( DeltaTime, TickType, ThisTickFunction );
AActor* owner = GetOwner();
if (Target && owner) {
USpineSkeletonComponent* skeleton = static_cast<USpineSkeletonComponent*>(Target->GetComponentByClass(USpineSkeletonComponent::StaticClass()));
if (skeleton) {
FTransform transform = skeleton->GetBoneWorldTransform(BoneName);
if (UsePosition) owner->SetActorLocation(transform.GetLocation());
if (UseRotation) owner->SetActorRotation(transform.GetRotation());
if (UseScale) owner->SetActorScale3D(transform.GetScale3D());
}
}
}

View File

@ -9,3 +9,4 @@
#include "SpineSkeletonComponent.h"
#include "SpineSkeletonAnimationComponent.h"
#include "SpineSkeletonRendererComponent.h"
#include "SpineBoneFollowerComponent.h"

View File

@ -25,17 +25,18 @@ FTransform USpineSkeletonComponent::GetBoneWorldTransform (const FString& BoneNa
CheckState();
if (skeleton) {
spBone* bone = spSkeleton_findBone(skeleton, TCHAR_TO_UTF8(*BoneName));
if (!bone->appliedValid) this->InternalTick(0);
if (!bone) return FTransform();
if (!bone->appliedValid) this->InternalTick(0);
// Need to fetch the renderer component to get world transform of actor plus
// offset by renderer component and its parent component(s).
// FIXME add overloaded method that takes a base world transform?
// offset by renderer component and its parent component(s). If no renderer
// component is found, this components owner's transform is used as a fallback
FTransform baseTransform;
AActor* owner = GetOwner();
if (owner) {
USpineSkeletonRendererComponent* rendererComponent = static_cast<USpineSkeletonRendererComponent*>(owner->GetComponentByClass(USpineSkeletonRendererComponent::StaticClass()));
if (rendererComponent) baseTransform = rendererComponent->GetComponentTransform();
else baseTransform = owner->GetActorTransform();
}
FVector position(bone->worldX, 0, bone->worldY);
@ -53,8 +54,36 @@ FTransform USpineSkeletonComponent::GetBoneWorldTransform (const FString& BoneNa
return FTransform();
}
FTransform USpineSkeletonComponent::GetBoneLocalTransform (const FString& BoneName) {
return FTransform();
void USpineSkeletonComponent::SetBoneWorldPosition (const FString& BoneName, const FVector& position) {
CheckState();
if (skeleton) {
spBone* bone = spSkeleton_findBone(skeleton, TCHAR_TO_UTF8(*BoneName));
// Need to fetch the renderer component to get world transform of actor plus
// offset by renderer component and its parent component(s). If no renderer
// component is found, this components owner's transform is used as a fallback
FTransform baseTransform;
AActor* owner = GetOwner();
if (owner) {
USpineSkeletonRendererComponent* rendererComponent = static_cast<USpineSkeletonRendererComponent*>(owner->GetComponentByClass(USpineSkeletonRendererComponent::StaticClass()));
if (rendererComponent) baseTransform = rendererComponent->GetComponentTransform();
else baseTransform = owner->GetActorTransform();
}
baseTransform = baseTransform.Inverse();
baseTransform.TransformVector(position);
float localX = 0, localY = 0;
spBone_worldToLocal(bone, position.X, position.Z, &localX, &localY);
bone->x = localX;
bone->y = localY;
}
}
void USpineSkeletonComponent::UpdateWorldTransform() {
CheckState();
if (skeleton) {
spSkeleton_updateWorldTransform(skeleton);
}
}
void USpineSkeletonComponent::SetToSetupPose () {
@ -72,6 +101,28 @@ void USpineSkeletonComponent::SetSlotsToSetupPose () {
if (skeleton) spSkeleton_setSlotsToSetupPose(skeleton);
}
void USpineSkeletonComponent::SetFlipX (bool flipX) {
CheckState();
if (skeleton) skeleton->flipX = flipX ? 1 : 0;
}
bool USpineSkeletonComponent::GetFlipX() {
CheckState();
if (skeleton) return skeleton->flipX != 0;
return false;
}
void USpineSkeletonComponent::SetFlipY(bool flipY) {
CheckState();
if (skeleton) skeleton->flipY = flipY ? 1 : 0;
}
bool USpineSkeletonComponent::GetFlipY() {
CheckState();
if (skeleton) return skeleton->flipY != 0;
return false;
}
void USpineSkeletonComponent::BeginPlay() {
Super::BeginPlay();
}

View File

@ -0,0 +1,32 @@
#pragma once
#include "Components/ActorComponent.h"
#include "SpineBoneFollowerComponent.generated.h"
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class SPINEPLUGIN_API USpineBoneFollowerComponent : public UActorComponent {
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
AActor* Target = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString BoneName;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
bool UsePosition = true;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
bool UseRotation = true;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
bool UseScale = true;
USpineBoneFollowerComponent ();
virtual void BeginPlay () override;
virtual void TickComponent (float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
};

View File

@ -35,7 +35,7 @@ public:
FTransform GetBoneWorldTransform (const FString& BoneName);
UFUNCTION(BlueprintCallable, Category = "Components|Spine")
FTransform GetBoneLocalTransform (const FString& BoneName);
void SetBoneWorldPosition (const FString& BoneName, const FVector& position);
UFUNCTION(BlueprintCallable, Category = "Components|Spine")
void SetToSetupPose ();
@ -43,9 +43,24 @@ public:
UFUNCTION(BlueprintCallable, Category = "Components|Spine")
void SetBonesToSetupPose ();
UFUNCTION(BlueprintCallable, Category = "Components|Spine")
void UpdateWorldTransform ();
UFUNCTION(BlueprintCallable, Category = "Components|Spine")
void SetSlotsToSetupPose ();
UFUNCTION(BlueprintCallable, Category = "Components|Spine")
void SetFlipX(bool flipX);
UFUNCTION(BlueprintCallable, Category = "Components|Spine")
bool GetFlipX();
UFUNCTION(BlueprintCallable, Category = "Components|Spine")
void SetFlipY(bool flipY);
UFUNCTION(BlueprintCallable, Category = "Components|Spine")
bool GetFlipY();
UPROPERTY(BlueprintAssignable, Category = "Components|Spine")
FSpineBeforeUpdateWorldTransformDelegate BeforeUpdateWorldTransform;