From f540dd4985e6e42cf8e7e4b9e8ddafb0ac91f8df Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Wed, 29 Nov 2023 00:43:13 +0100 Subject: [PATCH] [ue] Remove PostLoadAssetRegistryTags usage for compatibility with UE 4.27 --- spine-sfml/cpp/example/testbed.cpp | 6 +- .../SpinePlugin/Private/SpineAtlasAsset.cpp | 29 ++-- .../Private/SpineSkeletonDataAsset.cpp | 162 +++++++++++------- .../SpinePlugin/Public/SpineAtlasAsset.h | 1 - .../Public/SpineSkeletonDataAsset.h | 4 +- 5 files changed, 121 insertions(+), 81 deletions(-) diff --git a/spine-sfml/cpp/example/testbed.cpp b/spine-sfml/cpp/example/testbed.cpp index 3da197883..bc8c6a61b 100644 --- a/spine-sfml/cpp/example/testbed.cpp +++ b/spine-sfml/cpp/example/testbed.cpp @@ -73,7 +73,7 @@ int main(void) { String atlasFile("/Users/badlogic/Desktop/basemodel-male/basemodel-male.atlas"); String skeletonFile("/Users/badlogic/Desktop/basemodel-male/basemodel-male.skel"); String animation = ""; - String skin = "BasicBody"; + String skin = "BasicBody"; float scale = 0.1f; SFMLTextureLoader textureLoader; @@ -104,10 +104,10 @@ int main(void) { AnimationStateData stateData(skeletonData); SkeletonDrawable drawable(skeletonData, &stateData); - drawable.skeleton->updateWorldTransform(); + drawable.skeleton->updateWorldTransform(); drawable.skeleton->setPosition(320, 590); if (animation.length() > 0) drawable.state->setAnimation(0, animation, true); - if (skin.length() > 0) drawable.skeleton->setSkin(skin); + if (skin.length() > 0) drawable.skeleton->setSkin(skin); sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - testbed"); window.setFramerateLimit(60); diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineAtlasAsset.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineAtlasAsset.cpp index c1759eed7..cf8e99951 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineAtlasAsset.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineAtlasAsset.cpp @@ -44,38 +44,32 @@ void USpineAtlasAsset::SetAtlasFileName(const FName &AtlasFileName) { importData->UpdateFilenameOnly(AtlasFileName.ToString()); TArray files; importData->ExtractFilenames(files); - if (files.Num() > 0) atlasFileName = FName(*files[0]); + if (files.Num() > 0) + atlasFileName = FName(*files[0]); } void USpineAtlasAsset::PostInitProperties() { - if (!HasAnyFlags(RF_ClassDefaultObject)) importData = NewObject(this, TEXT("AssetImportData")); + if (!HasAnyFlags(RF_ClassDefaultObject)) + importData = NewObject(this, TEXT("AssetImportData")); Super::PostInitProperties(); } void USpineAtlasAsset::Serialize(FArchive &Ar) { Super::Serialize(Ar); - if (Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_ASSET_IMPORT_DATA_AS_JSON && !importData) + if (Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_ASSET_IMPORT_DATA_AS_JSON && + !importData) importData = NewObject(this, TEXT("AssetImportData")); } -void USpineAtlasAsset::PostLoadAssetRegistryTags(const FAssetData &InAssetData, - TArray &OutTagsAndValuesToUpdate) const { - // FIXME: this is a massive hack. It will set the PackageFlags of the FAssetData - // in the AssetRegistry to PKG_FilterEditorOnly so the content browser displays it. - // This is necessary in UE 5.3 due to a regression in ContentBrowserAssetDataCore::IsPrimaryAsset - // See https://github.com/EsotericSoftware/spine-runtimes/issues/2368 - FAssetData &MutableAssetData = const_cast(InAssetData); - // MutableAssetData.PackageFlags = EPackageFlags::PKG_FilterEditorOnly; - UObject::PostLoadAssetRegistryTags(MutableAssetData, OutTagsAndValuesToUpdate); -} - #endif FName USpineAtlasAsset::GetAtlasFileName() const { #if WITH_EDITORONLY_DATA TArray files; - if (importData) importData->ExtractFilenames(files); - if (files.Num() > 0) return FName(*files[0]); + if (importData) + importData->ExtractFilenames(files); + if (files.Num() > 0) + return FName(*files[0]); else return atlasFileName; #else @@ -107,7 +101,8 @@ Atlas *USpineAtlasAsset::GetAtlas() { } std::string t = TCHAR_TO_UTF8(*rawData); - atlas = new (__FILE__, __LINE__) Atlas(t.c_str(), strlen(t.c_str()), "", nullptr); + atlas = new (__FILE__, __LINE__) + Atlas(t.c_str(), strlen(t.c_str()), "", nullptr); Vector &pages = atlas->getPages(); for (size_t i = 0, n = pages.size(), j = 0; i < n; i++) { AtlasPage *page = pages[i]; diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp index 55e87afab..644e2deb6 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonDataAsset.cpp @@ -28,11 +28,11 @@ *****************************************************************************/ #include "SpineSkeletonDataAsset.h" -#include "SpinePlugin.h" -#include "Runtime/Core/Public/Misc/MessageDialog.h" #include "EditorFramework/AssetImportData.h" -#include "spine/spine.h" +#include "Runtime/Core/Public/Misc/MessageDialog.h" +#include "SpinePlugin.h" #include "spine/Version.h" +#include "spine/spine.h" #include #define LOCTEXT_NAMESPACE "Spine" @@ -42,8 +42,10 @@ using namespace spine; FName USpineSkeletonDataAsset::GetSkeletonDataFileName() const { #if WITH_EDITORONLY_DATA TArray files; - if (importData) importData->ExtractFilenames(files); - if (files.Num() > 0) return FName(*files[0]); + if (importData) + importData->ExtractFilenames(files); + if (files.Num() > 0) + return FName(*files[0]); else return skeletonDataFileName; #else @@ -53,21 +55,27 @@ FName USpineSkeletonDataAsset::GetSkeletonDataFileName() const { #if WITH_EDITORONLY_DATA -void USpineSkeletonDataAsset::SetSkeletonDataFileName(const FName &SkeletonDataFileName) { +void USpineSkeletonDataAsset::SetSkeletonDataFileName( + const FName &SkeletonDataFileName) { importData->UpdateFilenameOnly(SkeletonDataFileName.ToString()); TArray files; importData->ExtractFilenames(files); - if (files.Num() > 0) this->skeletonDataFileName = FName(*files[0]); + if (files.Num() > 0) + this->skeletonDataFileName = FName(*files[0]); } void USpineSkeletonDataAsset::PostInitProperties() { - if (!HasAnyFlags(RF_ClassDefaultObject)) importData = NewObject(this, TEXT("AssetImportData")); + if (!HasAnyFlags(RF_ClassDefaultObject)) + importData = NewObject(this, TEXT("AssetImportData")); Super::PostInitProperties(); } -void USpineSkeletonDataAsset::GetAssetRegistryTags(TArray &OutTags) const { +void USpineSkeletonDataAsset::GetAssetRegistryTags( + TArray &OutTags) const { if (importData) { - OutTags.Add(FAssetRegistryTag(SourceFileTagName(), importData->GetSourceData().ToJson(), FAssetRegistryTag::TT_Hidden)); + OutTags.Add(FAssetRegistryTag(SourceFileTagName(), + importData->GetSourceData().ToJson(), + FAssetRegistryTag::TT_Hidden)); } Super::GetAssetRegistryTags(OutTags); @@ -75,29 +83,20 @@ void USpineSkeletonDataAsset::GetAssetRegistryTags(TArray &Ou void USpineSkeletonDataAsset::Serialize(FArchive &Ar) { Super::Serialize(Ar); - if (Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_ASSET_IMPORT_DATA_AS_JSON && !importData) + if (Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_ASSET_IMPORT_DATA_AS_JSON && + !importData) importData = NewObject(this, TEXT("AssetImportData")); LoadInfo(); } - -void USpineSkeletonDataAsset::PostLoadAssetRegistryTags(const FAssetData &InAssetData, - // FIXME: this is a massive hack. It will set the PackageFlags of the FAssetData - // in the AssetRegistry to PKG_FilterEditorOnly so the content browser displays it. - // This is necessary in UE 5.3 due to a regression in ContentBrowserAssetDataCore::IsPrimaryAsset - // See https://github.com/EsotericSoftware/spine-runtimes/issues/2368 - TArray &OutTagsAndValuesToUpdate) const { - FAssetData &MutableAssetData = const_cast(InAssetData); - // MutableAssetData.PackageFlags = EPackageFlags::PKG_FilterEditorOnly; - UObject::PostLoadAssetRegistryTags(MutableAssetData, OutTagsAndValuesToUpdate); -} - #endif void USpineSkeletonDataAsset::ClearNativeData() { for (auto &pair : atlasToNativeData) { - if (pair.Value.skeletonData) delete pair.Value.skeletonData; - if (pair.Value.animationStateData) delete pair.Value.animationStateData; + if (pair.Value.skeletonData) + delete pair.Value.skeletonData; + if (pair.Value.animationStateData) + delete pair.Value.animationStateData; } atlasToNativeData.Empty(); } @@ -110,15 +109,20 @@ void USpineSkeletonDataAsset::BeginDestroy() { class SP_API NullAttachmentLoader : public AttachmentLoader { public: - virtual RegionAttachment *newRegionAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence) { + virtual RegionAttachment *newRegionAttachment(Skin &skin, const String &name, + const String &path, + Sequence *sequence) { return new (__FILE__, __LINE__) RegionAttachment(name); } - virtual MeshAttachment *newMeshAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence) { + virtual MeshAttachment *newMeshAttachment(Skin &skin, const String &name, + const String &path, + Sequence *sequence) { return new (__FILE__, __LINE__) MeshAttachment(name); } - virtual BoundingBoxAttachment *newBoundingBoxAttachment(Skin &skin, const String &name) { + virtual BoundingBoxAttachment *newBoundingBoxAttachment(Skin &skin, + const String &name) { return new (__FILE__, __LINE__) BoundingBoxAttachment(name); } @@ -130,12 +134,12 @@ public: return new (__FILE__, __LINE__) PointAttachment(name); } - virtual ClippingAttachment *newClippingAttachment(Skin &skin, const String &name) { + virtual ClippingAttachment *newClippingAttachment(Skin &skin, + const String &name) { return new (__FILE__, __LINE__) ClippingAttachment(name); } - virtual void configureAttachment(Attachment *attachment) { - } + virtual void configureAttachment(Attachment *attachment) {} }; void USpineSkeletonDataAsset::SetRawData(TArray &Data) { @@ -148,7 +152,8 @@ void USpineSkeletonDataAsset::SetRawData(TArray &Data) { } static bool checkVersion(const char *version) { - if (!version) return false; + if (!version) + return false; char *result = (char *) (strstr(version, SPINE_VERSION_STRING) - version); return result == 0; } @@ -156,9 +161,11 @@ static bool checkVersion(const char *version) { static bool checkJson(const char *jsonData) { Json json(jsonData); Json *skeleton = Json::getItem(&json, "skeleton"); - if (!skeleton) return false; + if (!skeleton) + return false; const char *version = Json::getString(skeleton, "spine", 0); - if (!version) return false; + if (!version) + return false; return checkVersion(version); } @@ -168,9 +175,7 @@ struct BinaryInput { const unsigned char *end; }; -static unsigned char readByte(BinaryInput *input) { - return *input->cursor++; -} +static unsigned char readByte(BinaryInput *input) { return *input->cursor++; } static int readVarint(BinaryInput *input, bool optimizePositive) { unsigned char b = readByte(input); @@ -184,7 +189,8 @@ static int readVarint(BinaryInput *input, bool optimizePositive) { if (b & 0x80) { b = readByte(input); value |= (b & 0x7F) << 21; - if (b & 0x80) value |= (readByte(input) & 0x7F) << 28; + if (b & 0x80) + value |= (readByte(input) & 0x7F) << 28; } } } @@ -224,23 +230,39 @@ static bool checkBinary(const char *binaryData, int length) { void USpineSkeletonDataAsset::LoadInfo() { #if WITH_EDITORONLY_DATA int dataLen = rawData.Num(); - if (dataLen == 0) return; + if (dataLen == 0) + return; NullAttachmentLoader loader; SkeletonData *skeletonData = nullptr; if (skeletonDataFileName.GetPlainNameString().Contains(TEXT(".json"))) { SkeletonJson *json = new (__FILE__, __LINE__) SkeletonJson(&loader); - if (checkJson((const char *) rawData.GetData())) skeletonData = json->readSkeletonData((const char *) rawData.GetData()); + if (checkJson((const char *) rawData.GetData())) + skeletonData = json->readSkeletonData((const char *) rawData.GetData()); if (!skeletonData) { - FMessageDialog::Debugf(FText::FromString(FString("Couldn't load skeleton data and/or atlas. Please ensure the version of your exported data matches your runtime version.\n\n") + skeletonDataFileName.GetPlainNameString() + FString("\n\n") + 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())); + FMessageDialog::Debugf(FText::FromString( + FString("Couldn't load skeleton data and/or atlas. Please ensure the " + "version of your exported data matches your runtime " + "version.\n\n") + + skeletonDataFileName.GetPlainNameString() + FString("\n\n") + + 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); - if (checkBinary((const char *) rawData.GetData(), (int) rawData.Num())) skeletonData = binary->readSkeletonData((const unsigned char *) rawData.GetData(), (int) rawData.Num()); + if (checkBinary((const char *) rawData.GetData(), (int) rawData.Num())) + skeletonData = binary->readSkeletonData( + (const unsigned char *) rawData.GetData(), (int) rawData.Num()); if (!skeletonData) { - FMessageDialog::Debugf(FText::FromString(FString("Couldn't load skeleton data and/or atlas. Please ensure the version of your exported data matches your runtime version.\n\n") + skeletonDataFileName.GetPlainNameString() + FString("\n\n") + 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())); + FMessageDialog::Debugf(FText::FromString( + FString("Couldn't load skeleton data and/or atlas. Please ensure the " + "version of your exported data matches your runtime " + "version.\n\n") + + skeletonDataFileName.GetPlainNameString() + FString("\n\n") + + 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; } @@ -256,10 +278,12 @@ void USpineSkeletonDataAsset::LoadInfo() { Slots.Add(UTF8_TO_TCHAR(skeletonData->getSlots()[i]->getName().buffer())); Animations.Empty(); for (int i = 0; i < skeletonData->getAnimations().size(); i++) - Animations.Add(UTF8_TO_TCHAR(skeletonData->getAnimations()[i]->getName().buffer())); + Animations.Add( + UTF8_TO_TCHAR(skeletonData->getAnimations()[i]->getName().buffer())); Events.Empty(); for (int i = 0; i < skeletonData->getEvents().size(); i++) - Events.Add(UTF8_TO_TCHAR(skeletonData->getEvents()[i]->getName().buffer())); + Events.Add( + UTF8_TO_TCHAR(skeletonData->getEvents()[i]->getName().buffer())); delete skeletonData; } #endif @@ -277,28 +301,46 @@ SkeletonData *USpineSkeletonDataAsset::GetSkeletonData(Atlas *Atlas) { int dataLen = rawData.Num(); if (skeletonDataFileName.GetPlainNameString().Contains(TEXT(".json"))) { SkeletonJson *json = new (__FILE__, __LINE__) SkeletonJson(Atlas); - if (checkJson((const char *) rawData.GetData())) skeletonData = json->readSkeletonData((const char *) rawData.GetData()); + if (checkJson((const char *) rawData.GetData())) + skeletonData = json->readSkeletonData((const char *) rawData.GetData()); if (!skeletonData) { #if WITH_EDITORONLY_DATA - FMessageDialog::Debugf(FText::FromString(FString("Couldn't load skeleton data and/or atlas. Please ensure the version of your exported data matches your runtime version.\n\n") + skeletonDataFileName.GetPlainNameString() + FString("\n\n") + UTF8_TO_TCHAR(json->getError().buffer()))); + FMessageDialog::Debugf(FText::FromString( + FString("Couldn't load skeleton data and/or atlas. Please ensure " + "the version of your exported data matches your runtime " + "version.\n\n") + + skeletonDataFileName.GetPlainNameString() + FString("\n\n") + + UTF8_TO_TCHAR(json->getError().buffer()))); #endif - UE_LOG(SpineLog, Error, TEXT("Couldn't load skeleton data and atlas: %s"), 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(Atlas); - if (checkBinary((const char *) rawData.GetData(), (int) rawData.Num())) skeletonData = binary->readSkeletonData((const unsigned char *) rawData.GetData(), (int) rawData.Num()); + if (checkBinary((const char *) rawData.GetData(), (int) rawData.Num())) + skeletonData = binary->readSkeletonData( + (const unsigned char *) rawData.GetData(), (int) rawData.Num()); if (!skeletonData) { #if WITH_EDITORONLY_DATA - FMessageDialog::Debugf(FText::FromString(FString("Couldn't load skeleton data and/or atlas. Please ensure the version of your exported data matches your runtime version.\n\n") + skeletonDataFileName.GetPlainNameString() + FString("\n\n") + UTF8_TO_TCHAR(binary->getError().buffer()))); + FMessageDialog::Debugf(FText::FromString( + FString("Couldn't load skeleton data and/or atlas. Please ensure " + "the version of your exported data matches your runtime " + "version.\n\n") + + skeletonDataFileName.GetPlainNameString() + FString("\n\n") + + UTF8_TO_TCHAR(binary->getError().buffer()))); #endif - UE_LOG(SpineLog, Error, TEXT("Couldn't load skeleton data and atlas: %s"), 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) { - animationStateData = new (__FILE__, __LINE__) AnimationStateData(skeletonData); + animationStateData = + new (__FILE__, __LINE__) AnimationStateData(skeletonData); SetMixes(animationStateData); atlasToNativeData.Add(Atlas, {skeletonData, animationStateData}); } @@ -318,14 +360,17 @@ void USpineSkeletonDataAsset::SetMixes(AnimationStateData *animationStateData) { animationStateData->setDefaultMix(DefaultMix); } -AnimationStateData *USpineSkeletonDataAsset::GetAnimationStateData(Atlas *atlas) { - if (!atlasToNativeData.Contains(atlas)) return nullptr; +AnimationStateData * +USpineSkeletonDataAsset::GetAnimationStateData(Atlas *atlas) { + if (!atlasToNativeData.Contains(atlas)) + return nullptr; AnimationStateData *data = atlasToNativeData[atlas].animationStateData; SetMixes(data); return data; } -void USpineSkeletonDataAsset::SetMix(const FString &from, const FString &to, float mix) { +void USpineSkeletonDataAsset::SetMix(const FString &from, const FString &to, + float mix) { FSpineAnimationStateMixData data; data.From = from; data.To = to; @@ -338,7 +383,8 @@ void USpineSkeletonDataAsset::SetMix(const FString &from, const FString &to, flo float USpineSkeletonDataAsset::GetMix(const FString &from, const FString &to) { for (auto &data : MixData) { - if (data.From.Equals(from) && data.To.Equals(to)) return data.Mix; + if (data.From.Equals(from) && data.To.Equals(to)) + return data.Mix; } return 0; } diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineAtlasAsset.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineAtlasAsset.h index 8b0500ac9..2813a2c3f 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineAtlasAsset.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineAtlasAsset.h @@ -71,6 +71,5 @@ protected: virtual void PostInitProperties() override; virtual void Serialize(FArchive &Ar) override; - virtual void PostLoadAssetRegistryTags(const FAssetData &InAssetData, TArray &OutTagsAndValuesToUpdate) const override; #endif }; diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h index af9ade5b0..9970d8f6c 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonDataAsset.h @@ -114,9 +114,9 @@ protected: class UAssetImportData *importData = nullptr; virtual void PostInitProperties() override; - virtual void GetAssetRegistryTags(TArray &OutTags) const override; + virtual void + GetAssetRegistryTags(TArray &OutTags) const override; virtual void Serialize(FArchive &Ar) override; - virtual void PostLoadAssetRegistryTags(const FAssetData &InAssetData, TArray &OutTagsAndValuesToUpdate) const override; #endif void LoadInfo();