mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 07:14:55 +08:00
[ue4] Multi-page atlases and instanced materials working as intended! Only blend modes and functions for blueprints left!
This commit is contained in:
parent
7f96e2350b
commit
315dfe37ee
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -85,8 +85,7 @@ UTexture2D* resolveTexture (USpineAtlasAsset* asset, const FString& pageFileName
|
||||
|
||||
TArray<FString> fileNames;
|
||||
fileNames.Add(pageFileName);
|
||||
|
||||
//@TODO: Avoid the first compression, since we're going to recompress
|
||||
|
||||
TArray<UObject*> importedAsset = AssetToolsModule.Get().ImportAssets(fileNames, targetSubPath);
|
||||
UTexture2D* texture = (importedAsset.Num() > 0) ? Cast<UTexture2D>(importedAsset[0]) : nullptr;
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ void USpineSkeletonComponent::TickComponent( float DeltaTime, ELevelTick TickTyp
|
||||
DisposeState();
|
||||
|
||||
if (atlas && skeletonData) {
|
||||
spSkeletonData* data = skeletonData->GetSkeletonData(atlas->GetAtlas(true), true);
|
||||
spSkeletonData* data = skeletonData->GetSkeletonData(atlas->GetAtlas(false), false);
|
||||
skeleton = spSkeleton_create(data);
|
||||
stateData = spAnimationStateData_create(data);
|
||||
state = spAnimationState_create(stateData);
|
||||
|
||||
@ -31,13 +31,52 @@ void USpineSkeletonRendererComponent::TickComponent( float DeltaTime, ELevelTick
|
||||
AActor* owner = GetOwner();
|
||||
if (owner) {
|
||||
USpineSkeletonComponent* skeleton = Cast<USpineSkeletonComponent>(owner->GetComponentByClass(skeletonClass));
|
||||
if (skeleton && skeleton->skeleton) {
|
||||
if (skeleton && !skeleton->IsBeingDestroyed() && skeleton->skeleton) {
|
||||
if (atlasMaterials.Num() != skeleton->atlas->atlasPages.Num()) {
|
||||
atlasMaterials.SetNum(0);
|
||||
pageToMaterial.Empty();
|
||||
spAtlasPage* currPage = skeleton->atlas->GetAtlas(false)->pages;
|
||||
for (int i = 0; i < skeleton->atlas->atlasPages.Num(); i++) {
|
||||
UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(DefaultMaterial, owner);
|
||||
material->SetTextureParameterValue(FName(TEXT("SpriteTexture")), skeleton->atlas->atlasPages[i]);
|
||||
atlasMaterials.Add(material);
|
||||
pageToMaterial.Add(currPage, material);
|
||||
currPage = currPage->next;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pageToMaterial.Empty();
|
||||
spAtlasPage* currPage = skeleton->atlas->GetAtlas(false)->pages;
|
||||
for (int i = 0; i < skeleton->atlas->atlasPages.Num(); i++) {
|
||||
UMaterialInstanceDynamic* current = atlasMaterials[i];
|
||||
UTexture2D* texture = skeleton->atlas->atlasPages[i];
|
||||
UTexture* oldTexture = nullptr;
|
||||
if(!current->GetTextureParameterValue(FName(TEXT("SpriteTexture")), oldTexture) || oldTexture != texture) {
|
||||
UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(DefaultMaterial, owner);
|
||||
material->SetTextureParameterValue("SpriteTexture", texture);
|
||||
atlasMaterials[i] = material;
|
||||
}
|
||||
pageToMaterial.Add(currPage, atlasMaterials[i]);
|
||||
currPage = currPage->next;
|
||||
}
|
||||
}
|
||||
spSkeleton_updateWorldTransform(skeleton->skeleton);
|
||||
UpdateMesh(skeleton->skeleton);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void USpineSkeletonRendererComponent::Flush(int &idx, TArray<FVector> &vertices, TArray<int32> &indices, TArray<FVector2D> &uvs, TArray<FColor> &colors, UMaterialInstanceDynamic* material) {
|
||||
if (vertices.Num() == 0) return;
|
||||
CreateMeshSection(idx, vertices, indices, TArray<FVector>(), uvs, colors, TArray<FProcMeshTangent>(), false);
|
||||
SetMaterial(idx, material);
|
||||
vertices.SetNum(0);
|
||||
indices.SetNum(0);
|
||||
uvs.SetNum(0);
|
||||
colors.SetNum(0);
|
||||
idx++;
|
||||
}
|
||||
|
||||
void USpineSkeletonRendererComponent::UpdateMesh(spSkeleton* skeleton) {
|
||||
TArray<FVector> vertices;
|
||||
TArray<int32> indices;
|
||||
@ -48,6 +87,7 @@ void USpineSkeletonRendererComponent::UpdateMesh(spSkeleton* skeleton) {
|
||||
worldVertices.SetNumUninitialized(2 * 1024);
|
||||
int idx = 0;
|
||||
int meshSection = 0;
|
||||
UMaterialInstanceDynamic* lastMaterial = nullptr;
|
||||
|
||||
ClearAllMeshSections();
|
||||
|
||||
@ -59,7 +99,15 @@ void USpineSkeletonRendererComponent::UpdateMesh(spSkeleton* skeleton) {
|
||||
if (!attachment) continue;
|
||||
|
||||
if (attachment->type == SP_ATTACHMENT_REGION) {
|
||||
spRegionAttachment* regionAttachment = (spRegionAttachment*)attachment;
|
||||
spRegionAttachment* regionAttachment = (spRegionAttachment*)attachment;
|
||||
spAtlasRegion* region = (spAtlasRegion*)regionAttachment->rendererObject;
|
||||
UMaterialInstanceDynamic* material = pageToMaterial[region->page];
|
||||
|
||||
if (lastMaterial != material) {
|
||||
Flush(meshSection, vertices, indices, uvs, colors, lastMaterial);
|
||||
lastMaterial = material;
|
||||
}
|
||||
|
||||
spRegionAttachment_computeWorldVertices(regionAttachment, slot->bone, worldVertices.GetData());
|
||||
|
||||
uint8 r = static_cast<uint8>(skeleton->r * slot->r * 255);
|
||||
@ -91,8 +139,18 @@ void USpineSkeletonRendererComponent::UpdateMesh(spSkeleton* skeleton) {
|
||||
indices.Add(idx + 3);
|
||||
idx += 4;
|
||||
depthOffset -= this->depthOffset;
|
||||
|
||||
SetMaterial(meshSection, material);
|
||||
} else if (attachment->type == SP_ATTACHMENT_MESH) {
|
||||
spMeshAttachment* mesh = (spMeshAttachment*)attachment;
|
||||
spAtlasRegion* region = (spAtlasRegion*)mesh->rendererObject;
|
||||
UMaterialInstanceDynamic* material = pageToMaterial[region->page];
|
||||
|
||||
if (lastMaterial != material) {
|
||||
Flush(meshSection, vertices, indices, uvs, colors, lastMaterial);
|
||||
lastMaterial = material;
|
||||
}
|
||||
|
||||
if (mesh->super.worldVerticesLength> worldVertices.Num()) {
|
||||
worldVertices.SetNum(mesh->super.worldVerticesLength);
|
||||
}
|
||||
@ -114,16 +172,9 @@ void USpineSkeletonRendererComponent::UpdateMesh(spSkeleton* skeleton) {
|
||||
}
|
||||
idx += mesh->super.worldVerticesLength >> 1;
|
||||
depthOffset -= this->depthOffset;
|
||||
SetMaterial(meshSection, material);
|
||||
}
|
||||
}
|
||||
|
||||
CreateMeshSection(0, vertices, indices, TArray<FVector>(), uvs, colors, TArray<FProcMeshTangent>(), false);
|
||||
}
|
||||
|
||||
UMaterialInterface* USpineSkeletonRendererComponent::GetMaterial(int32 MaterialIndex) const {
|
||||
return MaterialIndex == 0 ? GetDefaultMaterial() : nullptr;
|
||||
}
|
||||
|
||||
int32 USpineSkeletonRendererComponent::GetNumMaterials() const {
|
||||
return 1;
|
||||
|
||||
Flush(meshSection, vertices, indices, uvs, colors, lastMaterial);
|
||||
}
|
||||
@ -21,21 +21,15 @@ public:
|
||||
virtual void TickComponent (float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
|
||||
|
||||
UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadOnly)
|
||||
UMaterialInterface* DefaultMaterial;
|
||||
|
||||
UMaterialInterface* GetDefaultMaterial() const { return DefaultMaterial; }
|
||||
|
||||
UMaterialInterface* GetAlternateMaterial() const { return nullptr; }
|
||||
|
||||
UMaterialInterface* GetMaterial(int32 MaterialIndex) const;
|
||||
|
||||
int32 GetNumMaterials() const;
|
||||
UMaterialInterface* DefaultMaterial;
|
||||
|
||||
UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadWrite)
|
||||
float depthOffset = 0.1f;
|
||||
protected:
|
||||
void UpdateMesh (spSkeleton* skeleton);
|
||||
|
||||
UPROPERTY()
|
||||
void Flush(int &idx, TArray<FVector> &vertices, TArray<int32> &indices, TArray<FVector2D> &uvs, TArray<FColor> &colors, UMaterialInstanceDynamic* material);
|
||||
|
||||
TArray<UMaterialInstanceDynamic*> atlasMaterials;
|
||||
TMap<spAtlasPage*, UMaterialInstanceDynamic*> pageToMaterial;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user