Merge branch '3.8' into 4.0-beta

This commit is contained in:
Harald Csaszar 2021-02-25 12:00:57 +01:00
commit ac23599638
4 changed files with 67 additions and 10 deletions

View File

@ -240,7 +240,8 @@
* Removed dependency on `RHI`, `RenderCore`, and `ShaderCore`. * Removed dependency on `RHI`, `RenderCore`, and `ShaderCore`.
* Re-importing atlases and their textures now works consistently in all situations. * Re-importing atlases and their textures now works consistently in all situations.
* Added mix-and-match example to demonstrate the new Skin API. * Added mix-and-match example to demonstrate the new Skin API.
* Materials on `SkeletonRendererComponent` are now blueprint read and writeable. This allows setting dynamic material instances at runtime * Materials on `SkeletonRendererComponent` are now blueprint read and writeable. This allows setting dynamic material instances at runtime.
* Added `InitialSkin` property to `USpineWidget`. This allows previewing different skins in the UMG Designer. Initial skins can still be overridden via blueprint events such as `On Initialized`.
## C# ## ## C# ##
* **Breaking changes** * **Breaking changes**

View File

@ -281,8 +281,16 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
} }
/* Skins. */ /* Skins. */
for (size_t i = 0, n = (size_t)readVarint(input, true); i < n; ++i) for (size_t i = 0, n = (size_t)readVarint(input, true); i < n; ++i) {
skeletonData->_skins.add(readSkin(input, false, skeletonData, nonessential)); Skin* skin = readSkin(input, false, skeletonData, nonessential);
if (skin)
skeletonData->_skins.add(skin);
else {
delete input;
delete skeletonData;
return NULL;
}
}
/* Linked meshes. */ /* Linked meshes. */
for (int i = 0, n = _linkedMeshes.size(); i < n; ++i) { for (int i = 0, n = _linkedMeshes.size(); i < n; ++i) {
@ -470,7 +478,12 @@ Skin *SkeletonBinary::readSkin(DataInput *input, bool defaultSkin, SkeletonData
for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) {
String name(readStringRef(input, skeletonData)); String name(readStringRef(input, skeletonData));
Attachment *attachment = readAttachment(input, skin, slotIndex, name, skeletonData, nonessential); Attachment *attachment = readAttachment(input, skin, slotIndex, name, skeletonData, nonessential);
if (attachment) skin->setAttachment(slotIndex, String(name), attachment); if (attachment)
skin->setAttachment(slotIndex, String(name), attachment);
else {
delete skin;
return nullptr;
}
} }
} }
return skin; return skin;
@ -488,6 +501,10 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
String path(readStringRef(input, skeletonData)); String path(readStringRef(input, skeletonData));
if (path.isEmpty()) path = name; if (path.isEmpty()) path = name;
RegionAttachment *region = _attachmentLoader->newRegionAttachment(*skin, String(name), String(path)); RegionAttachment *region = _attachmentLoader->newRegionAttachment(*skin, String(name), String(path));
if (!region) {
setError("Error reading attachment: ", name.buffer());
return nullptr;
}
region->_path = path; region->_path = path;
region->_rotation = readFloat(input); region->_rotation = readFloat(input);
region->_x = readFloat(input) * _scale; region->_x = readFloat(input) * _scale;
@ -504,6 +521,10 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
case AttachmentType_Boundingbox: { case AttachmentType_Boundingbox: {
int vertexCount = readVarint(input, true); int vertexCount = readVarint(input, true);
BoundingBoxAttachment *box = _attachmentLoader->newBoundingBoxAttachment(*skin, String(name)); BoundingBoxAttachment *box = _attachmentLoader->newBoundingBoxAttachment(*skin, String(name));
if (!box) {
setError("Error reading attachment: ", name.buffer());
return nullptr;
}
readVertices(input, static_cast<VertexAttachment *>(box), vertexCount); readVertices(input, static_cast<VertexAttachment *>(box), vertexCount);
if (nonessential) { if (nonessential) {
/* Skip color. */ /* Skip color. */
@ -519,6 +540,10 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
if (path.isEmpty()) path = name; if (path.isEmpty()) path = name;
mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path)); mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path));
if (!mesh) {
setError("Error reading attachment: ", name.buffer());
return nullptr;
}
mesh->_path = path; mesh->_path = path;
readColor(input, mesh->getColor()); readColor(input, mesh->getColor());
vertexCount = readVarint(input, true); vertexCount = readVarint(input, true);
@ -543,6 +568,10 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
if (path.isEmpty()) path = name; if (path.isEmpty()) path = name;
MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path)); MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path));
if (!mesh) {
setError("Error reading attachment: ", name.buffer());
return nullptr;
}
mesh->_path = path; mesh->_path = path;
readColor(input, mesh->getColor()); readColor(input, mesh->getColor());
String skinName(readStringRef(input, skeletonData)); String skinName(readStringRef(input, skeletonData));
@ -559,7 +588,11 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
return mesh; return mesh;
} }
case AttachmentType_Path: { case AttachmentType_Path: {
PathAttachment *path = _attachmentLoader->newPathAttachment(*skin, String(name)); PathAttachment* path = _attachmentLoader->newPathAttachment(*skin, String(name));
if (!path) {
setError("Error reading attachment: ", name.buffer());
return nullptr;
}
path->_closed = readBoolean(input); path->_closed = readBoolean(input);
path->_constantSpeed = readBoolean(input); path->_constantSpeed = readBoolean(input);
int vertexCount = readVarint(input, true); int vertexCount = readVarint(input, true);
@ -577,7 +610,11 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
return path; return path;
} }
case AttachmentType_Point: { case AttachmentType_Point: {
PointAttachment *point = _attachmentLoader->newPointAttachment(*skin, String(name)); PointAttachment* point = _attachmentLoader->newPointAttachment(*skin, String(name));
if (!point) {
setError("Error reading attachment: ", name.buffer());
return nullptr;
}
point->_rotation = readFloat(input); point->_rotation = readFloat(input);
point->_x = readFloat(input) * _scale; point->_x = readFloat(input) * _scale;
point->_y = readFloat(input) * _scale; point->_y = readFloat(input) * _scale;
@ -592,7 +629,11 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
case AttachmentType_Clipping: { case AttachmentType_Clipping: {
int endSlotIndex = readVarint(input, true); int endSlotIndex = readVarint(input, true);
int vertexCount = readVarint(input, true); int vertexCount = readVarint(input, true);
ClippingAttachment *clip = _attachmentLoader->newClippingAttachment(*skin, name); ClippingAttachment* clip = _attachmentLoader->newClippingAttachment(*skin, name);
if (!clip) {
setError("Error reading attachment: ", name.buffer());
return nullptr;
}
readVertices(input, static_cast<VertexAttachment *>(clip), vertexCount); readVertices(input, static_cast<VertexAttachment *>(clip), vertexCount);
clip->_endSlot = skeletonData->_slots[endSlotIndex]; clip->_endSlot = skeletonData->_slots[endSlotIndex];
if (nonessential) { if (nonessential) {
@ -603,7 +644,7 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
return clip; return clip;
} }
} }
return NULL; return nullptr;
} }
void SkeletonBinary::readVertices(DataInput *input, VertexAttachment *attachment, int vertexCount) { void SkeletonBinary::readVertices(DataInput *input, VertexAttachment *attachment, int vertexCount) {

View File

@ -99,6 +99,15 @@ void USpineWidget::SynchronizeProperties() {
if (slateWidget.IsValid()) { if (slateWidget.IsValid()) {
CheckState(); CheckState();
if (skeleton) { if (skeleton) {
if (!bSkinInitialized) { // blueprint On Initialized may be called beforehand
if (InitialSkin != "") SetSkin(InitialSkin);
#if WITH_EDITOR
if (IsDesignTime()) {
if (InitialSkin == "") SetSkin("default");
bSkinInitialized = false; // allow multiple edits in editor
}
#endif
}
Tick(0, false); Tick(0, false);
slateWidget->SetData(this); slateWidget->SetData(this);
} else { } else {
@ -204,6 +213,7 @@ bool USpineWidget::SetSkin(const FString skinName) {
spine::Skin* skin = skeleton->getData()->findSkin(TCHAR_TO_UTF8(*skinName)); spine::Skin* skin = skeleton->getData()->findSkin(TCHAR_TO_UTF8(*skinName));
if (!skin) return false; if (!skin) return false;
skeleton->setSkin(skin); skeleton->setSkin(skin);
bSkinInitialized = true;
return true; return true;
} }
else return false; else return false;
@ -222,6 +232,7 @@ bool USpineWidget::SetSkins(UPARAM(ref) TArray<FString>& SkinNames) {
newSkin->addSkin(skin); newSkin->addSkin(skin);
} }
skeleton->setSkin(newSkin); skeleton->setSkin(newSkin);
bSkinInitialized = true;
if (customSkin != nullptr) { if (customSkin != nullptr) {
delete customSkin; delete customSkin;
} }

View File

@ -51,6 +51,9 @@ public:
virtual const FText GetPaletteCategory() override; virtual const FText GetPaletteCategory() override;
#endif #endif
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Spine)
FString InitialSkin;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Spine) UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Spine)
USpineAtlasAsset* Atlas; USpineAtlasAsset* Atlas;
@ -254,4 +257,5 @@ private:
/* If the animation should update automatically. */ /* If the animation should update automatically. */
UPROPERTY() UPROPERTY()
bool bAutoPlaying; bool bAutoPlaying;
bool bSkinInitialized = false;
}; };