From f2e364be3ec2cabf57cf04a02bab507770b53694 Mon Sep 17 00:00:00 2001 From: badlogic Date: Tue, 6 Dec 2016 13:37:15 +0100 Subject: [PATCH] [ue4] Refactored skeleton component into two classes, one holding the skeleton, another adding an animation state. Fixed up renderer to be able to deal with both. --- .../Private/SpinePluginPrivatePCH.h | 3 +- .../SpineSkeletonAnimationComponent.cpp | 117 ++++++++++++++++++ .../Private/SpineSkeletonComponent.cpp | 67 +--------- .../SpineSkeletonRendererComponent.cpp | 7 +- .../Public/SpineSkeletonAnimationComponent.h | 67 ++++++++++ .../Public/SpineSkeletonComponent.h | 43 +------ .../Public/SpineSkeletonRendererComponent.h | 2 +- 7 files changed, 195 insertions(+), 111 deletions(-) create mode 100644 spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp create mode 100644 spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePluginPrivatePCH.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePluginPrivatePCH.h index 7af3f0312..f734fdd9c 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePluginPrivatePCH.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePluginPrivatePCH.h @@ -7,4 +7,5 @@ #include "SpineSkeletonDataAsset.h" #include "SpineAtlasAsset.h" #include "SpineSkeletonComponent.h" -#include "SpineSkeletonRendererComponent.h" \ No newline at end of file +#include "SpineSkeletonAnimationComponent.h" +#include "SpineSkeletonRendererComponent.h" diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp new file mode 100644 index 000000000..ebc0d0db9 --- /dev/null +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp @@ -0,0 +1,117 @@ +#include "SpinePluginPrivatePCH.h" + +#define LOCTEXT_NAMESPACE "Spine" + +void callback(spAnimationState* state, spEventType type, spTrackEntry* entry, spEvent* event) { + USpineSkeletonAnimationComponent* component = (USpineSkeletonAnimationComponent*)entry->rendererObject; +} + +USpineSkeletonAnimationComponent::USpineSkeletonAnimationComponent () { + bWantsBeginPlay = true; + PrimaryComponentTick.bCanEverTick = true; + bTickInEditor = true; + bAutoActivate = true; +} + +void USpineSkeletonAnimationComponent::BeginPlay() { + Super::BeginPlay(); +} + +void USpineSkeletonAnimationComponent::TickComponent (float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) { + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + CheckState(); + + if (state) { + spAnimationState_update(state, DeltaTime); + spAnimationState_apply(state, skeleton); + spSkeleton_updateWorldTransform(skeleton); + } +} + +void USpineSkeletonAnimationComponent::CheckState () { + if (lastAtlas != Atlas || lastData != SkeletonData) { + DisposeState(); + + if (Atlas && SkeletonData) { + spSkeletonData* data = SkeletonData->GetSkeletonData(Atlas->GetAtlas(false), false); + skeleton = spSkeleton_create(data); + stateData = spAnimationStateData_create(data); + state = spAnimationState_create(stateData); + } + + lastAtlas = Atlas; + lastData = SkeletonData; + } +} + +void USpineSkeletonAnimationComponent::DisposeState () { + if (stateData) { + spAnimationStateData_dispose(stateData); + stateData = nullptr; + } + + if (state) { + spAnimationState_dispose(state); + state = nullptr; + } + + if (skeleton) { + spSkeleton_dispose(skeleton); + skeleton = nullptr; + } +} + +void USpineSkeletonAnimationComponent::FinishDestroy () { + DisposeState(); + Super::FinishDestroy(); +} + +FTrackEntry USpineSkeletonAnimationComponent::SetAnimation (int trackIndex, FString animationName, bool loop) { + CheckState(); + if (state && spSkeletonData_findAnimation(skeleton->data, TCHAR_TO_UTF8(*animationName))) { + spTrackEntry* entry = spAnimationState_setAnimationByName(state, trackIndex, TCHAR_TO_UTF8(*animationName), loop ? 1 : 0); + return FTrackEntry(entry); + } else return FTrackEntry(); + +} + +FTrackEntry USpineSkeletonAnimationComponent::AddAnimation (int trackIndex, FString animationName, bool loop, float delay) { + CheckState(); + if (state && spSkeletonData_findAnimation(skeleton->data, TCHAR_TO_UTF8(*animationName))) { + spTrackEntry* entry = spAnimationState_addAnimationByName(state, trackIndex, TCHAR_TO_UTF8(*animationName), loop ? 1 : 0, delay); + return FTrackEntry(entry); + } else return FTrackEntry(); +} + +FTrackEntry USpineSkeletonAnimationComponent::SetEmptyAnimation (int trackIndex, float mixDuration) { + CheckState(); + if (state) { + spTrackEntry* entry = spAnimationState_setEmptyAnimation(state, trackIndex, mixDuration); + return FTrackEntry(entry); + } else return FTrackEntry(); +} + +FTrackEntry USpineSkeletonAnimationComponent::AddEmptyAnimation (int trackIndex, float mixDuration, float delay) { + CheckState(); + if (state) { + spTrackEntry* entry = spAnimationState_addEmptyAnimation(state, trackIndex, mixDuration, delay); + return FTrackEntry(entry); + } else return FTrackEntry(); +} + +void USpineSkeletonAnimationComponent::ClearTracks () { + CheckState(); + if (state) { + spAnimationState_clearTracks(state); + } +} + +void USpineSkeletonAnimationComponent::ClearTrack (int trackIndex) { + CheckState(); + if (state) { + spAnimationState_clearTrack(state, trackIndex); + } +} + +#undef LOCTEXT_NAMESPACE diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonComponent.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonComponent.cpp index 786f4f723..057c852fd 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonComponent.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonComponent.cpp @@ -2,10 +2,6 @@ #define LOCTEXT_NAMESPACE "Spine" -void callback(spAnimationState* state, spEventType type, spTrackEntry* entry, spEvent* event) { - USpineSkeletonComponent* component = (USpineSkeletonComponent*)entry->rendererObject; -} - USpineSkeletonComponent::USpineSkeletonComponent () { bWantsBeginPlay = true; PrimaryComponentTick.bCanEverTick = true; @@ -22,9 +18,7 @@ void USpineSkeletonComponent::TickComponent (float DeltaTime, ELevelTick TickTyp CheckState(); - if (state) { - spAnimationState_update(state, DeltaTime); - spAnimationState_apply(state, skeleton); + if (skeleton) { spSkeleton_updateWorldTransform(skeleton); } } @@ -36,8 +30,6 @@ void USpineSkeletonComponent::CheckState () { if (Atlas && SkeletonData) { spSkeletonData* data = SkeletonData->GetSkeletonData(Atlas->GetAtlas(false), false); skeleton = spSkeleton_create(data); - stateData = spAnimationStateData_create(data); - state = spAnimationState_create(stateData); } lastAtlas = Atlas; @@ -46,16 +38,6 @@ void USpineSkeletonComponent::CheckState () { } void USpineSkeletonComponent::DisposeState () { - if (stateData) { - spAnimationStateData_dispose(stateData); - stateData = nullptr; - } - - if (state) { - spAnimationState_dispose(state); - state = nullptr; - } - if (skeleton) { spSkeleton_dispose(skeleton); skeleton = nullptr; @@ -67,51 +49,4 @@ void USpineSkeletonComponent::FinishDestroy () { Super::FinishDestroy(); } -FTrackEntry USpineSkeletonComponent::SetAnimation (int trackIndex, FString animationName, bool loop) { - CheckState(); - if (state && spSkeletonData_findAnimation(skeleton->data, TCHAR_TO_UTF8(*animationName))) { - spTrackEntry* entry = spAnimationState_setAnimationByName(state, trackIndex, TCHAR_TO_UTF8(*animationName), loop ? 1 : 0); - return FTrackEntry(entry); - } else return FTrackEntry(); - -} - -FTrackEntry USpineSkeletonComponent::AddAnimation (int trackIndex, FString animationName, bool loop, float delay) { - CheckState(); - if (state && spSkeletonData_findAnimation(skeleton->data, TCHAR_TO_UTF8(*animationName))) { - spTrackEntry* entry = spAnimationState_addAnimationByName(state, trackIndex, TCHAR_TO_UTF8(*animationName), loop ? 1 : 0, delay); - return FTrackEntry(entry); - } else return FTrackEntry(); -} - -FTrackEntry USpineSkeletonComponent::SetEmptyAnimation (int trackIndex, float mixDuration) { - CheckState(); - if (state) { - spTrackEntry* entry = spAnimationState_setEmptyAnimation(state, trackIndex, mixDuration); - return FTrackEntry(entry); - } else return FTrackEntry(); -} - -FTrackEntry USpineSkeletonComponent::AddEmptyAnimation (int trackIndex, float mixDuration, float delay) { - CheckState(); - if (state) { - spTrackEntry* entry = spAnimationState_addEmptyAnimation(state, trackIndex, mixDuration, delay); - return FTrackEntry(entry); - } else return FTrackEntry(); -} - -void USpineSkeletonComponent::ClearTracks () { - CheckState(); - if (state) { - spAnimationState_clearTracks(state); - } -} - -void USpineSkeletonComponent::ClearTrack (int trackIndex) { - CheckState(); - if (state) { - spAnimationState_clearTrack(state, trackIndex); - } -} - #undef LOCTEXT_NAMESPACE diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponent.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponent.cpp index 12c3e80c5..60dbe35e0 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponent.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponent.cpp @@ -23,11 +23,12 @@ void USpineSkeletonRendererComponent::BeginPlay () { void USpineSkeletonRendererComponent::TickComponent (float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) { Super::TickComponent(DeltaTime, TickType, ThisTickFunction); - - UClass* skeletonClass = USpineSkeletonComponent::StaticClass(); + AActor* owner = GetOwner(); if (owner) { + UClass* skeletonClass = USpineSkeletonComponent::StaticClass(); USpineSkeletonComponent* skeleton = Cast(owner->GetComponentByClass(skeletonClass)); + if (skeleton && !skeleton->IsBeingDestroyed() && skeleton->GetSkeleton()) { if (atlasMaterials.Num() != skeleton->Atlas->atlasPages.Num()) { atlasMaterials.SetNum(0); @@ -57,6 +58,8 @@ void USpineSkeletonRendererComponent::TickComponent (float DeltaTime, ELevelTick } } UpdateMesh(skeleton->GetSkeleton()); + } else { + ClearAllMeshSections(); } } } diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h new file mode 100644 index 000000000..c39b42a97 --- /dev/null +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h @@ -0,0 +1,67 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "Components/ActorComponent.h" +#include "SpineSkeletonComponent.h" +#include "spine/spine.h" +#include "SpineSkeletonAnimationComponent.generated.h" + +USTRUCT(BlueprintType) +struct SPINEPLUGIN_API FTrackEntry { + GENERATED_BODY (); + + FTrackEntry (): entry(0) { } + + FTrackEntry (spTrackEntry* entry) { this->entry = entry; } + + spTrackEntry* entry; +}; + +class USpineAtlasAsset; +UCLASS(ClassGroup=(Spine), meta=(BlueprintSpawnableComponent)) +class SPINEPLUGIN_API USpineSkeletonAnimationComponent: public USpineSkeletonComponent { + GENERATED_BODY() + +public: + spAnimationStateData* GetAnimationStateData () { return stateData; }; + + spAnimationState* GetAnimationState () { return state; }; + + USpineSkeletonAnimationComponent (); + + virtual void BeginPlay () override; + + virtual void TickComponent (float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + + virtual void FinishDestroy () override; + + // Blueprint functions + UFUNCTION(BlueprintCallable, Category="Components|Spine") + FTrackEntry SetAnimation (int trackIndex, FString animationName, bool loop); + + UFUNCTION(BlueprintCallable, Category="Components|Spine") + FTrackEntry AddAnimation (int trackIndex, FString animationName, bool loop, float delay); + + UFUNCTION(BlueprintCallable, Category="Components|Spine") + FTrackEntry SetEmptyAnimation (int trackIndex, float mixDuration); + + UFUNCTION(BlueprintCallable, Category="Components|Spine") + FTrackEntry AddEmptyAnimation (int trackIndex, float mixDuration, float delay); + + UFUNCTION(BlueprintCallable, Category="Components|Spine") + void ClearTracks (); + + UFUNCTION(BlueprintCallable, Category="Components|Spine") + void ClearTrack (int trackIndex); + + // UFUNCTION(BlueprintImplentableEvent, category = "Components|Spine") + // void AnimationEvent(int trackIndex, ); + +protected: + virtual void CheckState () override; + virtual void DisposeState () override; + + spAnimationStateData* stateData; + 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 831206ff4..731371e64 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonComponent.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonComponent.h @@ -6,17 +6,6 @@ #include "spine/spine.h" #include "SpineSkeletonComponent.generated.h" -USTRUCT(BlueprintType) -struct SPINEPLUGIN_API FTrackEntry { - GENERATED_BODY (); - - FTrackEntry (): entry(0) { } - - FTrackEntry (spTrackEntry* entry) { this->entry = entry; } - - spTrackEntry* entry; -}; - class USpineAtlasAsset; UCLASS(ClassGroup=(Spine), meta=(BlueprintSpawnableComponent)) class SPINEPLUGIN_API USpineSkeletonComponent: public UActorComponent { @@ -29,10 +18,6 @@ public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Spine) USpineSkeletonDataAsset* SkeletonData; - spAnimationStateData* GetAnimationStateData () { return stateData; }; - - spAnimationState* GetAnimationState () { return state; }; - spSkeleton* GetSkeleton () { return skeleton; }; USpineSkeletonComponent (); @@ -43,34 +28,10 @@ public: virtual void FinishDestroy () override; - // Blueprint functions - UFUNCTION(BlueprintCallable, Category="Components|Spine") - FTrackEntry SetAnimation (int trackIndex, FString animationName, bool loop); - - UFUNCTION(BlueprintCallable, Category="Components|Spine") - FTrackEntry AddAnimation (int trackIndex, FString animationName, bool loop, float delay); - - UFUNCTION(BlueprintCallable, Category="Components|Spine") - FTrackEntry SetEmptyAnimation (int trackIndex, float mixDuration); - - UFUNCTION(BlueprintCallable, Category="Components|Spine") - FTrackEntry AddEmptyAnimation (int trackIndex, float mixDuration, float delay); - - UFUNCTION(BlueprintCallable, Category="Components|Spine") - void ClearTracks (); - - UFUNCTION(BlueprintCallable, Category="Components|Spine") - void ClearTrack (int trackIndex); - - UFUNCTION(BlueprintImplentableEvent, category = "Components|Spine") - void AnimationEvent(int trackIndex, ); - protected: - void CheckState (); - void DisposeState (); + virtual void CheckState (); + virtual void DisposeState (); - spAnimationStateData* stateData; - spAnimationState* state; spSkeleton* skeleton; USpineAtlasAsset* lastAtlas = nullptr; USpineSkeletonDataAsset* lastData = nullptr; diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonRendererComponent.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonRendererComponent.h index 23d63f4cb..0b79cb37f 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonRendererComponent.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonRendererComponent.h @@ -4,7 +4,7 @@ #include "Components/ActorComponent.h" #include "ProceduralMeshComponent.h" -#include "SpineSkeletonComponent.h" +#include "SpineSkeletonAnimationComponent.h" #include "SpineSkeletonRendererComponent.generated.h"