mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
[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.
This commit is contained in:
parent
4c4f2f9539
commit
f2e364be3e
@ -7,4 +7,5 @@
|
|||||||
#include "SpineSkeletonDataAsset.h"
|
#include "SpineSkeletonDataAsset.h"
|
||||||
#include "SpineAtlasAsset.h"
|
#include "SpineAtlasAsset.h"
|
||||||
#include "SpineSkeletonComponent.h"
|
#include "SpineSkeletonComponent.h"
|
||||||
|
#include "SpineSkeletonAnimationComponent.h"
|
||||||
#include "SpineSkeletonRendererComponent.h"
|
#include "SpineSkeletonRendererComponent.h"
|
||||||
@ -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
|
||||||
@ -2,10 +2,6 @@
|
|||||||
|
|
||||||
#define LOCTEXT_NAMESPACE "Spine"
|
#define LOCTEXT_NAMESPACE "Spine"
|
||||||
|
|
||||||
void callback(spAnimationState* state, spEventType type, spTrackEntry* entry, spEvent* event) {
|
|
||||||
USpineSkeletonComponent* component = (USpineSkeletonComponent*)entry->rendererObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
USpineSkeletonComponent::USpineSkeletonComponent () {
|
USpineSkeletonComponent::USpineSkeletonComponent () {
|
||||||
bWantsBeginPlay = true;
|
bWantsBeginPlay = true;
|
||||||
PrimaryComponentTick.bCanEverTick = true;
|
PrimaryComponentTick.bCanEverTick = true;
|
||||||
@ -22,9 +18,7 @@ void USpineSkeletonComponent::TickComponent (float DeltaTime, ELevelTick TickTyp
|
|||||||
|
|
||||||
CheckState();
|
CheckState();
|
||||||
|
|
||||||
if (state) {
|
if (skeleton) {
|
||||||
spAnimationState_update(state, DeltaTime);
|
|
||||||
spAnimationState_apply(state, skeleton);
|
|
||||||
spSkeleton_updateWorldTransform(skeleton);
|
spSkeleton_updateWorldTransform(skeleton);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,8 +30,6 @@ void USpineSkeletonComponent::CheckState () {
|
|||||||
if (Atlas && SkeletonData) {
|
if (Atlas && SkeletonData) {
|
||||||
spSkeletonData* data = SkeletonData->GetSkeletonData(Atlas->GetAtlas(false), false);
|
spSkeletonData* data = SkeletonData->GetSkeletonData(Atlas->GetAtlas(false), false);
|
||||||
skeleton = spSkeleton_create(data);
|
skeleton = spSkeleton_create(data);
|
||||||
stateData = spAnimationStateData_create(data);
|
|
||||||
state = spAnimationState_create(stateData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lastAtlas = Atlas;
|
lastAtlas = Atlas;
|
||||||
@ -46,16 +38,6 @@ void USpineSkeletonComponent::CheckState () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void USpineSkeletonComponent::DisposeState () {
|
void USpineSkeletonComponent::DisposeState () {
|
||||||
if (stateData) {
|
|
||||||
spAnimationStateData_dispose(stateData);
|
|
||||||
stateData = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state) {
|
|
||||||
spAnimationState_dispose(state);
|
|
||||||
state = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skeleton) {
|
if (skeleton) {
|
||||||
spSkeleton_dispose(skeleton);
|
spSkeleton_dispose(skeleton);
|
||||||
skeleton = nullptr;
|
skeleton = nullptr;
|
||||||
@ -67,51 +49,4 @@ void USpineSkeletonComponent::FinishDestroy () {
|
|||||||
Super::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
|
#undef LOCTEXT_NAMESPACE
|
||||||
|
|||||||
@ -24,10 +24,11 @@ void USpineSkeletonRendererComponent::BeginPlay () {
|
|||||||
void USpineSkeletonRendererComponent::TickComponent (float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) {
|
void USpineSkeletonRendererComponent::TickComponent (float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) {
|
||||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||||
|
|
||||||
UClass* skeletonClass = USpineSkeletonComponent::StaticClass();
|
|
||||||
AActor* owner = GetOwner();
|
AActor* owner = GetOwner();
|
||||||
if (owner) {
|
if (owner) {
|
||||||
|
UClass* skeletonClass = USpineSkeletonComponent::StaticClass();
|
||||||
USpineSkeletonComponent* skeleton = Cast<USpineSkeletonComponent>(owner->GetComponentByClass(skeletonClass));
|
USpineSkeletonComponent* skeleton = Cast<USpineSkeletonComponent>(owner->GetComponentByClass(skeletonClass));
|
||||||
|
|
||||||
if (skeleton && !skeleton->IsBeingDestroyed() && skeleton->GetSkeleton()) {
|
if (skeleton && !skeleton->IsBeingDestroyed() && skeleton->GetSkeleton()) {
|
||||||
if (atlasMaterials.Num() != skeleton->Atlas->atlasPages.Num()) {
|
if (atlasMaterials.Num() != skeleton->Atlas->atlasPages.Num()) {
|
||||||
atlasMaterials.SetNum(0);
|
atlasMaterials.SetNum(0);
|
||||||
@ -57,6 +58,8 @@ void USpineSkeletonRendererComponent::TickComponent (float DeltaTime, ELevelTick
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
UpdateMesh(skeleton->GetSkeleton());
|
UpdateMesh(skeleton->GetSkeleton());
|
||||||
|
} else {
|
||||||
|
ClearAllMeshSections();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
};
|
||||||
@ -6,17 +6,6 @@
|
|||||||
#include "spine/spine.h"
|
#include "spine/spine.h"
|
||||||
#include "SpineSkeletonComponent.generated.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;
|
class USpineAtlasAsset;
|
||||||
UCLASS(ClassGroup=(Spine), meta=(BlueprintSpawnableComponent))
|
UCLASS(ClassGroup=(Spine), meta=(BlueprintSpawnableComponent))
|
||||||
class SPINEPLUGIN_API USpineSkeletonComponent: public UActorComponent {
|
class SPINEPLUGIN_API USpineSkeletonComponent: public UActorComponent {
|
||||||
@ -29,10 +18,6 @@ public:
|
|||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Spine)
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Spine)
|
||||||
USpineSkeletonDataAsset* SkeletonData;
|
USpineSkeletonDataAsset* SkeletonData;
|
||||||
|
|
||||||
spAnimationStateData* GetAnimationStateData () { return stateData; };
|
|
||||||
|
|
||||||
spAnimationState* GetAnimationState () { return state; };
|
|
||||||
|
|
||||||
spSkeleton* GetSkeleton () { return skeleton; };
|
spSkeleton* GetSkeleton () { return skeleton; };
|
||||||
|
|
||||||
USpineSkeletonComponent ();
|
USpineSkeletonComponent ();
|
||||||
@ -43,34 +28,10 @@ public:
|
|||||||
|
|
||||||
virtual void FinishDestroy () 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:
|
protected:
|
||||||
void CheckState ();
|
virtual void CheckState ();
|
||||||
void DisposeState ();
|
virtual void DisposeState ();
|
||||||
|
|
||||||
spAnimationStateData* stateData;
|
|
||||||
spAnimationState* state;
|
|
||||||
spSkeleton* skeleton;
|
spSkeleton* skeleton;
|
||||||
USpineAtlasAsset* lastAtlas = nullptr;
|
USpineAtlasAsset* lastAtlas = nullptr;
|
||||||
USpineSkeletonDataAsset* lastData = nullptr;
|
USpineSkeletonDataAsset* lastData = nullptr;
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include "Components/ActorComponent.h"
|
#include "Components/ActorComponent.h"
|
||||||
#include "ProceduralMeshComponent.h"
|
#include "ProceduralMeshComponent.h"
|
||||||
#include "SpineSkeletonComponent.h"
|
#include "SpineSkeletonAnimationComponent.h"
|
||||||
#include "SpineSkeletonRendererComponent.generated.h"
|
#include "SpineSkeletonRendererComponent.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user