[ue4] Multi-page atlases and instanced materials working as intended! Only blend modes and functions for blueprints left!

This commit is contained in:
badlogic 2016-11-30 18:29:25 +01:00
parent 7f96e2350b
commit 315dfe37ee
7 changed files with 69 additions and 25 deletions

Binary file not shown.

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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;
};