mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-20 09:16:01 +08:00
Merge branch '3.7' of https://github.com/esotericsoftware/spine-runtimes into 3.7
This commit is contained in:
commit
b0629e51ec
@ -99,6 +99,8 @@
|
|||||||
* Updated to Unreal Engine 4.20 (samples require 4.17+), see the `spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/SpinePlugin.build.cs` file on how to compile in 4.20 with the latest UBT API changes.
|
* Updated to Unreal Engine 4.20 (samples require 4.17+), see the `spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/SpinePlugin.build.cs` file on how to compile in 4.20 with the latest UBT API changes.
|
||||||
* Updated to Unreal Engine 4.21 (samples require 4.21).
|
* Updated to Unreal Engine 4.21 (samples require 4.21).
|
||||||
* **Breaking change**: `UBoneDriverComponent` and `UBoneFollowerComponent` are now `USceneComponent` instead of `UActorComponent`. They either update only themselves, or also the owning `UActor`, depending on whether the new flag `UseComponentTransform` is set. See https://github.com/EsotericSoftware/spine-runtimes/pull/1175
|
* **Breaking change**: `UBoneDriverComponent` and `UBoneFollowerComponent` are now `USceneComponent` instead of `UActorComponent`. They either update only themselves, or also the owning `UActor`, depending on whether the new flag `UseComponentTransform` is set. See https://github.com/EsotericSoftware/spine-runtimes/pull/1175
|
||||||
|
* Added query methods for slots, bones, skins and animations to `SpineSkeletonComponent` and `UTrackEntry`. These allow you to query these objects by name in both C++ and blueprints.
|
||||||
|
* Added `Preview Animation` and `Preview Skin` properties to `SpineSkeletonAnimationComponent`. Enter an animation or skin name to live-preview it in the editor. Enter an empty string to reset the animation or skin.
|
||||||
|
|
||||||
## C# ##
|
## C# ##
|
||||||
* **Breaking changes**
|
* **Breaking changes**
|
||||||
|
|||||||
@ -8,7 +8,7 @@ This spine Runtime may only be used for personal or internal use, typically to e
|
|||||||
|
|
||||||
The spine Runtimes are developed with the intent to be used with data exported from spine. By purchasing spine, `Section 2` of the [spine Software License](https://esotericsoftware.com/files/license.txt) grants the right to create and distribute derivative works of the spine Runtimes.
|
The spine Runtimes are developed with the intent to be used with data exported from spine. By purchasing spine, `Section 2` of the [spine Software License](https://esotericsoftware.com/files/license.txt) grants the right to create and distribute derivative works of the spine Runtimes.
|
||||||
|
|
||||||
## spine version
|
## Spine version
|
||||||
|
|
||||||
spine-cpp works with data exported from spine 3.7.xx.
|
spine-cpp works with data exported from spine 3.7.xx.
|
||||||
|
|
||||||
@ -19,6 +19,9 @@ spine-cpp supports all spine features.
|
|||||||
1. Download the spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it as a zip via the download button above.
|
1. Download the spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it as a zip via the download button above.
|
||||||
2. Copy the contents of the `spine-cpp/spine-cpp/src` and `spine-cpp/spine-cpp/include` directories into your project. Be sure your header search is configured to find the contents of the `spine-cpp/spine-cpp/include` directory. Note that the includes use `spine/Xxx.h`, so the `spine` directory cannot be omitted when copying the files.
|
2. Copy the contents of the `spine-cpp/spine-cpp/src` and `spine-cpp/spine-cpp/include` directories into your project. Be sure your header search is configured to find the contents of the `spine-cpp/spine-cpp/include` directory. Note that the includes use `spine/Xxx.h`, so the `spine` directory cannot be omitted when copying the files.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
### [Please see the spine-cpp guide for full documentation](http://esotericsoftware.com/spine-cpp)
|
||||||
|
|
||||||
## Extension
|
## Extension
|
||||||
|
|
||||||
Extending spine-cpp requires implementing both the `SpineExtension` class and the TextureLoader class:
|
Extending spine-cpp requires implementing both the `SpineExtension` class and the TextureLoader class:
|
||||||
|
|||||||
@ -171,6 +171,8 @@ void TrackEntry::reset() {
|
|||||||
_mixingFrom = NULL;
|
_mixingFrom = NULL;
|
||||||
_mixingTo = NULL;
|
_mixingTo = NULL;
|
||||||
|
|
||||||
|
setRendererObject(NULL);
|
||||||
|
|
||||||
_timelineMode.clear();
|
_timelineMode.clear();
|
||||||
_timelineHoldMix.clear();
|
_timelineHoldMix.clear();
|
||||||
_timelinesRotation.clear();
|
_timelinesRotation.clear();
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
<groupId>com.esotericsoftware.spine</groupId>
|
<groupId>com.esotericsoftware.spine</groupId>
|
||||||
<artifactId>spine-libgdx</artifactId>
|
<artifactId>spine-libgdx</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<version>3.7.83.2-SNAPSHOT</version>
|
<version>3.7.92.1-SNAPSHOT</version>
|
||||||
|
|
||||||
|
|
||||||
<name>spine-libgdx</name>
|
<name>spine-libgdx</name>
|
||||||
|
|||||||
@ -81,9 +81,9 @@ UObject* USpineSkeletonAssetFactory::FactoryCreateFile (UClass * InClass, UObjec
|
|||||||
if (!FFileHelper::LoadFileToArray(rawData, *Filename, 0)) {
|
if (!FFileHelper::LoadFileToArray(rawData, *Filename, 0)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
asset->SetSkeletonDataFileName(FName(*Filename));
|
||||||
asset->SetRawData(rawData);
|
asset->SetRawData(rawData);
|
||||||
|
|
||||||
asset->SetSkeletonDataFileName(FName(*Filename));
|
|
||||||
const FString longPackagePath = FPackageName::GetLongPackagePath(asset->GetOutermost()->GetPathName());
|
const FString longPackagePath = FPackageName::GetLongPackagePath(asset->GetOutermost()->GetPathName());
|
||||||
LoadAtlas(Filename, longPackagePath);
|
LoadAtlas(Filename, longPackagePath);
|
||||||
return asset;
|
return asset;
|
||||||
|
|||||||
@ -96,6 +96,17 @@ void USpineSkeletonAnimationComponent::InternalTick(float DeltaTime, bool CallDe
|
|||||||
CheckState();
|
CheckState();
|
||||||
|
|
||||||
if (state && bAutoPlaying) {
|
if (state && bAutoPlaying) {
|
||||||
|
if (lastPreviewAnimation != PreviewAnimation) {
|
||||||
|
if (PreviewAnimation != "") SetAnimation(0, PreviewAnimation, true);
|
||||||
|
else SetEmptyAnimation(0, 0);
|
||||||
|
lastPreviewAnimation = PreviewAnimation;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastPreviewSkin != PreviewSkin) {
|
||||||
|
if (PreviewSkin != "") SetSkin(PreviewSkin);
|
||||||
|
else SetSkin("default");
|
||||||
|
lastPreviewSkin = PreviewSkin;
|
||||||
|
}
|
||||||
state->update(DeltaTime);
|
state->update(DeltaTime);
|
||||||
state->apply(*skeleton);
|
state->apply(*skeleton);
|
||||||
if (CallDelegates) BeforeUpdateWorldTransform.Broadcast(this);
|
if (CallDelegates) BeforeUpdateWorldTransform.Broadcast(this);
|
||||||
|
|||||||
@ -42,7 +42,7 @@ USpineSkeletonComponent::USpineSkeletonComponent () {
|
|||||||
bAutoActivate = true;
|
bAutoActivate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool USpineSkeletonComponent::SetSkin(const FString& skinName) {
|
bool USpineSkeletonComponent::SetSkin (const FString skinName) {
|
||||||
CheckState();
|
CheckState();
|
||||||
if (skeleton) {
|
if (skeleton) {
|
||||||
Skin* skin = skeleton->getData()->findSkin(TCHAR_TO_UTF8(*skinName));
|
Skin* skin = skeleton->getData()->findSkin(TCHAR_TO_UTF8(*skinName));
|
||||||
@ -53,7 +53,24 @@ bool USpineSkeletonComponent::SetSkin(const FString& skinName) {
|
|||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool USpineSkeletonComponent::SetAttachment (const FString& slotName, const FString& attachmentName) {
|
void USpineSkeletonComponent::GetSkins (TArray<FString> &Skins) {
|
||||||
|
CheckState();
|
||||||
|
if (skeleton) {
|
||||||
|
for (size_t i = 0, n = skeleton->getData()->getSkins().size(); i < n; i++) {
|
||||||
|
Skins.Add(skeleton->getData()->getSkins()[i]->getName().buffer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool USpineSkeletonComponent::HasSkin (const FString skinName) {
|
||||||
|
CheckState();
|
||||||
|
if (skeleton) {
|
||||||
|
return skeleton->getData()->findAnimation(TCHAR_TO_UTF8(*skinName)) != nullptr;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool USpineSkeletonComponent::SetAttachment (const FString slotName, const FString attachmentName) {
|
||||||
CheckState();
|
CheckState();
|
||||||
if (skeleton) {
|
if (skeleton) {
|
||||||
if (!skeleton->getAttachment(TCHAR_TO_UTF8(*slotName), TCHAR_TO_UTF8(*attachmentName))) return false;
|
if (!skeleton->getAttachment(TCHAR_TO_UTF8(*slotName), TCHAR_TO_UTF8(*attachmentName))) return false;
|
||||||
@ -127,7 +144,7 @@ void USpineSkeletonComponent::SetBoneWorldPosition (const FString& BoneName, con
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void USpineSkeletonComponent::UpdateWorldTransform() {
|
void USpineSkeletonComponent::UpdateWorldTransform () {
|
||||||
CheckState();
|
CheckState();
|
||||||
if (skeleton) {
|
if (skeleton) {
|
||||||
skeleton->updateWorldTransform();
|
skeleton->updateWorldTransform();
|
||||||
@ -154,24 +171,24 @@ void USpineSkeletonComponent::SetScaleX (float scaleX) {
|
|||||||
if (skeleton) skeleton->setScaleX(scaleX);
|
if (skeleton) skeleton->setScaleX(scaleX);
|
||||||
}
|
}
|
||||||
|
|
||||||
float USpineSkeletonComponent::GetScaleX() {
|
float USpineSkeletonComponent::GetScaleX () {
|
||||||
CheckState();
|
CheckState();
|
||||||
if (skeleton) return skeleton->getScaleX();
|
if (skeleton) return skeleton->getScaleX();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void USpineSkeletonComponent::SetScaleY(float scaleY) {
|
void USpineSkeletonComponent::SetScaleY (float scaleY) {
|
||||||
CheckState();
|
CheckState();
|
||||||
if (skeleton) skeleton->setScaleY(scaleY);
|
if (skeleton) skeleton->setScaleY(scaleY);
|
||||||
}
|
}
|
||||||
|
|
||||||
float USpineSkeletonComponent::GetScaleY() {
|
float USpineSkeletonComponent::GetScaleY () {
|
||||||
CheckState();
|
CheckState();
|
||||||
if (skeleton) return skeleton->getScaleY();
|
if (skeleton) return skeleton->getScaleY();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void USpineSkeletonComponent::GetBones(TArray<FString> &Bones) {
|
void USpineSkeletonComponent::GetBones (TArray<FString> &Bones) {
|
||||||
CheckState();
|
CheckState();
|
||||||
if (skeleton) {
|
if (skeleton) {
|
||||||
for (size_t i = 0, n = skeleton->getBones().size(); i < n; i++) {
|
for (size_t i = 0, n = skeleton->getBones().size(); i < n; i++) {
|
||||||
@ -180,6 +197,58 @@ void USpineSkeletonComponent::GetBones(TArray<FString> &Bones) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool USpineSkeletonComponent::HasBone (const FString BoneName) {
|
||||||
|
CheckState();
|
||||||
|
if (skeleton) {
|
||||||
|
return skeleton->getData()->findBone(TCHAR_TO_UTF8(*BoneName)) != nullptr;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USpineSkeletonComponent::GetSlots (TArray<FString> &Slots) {
|
||||||
|
CheckState();
|
||||||
|
if (skeleton) {
|
||||||
|
for (size_t i = 0, n = skeleton->getSlots().size(); i < n; i++) {
|
||||||
|
Slots.Add(skeleton->getSlots()[i]->getData().getName().buffer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool USpineSkeletonComponent::HasSlot (const FString SlotName) {
|
||||||
|
CheckState();
|
||||||
|
if (skeleton) {
|
||||||
|
return skeleton->getData()->findSlot(TCHAR_TO_UTF8(*SlotName)) != nullptr;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USpineSkeletonComponent::GetAnimations(TArray<FString> &Animations) {
|
||||||
|
CheckState();
|
||||||
|
if (skeleton) {
|
||||||
|
for (size_t i = 0, n = skeleton->getData()->getAnimations().size(); i < n; i++) {
|
||||||
|
Animations.Add(skeleton->getData()->getAnimations()[i]->getName().buffer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool USpineSkeletonComponent::HasAnimation(FString AnimationName) {
|
||||||
|
CheckState();
|
||||||
|
if (skeleton) {
|
||||||
|
return skeleton->getData()->findAnimation(TCHAR_TO_UTF8(*AnimationName)) != nullptr;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float USpineSkeletonComponent::GetAnimationDuration(FString AnimationName) {
|
||||||
|
CheckState();
|
||||||
|
if (skeleton) {
|
||||||
|
Animation *animation = skeleton->getData()->findAnimation(TCHAR_TO_UTF8(*AnimationName));
|
||||||
|
if (animation == nullptr) return 0;
|
||||||
|
else return animation->getDuration();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void USpineSkeletonComponent::BeginPlay() {
|
void USpineSkeletonComponent::BeginPlay() {
|
||||||
Super::BeginPlay();
|
Super::BeginPlay();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -76,6 +76,7 @@ void USpineSkeletonDataAsset::Serialize (FArchive& Ar) {
|
|||||||
Super::Serialize(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<UAssetImportData>(this, TEXT("AssetImportData"));
|
importData = NewObject<UAssetImportData>(this, TEXT("AssetImportData"));
|
||||||
|
LoadInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -92,13 +93,92 @@ void USpineSkeletonDataAsset::BeginDestroy () {
|
|||||||
Super::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();
|
||||||
|
if (dataLen == 0) return;
|
||||||
|
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(UTF8_TO_TCHAR(skeletonData->getBones()[i]->getName().buffer()));
|
||||||
|
Skins.Empty();
|
||||||
|
for (int i = 0; i < skeletonData->getSkins().size(); i++)
|
||||||
|
Skins.Add(UTF8_TO_TCHAR(skeletonData->getSkins()[i]->getName().buffer()));
|
||||||
|
Slots.Empty();
|
||||||
|
for (int i = 0; i < skeletonData->getSlots().size(); i++)
|
||||||
|
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()));
|
||||||
|
Events.Empty();
|
||||||
|
for (int i = 0; i < skeletonData->getEvents().size(); i++)
|
||||||
|
Events.Add(UTF8_TO_TCHAR(skeletonData->getEvents()[i]->getName().buffer()));
|
||||||
|
delete skeletonData;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void USpineSkeletonDataAsset::SetRawData(TArray<uint8> &Data) {
|
void USpineSkeletonDataAsset::SetRawData(TArray<uint8> &Data) {
|
||||||
this->rawData.Empty();
|
this->rawData.Empty();
|
||||||
this->rawData.Append(Data);
|
this->rawData.Append(Data);
|
||||||
|
|
||||||
if (skeletonData) {
|
if (skeletonData) {
|
||||||
delete skeletonData;
|
delete skeletonData;
|
||||||
skeletonData = nullptr;
|
skeletonData = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoadInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
SkeletonData* USpineSkeletonDataAsset::GetSkeletonData (Atlas* Atlas) {
|
SkeletonData* USpineSkeletonDataAsset::GetSkeletonData (Atlas* Atlas) {
|
||||||
|
|||||||
@ -76,94 +76,100 @@ void USpineSkeletonRendererComponent::TickComponent (float DeltaTime, ELevelTick
|
|||||||
UClass* skeletonClass = USpineSkeletonComponent::StaticClass();
|
UClass* skeletonClass = USpineSkeletonComponent::StaticClass();
|
||||||
USpineSkeletonComponent* skeleton = Cast<USpineSkeletonComponent>(owner->GetComponentByClass(skeletonClass));
|
USpineSkeletonComponent* skeleton = Cast<USpineSkeletonComponent>(owner->GetComponentByClass(skeletonClass));
|
||||||
|
|
||||||
if (skeleton && !skeleton->IsBeingDestroyed() && skeleton->GetSkeleton() && skeleton->Atlas) {
|
UpdateRenderer(skeleton);
|
||||||
skeleton->GetSkeleton()->getColor().set(Color.R, Color.G, Color.B, Color.A);
|
|
||||||
|
|
||||||
if (atlasNormalBlendMaterials.Num() != skeleton->Atlas->atlasPages.Num()) {
|
|
||||||
atlasNormalBlendMaterials.SetNum(0);
|
|
||||||
pageToNormalBlendMaterial.Empty();
|
|
||||||
atlasAdditiveBlendMaterials.SetNum(0);
|
|
||||||
pageToAdditiveBlendMaterial.Empty();
|
|
||||||
atlasMultiplyBlendMaterials.SetNum(0);
|
|
||||||
pageToMultiplyBlendMaterial.Empty();
|
|
||||||
atlasScreenBlendMaterials.SetNum(0);
|
|
||||||
pageToScreenBlendMaterial.Empty();
|
|
||||||
|
|
||||||
for (int i = 0; i < skeleton->Atlas->atlasPages.Num(); i++) {
|
|
||||||
AtlasPage* currPage = skeleton->Atlas->GetAtlas()->getPages()[i];
|
|
||||||
|
|
||||||
UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(NormalBlendMaterial, owner);
|
|
||||||
material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]);
|
|
||||||
atlasNormalBlendMaterials.Add(material);
|
|
||||||
pageToNormalBlendMaterial.Add(currPage, material);
|
|
||||||
|
|
||||||
material = UMaterialInstanceDynamic::Create(AdditiveBlendMaterial, owner);
|
|
||||||
material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]);
|
|
||||||
atlasAdditiveBlendMaterials.Add(material);
|
|
||||||
pageToAdditiveBlendMaterial.Add(currPage, material);
|
|
||||||
|
|
||||||
material = UMaterialInstanceDynamic::Create(MultiplyBlendMaterial, owner);
|
|
||||||
material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]);
|
|
||||||
atlasMultiplyBlendMaterials.Add(material);
|
|
||||||
pageToMultiplyBlendMaterial.Add(currPage, material);
|
|
||||||
|
|
||||||
material = UMaterialInstanceDynamic::Create(ScreenBlendMaterial, owner);
|
|
||||||
material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]);
|
|
||||||
atlasScreenBlendMaterials.Add(material);
|
|
||||||
pageToScreenBlendMaterial.Add(currPage, material);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pageToNormalBlendMaterial.Empty();
|
|
||||||
pageToAdditiveBlendMaterial.Empty();
|
|
||||||
pageToMultiplyBlendMaterial.Empty();
|
|
||||||
pageToScreenBlendMaterial.Empty();
|
|
||||||
|
|
||||||
for (int i = 0; i < skeleton->Atlas->atlasPages.Num(); i++) {
|
|
||||||
AtlasPage* currPage = skeleton->Atlas->GetAtlas()->getPages()[i];
|
|
||||||
|
|
||||||
UTexture2D* texture = skeleton->Atlas->atlasPages[i];
|
|
||||||
UTexture* oldTexture = nullptr;
|
|
||||||
|
|
||||||
UMaterialInstanceDynamic* current = atlasNormalBlendMaterials[i];
|
|
||||||
if(!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) {
|
|
||||||
UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(NormalBlendMaterial, owner);
|
|
||||||
material->SetTextureParameterValue(TextureParameterName, texture);
|
|
||||||
atlasNormalBlendMaterials[i] = material;
|
|
||||||
}
|
|
||||||
pageToNormalBlendMaterial.Add(currPage, atlasNormalBlendMaterials[i]);
|
|
||||||
|
|
||||||
current = atlasAdditiveBlendMaterials[i];
|
|
||||||
if(!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) {
|
|
||||||
UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(AdditiveBlendMaterial, owner);
|
|
||||||
material->SetTextureParameterValue(TextureParameterName, texture);
|
|
||||||
atlasAdditiveBlendMaterials[i] = material;
|
|
||||||
}
|
|
||||||
pageToAdditiveBlendMaterial.Add(currPage, atlasAdditiveBlendMaterials[i]);
|
|
||||||
|
|
||||||
current = atlasMultiplyBlendMaterials[i];
|
|
||||||
if(!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) {
|
|
||||||
UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(MultiplyBlendMaterial, owner);
|
|
||||||
material->SetTextureParameterValue(TextureParameterName, texture);
|
|
||||||
atlasMultiplyBlendMaterials[i] = material;
|
|
||||||
}
|
|
||||||
pageToMultiplyBlendMaterial.Add(currPage, atlasMultiplyBlendMaterials[i]);
|
|
||||||
|
|
||||||
current = atlasScreenBlendMaterials[i];
|
|
||||||
if(!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) {
|
|
||||||
UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(ScreenBlendMaterial, owner);
|
|
||||||
material->SetTextureParameterValue(TextureParameterName, texture);
|
|
||||||
atlasScreenBlendMaterials[i] = material;
|
|
||||||
}
|
|
||||||
pageToScreenBlendMaterial.Add(currPage, atlasScreenBlendMaterials[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UpdateMesh(skeleton->GetSkeleton());
|
|
||||||
} else {
|
|
||||||
ClearAllMeshSections();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void USpineSkeletonRendererComponent::UpdateRenderer(USpineSkeletonComponent* skeleton)
|
||||||
|
{
|
||||||
|
if (skeleton && !skeleton->IsBeingDestroyed() && skeleton->GetSkeleton() && skeleton->Atlas) {
|
||||||
|
skeleton->GetSkeleton()->getColor().set(Color.R, Color.G, Color.B, Color.A);
|
||||||
|
|
||||||
|
if (atlasNormalBlendMaterials.Num() != skeleton->Atlas->atlasPages.Num()) {
|
||||||
|
atlasNormalBlendMaterials.SetNum(0);
|
||||||
|
pageToNormalBlendMaterial.Empty();
|
||||||
|
atlasAdditiveBlendMaterials.SetNum(0);
|
||||||
|
pageToAdditiveBlendMaterial.Empty();
|
||||||
|
atlasMultiplyBlendMaterials.SetNum(0);
|
||||||
|
pageToMultiplyBlendMaterial.Empty();
|
||||||
|
atlasScreenBlendMaterials.SetNum(0);
|
||||||
|
pageToScreenBlendMaterial.Empty();
|
||||||
|
|
||||||
|
for (int i = 0; i < skeleton->Atlas->atlasPages.Num(); i++) {
|
||||||
|
AtlasPage* currPage = skeleton->Atlas->GetAtlas()->getPages()[i];
|
||||||
|
|
||||||
|
UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(NormalBlendMaterial, this);
|
||||||
|
material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]);
|
||||||
|
atlasNormalBlendMaterials.Add(material);
|
||||||
|
pageToNormalBlendMaterial.Add(currPage, material);
|
||||||
|
|
||||||
|
material = UMaterialInstanceDynamic::Create(AdditiveBlendMaterial, this);
|
||||||
|
material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]);
|
||||||
|
atlasAdditiveBlendMaterials.Add(material);
|
||||||
|
pageToAdditiveBlendMaterial.Add(currPage, material);
|
||||||
|
|
||||||
|
material = UMaterialInstanceDynamic::Create(MultiplyBlendMaterial, this);
|
||||||
|
material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]);
|
||||||
|
atlasMultiplyBlendMaterials.Add(material);
|
||||||
|
pageToMultiplyBlendMaterial.Add(currPage, material);
|
||||||
|
|
||||||
|
material = UMaterialInstanceDynamic::Create(ScreenBlendMaterial, this);
|
||||||
|
material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]);
|
||||||
|
atlasScreenBlendMaterials.Add(material);
|
||||||
|
pageToScreenBlendMaterial.Add(currPage, material);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pageToNormalBlendMaterial.Empty();
|
||||||
|
pageToAdditiveBlendMaterial.Empty();
|
||||||
|
pageToMultiplyBlendMaterial.Empty();
|
||||||
|
pageToScreenBlendMaterial.Empty();
|
||||||
|
|
||||||
|
for (int i = 0; i < skeleton->Atlas->atlasPages.Num(); i++) {
|
||||||
|
AtlasPage* currPage = skeleton->Atlas->GetAtlas()->getPages()[i];
|
||||||
|
|
||||||
|
UTexture2D* texture = skeleton->Atlas->atlasPages[i];
|
||||||
|
UTexture* oldTexture = nullptr;
|
||||||
|
|
||||||
|
UMaterialInstanceDynamic* current = atlasNormalBlendMaterials[i];
|
||||||
|
if (!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) {
|
||||||
|
UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(NormalBlendMaterial, this);
|
||||||
|
material->SetTextureParameterValue(TextureParameterName, texture);
|
||||||
|
atlasNormalBlendMaterials[i] = material;
|
||||||
|
}
|
||||||
|
pageToNormalBlendMaterial.Add(currPage, atlasNormalBlendMaterials[i]);
|
||||||
|
|
||||||
|
current = atlasAdditiveBlendMaterials[i];
|
||||||
|
if (!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) {
|
||||||
|
UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(AdditiveBlendMaterial, this);
|
||||||
|
material->SetTextureParameterValue(TextureParameterName, texture);
|
||||||
|
atlasAdditiveBlendMaterials[i] = material;
|
||||||
|
}
|
||||||
|
pageToAdditiveBlendMaterial.Add(currPage, atlasAdditiveBlendMaterials[i]);
|
||||||
|
|
||||||
|
current = atlasMultiplyBlendMaterials[i];
|
||||||
|
if (!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) {
|
||||||
|
UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(MultiplyBlendMaterial, this);
|
||||||
|
material->SetTextureParameterValue(TextureParameterName, texture);
|
||||||
|
atlasMultiplyBlendMaterials[i] = material;
|
||||||
|
}
|
||||||
|
pageToMultiplyBlendMaterial.Add(currPage, atlasMultiplyBlendMaterials[i]);
|
||||||
|
|
||||||
|
current = atlasScreenBlendMaterials[i];
|
||||||
|
if (!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) {
|
||||||
|
UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(ScreenBlendMaterial, this);
|
||||||
|
material->SetTextureParameterValue(TextureParameterName, texture);
|
||||||
|
atlasScreenBlendMaterials[i] = material;
|
||||||
|
}
|
||||||
|
pageToScreenBlendMaterial.Add(currPage, atlasScreenBlendMaterials[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UpdateMesh(skeleton->GetSkeleton());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ClearAllMeshSections();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void USpineSkeletonRendererComponent::Flush (int &Idx, TArray<FVector> &Vertices, TArray<int32> &Indices, TArray<FVector2D> &Uvs, TArray<FColor> &Colors, TArray<FVector>& Colors2, UMaterialInstanceDynamic* Material) {
|
void USpineSkeletonRendererComponent::Flush (int &Idx, TArray<FVector> &Vertices, TArray<int32> &Indices, TArray<FVector2D> &Uvs, TArray<FColor> &Colors, TArray<FVector>& Colors2, UMaterialInstanceDynamic* Material) {
|
||||||
if (Vertices.Num() == 0) return;
|
if (Vertices.Num() == 0) return;
|
||||||
|
|||||||
@ -90,7 +90,7 @@ public:
|
|||||||
UFUNCTION(BlueprintCallable, Category="Components|Spine|TrackEntry")
|
UFUNCTION(BlueprintCallable, Category="Components|Spine|TrackEntry")
|
||||||
bool GetLoop () { return entry ? entry->getLoop() : false; }
|
bool GetLoop () { return entry ? entry->getLoop() : false; }
|
||||||
UFUNCTION(BlueprintCallable, Category="Components|Spine|TrackEntry")
|
UFUNCTION(BlueprintCallable, Category="Components|Spine|TrackEntry")
|
||||||
void SetLoop(bool loop) { if (entry) entry->setLoop(loop); }
|
void SetLoop(bool loop) { if (entry) entry->setLoop(loop); }
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category="Components|Spine|TrackEntry")
|
UFUNCTION(BlueprintCallable, Category="Components|Spine|TrackEntry")
|
||||||
float GetEventThreshold () { return entry ? entry->getEventThreshold() : 0; }
|
float GetEventThreshold () { return entry ? entry->getEventThreshold() : 0; }
|
||||||
@ -157,6 +157,15 @@ public:
|
|||||||
UFUNCTION(BlueprintCallable, Category="Components|Spine|TrackEntry")
|
UFUNCTION(BlueprintCallable, Category="Components|Spine|TrackEntry")
|
||||||
void SetMixDuration(float mixDuration) { if (entry) entry->setMixDuration(mixDuration); }
|
void SetMixDuration(float mixDuration) { if (entry) entry->setMixDuration(mixDuration); }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Components|Spine|TrackEntry")
|
||||||
|
FString getAnimationName() { return entry ? entry->getAnimation()->getName().buffer() : ""; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Components|Spine|TrackEntry")
|
||||||
|
float getAnimationDuration() { return entry ? entry->getAnimation()->getDuration(): 0; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Components|Spine|TrackEntry")
|
||||||
|
float isValidAnimation() { return entry != nullptr; }
|
||||||
|
|
||||||
UPROPERTY(BlueprintAssignable, Category = "Components|Spine|TrackEntry")
|
UPROPERTY(BlueprintAssignable, Category = "Components|Spine|TrackEntry")
|
||||||
FSpineAnimationStartDelegate AnimationStart;
|
FSpineAnimationStartDelegate AnimationStart;
|
||||||
|
|
||||||
@ -251,6 +260,12 @@ public:
|
|||||||
UPROPERTY(BlueprintAssignable, Category="Components|Spine|Animation")
|
UPROPERTY(BlueprintAssignable, Category="Components|Spine|Animation")
|
||||||
FSpineAnimationDisposeDelegate AnimationDispose;
|
FSpineAnimationDisposeDelegate AnimationDispose;
|
||||||
|
|
||||||
|
UPROPERTY(Transient, EditAnywhere, Category=Spine)
|
||||||
|
FString PreviewAnimation;
|
||||||
|
|
||||||
|
UPROPERTY(Transient, EditAnywhere, Category=Spine)
|
||||||
|
FString PreviewSkin;
|
||||||
|
|
||||||
// used in C event callback. Needs to be public as we can't call
|
// used in C event callback. Needs to be public as we can't call
|
||||||
// protected methods from plain old C function.
|
// protected methods from plain old C function.
|
||||||
void GCTrackEntry(UTrackEntry* entry) { trackEntries.Remove(entry); }
|
void GCTrackEntry(UTrackEntry* entry) { trackEntries.Remove(entry); }
|
||||||
@ -270,4 +285,7 @@ private:
|
|||||||
/* If the animation should update automatically. */
|
/* If the animation should update automatically. */
|
||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
bool bAutoPlaying;
|
bool bAutoPlaying;
|
||||||
|
|
||||||
|
FString lastPreviewAnimation;
|
||||||
|
FString lastPreviewSkin;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -54,11 +54,17 @@ public:
|
|||||||
|
|
||||||
spine::Skeleton* GetSkeleton () { return skeleton; };
|
spine::Skeleton* GetSkeleton () { return skeleton; };
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton")
|
UFUNCTION(BlueprintPure, Category = "Components|Spine|Skeleton")
|
||||||
bool SetSkin (const FString& SkinName);
|
void GetSkins(TArray<FString> &Skins);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton")
|
UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton")
|
||||||
bool SetAttachment (const FString& slotName, const FString& attachmentName);
|
bool SetSkin (const FString SkinName);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton")
|
||||||
|
bool HasSkin(const FString SkinName);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton")
|
||||||
|
bool SetAttachment (const FString slotName, const FString attachmentName);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton")
|
UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton")
|
||||||
FTransform GetBoneWorldTransform (const FString& BoneName);
|
FTransform GetBoneWorldTransform (const FString& BoneName);
|
||||||
@ -93,6 +99,24 @@ public:
|
|||||||
UFUNCTION(BlueprintPure, Category = "Components|Spine|Skeleton")
|
UFUNCTION(BlueprintPure, Category = "Components|Spine|Skeleton")
|
||||||
void GetBones(TArray<FString> &Bones);
|
void GetBones(TArray<FString> &Bones);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton")
|
||||||
|
bool HasBone(const FString BoneName);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Components|Spine|Skeleton")
|
||||||
|
void GetSlots(TArray<FString> &Slots);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton")
|
||||||
|
bool HasSlot(const FString SlotName);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Components|Spine|Skeleton")
|
||||||
|
void GetAnimations(TArray<FString> &Animations);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton")
|
||||||
|
bool HasAnimation(FString AnimationName);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Components|Spine|Skeleton")
|
||||||
|
float GetAnimationDuration(FString AnimationName);
|
||||||
|
|
||||||
UPROPERTY(BlueprintAssignable, Category = "Components|Spine|Skeleton")
|
UPROPERTY(BlueprintAssignable, Category = "Components|Spine|Skeleton")
|
||||||
FSpineBeforeUpdateWorldTransformDelegate BeforeUpdateWorldTransform;
|
FSpineBeforeUpdateWorldTransformDelegate BeforeUpdateWorldTransform;
|
||||||
|
|
||||||
|
|||||||
@ -46,7 +46,7 @@ public:
|
|||||||
FString To;
|
FString To;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||||
float Mix = 0;
|
float Mix = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
UCLASS(BlueprintType, ClassGroup=(Spine))
|
UCLASS(BlueprintType, ClassGroup=(Spine))
|
||||||
@ -71,6 +71,21 @@ public:
|
|||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||||
TArray<FSpineAnimationStateMixData> MixData;
|
TArray<FSpineAnimationStateMixData> MixData;
|
||||||
|
|
||||||
|
UPROPERTY(Transient, VisibleAnywhere)
|
||||||
|
TArray<FString> Bones;
|
||||||
|
|
||||||
|
UPROPERTY(Transient, VisibleAnywhere)
|
||||||
|
TArray<FString> Slots;
|
||||||
|
|
||||||
|
UPROPERTY(Transient, VisibleAnywhere)
|
||||||
|
TArray<FString> Skins;
|
||||||
|
|
||||||
|
UPROPERTY(Transient, VisibleAnywhere)
|
||||||
|
TArray<FString> Animations;
|
||||||
|
|
||||||
|
UPROPERTY(Transient, VisibleAnywhere)
|
||||||
|
TArray<FString> Events;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
TArray<uint8> rawData;
|
TArray<uint8> rawData;
|
||||||
@ -94,4 +109,6 @@ protected:
|
|||||||
virtual void GetAssetRegistryTags(TArray<FAssetRegistryTag>& OutTags) const override;
|
virtual void GetAssetRegistryTags(TArray<FAssetRegistryTag>& OutTags) const override;
|
||||||
virtual void Serialize (FArchive& Ar) override;
|
virtual void Serialize (FArchive& Ar) override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void LoadInfo();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -47,6 +47,9 @@ public:
|
|||||||
|
|
||||||
virtual void TickComponent (float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
|
virtual void TickComponent (float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
|
||||||
|
|
||||||
|
/* Updates this skeleton renderer using the provided skeleton animation component. */
|
||||||
|
void UpdateRenderer(USpineSkeletonComponent* Skeleton);
|
||||||
|
|
||||||
// Material Instance parents
|
// Material Instance parents
|
||||||
UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadOnly)
|
UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadOnly)
|
||||||
UMaterialInterface* NormalBlendMaterial;
|
UMaterialInterface* NormalBlendMaterial;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user