diff --git a/spine-ue4/Content/Maps/example.umap b/spine-ue4/Content/Maps/example.umap index 0ca8fd340..bf3bc2f02 100644 Binary files a/spine-ue4/Content/Maps/example.umap and b/spine-ue4/Content/Maps/example.umap differ diff --git a/spine-ue4/Content/SpineBoy/Spineboy_Blueprint.uasset b/spine-ue4/Content/SpineBoy/Spineboy_Blueprint.uasset index 0cb7d8eda..4cfeafb10 100644 Binary files a/spine-ue4/Content/SpineBoy/Spineboy_Blueprint.uasset and b/spine-ue4/Content/SpineBoy/Spineboy_Blueprint.uasset differ diff --git a/spine-ue4/Content/SpineBoy/spineboy-hover.uasset b/spine-ue4/Content/SpineBoy/spineboy-hover.uasset new file mode 100644 index 000000000..8af9feb35 Binary files /dev/null and b/spine-ue4/Content/SpineBoy/spineboy-hover.uasset differ diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineBoneDriverComponent.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineBoneDriverComponent.cpp new file mode 100644 index 000000000..6676534ec --- /dev/null +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineBoneDriverComponent.cpp @@ -0,0 +1,33 @@ +#include "SpinePluginPrivatePCH.h" + +USpineBoneDriverComponent::USpineBoneDriverComponent () { + bWantsBeginPlay = true; + PrimaryComponentTick.bCanEverTick = true; + bTickInEditor = true; + bAutoActivate = true; +} + +void USpineBoneDriverComponent::BeginPlay () { + Super::BeginPlay(); +} + +void USpineBoneDriverComponent::BeforeUpdateWorldTransform(USpineSkeletonComponent* skeleton) { + AActor* owner = GetOwner(); + if (owner) { + skeleton->SetBoneWorldPosition(BoneName, owner->GetActorLocation() ); + } +} + +void USpineBoneDriverComponent::TickComponent (float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) { + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + if (Target) { + USpineSkeletonComponent* skeleton = static_cast(Target->GetComponentByClass(USpineSkeletonComponent::StaticClass())); + if (skeleton != lastBoundComponent) { + // if (lastBoundComponent) lastBoundComponent->BeforeUpdateWorldTransform.RemoveAll(this); + skeleton->BeforeUpdateWorldTransform.AddDynamic(this, &USpineBoneDriverComponent::BeforeUpdateWorldTransform); + lastBoundComponent = skeleton; + } + } +} + diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineBoneFollowerComponent.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineBoneFollowerComponent.cpp index 30136279b..d4161d309 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineBoneFollowerComponent.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineBoneFollowerComponent.cpp @@ -11,7 +11,6 @@ void USpineBoneFollowerComponent::BeginPlay () { Super::BeginPlay(); } - void USpineBoneFollowerComponent::TickComponent ( float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction ) { Super::TickComponent( DeltaTime, TickType, ThisTickFunction ); diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePluginPrivatePCH.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePluginPrivatePCH.h index 0dc9a2be0..df921b08b 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePluginPrivatePCH.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePluginPrivatePCH.h @@ -10,3 +10,4 @@ #include "SpineSkeletonAnimationComponent.h" #include "SpineSkeletonRendererComponent.h" #include "SpineBoneFollowerComponent.h" +#include "SpineBoneDriverComponent.h" diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp index 26ff16302..c2daba313 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp @@ -60,15 +60,15 @@ void USpineSkeletonAnimationComponent::TickComponent(float DeltaTime, ELevelTick InternalTick(DeltaTime); } -void USpineSkeletonAnimationComponent::InternalTick(float DeltaTime) { +void USpineSkeletonAnimationComponent::InternalTick(float DeltaTime, bool CallDelegates) { CheckState(); if (state) { spAnimationState_update(state, DeltaTime); spAnimationState_apply(state, skeleton); - BeforeUpdateWorldTransform.Broadcast(this); + if (CallDelegates) BeforeUpdateWorldTransform.Broadcast(this); spSkeleton_updateWorldTransform(skeleton); - AfterUpdateWorldTransform.Broadcast(this); + if (CallDelegates) AfterUpdateWorldTransform.Broadcast(this); } } diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonComponent.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonComponent.cpp index 9242af4e5..60596fcaa 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonComponent.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonComponent.cpp @@ -26,7 +26,7 @@ FTransform USpineSkeletonComponent::GetBoneWorldTransform (const FString& BoneNa if (skeleton) { spBone* bone = spSkeleton_findBone(skeleton, TCHAR_TO_UTF8(*BoneName)); if (!bone) return FTransform(); - if (!bone->appliedValid) this->InternalTick(0); + if (!bone->appliedValid) this->InternalTick(0, false); // 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 @@ -57,7 +57,9 @@ FTransform USpineSkeletonComponent::GetBoneWorldTransform (const FString& BoneNa void USpineSkeletonComponent::SetBoneWorldPosition (const FString& BoneName, const FVector& position) { CheckState(); if (skeleton) { - spBone* bone = spSkeleton_findBone(skeleton, TCHAR_TO_UTF8(*BoneName)); + spBone* bone = spSkeleton_findBone(skeleton, TCHAR_TO_UTF8(*BoneName)); + if (!bone) return; + if (!bone->appliedValid) this->InternalTick(0, false); // 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 @@ -71,9 +73,9 @@ void USpineSkeletonComponent::SetBoneWorldPosition (const FString& BoneName, con } baseTransform = baseTransform.Inverse(); - baseTransform.TransformVector(position); + FVector localPosition = baseTransform.TransformVector(position); float localX = 0, localY = 0; - spBone_worldToLocal(bone, position.X, position.Z, &localX, &localY); + spBone_worldToLocal(bone, localPosition.X, localPosition.Z, &localX, &localY); bone->x = localX; bone->y = localY; } @@ -132,13 +134,13 @@ void USpineSkeletonComponent::TickComponent (float DeltaTime, ELevelTick TickTyp InternalTick(DeltaTime); } -void USpineSkeletonComponent::InternalTick(float DeltaTime) { +void USpineSkeletonComponent::InternalTick(float DeltaTime, bool CallDelegates) { CheckState(); if (skeleton) { - BeforeUpdateWorldTransform.Broadcast(this); + if (CallDelegates) BeforeUpdateWorldTransform.Broadcast(this); spSkeleton_updateWorldTransform(skeleton); - AfterUpdateWorldTransform.Broadcast(this); + if (CallDelegates) AfterUpdateWorldTransform.Broadcast(this); } } diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineBoneDriverComponent.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineBoneDriverComponent.h new file mode 100644 index 000000000..5810afd5b --- /dev/null +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineBoneDriverComponent.h @@ -0,0 +1,39 @@ +#pragma once + +#include "Components/ActorComponent.h" +#include "SpineBoneDriverComponent.generated.h" + +class USpineSkeletonComponent; + +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) +class SPINEPLUGIN_API USpineBoneDriverComponent : 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; + + USpineBoneDriverComponent(); + + virtual void BeginPlay() override; + + virtual void TickComponent( float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction ) override; + +protected: + UFUNCTION() + void BeforeUpdateWorldTransform(USpineSkeletonComponent* skeleton); + + USpineSkeletonComponent* lastBoundComponent = nullptr; +}; diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h index 37bd795e8..b1b1def3d 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h @@ -238,7 +238,7 @@ public: void GCTrackEntry(UTrackEntry* entry) { trackEntries.Remove(entry); } protected: virtual void CheckState () override; - virtual void InternalTick(float DeltaTime) override; + virtual void InternalTick(float DeltaTime, bool CallDelegates = true) override; virtual void DisposeState () override; spAnimationState* state; diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonComponent.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonComponent.h index 5448d38cd..327e8e063 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonComponent.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonComponent.h @@ -77,7 +77,7 @@ public: protected: virtual void CheckState (); - virtual void InternalTick(float DeltaTime); + virtual void InternalTick(float DeltaTime, bool CallDelegates = true); virtual void DisposeState (); spSkeleton* skeleton;