diff --git a/spine-ue4/Plugins/SpinePlugin/Content/SpineUnlitAdditiveMaterialPMC.uasset b/spine-ue4/Plugins/SpinePlugin/Content/SpineUnlitAdditiveMaterialPMC.uasset new file mode 100644 index 000000000..56a2c67bc Binary files /dev/null and b/spine-ue4/Plugins/SpinePlugin/Content/SpineUnlitAdditiveMaterialPMC.uasset differ diff --git a/spine-ue4/Plugins/SpinePlugin/Content/SpineUnlitMultiplyMaterialPMC.uasset b/spine-ue4/Plugins/SpinePlugin/Content/SpineUnlitMultiplyMaterialPMC.uasset new file mode 100644 index 000000000..8b686f9e4 Binary files /dev/null and b/spine-ue4/Plugins/SpinePlugin/Content/SpineUnlitMultiplyMaterialPMC.uasset differ diff --git a/spine-ue4/Plugins/SpinePlugin/Content/SpineUnlitNormalMaterialPMC.uasset b/spine-ue4/Plugins/SpinePlugin/Content/SpineUnlitNormalMaterialPMC.uasset new file mode 100644 index 000000000..52d257e31 Binary files /dev/null and b/spine-ue4/Plugins/SpinePlugin/Content/SpineUnlitNormalMaterialPMC.uasset differ diff --git a/spine-ue4/Plugins/SpinePlugin/Content/SpineUnlitScreenMaterialPMC.uasset b/spine-ue4/Plugins/SpinePlugin/Content/SpineUnlitScreenMaterialPMC.uasset new file mode 100644 index 000000000..c597e3f91 Binary files /dev/null and b/spine-ue4/Plugins/SpinePlugin/Content/SpineUnlitScreenMaterialPMC.uasset differ diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePlugin.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePlugin.cpp index c0ccd7dd9..993fc2757 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePlugin.cpp +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePlugin.cpp @@ -43,8 +43,33 @@ void FSpinePlugin::StartupModule() { void FSpinePlugin::ShutdownModule() { } +class Ue4Extension : public spine::DefaultSpineExtension { +public: + Ue4Extension() : spine::DefaultSpineExtension() { } + + virtual ~Ue4Extension() { } + + virtual void *_alloc(size_t size, const char *file, int line) { + return FMemory::Malloc(size); + } + + virtual void *_calloc(size_t size, const char *file, int line) { + void * result = FMemory::Malloc(size); + FMemory::Memset(result, 0, size); + return result; + } + + virtual void *_realloc(void *ptr, size_t size, const char *file, int line) { + return FMemory::Realloc(ptr, size); + } + + virtual void _free(void *mem, const char *file, int line) { + FMemory::Free(mem); + } +}; + spine::SpineExtension* spine::getDefaultExtension() { - return new spine::DefaultSpineExtension(); + return new Ue4Extension(); } diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePluginPrivatePCH.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePluginPrivatePCH.h index d73ab820d..a49f1081b 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePluginPrivatePCH.h +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePluginPrivatePCH.h @@ -34,6 +34,7 @@ #include "SpineSkeletonComponent.h" #include "SpineSkeletonAnimationComponent.h" #include "SpineSkeletonRendererComponent.h" +#include "SpineSkeletonRendererComponentPMC.h" #include "SpineBoneFollowerComponent.h" #include "SpineBoneDriverComponent.h" #include "SpineWidget.h" diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponentPMC.cpp b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponentPMC.cpp new file mode 100644 index 000000000..972908799 --- /dev/null +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponentPMC.cpp @@ -0,0 +1,311 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF + * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include "SpinePluginPrivatePCH.h" +#include "Engine.h" +#include "spine/spine.h" +#include + +#define LOCTEXT_NAMESPACE "Spine" + +using namespace spine; + +USpineSkeletonRendererComponentPMC::USpineSkeletonRendererComponentPMC(const FObjectInitializer& ObjectInitializer) +: UProceduralMeshComponent(ObjectInitializer) { + PrimaryComponentTick.bCanEverTick = true; + bTickInEditor = true; + bAutoActivate = true; + + static ConstructorHelpers::FObjectFinder NormalMaterialRef(TEXT("/SpinePlugin/SpineUnlitNormalMaterialPMC")); + NormalBlendMaterial = NormalMaterialRef.Object; + + static ConstructorHelpers::FObjectFinder AdditiveMaterialRef(TEXT("/SpinePlugin/SpineUnlitAdditiveMaterialPMC")); + AdditiveBlendMaterial = AdditiveMaterialRef.Object; + + static ConstructorHelpers::FObjectFinder MultiplyMaterialRef(TEXT("/SpinePlugin/SpineUnlitMultiplyMaterialPMC")); + MultiplyBlendMaterial = MultiplyMaterialRef.Object; + + static ConstructorHelpers::FObjectFinder ScreenMaterialRef(TEXT("/SpinePlugin/SpineUnlitScreenMaterialPMC")); + ScreenBlendMaterial = ScreenMaterialRef.Object; + + TextureParameterName = FName(TEXT("SpriteTexture")); + + worldVertices.ensureCapacity(1024 * 2); +} + +void USpineSkeletonRendererComponentPMC::FinishDestroy() { + Super::FinishDestroy(); +} + +void USpineSkeletonRendererComponentPMC::BeginPlay () { + Super::BeginPlay(); +} + +void USpineSkeletonRendererComponentPMC::TickComponent (float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) { + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + AActor* owner = GetOwner(); + if (owner) { + UClass* skeletonClass = USpineSkeletonComponent::StaticClass(); + USpineSkeletonComponent* skeleton = Cast(owner->GetComponentByClass(skeletonClass)); + + 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(false)->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(false)->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 USpineSkeletonRendererComponentPMC::Flush (int &Idx, TArray &Vertices, TArray &Indices, TArray &Uvs, TArray &Colors, TArray& Colors2, UMaterialInstanceDynamic* Material) { + if (Vertices.Num() == 0) return; + SetMaterial(Idx, Material); + + CreateMeshSection(Idx, Vertices, Indices, TArray(), Uvs, Colors, TArray(), true); + + Vertices.SetNum(0); + Indices.SetNum(0); + Uvs.SetNum(0); + Colors.SetNum(0); + Colors2.SetNum(0); + Idx++; +} + +void USpineSkeletonRendererComponentPMC::UpdateMesh(Skeleton* Skeleton) { + TArray vertices; + TArray indices; + TArray uvs; + TArray colors; + TArray darkColors; + + int idx = 0; + int meshSection = 0; + UMaterialInstanceDynamic* lastMaterial = nullptr; + + ClearAllMeshSections(); + + float depthOffset = 0; + unsigned short quadIndices[] = { 0, 1, 2, 0, 2, 3 }; + + for (int i = 0; i < Skeleton->getSlots().size(); ++i) { + Vector &attachmentVertices = worldVertices; + unsigned short* attachmentIndices = nullptr; + int numVertices; + int numIndices; + AtlasRegion* attachmentAtlasRegion = nullptr; + spine::Color attachmentColor; + attachmentColor.set(1, 1, 1, 1); + float* attachmentUvs = nullptr; + + Slot* slot = Skeleton->getDrawOrder()[i]; + Attachment* attachment = slot->getAttachment(); + if (!attachment) continue; + if (!attachment->getRTTI().isExactly(RegionAttachment::rtti) && !attachment->getRTTI().isExactly(MeshAttachment::rtti) && !attachment->getRTTI().isExactly(ClippingAttachment::rtti)) continue; + + if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) { + RegionAttachment* regionAttachment = (RegionAttachment*)attachment; + attachmentColor.set(regionAttachment->getColor()); + attachmentAtlasRegion = (AtlasRegion*)regionAttachment->getRendererObject(); + regionAttachment->computeWorldVertices(slot->getBone(), attachmentVertices, 0, 2); + attachmentIndices = quadIndices; + attachmentUvs = regionAttachment->getUVs().buffer(); + numVertices = 4; + numIndices = 6; + } else if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) { + MeshAttachment* mesh = (MeshAttachment*)attachment; + attachmentColor.set(mesh->getColor()); + attachmentAtlasRegion = (AtlasRegion*)mesh->getRendererObject(); + mesh->computeWorldVertices(*slot, 0, mesh->getWorldVerticesLength(), attachmentVertices, 0, 2); + attachmentIndices = mesh->getTriangles().buffer(); + attachmentUvs = mesh->getUVs().buffer(); + numVertices = mesh->getWorldVerticesLength() >> 1; + numIndices = mesh->getTriangles().size(); + } else /* clipping */ { + ClippingAttachment* clip = (ClippingAttachment*)attachment; + clipper.clipStart(*slot, clip); + continue; + } + + // if the user switches the atlas data while not having switched + // to the correct skeleton data yet, we won't find any regions. + // ignore regions for which we can't find a material + UMaterialInstanceDynamic* material = nullptr; + switch (slot->getData().getBlendMode()) { + case BlendMode_Normal: + if (!pageToNormalBlendMaterial.Contains(attachmentAtlasRegion->page)) continue; + material = pageToNormalBlendMaterial[attachmentAtlasRegion->page]; + break; + case BlendMode_Additive: + if (!pageToAdditiveBlendMaterial.Contains(attachmentAtlasRegion->page)) continue; + material = pageToAdditiveBlendMaterial[attachmentAtlasRegion->page]; + break; + case BlendMode_Multiply: + if (!pageToMultiplyBlendMaterial.Contains(attachmentAtlasRegion->page)) continue; + material = pageToMultiplyBlendMaterial[attachmentAtlasRegion->page]; + break; + case BlendMode_Screen: + if (!pageToScreenBlendMaterial.Contains(attachmentAtlasRegion->page)) continue; + material = pageToScreenBlendMaterial[attachmentAtlasRegion->page]; + break; + default: + if (!pageToNormalBlendMaterial.Contains(attachmentAtlasRegion->page)) continue; + material = pageToNormalBlendMaterial[attachmentAtlasRegion->page]; + } + + if (clipper.isClipping()) { + clipper.clipTriangles(attachmentVertices.buffer(), attachmentIndices, numIndices, attachmentUvs, 2); + attachmentVertices = clipper.getClippedVertices(); + numVertices = clipper.getClippedVertices().size() >> 1; + attachmentIndices = clipper.getClippedTriangles().buffer(); + numIndices = clipper.getClippedTriangles().size(); + attachmentUvs = clipper.getClippedUVs().buffer(); + if (clipper.getClippedTriangles().size() == 0) continue; + } + + if (lastMaterial != material) { + Flush(meshSection, vertices, indices, uvs, colors, darkColors, lastMaterial); + lastMaterial = material; + idx = 0; + } + + SetMaterial(meshSection, material); + + uint8 r = static_cast(Skeleton->getColor().r * slot->getColor().r * attachmentColor.r * 255); + uint8 g = static_cast(Skeleton->getColor().g * slot->getColor().g * attachmentColor.g * 255); + uint8 b = static_cast(Skeleton->getColor().b * slot->getColor().b * attachmentColor.b * 255); + uint8 a = static_cast(Skeleton->getColor().a * slot->getColor().a * attachmentColor.a * 255); + + float dr = slot->hasDarkColor() ? slot->getDarkColor().r : 0.0f; + float dg = slot->hasDarkColor() ? slot->getDarkColor().g : 0.0f; + float db = slot->hasDarkColor() ? slot->getDarkColor().b : 0.0f; + + for (int j = 0; j < numVertices << 1; j += 2) { + colors.Add(FColor(r, g, b, a)); + darkColors.Add(FVector(dr, dg, db)); + vertices.Add(FVector(attachmentVertices[j], depthOffset, attachmentVertices[j + 1])); + uvs.Add(FVector2D(attachmentUvs[j], attachmentUvs[j + 1])); + } + + for (int j = 0; j < numIndices; j++) { + indices.Add(idx + attachmentIndices[j]); + } + + idx += numVertices; + depthOffset += this->DepthOffset; + + clipper.clipEnd(*slot); + } + + Flush(meshSection, vertices, indices, uvs, colors, darkColors, lastMaterial); + clipper.clipEnd(); +} + +#undef LOCTEXT_NAMESPACE diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonRendererComponentPMC.h b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonRendererComponentPMC.h new file mode 100644 index 000000000..5d2ba8f30 --- /dev/null +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonRendererComponentPMC.h @@ -0,0 +1,97 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF + * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#pragma once + +#include "Components/ActorComponent.h" +#include "ProceduralMeshComponent.h" +#include "SpineSkeletonAnimationComponent.h" +#include "SpineSkeletonRendererComponentPMC.generated.h" + + +UCLASS(ClassGroup=(Spine), meta=(BlueprintSpawnableComponent)) +class SPINEPLUGIN_API USpineSkeletonRendererComponentPMC: public UProceduralMeshComponent { + GENERATED_BODY() + +public: + USpineSkeletonRendererComponentPMC(const FObjectInitializer& ObjectInitializer); + + virtual void BeginPlay () override; + + virtual void TickComponent (float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + + UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadOnly) + UMaterialInterface* NormalBlendMaterial; + + UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadOnly) + UMaterialInterface* AdditiveBlendMaterial; + + UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadOnly) + UMaterialInterface* MultiplyBlendMaterial; + + UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadOnly) + UMaterialInterface* ScreenBlendMaterial; + + UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadWrite) + float DepthOffset = 0.1f; + + UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadWrite) + FName TextureParameterName; + + UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadWrite) + FLinearColor Color = FLinearColor(1, 1, 1, 1); + + virtual void FinishDestroy() override; + +protected: + void UpdateMesh (spine::Skeleton* Skeleton); + + void Flush (int &Idx, TArray &Vertices, TArray &Indices, TArray &Uvs, TArray &Colors, TArray &Colors2, UMaterialInstanceDynamic* Material); + + // Need to hold on to the dynamic instances, or the GC will kill us while updating them + UPROPERTY() + TArray atlasNormalBlendMaterials; + TMap pageToNormalBlendMaterial; + + UPROPERTY() + TArray atlasAdditiveBlendMaterials; + TMap pageToAdditiveBlendMaterial; + + UPROPERTY() + TArray atlasMultiplyBlendMaterials; + TMap pageToMultiplyBlendMaterial; + + UPROPERTY() + TArray atlasScreenBlendMaterials; + TMap pageToScreenBlendMaterial; + + spine::Vector worldVertices; + spine::SkeletonClipping clipper; +}; diff --git a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/SpinePlugin.Build.cs b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/SpinePlugin.Build.cs index 7dd06fb1d..69b5a1b4b 100644 --- a/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/SpinePlugin.Build.cs +++ b/spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/SpinePlugin.Build.cs @@ -8,7 +8,7 @@ namespace UnrealBuildTool.Rules { PublicIncludePaths.AddRange(new string[] { "SpinePlugin/Public", "SpinePlugin/Public/spine-cpp/include" }); PrivateIncludePaths.AddRange(new string[] { "SpinePlugin/Private", "SpinePlugin/Public/spine-cpp/include" }); - PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "RHI", "RenderCore", "ShaderCore", "RuntimeMeshComponent", "UMG", "Slate", "SlateCore" }); + PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "RHI", "RenderCore", "ShaderCore", "RuntimeMeshComponent", "ProceduralMeshComponent", "UMG", "Slate", "SlateCore" }); OptimizeCode = CodeOptimization.Never; Definitions.Add("SPINE_UE4"); }