From 4ba46d76e88621d6f127202d9ef199d40c794e3c Mon Sep 17 00:00:00 2001 From: badlogic Date: Wed, 6 Mar 2019 16:20:32 +0100 Subject: [PATCH 1/2] [ue4] Extended skeleton data editor preview. It now shows bones, slots, animations, and skins. Closes #1047. --- .../Private/SpineSkeletonDataAsset.cpp | 73 +++++++++++++++++++ .../Public/SpineSkeletonDataAsset.h | 14 ++++ 2 files changed, 87 insertions(+) diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp index 5d1c378ee..94919b6cb 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp @@ -76,6 +76,7 @@ void USpineSkeletonDataAsset::Serialize (FArchive& Ar) { Super::Serialize(Ar); if (Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_ASSET_IMPORT_DATA_AS_JSON && !importData) importData = NewObject(this, TEXT("AssetImportData")); + LoadInfo(); } #endif @@ -92,13 +93,85 @@ void USpineSkeletonDataAsset::BeginDestroy () { Super::BeginDestroy(); } +class SP_API NullAttachmentLoader : public AttachmentLoader { +public: + + virtual RegionAttachment* newRegionAttachment(Skin& skin, const String& name, const String& path) { + return new(__FILE__, __LINE__) RegionAttachment(name); + } + + virtual MeshAttachment* newMeshAttachment(Skin& skin, const String& name, const String& path) { + return new(__FILE__, __LINE__) MeshAttachment(name); + } + + virtual BoundingBoxAttachment* newBoundingBoxAttachment(Skin& skin, const String& name) { + return new(__FILE__, __LINE__) BoundingBoxAttachment(name); + } + + virtual PathAttachment* newPathAttachment(Skin& skin, const String& name) { + return new(__FILE__, __LINE__) PathAttachment(name); + } + + virtual PointAttachment* newPointAttachment(Skin& skin, const String& name) { + return new(__FILE__, __LINE__) PointAttachment(name); + } + + virtual ClippingAttachment* newClippingAttachment(Skin& skin, const String& name) { + return new(__FILE__, __LINE__) ClippingAttachment(name); + } + + virtual void configureAttachment(Attachment* attachment) { + + } +}; + +void USpineSkeletonDataAsset::LoadInfo() { +#if WITH_EDITORONLY_DATA + int dataLen = rawData.Num(); + NullAttachmentLoader loader; + SkeletonData* skeletonData = nullptr; + if (skeletonDataFileName.GetPlainNameString().Contains(TEXT(".json"))) { + SkeletonJson* json = new (__FILE__, __LINE__) SkeletonJson(&loader); + skeletonData = json->readSkeletonData((const char*)rawData.GetData()); + if (!skeletonData) { + FMessageDialog::Debugf(FText::FromString(UTF8_TO_TCHAR(json->getError().buffer()))); + UE_LOG(SpineLog, Error, TEXT("Couldn't load skeleton data and atlas: %s"), UTF8_TO_TCHAR(json->getError().buffer())); + } + delete json; + } else { + SkeletonBinary* binary = new (__FILE__, __LINE__) SkeletonBinary(&loader); + skeletonData = binary->readSkeletonData((const unsigned char*)rawData.GetData(), (int)rawData.Num()); + if (!skeletonData) { + FMessageDialog::Debugf(FText::FromString(UTF8_TO_TCHAR(binary->getError().buffer()))); + UE_LOG(SpineLog, Error, TEXT("Couldn't load skeleton data and atlas: %s"), UTF8_TO_TCHAR(binary->getError().buffer())); + } + delete binary; + } + if (skeletonData) { + Bones.Empty(); + for (int i = 0; i < skeletonData->getBones().size(); i++) + Bones.Add(skeletonData->getBones()[i]->getName().buffer()); + Skins.Empty(); + for (int i = 0; i < skeletonData->getSkins().size(); i++) + Skins.Add(skeletonData->getSkins()[i]->getName().buffer()); + Animations.Empty(); + for (int i = 0; i < skeletonData->getAnimations().size(); i++) + Animations.Add(skeletonData->getAnimations()[i]->getName().buffer()); + delete skeletonData; + } +#endif +} + void USpineSkeletonDataAsset::SetRawData(TArray &Data) { this->rawData.Empty(); this->rawData.Append(Data); + if (skeletonData) { delete skeletonData; skeletonData = nullptr; } + + LoadInfo(); } SkeletonData* USpineSkeletonDataAsset::GetSkeletonData (Atlas* Atlas) { diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h index b9940a534..c94a896ce 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h @@ -70,6 +70,18 @@ public: UPROPERTY(EditAnywhere, BlueprintReadWrite) TArray MixData; + + UPROPERTY(Transient, VisibleAnywhere) + TArray Bones; + + UPROPERTY(Transient, VisibleAnywhere) + TArray Slots; + + UPROPERTY(Transient, VisibleAnywhere) + TArray Skins; + + UPROPERTY(Transient, VisibleAnywhere) + TArray Animations; protected: UPROPERTY() @@ -94,4 +106,6 @@ protected: virtual void GetAssetRegistryTags(TArray& OutTags) const override; virtual void Serialize (FArchive& Ar) override; #endif + + void LoadInfo(); }; From cef191f6c671d6c239d2b57a1781072738af931e Mon Sep 17 00:00:00 2001 From: badlogic Date: Wed, 6 Mar 2019 16:54:47 +0100 Subject: [PATCH 2/2] [ue4] Fixed segfault in SpineSkeletonDataAsset. Added PreviewAnimation and PreviewSkin to SpineSkeletonAnimationComponent. Enter the name of an animation or skin and it will be previewed live in the editor view. Use an empty string to reset the animation or skin. --- .../Private/SpineSkeletonAnimationComponent.cpp | 11 +++++++++++ .../SpinePlugin/Private/SpineSkeletonDataAsset.cpp | 1 + .../Public/SpineSkeletonAnimationComponent.h | 9 +++++++++ 3 files changed, 21 insertions(+) diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp index 8dabf4250..cb62ac8be 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonAnimationComponent.cpp @@ -96,6 +96,17 @@ void USpineSkeletonAnimationComponent::InternalTick(float DeltaTime, bool CallDe CheckState(); if (state && bAutoPlaying) { + if (lastPreviewAnimation != PreviewAnimation) { + if (PreviewAnimation != "") SetAnimation(0, TCHAR_TO_UTF8(*PreviewAnimation), true); + else SetEmptyAnimation(0, 0); + lastPreviewAnimation = PreviewAnimation; + } + + if (lastPreviewSkin != PreviewSkin) { + if (PreviewSkin != "") SetSkin(TCHAR_TO_UTF8(*PreviewSkin)); + else SetSkin("default"); + lastPreviewSkin = PreviewSkin; + } state->update(DeltaTime); state->apply(*skeleton); if (CallDelegates) BeforeUpdateWorldTransform.Broadcast(this); diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp index 94919b6cb..34423f537 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp @@ -128,6 +128,7 @@ public: void USpineSkeletonDataAsset::LoadInfo() { #if WITH_EDITORONLY_DATA int dataLen = rawData.Num(); + if (dataLen == 0) return; NullAttachmentLoader loader; SkeletonData* skeletonData = nullptr; if (skeletonDataFileName.GetPlainNameString().Contains(TEXT(".json"))) { diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h index eac35678a..3403d1fca 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonAnimationComponent.h @@ -259,6 +259,12 @@ public: UPROPERTY(BlueprintAssignable, Category="Components|Spine|Animation") FSpineAnimationDisposeDelegate AnimationDispose; + + UPROPERTY(Transient, EditAnywhere) + FString PreviewAnimation; + + UPROPERTY(Transient, EditAnywhere) + FString PreviewSkin; // used in C event callback. Needs to be public as we can't call // protected methods from plain old C function. @@ -279,4 +285,7 @@ private: /* If the animation should update automatically. */ UPROPERTY() bool bAutoPlaying; + + FString lastPreviewAnimation; + FString lastPreviewSkin; };