diff --git a/spine-cocos2dx/src/spine/SkeletonRenderer.cpp b/spine-cocos2dx/src/spine/SkeletonRenderer.cpp index ef33f332b..6351dea5f 100644 --- a/spine-cocos2dx/src/spine/SkeletonRenderer.cpp +++ b/spine-cocos2dx/src/spine/SkeletonRenderer.cpp @@ -56,7 +56,7 @@ using std::min; using std::max; namespace spine { - + static Cocos2dTextureLoader textureLoader; void SkeletonRenderer::destroyScratchBuffers() { @@ -72,7 +72,7 @@ SkeletonRenderer* SkeletonRenderer::createWithSkeleton(Skeleton* skeleton, bool node->autorelease(); return node; } - + SkeletonRenderer* SkeletonRenderer::createWithData (SkeletonData* skeletonData, bool ownsSkeletonData) { SkeletonRenderer* node = new SkeletonRenderer(skeletonData, ownsSkeletonData); node->autorelease(); @@ -96,24 +96,24 @@ void SkeletonRenderer::initialize () { worldVertices = new float[INITIAL_WORLD_VERTICES_LENGTH]; worldVerticesLength = INITIAL_WORLD_VERTICES_LENGTH; } - + _clipper = new (__FILE__, __LINE__) SkeletonClipping(); _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED; setOpacityModifyRGB(true); setupGLProgramState(false); - + _skeleton->setToSetupPose(); _skeleton->updateWorldTransform(); } - + void SkeletonRenderer::setupGLProgramState (bool twoColorTintEnabled) { if (twoColorTintEnabled) { setGLProgramState(SkeletonTwoColorBatch::getInstance()->getTwoColorTintProgramState()); return; } - + Texture2D *texture = nullptr; for (int i = 0, n = _skeleton->getSlots().size(); i < n; i++) { Slot* slot = _skeleton->getDrawOrder()[i]; @@ -127,7 +127,7 @@ void SkeletonRenderer::setupGLProgramState (bool twoColorTintEnabled) { } else { continue; } - + if (texture != nullptr) { break; } @@ -143,7 +143,7 @@ void SkeletonRenderer::setSkeletonData (SkeletonData *skeletonData, bool ownsSke SkeletonRenderer::SkeletonRenderer () : _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1), _effect(nullptr), _startSlotIndex(-1), _endSlotIndex(-1) { } - + SkeletonRenderer::SkeletonRenderer(Skeleton* skeleton, bool ownsSkeleton, bool ownsSkeletonData, bool ownsAtlas) : _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1), _effect(nullptr), _startSlotIndex(-1), _endSlotIndex(-1) { initWithSkeleton(skeleton, ownsSkeleton, ownsSkeletonData, ownsAtlas); @@ -177,10 +177,10 @@ void SkeletonRenderer::initWithSkeleton(Skeleton* skeleton, bool ownsSkeleton, b _ownsSkeleton = ownsSkeleton; _ownsSkeletonData = ownsSkeletonData; _ownsAtlas = ownsAtlas; - + initialize(); } - + void SkeletonRenderer::initWithData (SkeletonData* skeletonData, bool ownsSkeletonData) { _ownsSkeleton = true; setSkeletonData(skeletonData, ownsSkeletonData); @@ -221,11 +221,11 @@ void SkeletonRenderer::initWithJsonFile (const std::string& skeletonDataFile, co initialize(); } - + void SkeletonRenderer::initWithBinaryFile (const std::string& skeletonDataFile, Atlas* atlas, float scale) { _atlas = atlas; _attachmentLoader = new (__FILE__, __LINE__) Cocos2dAtlasAttachmentLoader(_atlas); - + SkeletonBinary* binary = new (__FILE__, __LINE__) SkeletonBinary(_attachmentLoader); binary->setScale(scale); SkeletonData* skeletonData = binary->readSkeletonDataFile(skeletonDataFile.c_str()); @@ -233,16 +233,16 @@ void SkeletonRenderer::initWithBinaryFile (const std::string& skeletonDataFile, delete binary; _ownsSkeleton = true; setSkeletonData(skeletonData, true); - + initialize(); } void SkeletonRenderer::initWithBinaryFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale) { _atlas = new (__FILE__, __LINE__) Atlas(atlasFile.c_str(), &textureLoader); CCASSERT(_atlas, "Error reading atlas file."); - + _attachmentLoader = new (__FILE__, __LINE__) Cocos2dAtlasAttachmentLoader(_atlas); - + SkeletonBinary* binary = new (__FILE__, __LINE__) SkeletonBinary(_attachmentLoader); binary->setScale(scale); SkeletonData* skeletonData = binary->readSkeletonDataFile(skeletonDataFile.c_str()); @@ -251,7 +251,7 @@ void SkeletonRenderer::initWithBinaryFile (const std::string& skeletonDataFile, _ownsSkeleton = true; _ownsAtlas = true; setSkeletonData(skeletonData, true); - + initialize(); } @@ -259,20 +259,25 @@ void SkeletonRenderer::update (float deltaTime) { Node::update(deltaTime); if (_ownsSkeleton) _skeleton->update(deltaTime * _timeScale); } - + void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t transformFlags) { SkeletonBatch* batch = SkeletonBatch::getInstance(); SkeletonTwoColorBatch* twoColorBatch = SkeletonTwoColorBatch::getInstance(); bool isTwoColorTint = this->isTwoColorTint(); - - if (_effect) _effect->begin(*_skeleton); + + // Early exit if the skeleton is invisible + if (getDisplayedOpacity() == 0 || _skeleton->color.a == 0){ + return; + } + + if (_effect) _effect->begin(_effect, _skeleton); Color4F nodeColor; nodeColor.r = getDisplayedColor().r / (float)255; nodeColor.g = getDisplayedColor().g / (float)255; nodeColor.b = getDisplayedColor().b / (float)255; nodeColor.a = getDisplayedOpacity() / (float)255; - + Color4F color; Color4F darkColor; float darkPremultipliedAlpha = _premultipliedAlpha ? 255 : 0; @@ -281,32 +286,44 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t bool inRange = _startSlotIndex != -1 || _endSlotIndex != -1 ? false : true; for (int i = 0, n = _skeleton->getSlots().size(); i < n; ++i) { Slot* slot = _skeleton->getDrawOrder()[i]; - + if (_startSlotIndex >= 0 && _startSlotIndex == slot->getData().getIndex()) { inRange = true; } - + if (!inRange) { _clipper->clipEnd(*slot); continue; } - + if (_endSlotIndex >= 0 && _endSlotIndex == slot->getData().getIndex()) { inRange = false; } - + if (!slot->getAttachment()) { _clipper->clipEnd(*slot); continue; } - + + // Early exit if slot is invisible + if (slot->color.a == 0) { + spSkeletonClipping_clipEnd(_clipper, slot); + continue; + } + cocos2d::TrianglesCommand::Triangles triangles; TwoColorTriangles trianglesTwoColor; - + if (slot->getAttachment()->getRTTI().isExactly(RegionAttachment::rtti)) { RegionAttachment* attachment = (RegionAttachment*)slot->getAttachment(); attachmentVertices = (AttachmentVertices*)attachment->getRendererObject(); - + + // Early exit if attachment is invisible + if (attachment->color.a == 0) { + spSkeletonClipping_clipEnd(_clipper, slot); + continue; + } + if (!isTwoColorTint) { triangles.indices = attachmentVertices->_triangles->indices; triangles.indexCount = attachmentVertices->_triangles->indexCount; @@ -324,16 +341,22 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t } attachment->computeWorldVertices(slot->getBone(), (float*)trianglesTwoColor.verts, 0, 7); } - + color.r = attachment->getColor().r; color.g = attachment->getColor().g; color.b = attachment->getColor().b; color.a = attachment->getColor().a; } else if (slot->getAttachment()->getRTTI().isExactly(MeshAttachment::rtti)) { - MeshAttachment* attachment = (MeshAttachment*)slot->getAttachment(); + MeshAttachment* attachment = (MeshAttachment*)slot->getAttachment(); attachmentVertices = (AttachmentVertices*)attachment->getRendererObject(); - + + // Early exit if attachment is invisible + if (attachment->color.a == 0) { + spSkeletonClipping_clipEnd(_clipper, slot); + continue; + } + if (!isTwoColorTint) { triangles.indices = attachmentVertices->_triangles->indices; triangles.indexCount = attachmentVertices->_triangles->indexCount; @@ -351,7 +374,7 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t } attachment->computeWorldVertices(*slot, 0, attachment->getWorldVerticesLength(), (float*)trianglesTwoColor.verts, 0, 7); } - + color.r = attachment->getColor().r; color.g = attachment->getColor().g; color.b = attachment->getColor().b; @@ -365,7 +388,7 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t _clipper->clipEnd(*slot); continue; } - + if (slot->hasDarkColor()) { darkColor.r = slot->getDarkColor().r * 255; darkColor.g = slot->getDarkColor().g * 255; @@ -376,7 +399,7 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t darkColor.b = 0; } darkColor.a = darkPremultipliedAlpha; - + color.a *= nodeColor.a * _skeleton->getColor().a * slot->getColor().a * 255; // skip rendering if the color of this attachment is 0 if (color.a == 0){ @@ -387,7 +410,7 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t color.r *= nodeColor.r * _skeleton->getColor().r * slot->getColor().r * multiplier; color.g *= nodeColor.g * _skeleton->getColor().g * slot->getColor().g * multiplier; color.b *= nodeColor.b * _skeleton->getColor().b * slot->getColor().b * multiplier; - + BlendFunc blendFunc; switch (slot->getData().getBlendMode()) { case BlendMode_Additive: @@ -406,25 +429,25 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t blendFunc.src = _premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA; blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA; } - + if (!isTwoColorTint) { if (_clipper->isClipping()) { _clipper->clipTriangles((float*)&triangles.verts[0].vertices, triangles.indices, triangles.indexCount, (float*)&triangles.verts[0].texCoords, sizeof(cocos2d::V3F_C4B_T2F) / 4); batch->deallocateVertices(triangles.vertCount); - + if (_clipper->getClippedTriangles().size() == 0){ _clipper->clipEnd(*slot); continue; } - + triangles.vertCount = _clipper->getClippedVertices().size() >> 1; triangles.verts = batch->allocateVertices(triangles.vertCount); triangles.indexCount = _clipper->getClippedTriangles().size(); triangles.indices = batch->allocateIndices(triangles.indexCount); memcpy(triangles.indices, _clipper->getClippedTriangles().buffer(), sizeof(unsigned short) * _clipper->getClippedTriangles().size()); - + cocos2d::TrianglesCommand* batchedTriangles = batch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture, _glProgramState, blendFunc, triangles, transform, transformFlags); - + float* verts = _clipper->getClippedVertices().buffer(); float* uvs = _clipper->getClippedUVs().buffer(); if (_effect) { @@ -464,7 +487,7 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t } } else { cocos2d::TrianglesCommand* batchedTriangles = batch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture, _glProgramState, blendFunc, triangles, transform, transformFlags); - + if (_effect) { Color light; Color dark; @@ -497,23 +520,23 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t if (_clipper->isClipping()) { _clipper->clipTriangles((float*)&trianglesTwoColor.verts[0].position, trianglesTwoColor.indices, trianglesTwoColor.indexCount, (float*)&trianglesTwoColor.verts[0].texCoords, sizeof(V3F_C4B_C4B_T2F) / 4); twoColorBatch->deallocateVertices(trianglesTwoColor.vertCount); - + if (_clipper->getClippedTriangles().size() == 0){ _clipper->clipEnd(*slot); continue; } - + trianglesTwoColor.vertCount = _clipper->getClippedVertices().size() >> 1; trianglesTwoColor.verts = twoColorBatch->allocateVertices(trianglesTwoColor.vertCount); trianglesTwoColor.indexCount = _clipper->getClippedTriangles().size(); trianglesTwoColor.indices = twoColorBatch->allocateIndices(trianglesTwoColor.indexCount); memcpy(trianglesTwoColor.indices, _clipper->getClippedTriangles().buffer(), sizeof(unsigned short) * _clipper->getClippedTriangles().size()); - + TwoColorTrianglesCommand* batchedTriangles = lastTwoColorTrianglesCommand = twoColorBatch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture->getName(), _glProgramState, blendFunc, trianglesTwoColor, transform, transformFlags); - + float* verts = _clipper->getClippedVertices().buffer(); float* uvs = _clipper->getClippedUVs().buffer(); - + if (_effect) { Color light; Color dark; @@ -562,7 +585,7 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t } } else { TwoColorTrianglesCommand* batchedTriangles = lastTwoColorTrianglesCommand = twoColorBatch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture->getName(), _glProgramState, blendFunc, trianglesTwoColor, transform, transformFlags); - + if (_effect) { Color light; Color dark; @@ -574,7 +597,7 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t dark.g = darkColor.g / 255.0f; dark.b = darkColor.b / 255.0f; dark.a = darkColor.a / 255.0f; - + for (int v = 0, vn = batchedTriangles->getTriangles().vertCount; v < vn; ++v) { V3F_C4B_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v; Color lightCopy = light; @@ -607,10 +630,10 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t _clipper->clipEnd(*slot); } _clipper->clipEnd(); - + if (lastTwoColorTrianglesCommand) { Node* parent = this->getParent(); - + // We need to decide if we can postpone flushing the current // batch. We can postpone if the next sibling node is a // two color tinted skeleton with the same global-z. @@ -644,7 +667,7 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t } } } - + if (_effect) _effect->end(); if (_debugSlots || _debugBones || _debugMeshes) { @@ -657,9 +680,9 @@ void SkeletonRenderer::drawDebug (Renderer* renderer, const Mat4 &transform, uin Director* director = Director::getInstance(); director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, transform); - + DrawNode* drawNode = DrawNode::create(); - + if (_debugSlots) { // Slots. // DrawPrimitives::setDrawColor4B(0, 0, 255, 255); @@ -695,7 +718,7 @@ void SkeletonRenderer::drawDebug (Renderer* renderer, const Mat4 &transform, uin if (i == 0) color = Color4F::GREEN; } } - + if (_debugMeshes) { // Meshes. glLineWidth(1); @@ -714,13 +737,13 @@ void SkeletonRenderer::drawDebug (Renderer* renderer, const Mat4 &transform, uin drawNode->drawLine(v3, v1, Color4F::YELLOW); } } - + } - + drawNode->draw(renderer, transform, transformFlags); director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); } - + Rect SkeletonRenderer::getBoundingBox () const { float minX = FLT_MAX, minY = FLT_MAX, maxX = -FLT_MAX, maxY = -FLT_MAX; float scaleX = getScaleX(), scaleY = getScaleY(); @@ -748,7 +771,7 @@ Rect SkeletonRenderer::getBoundingBox () const { } } Vec2 position = getPosition(); - if (minX == FLT_MAX) minX = minY = maxX = maxY = 0; + if (minX == FLT_MAX) minX = minY = maxX = maxY = 0; return Rect(position.x + minX, position.y + minY, maxX - minX, maxY - minY); } @@ -792,7 +815,7 @@ bool SkeletonRenderer::setAttachment (const std::string& slotName, const std::st bool SkeletonRenderer::setAttachment (const std::string& slotName, const char* attachmentName) { return _skeleton->getAttachment(slotName.c_str(), attachmentName) ? true : false; } - + void SkeletonRenderer::setTwoColorTint(bool enabled) { setupGLProgramState(enabled); } @@ -800,11 +823,11 @@ void SkeletonRenderer::setTwoColorTint(bool enabled) { bool SkeletonRenderer::isTwoColorTint() { return getGLProgramState() == SkeletonTwoColorBatch::getInstance()->getTwoColorTintProgramState(); } - + void SkeletonRenderer::setVertexEffect(VertexEffect *effect) { this->_effect = effect; } - + void SkeletonRenderer::setSlotsRange(int startSlotIndex, int endSlotIndex) { this->_startSlotIndex = startSlotIndex; this->_endSlotIndex = endSlotIndex; @@ -834,7 +857,7 @@ void SkeletonRenderer::setDebugBonesEnabled (bool enabled) { bool SkeletonRenderer::getDebugBonesEnabled () const { return _debugBones; } - + void SkeletonRenderer::setDebugMeshesEnabled (bool enabled) { _debugMeshes = enabled; } diff --git a/spine-csharp/src/Bone.cs b/spine-csharp/src/Bone.cs index 3357ec3c0..21b471894 100644 --- a/spine-csharp/src/Bone.cs +++ b/spine-csharp/src/Bone.cs @@ -53,10 +53,6 @@ namespace Spine { internal float a, b, worldX; internal float c, d, worldY; -// internal float worldSignX, worldSignY; -// public float WorldSignX { get { return worldSignX; } } -// public float WorldSignY { get { return worldSignY; } } - internal bool sorted; public BoneData Data { get { return data; } } @@ -152,27 +148,13 @@ namespace Spine { Bone parent = this.parent; if (parent == null) { // Root bone. - float rotationY = rotation + 90 + shearY; - float la = MathUtils.CosDeg(rotation + shearX) * scaleX; - float lb = MathUtils.CosDeg(rotationY) * scaleY; - float lc = MathUtils.SinDeg(rotation + shearX) * scaleX; - float ld = MathUtils.SinDeg(rotationY) * scaleY; - if (skeleton.flipX) { - x = -x; - la = -la; - lb = -lb; - } - if (skeleton.flipY != yDown) { - y = -y; - lc = -lc; - ld = -ld; - } - a = la; - b = lb; - c = lc; - d = ld; - worldX = x + skeleton.x; - worldY = y + skeleton.y; + float rotationY = rotation + 90 + shearY, sx = skeleton.scaleX, sy = skeleton.scaleY; + a = MathUtils.CosDeg(rotation + shearX) * scaleX * sx; + b = MathUtils.CosDeg(rotationY) * scaleY * sy; + c = MathUtils.SinDeg(rotation + shearX) * scaleX * sx; + d = MathUtils.SinDeg(rotationY) * scaleY * sy; + worldX = x * sx + skeleton.x; + worldY = y * sy + skeleton.y; return; } @@ -228,8 +210,8 @@ namespace Spine { case TransformMode.NoScale: case TransformMode.NoScaleOrReflection: { float cos = MathUtils.CosDeg(rotation), sin = MathUtils.SinDeg(rotation); - float za = pa * cos + pb * sin; - float zc = pc * cos + pd * sin; + float za = (pa * cos + pb * sin) / skeleton.scaleX; + float zc = (pc * cos + pd * sin) / skeleton.scaleY; float s = (float)Math.Sqrt(za * za + zc * zc); if (s > 0.00001f) s = 1 / s; za *= s; @@ -242,26 +224,18 @@ namespace Spine { float lb = MathUtils.CosDeg(90 + shearY) * scaleY; float lc = MathUtils.SinDeg(shearX) * scaleX; float ld = MathUtils.SinDeg(90 + shearY) * scaleY; - if (data.transformMode != TransformMode.NoScaleOrReflection? pa * pd - pb* pc< 0 : skeleton.flipX != skeleton.flipY) { - zb = -zb; - zd = -zd; - } a = za * la + zb * lc; b = za * lb + zb * ld; c = zc * la + zd * lc; - d = zc * lb + zd * ld; - return; + d = zc * lb + zd * ld; + break; } } - if (skeleton.flipX) { - a = -a; - b = -b; - } - if (skeleton.flipY != Bone.yDown) { - c = -c; - d = -d; - } + a *= skeleton.scaleX; + b *= skeleton.scaleX; + c *= skeleton.scaleY; + d *= skeleton.scaleY; } public void SetToSetupPose () { diff --git a/spine-csharp/src/Skeleton.cs b/spine-csharp/src/Skeleton.cs index ed4897ae6..f774e0490 100644 --- a/spine-csharp/src/Skeleton.cs +++ b/spine-csharp/src/Skeleton.cs @@ -45,7 +45,7 @@ namespace Spine { internal Skin skin; internal float r = 1, g = 1, b = 1, a = 1; internal float time; - internal bool flipX, flipY; + internal float scaleX, scaleY; internal float x, y; public SkeletonData Data { get { return data; } } @@ -64,8 +64,14 @@ namespace Spine { public float Time { get { return time; } set { time = value; } } public float X { get { return x; } set { x = value; } } public float Y { get { return y; } set { y = value; } } - public bool FlipX { get { return flipX; } set { flipX = value; } } - public bool FlipY { get { return flipY; } set { flipY = value; } } + public float ScaleX { get { return scaleX; } set { scaleX = value; } } + public float ScaleY { get { return scaleY; } set { scaleY = value; } } + + [Obsolete("Use ScaleX instead. FlipX is when ScaleX is negative.")] + public bool FlipX { get { return scaleX < 0; } set { scaleX = value ? -1f : 1f; } } + + [Obsolete("Use ScaleY instead. FlipY is when ScaleY is negative.")] + public bool FlipY { get { return scaleY < 0; } set { scaleY = value ? -1f : 1f; } } public Bone RootBone { get { return bones.Count == 0 ? null : bones.Items[0]; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java index d4a2ca6dd..6fa9f2d8c 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java @@ -37,6 +37,7 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.FloatArray; + import com.esotericsoftware.spine.attachments.Attachment; import com.esotericsoftware.spine.attachments.VertexAttachment; @@ -1294,11 +1295,12 @@ public class Animation { } } - /** Changes an IK constraint's {@link IkConstraint#getMix()} and {@link IkConstraint#getBendDirection()}. */ + /** Changes an IK constraint's {@link IkConstraint#getMix()}, {@link IkConstraint#getBendDirection()}, and + * {@link IkConstraint#getStretch()}. */ static public class IkConstraintTimeline extends CurveTimeline { - static public final int ENTRIES = 3; - static private final int PREV_TIME = -3, PREV_MIX = -2, PREV_BEND_DIRECTION = -1; - static private final int MIX = 1, BEND_DIRECTION = 2; + static public final int ENTRIES = 4; + static private final int PREV_TIME = -4, PREV_MIX = -3, PREV_BEND_DIRECTION = -2, PREV_STRETCH = -1; + static private final int MIX = 1, BEND_DIRECTION = 2, STRETCH = 3; int ikConstraintIndex; private final float[] frames; // time, mix, bendDirection, ... @@ -1328,11 +1330,12 @@ public class Animation { } /** Sets the time in seconds, mix, and bend direction for the specified key frame. */ - public void setFrame (int frameIndex, float time, float mix, int bendDirection) { + public void setFrame (int frameIndex, float time, float mix, int bendDirection, boolean stretch) { frameIndex *= ENTRIES; frames[frameIndex] = time; frames[frameIndex + MIX] = mix; frames[frameIndex + BEND_DIRECTION] = bendDirection; + frames[frameIndex + STRETCH] = stretch ? 1 : 0; } public void apply (Skeleton skeleton, float lastTime, float time, Array events, float alpha, MixBlend blend, @@ -1345,10 +1348,12 @@ public class Animation { case setup: constraint.mix = constraint.data.mix; constraint.bendDirection = constraint.data.bendDirection; + constraint.stretch = constraint.data.stretch; return; case first: constraint.mix += (constraint.data.mix - constraint.mix) * alpha; constraint.bendDirection = constraint.data.bendDirection; + constraint.stretch = constraint.data.stretch; } return; } @@ -1356,11 +1361,19 @@ public class Animation { if (time >= frames[frames.length - ENTRIES]) { // Time is after last frame. if (blend == setup) { constraint.mix = constraint.data.mix + (frames[frames.length + PREV_MIX] - constraint.data.mix) * alpha; - constraint.bendDirection = direction == out ? constraint.data.bendDirection - : (int)frames[frames.length + PREV_BEND_DIRECTION]; + if (direction == out) { + constraint.bendDirection = constraint.data.bendDirection; + constraint.stretch = constraint.data.stretch; + } else { + constraint.bendDirection = (int)frames[frames.length + PREV_BEND_DIRECTION]; + constraint.stretch = frames[frames.length + PREV_STRETCH] != 0; + } } else { constraint.mix += (frames[frames.length + PREV_MIX] - constraint.mix) * alpha; - if (direction == in) constraint.bendDirection = (int)frames[frames.length + PREV_BEND_DIRECTION]; + if (direction == in) { + constraint.bendDirection = (int)frames[frames.length + PREV_BEND_DIRECTION]; + constraint.stretch = frames[frames.length + PREV_STRETCH] != 0; + } } return; } @@ -1373,11 +1386,19 @@ public class Animation { if (blend == setup) { constraint.mix = constraint.data.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.data.mix) * alpha; - constraint.bendDirection = direction == out ? constraint.data.bendDirection - : (int)frames[frame + PREV_BEND_DIRECTION]; + if (direction == out) { + constraint.bendDirection = constraint.data.bendDirection; + constraint.stretch = constraint.data.stretch; + } else { + constraint.bendDirection = (int)frames[frame + PREV_BEND_DIRECTION]; + constraint.stretch = frames[frame + PREV_STRETCH] != 0; + } } else { constraint.mix += (mix + (frames[frame + MIX] - mix) * percent - constraint.mix) * alpha; - if (direction == in) constraint.bendDirection = (int)frames[frame + PREV_BEND_DIRECTION]; + if (direction == in) { + constraint.bendDirection = (int)frames[frame + PREV_BEND_DIRECTION]; + constraint.stretch = frames[frame + PREV_STRETCH] != 0; + } } } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java index d6128a332..77623cbad 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java @@ -42,8 +42,9 @@ public class IkConstraint implements Constraint { final IkConstraintData data; final Array bones; Bone target; - float mix = 1; int bendDirection; + boolean stretch; + float mix = 1; public IkConstraint (IkConstraintData data, Skeleton skeleton) { if (data == null) throw new IllegalArgumentException("data cannot be null."); @@ -51,6 +52,7 @@ public class IkConstraint implements Constraint { this.data = data; mix = data.mix; bendDirection = data.bendDirection; + stretch = data.stretch; bones = new Array(data.bones.size); for (BoneData boneData : data.bones) @@ -69,6 +71,7 @@ public class IkConstraint implements Constraint { target = skeleton.bones.get(constraint.target.data.index); mix = constraint.mix; bendDirection = constraint.bendDirection; + stretch = constraint.stretch; } /** Applies the constraint to the constrained bones. */ @@ -81,10 +84,10 @@ public class IkConstraint implements Constraint { Array bones = this.bones; switch (bones.size) { case 1: - apply(bones.first(), target.worldX, target.worldY, mix); + apply(bones.first(), target.worldX, target.worldY, stretch, mix); break; case 2: - apply(bones.first(), bones.get(1), target.worldX, target.worldY, bendDirection, mix); + apply(bones.first(), bones.get(1), target.worldX, target.worldY, bendDirection, stretch, mix); break; } } @@ -125,6 +128,16 @@ public class IkConstraint implements Constraint { this.bendDirection = bendDirection; } + /** When true, if the target is out of range, the parent bone is scaled on the X axis to reach it. If the parent bone has local + * nonuniform scale, stretching is not applied. */ + public boolean getStretch () { + return stretch; + } + + public void setStretch (boolean stretch) { + this.stretch = stretch; + } + /** The IK constraint's setup pose data. */ public IkConstraintData getData () { return data; @@ -135,7 +148,7 @@ public class IkConstraint implements Constraint { } /** Applies 1 bone IK. The target is specified in the world coordinate system. */ - static public void apply (Bone bone, float targetX, float targetY, float alpha) { + static public void apply (Bone bone, float targetX, float targetY, boolean stretch, float alpha) { if (!bone.appliedValid) bone.updateAppliedTransform(); Bone p = bone.parent; float id = 1 / (p.a * p.d - p.b * p.c); @@ -146,20 +159,25 @@ public class IkConstraint implements Constraint { if (rotationIK > 180) rotationIK -= 360; else if (rotationIK < -180) rotationIK += 360; - bone.updateWorldTransform(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, bone.ascaleX, bone.ascaleY, bone.ashearX, + float sx = bone.ascaleX; + if (stretch) { + float b = bone.data.length * sx, dd = (float)Math.sqrt(tx * tx + ty * ty); + if (dd > b && b > 0.0001f) sx *= (dd / b - 1) * alpha + 1; + } + bone.updateWorldTransform(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, bone.ascaleY, bone.ashearX, bone.ashearY); } /** Applies 2 bone IK. The target is specified in the world coordinate system. * @param child A direct descendant of the parent bone. */ - static public void apply (Bone parent, Bone child, float targetX, float targetY, int bendDir, float alpha) { + static public void apply (Bone parent, Bone child, float targetX, float targetY, int bendDir, boolean stretch, float alpha) { if (alpha == 0) { child.updateWorldTransform(); return; } if (!parent.appliedValid) parent.updateAppliedTransform(); if (!child.appliedValid) child.updateAppliedTransform(); - float px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, csx = child.ascaleX; + float px = parent.ax, py = parent.ay, psx = parent.ascaleX, sx = psx, psy = parent.ascaleY, csx = child.ascaleX; int os1, os2, s2; if (psx < 0) { psx = -psx; @@ -195,7 +213,7 @@ public class IkConstraint implements Constraint { c = pp.c; d = pp.d; float id = 1 / (a * d - b * c), x = targetX - pp.worldX, y = targetY - pp.worldY; - float tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; + float tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py, dd = tx * tx + ty * ty; x = cwx - pp.worldX; y = cwy - pp.worldY; float dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; @@ -203,10 +221,13 @@ public class IkConstraint implements Constraint { outer: if (u) { l2 *= psx; - float cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2); + float cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); if (cos < -1) cos = -1; - else if (cos > 1) cos = 1; + else if (cos > 1) { + cos = 1; + if (stretch && l1 + l2 > 0.0001f) sx *= ((float)Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1; + } a2 = (float)Math.acos(cos) * bendDir; a = l1 + l2 * cos; b = l2 * sin(a2); @@ -214,7 +235,7 @@ public class IkConstraint implements Constraint { } else { a = psx * l2; b = psy * l2; - float aa = a * a, bb = b * b, dd = tx * tx + ty * ty, ta = atan2(ty, tx); + float aa = a * a, bb = b * b, ta = atan2(ty, tx); c = bb * l1 * l1 + aa * dd - aa * bb; float c1 = -2 * bb * l1, c2 = bb - aa; d = c1 * c1 - 4 * c2 * c; @@ -266,7 +287,7 @@ public class IkConstraint implements Constraint { if (a1 > 180) a1 -= 360; else if (a1 < -180) a1 += 360; - parent.updateWorldTransform(px, py, rotation + a1 * alpha, parent.ascaleX, parent.ascaleY, 0, 0); + parent.updateWorldTransform(px, py, rotation + a1 * alpha, sx, parent.ascaleY, 0, 0); rotation = child.arotation; a2 = ((a2 + os) * radDeg - child.ashearX) * s2 + os2 - rotation; if (a2 > 180) diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java index 75b3e49d6..81bceb23b 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java @@ -41,6 +41,7 @@ public class IkConstraintData { final Array bones = new Array(); BoneData target; int bendDirection = 1; + boolean stretch; float mix = 1; public IkConstraintData (String name) { @@ -86,6 +87,16 @@ public class IkConstraintData { this.bendDirection = bendDirection; } + /** When true, if the target is out of range, the parent bone is scaled on the X axis to reach it. If the parent bone has local + * nonuniform scale, stretching is not applied. */ + public boolean getStretch () { + return stretch; + } + + public void setStretch (boolean stretch) { + this.stretch = stretch; + } + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */ public float getMix () { return mix; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java index e267fa1a2..1e3168037 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java @@ -395,6 +395,7 @@ public class Skeleton { for (int i = 0, n = ikConstraints.size; i < n; i++) { IkConstraint constraint = ikConstraints.get(i); constraint.bendDirection = constraint.data.bendDirection; + constraint.stretch = constraint.data.stretch; constraint.mix = constraint.data.mix; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java index 81884693a..1d5e0959b 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java @@ -232,6 +232,7 @@ public class SkeletonBinary { data.target = skeletonData.bones.get(input.readInt(true)); data.mix = input.readFloat(); data.bendDirection = input.readByte(); + data.stretch = input.readBoolean(); skeletonData.ikConstraints.add(data); } @@ -660,7 +661,7 @@ public class SkeletonBinary { IkConstraintTimeline timeline = new IkConstraintTimeline(frameCount); timeline.ikConstraintIndex = index; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { - timeline.setFrame(frameIndex, input.readFloat(), input.readFloat(), input.readByte()); + timeline.setFrame(frameIndex, input.readFloat(), input.readFloat(), input.readByte(), input.readBoolean()); if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline); } timelines.add(timeline); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java index 904ce4752..3120595b6 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java @@ -186,6 +186,7 @@ public class SkeletonJson { if (data.target == null) throw new SerializationException("IK target bone not found: " + targetName); data.bendDirection = constraintMap.getBoolean("bendPositive", true) ? 1 : -1; + data.stretch = constraintMap.getBoolean("stretch", false); data.mix = constraintMap.getFloat("mix", 1); skeletonData.ikConstraints.add(data); @@ -568,7 +569,7 @@ public class SkeletonJson { int frameIndex = 0; for (JsonValue valueMap = constraintMap.child; valueMap != null; valueMap = valueMap.next) { timeline.setFrame(frameIndex, valueMap.getFloat("time"), valueMap.getFloat("mix", 1), - valueMap.getBoolean("bendPositive", true) ? 1 : -1); + valueMap.getBoolean("bendPositive", true) ? 1 : -1, valueMap.getBoolean("stretch", false)); readCurve(valueMap, timeline, frameIndex); frameIndex++; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java index a231e8167..19a9de0db 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java @@ -67,7 +67,7 @@ public class SkeletonRenderer { * skeleton is rendered without two color tinting and any mesh attachments will throw an exception. *

* This method may change the batch's {@link Batch#setBlendFunctionSeparate(int, int, int, int) blending function}. The - * previous blend function is not restore, since that could result in unnecessary flushes, depending on what is rendered + * previous blend function is not restored, since that could result in unnecessary flushes, depending on what is rendered * next. */ public void draw (Batch batch, Skeleton skeleton) { if (batch instanceof PolygonSpriteBatch) { @@ -144,7 +144,7 @@ public class SkeletonRenderer { /** Renders the specified skeleton, including meshes, but without two color tinting. *

* This method may change the batch's {@link Batch#setBlendFunctionSeparate(int, int, int, int) blending function}. The - * previous blend function is not restore, since that could result in unnecessary flushes, depending on what is rendered + * previous blend function is not restored, since that could result in unnecessary flushes, depending on what is rendered * next. */ @SuppressWarnings("null") public void draw (PolygonSpriteBatch batch, Skeleton skeleton) { @@ -266,7 +266,7 @@ public class SkeletonRenderer { /** Renders the specified skeleton, including meshes and two color tinting. *

* This method may change the batch's {@link Batch#setBlendFunctionSeparate(int, int, int, int) blending function}. The - * previous blend function is not restore, since that could result in unnecessary flushes, depending on what is rendered + * previous blend function is not restored, since that could result in unnecessary flushes, depending on what is rendered * next. */ @SuppressWarnings("null") public void draw (TwoColorPolygonBatch batch, Skeleton skeleton) { diff --git a/spine-sfml/c/src/spine/spine-sfml.cpp b/spine-sfml/c/src/spine/spine-sfml.cpp index c3304d77e..e48fc0856 100644 --- a/spine-sfml/c/src/spine/spine-sfml.cpp +++ b/spine-sfml/c/src/spine/spine-sfml.cpp @@ -116,6 +116,9 @@ void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const { states.texture = 0; unsigned short quadIndices[6] = { 0, 1, 2, 2, 3, 0 }; + // Early out if skeleton is invisible + if (skeleton->color.a == 0) return; + if (vertexEffect != 0) vertexEffect->begin(vertexEffect, skeleton); sf::Vertex vertex; @@ -125,6 +128,12 @@ void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const { Attachment* attachment = slot->attachment; if (!attachment) continue; + // Early out if slot is invisible + if (slot->color.a == 0) { + spSkeletonClipping_clipEnd(clipper, slot); + continue; + } + float* vertices = worldVertices; int verticesCount = 0; float* uvs = 0; @@ -134,16 +143,31 @@ void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const { if (attachment->type == ATTACHMENT_REGION) { RegionAttachment* regionAttachment = (RegionAttachment*)attachment; + attachmentColor = ®ionAttachment->color; + + // Early out if slot is invisible + if (attachmentColor->a == 0) { + spSkeletonClipping_clipEnd(clipper, slot); + continue; + } + spRegionAttachment_computeWorldVertices(regionAttachment, slot->bone, vertices, 0, 2); verticesCount = 4; uvs = regionAttachment->uvs; indices = quadIndices; indicesCount = 6; texture = (Texture*)((AtlasRegion*)regionAttachment->rendererObject)->page->rendererObject; - attachmentColor = ®ionAttachment->color; } else if (attachment->type == ATTACHMENT_MESH) { MeshAttachment* mesh = (MeshAttachment*)attachment; + attachmentColor = &mesh->color; + + // Early out if slot is invisible + if (attachmentColor->a == 0) { + spSkeletonClipping_clipEnd(clipper, slot); + continue; + } + if (mesh->super.worldVerticesLength > SPINE_MESH_VERTEX_COUNT_MAX) continue; texture = (Texture*)((AtlasRegion*)mesh->rendererObject)->page->rendererObject; spVertexAttachment_computeWorldVertices(SUPER(mesh), slot, 0, mesh->super.worldVerticesLength, worldVertices, 0, 2); @@ -151,7 +175,7 @@ void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const { uvs = mesh->uvs; indices = mesh->triangles; indicesCount = mesh->trianglesCount; - attachmentColor = &mesh->color; + } else if (attachment->type == SP_ATTACHMENT_CLIPPING) { spClippingAttachment* clip = (spClippingAttachment*)slot->attachment; spSkeletonClipping_clipStart(clipper, slot, clip); diff --git a/spine-sfml/cpp/src/spine/spine-sfml.cpp b/spine-sfml/cpp/src/spine/spine-sfml.cpp index 39d372ea5..60998cf0a 100644 --- a/spine-sfml/cpp/src/spine/spine-sfml.cpp +++ b/spine-sfml/cpp/src/spine/spine-sfml.cpp @@ -91,6 +91,9 @@ void SkeletonDrawable::draw(RenderTarget &target, RenderStates states) const { vertexArray->clear(); states.texture = NULL; + // Early out if the skeleton alpha is 0 + if (skeleton->getColor().a == 0) return; + if (vertexEffect != NULL) vertexEffect->begin(*skeleton); sf::Vertex vertex; @@ -100,6 +103,12 @@ void SkeletonDrawable::draw(RenderTarget &target, RenderStates states) const { Attachment *attachment = slot.getAttachment(); if (!attachment) continue; + // Early out if the slot color is 0 + if (slot.getColor().a == 0) { + clipper.clipEnd(slot); + continue; + } + Vector *vertices = &worldVertices; int verticesCount = 0; Vector *uvs = NULL; @@ -109,17 +118,32 @@ void SkeletonDrawable::draw(RenderTarget &target, RenderStates states) const { if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) { RegionAttachment *regionAttachment = (RegionAttachment *) attachment; + attachmentColor = ®ionAttachment->getColor(); + + // Early out if the attachment color is 0 + if (attachmentColor->a == 0) { + clipper.clipEnd(slot); + continue; + } + worldVertices.setSize(8, 0); regionAttachment->computeWorldVertices(slot.getBone(), worldVertices, 0, 2); verticesCount = 4; uvs = ®ionAttachment->getUVs(); indices = &quadIndices; indicesCount = 6; - texture = (Texture *) ((AtlasRegion *) regionAttachment->getRendererObject())->page->getRendererObject(); - attachmentColor = ®ionAttachment->getColor(); + texture = (Texture *) ((AtlasRegion *) regionAttachment->getRendererObject())->page->rendererObject; } else if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) { MeshAttachment *mesh = (MeshAttachment *) attachment; + attachmentColor = &mesh->getColor(); + + // Early out if the attachment color is 0 + if (attachmentColor->a == 0) { + clipper.clipEnd(slot); + continue; + } + worldVertices.setSize(mesh->getWorldVerticesLength(), 0); texture = (Texture *) ((AtlasRegion *) mesh->getRendererObject())->page->getRendererObject(); mesh->computeWorldVertices(slot, 0, mesh->getWorldVerticesLength(), worldVertices, 0, 2); @@ -127,7 +151,6 @@ void SkeletonDrawable::draw(RenderTarget &target, RenderStates states) const { uvs = &mesh->getUVs(); indices = &mesh->getTriangles(); indicesCount = mesh->getTriangles().size(); - attachmentColor = &mesh->getColor(); } else if (attachment->getRTTI().isExactly(ClippingAttachment::rtti)) { ClippingAttachment *clip = (ClippingAttachment *) slot.getAttachment(); clipper.clipStart(slot, clip); diff --git a/spine-unity/Assets/Spine Examples/Other Examples/Animation Tester.meta b/spine-unity/Assets/Spine Examples/Other Examples/Animation Tester.meta new file mode 100644 index 000000000..8e1382599 --- /dev/null +++ b/spine-unity/Assets/Spine Examples/Other Examples/Animation Tester.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 173cd2c662ebd674f994bff2385cfbf6 +folderAsset: yes +timeCreated: 1529972040 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/Spine Examples/Other Examples/Animation Tester/Animation Tester.unity b/spine-unity/Assets/Spine Examples/Other Examples/Animation Tester/Animation Tester.unity new file mode 100644 index 000000000..7c5ca0bce Binary files /dev/null and b/spine-unity/Assets/Spine Examples/Other Examples/Animation Tester/Animation Tester.unity differ diff --git a/spine-unity/Assets/Spine Examples/Other Examples/Animation Tester/Animation Tester.unity.meta b/spine-unity/Assets/Spine Examples/Other Examples/Animation Tester/Animation Tester.unity.meta new file mode 100644 index 000000000..43460e8bd --- /dev/null +++ b/spine-unity/Assets/Spine Examples/Other Examples/Animation Tester/Animation Tester.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b804088948820194cbda76af39c08174 +timeCreated: 1529972058 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/Spine Examples/Other Examples/Animation Tester/SpineAnimationTesterTool.cs b/spine-unity/Assets/Spine Examples/Other Examples/Animation Tester/SpineAnimationTesterTool.cs new file mode 100644 index 000000000..37cf5f8ba --- /dev/null +++ b/spine-unity/Assets/Spine Examples/Other Examples/Animation Tester/SpineAnimationTesterTool.cs @@ -0,0 +1,117 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +using Spine; +using Spine.Unity; + +using System.Text; + +namespace Spine.Unity.Examples { + public class SpineAnimationTesterTool : MonoBehaviour, IHasSkeletonDataAsset, IHasSkeletonComponent { + + public SkeletonAnimation skeletonAnimation; + public SkeletonDataAsset SkeletonDataAsset { get { return skeletonAnimation.SkeletonDataAsset; } } + public ISkeletonComponent SkeletonComponent { get { return skeletonAnimation; } } + + public bool useOverrideMixDuration; + public float overrideMixDuration = 0.2f; + + [System.Serializable] + public struct AnimationControl { + [SpineAnimation] + public string animationName; + public bool loop; + public KeyCode key; + + [Space] + public bool useCustomMixDuration; + public float mixDuration; + //public bool useChainToControl; + //public int chainToControl; + } + [System.Serializable] + public class ControlledTrack { + public List controls = new List(); + } + + [Space] + public List trackControls = new List(); + + [Header("UI")] + public UnityEngine.UI.Text boundAnimationsText; + public UnityEngine.UI.Text skeletonNameText; + + void OnValidate () { + // Fill in the SkeletonData asset name + if (skeletonNameText != null) { + if (skeletonAnimation != null && skeletonAnimation.skeletonDataAsset != null) { + skeletonNameText.text = SkeletonDataAsset.name.Replace("_SkeletonData", ""); + } + } + + // Fill in the control list. + if (boundAnimationsText != null) { + var boundAnimationsStringBuilder = new StringBuilder(); + boundAnimationsStringBuilder.AppendLine("Animation Controls:"); + + for (int trackIndex = 0; trackIndex < trackControls.Count; trackIndex++) { + + if (trackIndex > 0) + boundAnimationsStringBuilder.AppendLine(); + + boundAnimationsStringBuilder.AppendFormat("---- Track {0} ---- \n", trackIndex); + foreach (var ba in trackControls[trackIndex].controls) { + string animationName = ba.animationName; + if (string.IsNullOrEmpty(animationName)) + animationName = "SetEmptyAnimation"; + + boundAnimationsStringBuilder.AppendFormat("[{0}] {1}\n", ba.key.ToString(), animationName); + } + + } + + boundAnimationsText.text = boundAnimationsStringBuilder.ToString(); + + } + + } + + void Start () { + if (useOverrideMixDuration) { + skeletonAnimation.AnimationState.Data.DefaultMix = overrideMixDuration; + } + } + + void Update () { + var animationState = skeletonAnimation.AnimationState; + + // For each track + for (int trackIndex = 0; trackIndex < trackControls.Count; trackIndex++) { + + // For each control in the track + foreach (var control in trackControls[trackIndex].controls) { + + // Check each control, and play the appropriate animation. + if (Input.GetKeyDown(control.key)) { + if (!string.IsNullOrEmpty(control.animationName)) { + var trackEntry = animationState.SetAnimation(trackIndex, control.animationName, control.loop); + if (control.useCustomMixDuration) + trackEntry.MixDuration = control.mixDuration; + + } else { + float mix = control.useCustomMixDuration ? control.mixDuration : animationState.Data.DefaultMix; + animationState.SetEmptyAnimation(trackIndex, mix); + } + + // Don't parse more than one animation per track. + break; + } + } + } + + } + + } +} + diff --git a/spine-unity/Assets/Spine Examples/Other Examples/Animation Tester/SpineAnimationTesterTool.cs.meta b/spine-unity/Assets/Spine Examples/Other Examples/Animation Tester/SpineAnimationTesterTool.cs.meta new file mode 100644 index 000000000..b5c006260 --- /dev/null +++ b/spine-unity/Assets/Spine Examples/Other Examples/Animation Tester/SpineAnimationTesterTool.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b99b2d8e59226fa4db070f241259fd98 +timeCreated: 1529972356 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/Spine Examples/Other Examples/Mix and Match Equip.unity b/spine-unity/Assets/Spine Examples/Other Examples/Mix and Match Equip.unity index 4df601543..f36bb0745 100644 Binary files a/spine-unity/Assets/Spine Examples/Other Examples/Mix and Match Equip.unity and b/spine-unity/Assets/Spine Examples/Other Examples/Mix and Match Equip.unity differ diff --git a/spine-unity/Assets/Spine Examples/Other Examples/StateMachine SkeletonAnimation.meta b/spine-unity/Assets/Spine Examples/Other Examples/StateMachine SkeletonAnimation.meta new file mode 100644 index 000000000..0dc2b8f85 --- /dev/null +++ b/spine-unity/Assets/Spine Examples/Other Examples/StateMachine SkeletonAnimation.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 4766fcfd6167d2e46aad772ce3bc898c +folderAsset: yes +timeCreated: 1531292725 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/Spine Examples/Other Examples/StateMachine SkeletonAnimation/AnimationState with Mecanim.unity b/spine-unity/Assets/Spine Examples/Other Examples/StateMachine SkeletonAnimation/AnimationState with Mecanim.unity new file mode 100644 index 000000000..aaf9462cd Binary files /dev/null and b/spine-unity/Assets/Spine Examples/Other Examples/StateMachine SkeletonAnimation/AnimationState with Mecanim.unity differ diff --git a/spine-unity/Assets/Spine Examples/Other Examples/StateMachine SkeletonAnimation/AnimationState with Mecanim.unity.meta b/spine-unity/Assets/Spine Examples/Other Examples/StateMachine SkeletonAnimation/AnimationState with Mecanim.unity.meta new file mode 100644 index 000000000..20063753f --- /dev/null +++ b/spine-unity/Assets/Spine Examples/Other Examples/StateMachine SkeletonAnimation/AnimationState with Mecanim.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: afd3c9ec31200bc49b169c22f00b010b +timeCreated: 1531300871 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/Spine Examples/Other Examples/StateMachine SkeletonAnimation/Hero.controller b/spine-unity/Assets/Spine Examples/Other Examples/StateMachine SkeletonAnimation/Hero.controller new file mode 100644 index 000000000..ae8ec504c Binary files /dev/null and b/spine-unity/Assets/Spine Examples/Other Examples/StateMachine SkeletonAnimation/Hero.controller differ diff --git a/spine-unity/Assets/Spine Examples/Other Examples/StateMachine SkeletonAnimation/Hero.controller.meta b/spine-unity/Assets/Spine Examples/Other Examples/StateMachine SkeletonAnimation/Hero.controller.meta new file mode 100644 index 000000000..7c90a3d5b --- /dev/null +++ b/spine-unity/Assets/Spine Examples/Other Examples/StateMachine SkeletonAnimation/Hero.controller.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: cec34498f2eb26b488452ec274c54439 +timeCreated: 1531292741 +licenseType: Free +NativeFormatImporter: + mainObjectFileID: 9100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/Spine Examples/Scripts/AnimationStateMecanimState.cs b/spine-unity/Assets/Spine Examples/Scripts/AnimationStateMecanimState.cs new file mode 100644 index 000000000..46afe77f5 --- /dev/null +++ b/spine-unity/Assets/Spine Examples/Scripts/AnimationStateMecanimState.cs @@ -0,0 +1,62 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +using Spine; +using Spine.Unity; + +public class AnimationStateMecanimState : StateMachineBehaviour { + + #region Inspector + public AnimationReferenceAsset animation; + + [System.Serializable] + public struct AnimationTransition { + public AnimationReferenceAsset from; + public AnimationReferenceAsset transition; + } + + [UnityEngine.Serialization.FormerlySerializedAs("transitions")] + public List fromTransitions = new List(); + #endregion + + Spine.AnimationState state; + + public void Initialize (Animator animator) { + if (state == null) { + var animationStateComponent = (animator.GetComponent(typeof(IAnimationStateComponent))) as IAnimationStateComponent; + state = animationStateComponent.AnimationState; + } + } + + override public void OnStateEnter (Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { + if (state == null) { + Initialize(animator); + } + + float timeScale = stateInfo.speed; + var current = state.GetCurrent(layerIndex); + + bool transitionPlayed = false; + if (current != null && fromTransitions.Count > 0) { + foreach (var t in fromTransitions) { + if (t.from.Animation == current.Animation) { + var transitionEntry = state.SetAnimation(layerIndex, t.transition.Animation, false); + transitionEntry.TimeScale = timeScale; + transitionPlayed = true; + break; + } + } + } + + TrackEntry trackEntry; + if (transitionPlayed) { + trackEntry = state.AddAnimation(layerIndex, animation.Animation, stateInfo.loop, 0); + } else { + trackEntry = state.SetAnimation(layerIndex, animation.Animation, stateInfo.loop); + } + trackEntry.TimeScale = timeScale; + + } + +} diff --git a/spine-unity/Assets/Spine Examples/Scripts/AnimationStateMecanimState.cs.meta b/spine-unity/Assets/Spine Examples/Scripts/AnimationStateMecanimState.cs.meta new file mode 100644 index 000000000..b205d8341 --- /dev/null +++ b/spine-unity/Assets/Spine Examples/Scripts/AnimationStateMecanimState.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 536bdde8dc7bbb641b17da9221d6562f +timeCreated: 1531293563 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/Spine Examples/Scripts/AnimationStateWithMecanimExample.cs b/spine-unity/Assets/Spine Examples/Scripts/AnimationStateWithMecanimExample.cs new file mode 100644 index 000000000..9121fdeb8 --- /dev/null +++ b/spine-unity/Assets/Spine Examples/Scripts/AnimationStateWithMecanimExample.cs @@ -0,0 +1,82 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +using Spine; +using Spine.Unity; + +namespace Spine.Unity.Examples { + public class AnimationStateWithMecanimExample : MonoBehaviour { + + SkeletonAnimation skeletonAnimation; + Animator logicAnimator; + + [Header("Controls")] + public KeyCode walkButton = KeyCode.LeftShift; + public KeyCode jumpButton = KeyCode.Space; + + [Header("Animator Properties")] + public string horizontalSpeedProperty = "Speed"; + public string verticalSpeedProperty = "VerticalSpeed"; + public string groundedProperty = "Grounded"; + + [Header("Fake Physics")] + public float jumpDuration = 1.5f; + public Vector2 speed; + public bool isGrounded; + + void Awake () { + skeletonAnimation = GetComponent(); + logicAnimator = GetComponent(); + + isGrounded = true; + } + + void Update () { + float x = Input.GetAxisRaw("Horizontal"); + if (Input.GetKey(walkButton)) { + x *= 0.4f; + } + + speed.x = x; + + // Flip skeleton. + if (x != 0) { + skeletonAnimation.Skeleton.ScaleX = x > 0 ? 1f : -1f; + } + + if (Input.GetKeyDown(jumpButton)) { + if (isGrounded) + StartCoroutine(FakeJump()); + } + + logicAnimator.SetFloat(horizontalSpeedProperty, Mathf.Abs(speed.x)); + logicAnimator.SetFloat(verticalSpeedProperty, speed.y); + logicAnimator.SetBool(groundedProperty, isGrounded); + + } + + IEnumerator FakeJump () { + // Rise + isGrounded = false; + speed.y = 10f; + float durationLeft = jumpDuration * 0.5f; + while (durationLeft > 0) { + durationLeft -= Time.deltaTime; + if (!Input.GetKey(jumpButton)) break; + yield return null; + } + + // Fall + speed.y = -10f; + float fallDuration = (jumpDuration * 0.5f) - durationLeft; + yield return new WaitForSeconds(fallDuration); + + // Land + speed.y = 0f; + isGrounded = true; + yield return null; + } + } + +} diff --git a/spine-unity/Assets/Spine Examples/Scripts/AnimationStateWithMecanimExample.cs.meta b/spine-unity/Assets/Spine Examples/Scripts/AnimationStateWithMecanimExample.cs.meta new file mode 100644 index 000000000..6f5b125ab --- /dev/null +++ b/spine-unity/Assets/Spine Examples/Scripts/AnimationStateWithMecanimExample.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 782062825deffd64ba7e7e9f978788e5 +timeCreated: 1531300740 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/Spine Examples/Scripts/FootSoldierExample.cs b/spine-unity/Assets/Spine Examples/Scripts/FootSoldierExample.cs index 08cf1a6a7..971d96213 100644 --- a/spine-unity/Assets/Spine Examples/Scripts/FootSoldierExample.cs +++ b/spine-unity/Assets/Spine Examples/Scripts/FootSoldierExample.cs @@ -80,11 +80,11 @@ namespace Spine.Unity.Examples { } else { if (Input.GetKey(rightKey)) { skeletonAnimation.AnimationName = moveAnimation; - skeletonAnimation.Skeleton.FlipX = false; + skeletonAnimation.Skeleton.ScaleX = 1; transform.Translate(moveSpeed * Time.deltaTime, 0, 0); } else if(Input.GetKey(leftKey)) { skeletonAnimation.AnimationName = moveAnimation; - skeletonAnimation.Skeleton.FlipX = true; + skeletonAnimation.Skeleton.ScaleX = -1; transform.Translate(-moveSpeed * Time.deltaTime, 0, 0); } else { skeletonAnimation.AnimationName = idleAnimation; diff --git a/spine-unity/Assets/Spine Examples/Scripts/Getting Started Scripts/BasicPlatformerController.cs b/spine-unity/Assets/Spine Examples/Scripts/Getting Started Scripts/BasicPlatformerController.cs index 3166055a4..67f8a0dbf 100644 --- a/spine-unity/Assets/Spine Examples/Scripts/Getting Started Scripts/BasicPlatformerController.cs +++ b/spine-unity/Assets/Spine Examples/Scripts/Getting Started Scripts/BasicPlatformerController.cs @@ -183,7 +183,7 @@ namespace Spine.Unity.Examples { // Face intended direction. if (input.x != 0) - skeletonAnimation.Skeleton.FlipX = input.x < 0; + skeletonAnimation.Skeleton.ScaleX = Mathf.Sign(input.x); // Effects diff --git a/spine-unity/Assets/Spine Examples/Scripts/Getting Started Scripts/SpineBeginnerTwo.cs b/spine-unity/Assets/Spine Examples/Scripts/Getting Started Scripts/SpineBeginnerTwo.cs index 0de31c2f8..7a4b15015 100644 --- a/spine-unity/Assets/Spine Examples/Scripts/Getting Started Scripts/SpineBeginnerTwo.cs +++ b/spine-unity/Assets/Spine Examples/Scripts/Getting Started Scripts/SpineBeginnerTwo.cs @@ -93,11 +93,11 @@ namespace Spine.Unity.Examples { spineAnimationState.AddAnimation(0, idleAnimationName, true, 0); yield return new WaitForSeconds(1f); - skeleton.FlipX = true; // skeleton allows you to flip the skeleton. + skeleton.ScaleX = -1; // skeleton allows you to flip the skeleton. spineAnimationState.SetAnimation(0, idleTurnAnimationName, false); spineAnimationState.AddAnimation(0, idleAnimationName, true, 0); yield return new WaitForSeconds(0.5f); - skeleton.FlipX = false; + skeleton.ScaleX = 1; spineAnimationState.SetAnimation(0, idleTurnAnimationName, false); spineAnimationState.AddAnimation(0, idleAnimationName, true, 0); yield return new WaitForSeconds(0.5f); diff --git a/spine-unity/Assets/Spine Examples/Scripts/Getting Started Scripts/SpineboyBeginnerView.cs b/spine-unity/Assets/Spine Examples/Scripts/Getting Started Scripts/SpineboyBeginnerView.cs index 041725cbc..7e8b46353 100644 --- a/spine-unity/Assets/Spine Examples/Scripts/Getting Started Scripts/SpineboyBeginnerView.cs +++ b/spine-unity/Assets/Spine Examples/Scripts/Getting Started Scripts/SpineboyBeginnerView.cs @@ -69,7 +69,7 @@ namespace Spine.Unity.Examples { if (skeletonAnimation == null) return; if (model == null) return; - if (skeletonAnimation.skeleton.FlipX != model.facingLeft) { // Detect changes in model.facingLeft + if ((skeletonAnimation.skeleton.ScaleX < 0) != model.facingLeft) { // Detect changes in model.facingLeft Turn(model.facingLeft); } @@ -134,7 +134,7 @@ namespace Spine.Unity.Examples { } public void Turn (bool facingLeft) { - skeletonAnimation.Skeleton.FlipX = facingLeft; + skeletonAnimation.Skeleton.ScaleX = facingLeft ? -1f : 1f; // Maybe play a transient turning animation too, then call ChangeStableAnimation. } #endregion diff --git a/spine-unity/Assets/Spine Examples/Scripts/Getting Started Scripts/SpineboyTargetController.cs b/spine-unity/Assets/Spine Examples/Scripts/Getting Started Scripts/SpineboyTargetController.cs index 63242c16f..8e2871915 100644 --- a/spine-unity/Assets/Spine Examples/Scripts/Getting Started Scripts/SpineboyTargetController.cs +++ b/spine-unity/Assets/Spine Examples/Scripts/Getting Started Scripts/SpineboyTargetController.cs @@ -23,7 +23,7 @@ namespace Spine.Unity.Examples { var mousePosition = Input.mousePosition; var worldMousePosition = camera.ScreenToWorldPoint(mousePosition); var skeletonSpacePoint = skeletonAnimation.transform.InverseTransformPoint(worldMousePosition); - if (skeletonAnimation.Skeleton.FlipX) skeletonSpacePoint.x *= -1; + //if (skeletonAnimation.Skeleton.FlipX) skeletonSpacePoint.x *= -1; bone.SetPosition(skeletonSpacePoint); } } diff --git a/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonAnimationMulti/SkeletonAnimationMulti.cs b/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonAnimationMulti/SkeletonAnimationMulti.cs index d071f565c..dd0e80d8e 100644 --- a/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonAnimationMulti/SkeletonAnimationMulti.cs +++ b/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonAnimationMulti/SkeletonAnimationMulti.cs @@ -69,8 +69,8 @@ namespace Spine.Unity { sa.initialFlipX = this.initialFlipX; sa.initialFlipY = this.initialFlipY; var skeleton = sa.skeleton; - skeleton.FlipX = this.initialFlipX; - skeleton.FlipY = this.initialFlipY; + skeleton.ScaleX = this.initialFlipX ? 1 : -1; + skeleton.ScaleY = this.initialFlipY ? 1 : -1; sa.Initialize(false); skeletonAnimations.Add(sa); diff --git a/spine-unity/Assets/Spine Examples/Spine.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/dragon.atlas.txt b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.atlas.txt similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/dragon.atlas.txt rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.atlas.txt diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/dragon.atlas.txt.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.atlas.txt.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/dragon.atlas.txt.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.atlas.txt.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/dragon.json b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.json similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/dragon.json rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.json diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/dragon.json.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.json.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/dragon.json.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.json.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/dragon.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/dragon.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.png diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/dragon.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/dragon.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/dragon2.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon2.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/dragon2.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon2.png diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/dragon2.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon2.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/dragon2.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon2.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/dragon_Atlas.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_Atlas.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/dragon_Atlas.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_Atlas.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/dragon_Atlas.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_Atlas.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/dragon_Atlas.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_Atlas.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/dragon_SkeletonData.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_SkeletonData.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/dragon_SkeletonData.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_SkeletonData.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/dragon_SkeletonData.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_SkeletonData.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/dragon_SkeletonData.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_SkeletonData.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/dragon_dragon.mat b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon.mat similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/dragon_dragon.mat rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon.mat diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/dragon_dragon.mat.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon.mat.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/dragon_dragon.mat.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon.mat.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/dragon_dragon2.mat b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon2.mat similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/dragon_dragon2.mat rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon2.mat diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/dragon_dragon2.mat.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon2.mat.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/dragon_dragon2.mat.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/dragon_dragon2.mat.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/license.txt b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/license.txt similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/license.txt rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/license.txt diff --git a/spine-unity/Assets/Spine Examples/Spine/Dragon/license.txt.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/license.txt.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Dragon/license.txt.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Dragon/license.txt.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Eyes.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Eyes.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Eyes/eyes.atlas.txt b/spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes.atlas.txt similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Eyes/eyes.atlas.txt rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes.atlas.txt diff --git a/spine-unity/Assets/Spine Examples/Spine/Eyes/eyes.atlas.txt.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes.atlas.txt.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Eyes/eyes.atlas.txt.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes.atlas.txt.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Eyes/eyes.json b/spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes.json similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Eyes/eyes.json rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes.json diff --git a/spine-unity/Assets/Spine Examples/Spine/Eyes/eyes.json.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes.json.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Eyes/eyes.json.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes.json.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Eyes/eyes.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Eyes/eyes.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes.png diff --git a/spine-unity/Assets/Spine Examples/Spine/Eyes/eyes.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Eyes/eyes.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Eyes/eyes_Atlas.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes_Atlas.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Eyes/eyes_Atlas.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes_Atlas.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Eyes/eyes_Atlas.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes_Atlas.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Eyes/eyes_Atlas.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes_Atlas.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Eyes/eyes_Material.mat b/spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes_Material.mat similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Eyes/eyes_Material.mat rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes_Material.mat diff --git a/spine-unity/Assets/Spine Examples/Spine/Eyes/eyes_Material.mat.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes_Material.mat.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Eyes/eyes_Material.mat.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes_Material.mat.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Eyes/eyes_SkeletonData.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes_SkeletonData.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Eyes/eyes_SkeletonData.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes_SkeletonData.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Eyes/eyes_SkeletonData.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes_SkeletonData.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Eyes/eyes_SkeletonData.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Eyes/eyes_SkeletonData.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment/Equipment.atlas.txt b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment/Equipment.atlas.txt similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment/Equipment.atlas.txt rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment/Equipment.atlas.txt diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment/Equipment.atlas.txt.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment/Equipment.atlas.txt.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment/Equipment.atlas.txt.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment/Equipment.atlas.txt.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment/Equipment.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment/Equipment.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment/Equipment.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment/Equipment.png diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment/Equipment.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment/Equipment.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment/Equipment.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment/Equipment.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment/Equipment_Atlas.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment/Equipment_Atlas.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment/Equipment_Atlas.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment/Equipment_Atlas.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment/Equipment_Atlas.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment/Equipment_Atlas.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment/Equipment_Atlas.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment/Equipment_Atlas.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment/Equipment_Material.mat b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment/Equipment_Material.mat similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment/Equipment_Material.mat rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment/Equipment_Material.mat diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment/Equipment_Material.mat.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment/Equipment_Material.mat.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/Equipment/Equipment_Material.mat.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/Equipment/Equipment_Material.mat.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/FS_White.atlas.txt b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White.atlas.txt similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/FS_White.atlas.txt rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White.atlas.txt diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/FS_White.atlas.txt.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White.atlas.txt.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/FS_White.atlas.txt.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White.atlas.txt.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/FS_White.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/FS_White.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White.png diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/FS_White.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/FS_White.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/FS_White_Atlas.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White_Atlas.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/FS_White_Atlas.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White_Atlas.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/FS_White_Atlas.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White_Atlas.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/FS_White_Atlas.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White_Atlas.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/FS_White_Material.mat b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White_Material.mat similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/FS_White_Material.mat rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White_Material.mat diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/FS_White_Material.mat.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White_Material.mat.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/FS_White_Material.mat.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FS_White_Material.mat.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/FootSoldier.json b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FootSoldier.json similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/FootSoldier.json rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FootSoldier.json diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/FootSoldier.json.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FootSoldier.json.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/FootSoldier.json.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FootSoldier.json.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/FootSoldier_SkeletonData.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FootSoldier_SkeletonData.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/FootSoldier_SkeletonData.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FootSoldier_SkeletonData.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/FootSoldier_SkeletonData.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FootSoldier_SkeletonData.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/FootSoldier_SkeletonData.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/FootSoldier_SkeletonData.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/license.txt b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/license.txt similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/license.txt rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/license.txt diff --git a/spine-unity/Assets/Spine Examples/Spine/FootSoldier/license.txt.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/license.txt.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/FootSoldier/license.txt.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/FootSoldier/license.txt.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Gauge.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Gauge.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge.atlas.txt b/spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge.atlas.txt similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge.atlas.txt rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge.atlas.txt diff --git a/spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge.atlas.txt.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge.atlas.txt.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge.atlas.txt.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge.atlas.txt.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge.json b/spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge.json similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge.json rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge.json diff --git a/spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge.json.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge.json.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge.json.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge.json.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge.png diff --git a/spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge_Atlas.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge_Atlas.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge_Atlas.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge_Atlas.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge_Atlas.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge_Atlas.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge_Atlas.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge_Atlas.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge_Material.mat b/spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge_Material.mat similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge_Material.mat rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge_Material.mat diff --git a/spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge_Material.mat.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge_Material.mat.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge_Material.mat.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge_Material.mat.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge_SkeletonData.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge_SkeletonData.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge_SkeletonData.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge_SkeletonData.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge_SkeletonData.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge_SkeletonData.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Gauge/Gauge_SkeletonData.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/Gauge_SkeletonData.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Gauge/ReferenceAssets.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/ReferenceAssets.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Gauge/ReferenceAssets.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/ReferenceAssets.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Gauge/ReferenceAssets/Fill.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/ReferenceAssets/Fill.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Gauge/ReferenceAssets/Fill.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/ReferenceAssets/Fill.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Gauge/ReferenceAssets/Fill.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/ReferenceAssets/Fill.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Gauge/ReferenceAssets/Fill.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Gauge/ReferenceAssets/Fill.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Goblins.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Goblins.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Goblins/dagger.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/dagger.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Goblins/dagger.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/dagger.png diff --git a/spine-unity/Assets/Spine Examples/Spine/Goblins/dagger.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/dagger.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Goblins/dagger.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/dagger.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Goblins/goblins.atlas.txt b/spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins.atlas.txt similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Goblins/goblins.atlas.txt rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins.atlas.txt diff --git a/spine-unity/Assets/Spine Examples/Spine/Goblins/goblins.atlas.txt.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins.atlas.txt.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Goblins/goblins.atlas.txt.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins.atlas.txt.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Goblins/goblins.json b/spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins.json similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Goblins/goblins.json rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins.json diff --git a/spine-unity/Assets/Spine Examples/Spine/Goblins/goblins.json.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins.json.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Goblins/goblins.json.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins.json.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Goblins/goblins.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Goblins/goblins.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins.png diff --git a/spine-unity/Assets/Spine Examples/Spine/Goblins/goblins.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Goblins/goblins.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Goblins/goblins_Atlas.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins_Atlas.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Goblins/goblins_Atlas.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins_Atlas.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Goblins/goblins_Atlas.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins_Atlas.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Goblins/goblins_Atlas.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins_Atlas.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Goblins/goblins_Material.mat b/spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins_Material.mat similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Goblins/goblins_Material.mat rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins_Material.mat diff --git a/spine-unity/Assets/Spine Examples/Spine/Goblins/goblins_Material.mat.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins_Material.mat.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Goblins/goblins_Material.mat.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins_Material.mat.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Goblins/goblins_SkeletonData.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins_SkeletonData.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Goblins/goblins_SkeletonData.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins_SkeletonData.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Goblins/goblins_SkeletonData.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins_SkeletonData.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Goblins/goblins_SkeletonData.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Goblins/goblins_SkeletonData.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/attack.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/attack.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/attack.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/attack.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/attack.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/attack.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/attack.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/attack.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/crouch-from fall.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/crouch-from fall.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/crouch-from fall.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/crouch-from fall.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/crouch-from fall.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/crouch-from fall.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/crouch-from fall.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/crouch-from fall.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/crouch.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/crouch.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/crouch.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/crouch.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/crouch.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/crouch.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/crouch.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/crouch.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/fall.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/fall.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/fall.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/fall.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/fall.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/fall.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/fall.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/fall.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/head-turn.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/head-turn.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/head-turn.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/head-turn.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/head-turn.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/head-turn.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/head-turn.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/head-turn.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/idle-from fall.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/idle-from fall.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/idle-from fall.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/idle-from fall.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/idle-from fall.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/idle-from fall.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/idle-from fall.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/idle-from fall.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/idle.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/idle.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/idle.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/idle.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/idle.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/idle.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/idle.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/idle.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/jump.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/jump.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/jump.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/jump.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/jump.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/jump.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/jump.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/jump.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/run-from fall.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/run-from fall.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/run-from fall.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/run-from fall.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/run-from fall.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/run-from fall.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/run-from fall.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/run-from fall.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/run.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/run.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/run.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/run.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/run.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/run.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/run.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/run.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/walk.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/walk.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/walk.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/walk.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/walk.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/walk.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/ReferenceAssets/walk.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/ReferenceAssets/walk.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro.atlas.txt b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro.atlas.txt similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro.atlas.txt rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro.atlas.txt diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro.atlas.txt.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro.atlas.txt.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro.atlas.txt.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro.atlas.txt.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro.json b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro.json similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro.json rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro.json diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro.json.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro.json.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro.json.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro.json.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro.png diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro_Atlas.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro_Atlas.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro_Atlas.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro_Atlas.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro_Atlas.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro_Atlas.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro_Atlas.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro_Atlas.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro_Material.mat b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro_Material.mat similarity index 92% rename from spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro_Material.mat rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro_Material.mat index c0db3163e..993985b66 100644 Binary files a/spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro_Material.mat and b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro_Material.mat differ diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro_Material.mat.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro_Material.mat.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro_Material.mat.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro_Material.mat.meta diff --git a/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro_SkeletonData.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro_SkeletonData.asset new file mode 100644 index 000000000..68f84d5b1 Binary files /dev/null and b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro_SkeletonData.asset differ diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro_SkeletonData.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro_SkeletonData.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro_SkeletonData.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/hero-pro_SkeletonData.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/license.txt b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/license.txt similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/license.txt rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/license.txt diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/license.txt.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/license.txt.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Hero/license.txt.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Hero/license.txt.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.atlas.txt b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy.atlas.txt similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.atlas.txt rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy.atlas.txt diff --git a/spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.atlas.txt.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy.atlas.txt.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.atlas.txt.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy.atlas.txt.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy.png diff --git a/spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Atlas.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy_Atlas.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Atlas.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy_Atlas.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Atlas.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy_Atlas.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Atlas.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy_Atlas.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Material.mat b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy_Material.mat similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Material.mat rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy_Material.mat diff --git a/spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Material.mat.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy_Material.mat.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Material.mat.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy_Material.mat.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_SkeletonData.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy_SkeletonData.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_SkeletonData.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy_SkeletonData.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_SkeletonData.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy_SkeletonData.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_SkeletonData.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/Raggedy Spineboy_SkeletonData.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/raggedy spineboy.json b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/raggedy spineboy.json similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/raggedy spineboy.json rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/raggedy spineboy.json diff --git a/spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/raggedy spineboy.json.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/raggedy spineboy.json.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raggedy Spineboy/raggedy spineboy.json.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raggedy Spineboy/raggedy spineboy.json.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets/Jump.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets/Jump.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets/Jump.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets/Jump.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets/Jump.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets/Jump.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets/Jump.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets/Jump.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets/gungrab.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets/gungrab.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets/gungrab.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets/gungrab.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets/gungrab.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets/gungrab.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets/gungrab.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets/gungrab.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets/gunkeep.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets/gunkeep.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets/gunkeep.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets/gunkeep.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets/gunkeep.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets/gunkeep.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets/gunkeep.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets/gunkeep.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets/walk.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets/walk.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets/walk.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets/walk.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets/walk.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets/walk.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/ReferenceAssets/walk.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/ReferenceAssets/walk.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/raptor.atlas.txt b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor.atlas.txt similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/raptor.atlas.txt rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor.atlas.txt diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/raptor.atlas.txt.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor.atlas.txt.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/raptor.atlas.txt.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor.atlas.txt.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/raptor.json b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor.json similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/raptor.json rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor.json diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/raptor.json.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor.json.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/raptor.json.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor.json.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/raptor.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/raptor.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor.png diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/raptor.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/raptor.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/raptor_Atlas.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor_Atlas.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/raptor_Atlas.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor_Atlas.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/raptor_Atlas.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor_Atlas.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/raptor_Atlas.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor_Atlas.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/raptor_Material.mat b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor_Material.mat similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/raptor_Material.mat rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor_Material.mat diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/raptor_Material.mat.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor_Material.mat.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/raptor_Material.mat.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor_Material.mat.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/raptor_SkeletonData.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor_SkeletonData.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/raptor_SkeletonData.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor_SkeletonData.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Raptor/raptor_SkeletonData.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor_SkeletonData.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Raptor/raptor_SkeletonData.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Raptor/raptor_SkeletonData.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Runtime Template Material.mat b/spine-unity/Assets/Spine Examples/Spine Skeletons/Runtime Template Material.mat similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Runtime Template Material.mat rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Runtime Template Material.mat diff --git a/spine-unity/Assets/Spine Examples/Spine/Runtime Template Material.mat.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Runtime Template Material.mat.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Runtime Template Material.mat.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Runtime Template Material.mat.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi.atlas.txt b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi.atlas.txt similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi.atlas.txt rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi.atlas.txt diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi.atlas.txt.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi.atlas.txt.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi.atlas.txt.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi.atlas.txt.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi.json b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi.json similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi.json rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi.json diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi.json.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi.json.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi.json.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi.json.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi.png diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi_Atlas.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi_Atlas.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi_Atlas.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi_Atlas.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi_Atlas.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi_Atlas.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi_Atlas.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi_Atlas.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi_Material.mat b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi_Material.mat similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi_Material.mat rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi_Material.mat diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi_Material.mat.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi_Material.mat.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi_Material.mat.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi_Material.mat.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi_SkeletonData.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi_SkeletonData.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi_SkeletonData.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi_SkeletonData.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi_SkeletonData.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi_SkeletonData.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/Doi_SkeletonData.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/Doi_SkeletonData.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/ReferenceAssets.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/ReferenceAssets.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/ReferenceAssets.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/ReferenceAssets.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/ReferenceAssets/blink.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/ReferenceAssets/blink.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/ReferenceAssets/blink.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/ReferenceAssets/blink.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/ReferenceAssets/blink.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/ReferenceAssets/blink.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/ReferenceAssets/blink.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/ReferenceAssets/blink.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/ReferenceAssets/main.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/ReferenceAssets/main.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/ReferenceAssets/main.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/ReferenceAssets/main.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/ReferenceAssets/main.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/ReferenceAssets/main.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Spineunitygirl/ReferenceAssets/main.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Spineunitygirl/ReferenceAssets/main.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Strechyman.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Strechyman.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-diffuse-pma.atlas.txt b/spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-diffuse-pma.atlas.txt similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-diffuse-pma.atlas.txt rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-diffuse-pma.atlas.txt diff --git a/spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-diffuse-pma.atlas.txt.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-diffuse-pma.atlas.txt.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-diffuse-pma.atlas.txt.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-diffuse-pma.atlas.txt.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-diffuse-pma.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-diffuse-pma.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-diffuse-pma.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-diffuse-pma.png diff --git a/spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-diffuse-pma.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-diffuse-pma.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-diffuse-pma.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-diffuse-pma.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-diffuse-pma_Atlas.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-diffuse-pma_Atlas.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-diffuse-pma_Atlas.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-diffuse-pma_Atlas.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-diffuse-pma_Atlas.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-diffuse-pma_Atlas.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-diffuse-pma_Atlas.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-diffuse-pma_Atlas.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-diffuse-pma_Material.mat b/spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-diffuse-pma_Material.mat similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-diffuse-pma_Material.mat rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-diffuse-pma_Material.mat diff --git a/spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-diffuse-pma_Material.mat.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-diffuse-pma_Material.mat.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-diffuse-pma_Material.mat.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-diffuse-pma_Material.mat.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-emission.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-emission.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-emission.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-emission.png diff --git a/spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-emission.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-emission.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-emission.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-emission.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-normals.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-normals.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-normals.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-normals.png diff --git a/spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-normals.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-normals.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman-normals.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman-normals.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman.json b/spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman.json similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman.json rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman.json diff --git a/spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman.json.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman.json.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman.json.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman.json.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman_SkeletonData.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman_SkeletonData.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman_SkeletonData.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman_SkeletonData.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman_SkeletonData.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman_SkeletonData.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/Strechyman/stretchyman_SkeletonData.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/Strechyman/stretchyman_SkeletonData.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-pro.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-pro.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro.atlas.txt b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro.atlas.txt similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro.atlas.txt rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro.atlas.txt diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro.atlas.txt.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro.atlas.txt.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro.atlas.txt.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro.atlas.txt.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro.json b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro.json similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro.json rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro.json diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro.json.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro.json.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro.json.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro.json.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro.png diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro_Atlas.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro_Atlas.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro_Atlas.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro_Atlas.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro_Atlas.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro_Atlas.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro_Atlas.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro_Atlas.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro_Material.mat b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro_Material.mat similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro_Material.mat rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro_Material.mat diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro_Material.mat.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro_Material.mat.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro_Material.mat.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro_Material.mat.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro_SkeletonData.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro_SkeletonData.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro_SkeletonData.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro_SkeletonData.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro_SkeletonData.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro_SkeletonData.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-pro/spineboy-pro_SkeletonData.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-pro/spineboy-pro_SkeletonData.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips/goggles-normal.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips/goggles-normal.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips/goggles-normal.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips/goggles-normal.png diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips/goggles-normal.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips/goggles-normal.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips/goggles-normal.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips/goggles-normal.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips/goggles-tactical.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips/goggles-tactical.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips/goggles-tactical.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips/goggles-tactical.png diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips/goggles-tactical.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips/goggles-tactical.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips/goggles-tactical.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips/goggles-tactical.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips/gun-freeze.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips/gun-freeze.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips/gun-freeze.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips/gun-freeze.png diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips/gun-freeze.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips/gun-freeze.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips/gun-freeze.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips/gun-freeze.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips/gun-normal.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips/gun-normal.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips/gun-normal.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips/gun-normal.png diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips/gun-normal.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips/gun-normal.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/Equips/gun-normal.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/Equips/gun-normal.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/death.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/death.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/death.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/death.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/death.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/death.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/death.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/death.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/diagonal.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/diagonal.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/diagonal.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/diagonal.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/diagonal.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/diagonal.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/diagonal.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/diagonal.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/footstep.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/footstep.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/footstep.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/footstep.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/footstep.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/footstep.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/footstep.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/footstep.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/frozen.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/frozen.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/frozen.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/frozen.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/frozen.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/frozen.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/frozen.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/frozen.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/gun toss.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/gun toss.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/gun toss.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/gun toss.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/gun toss.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/gun toss.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/gun toss.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/gun toss.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/hit old.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/hit old.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/hit old.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/hit old.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/hit old.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/hit old.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/hit old.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/hit old.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/hit.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/hit.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/hit.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/hit.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/hit.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/hit.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/hit.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/hit.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/idle.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/idle.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/idle.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/idle.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/idle.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/idle.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/idle.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/idle.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/idlebag.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/idlebag.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/idlebag.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/idlebag.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/idlebag.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/idlebag.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/idlebag.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/idlebag.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/jump old.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/jump old.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/jump old.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/jump old.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/jump old.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/jump old.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/jump old.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/jump old.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/jump rm.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/jump rm.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/jump rm.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/jump rm.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/jump rm.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/jump rm.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/jump rm.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/jump rm.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/jump.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/jump.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/jump.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/jump.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/jump.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/jump.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/jump.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/jump.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/pole.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/pole.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/pole.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/pole.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/pole.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/pole.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/pole.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/pole.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/run rm.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/run rm.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/run rm.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/run rm.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/run rm.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/run rm.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/run rm.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/run rm.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/run.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/run.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/run.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/run.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/run.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/run.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/run.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/run.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/shoot.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/shoot.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/shoot.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/shoot.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/shoot.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/shoot.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/shoot.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/shoot.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/walk rm.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/walk rm.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/walk rm.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/walk rm.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/walk rm.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/walk rm.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/walk rm.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/walk rm.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/walk.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/walk.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/walk.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/walk.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/walk.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/walk.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/ReferenceAssets/walk.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/ReferenceAssets/walk.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy-unity.json b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy-unity.json similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy-unity.json rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy-unity.json diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy-unity.json.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy-unity.json.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy-unity.json.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy-unity.json.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy-unity_SkeletonData.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy-unity_SkeletonData.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy-unity_SkeletonData.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy-unity_SkeletonData.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy-unity_SkeletonData.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy-unity_SkeletonData.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy-unity_SkeletonData.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy-unity_SkeletonData.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy.atlas.txt b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy.atlas.txt similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy.atlas.txt rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy.atlas.txt diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy.atlas.txt.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy.atlas.txt.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy.atlas.txt.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy.atlas.txt.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy.png diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy_Atlas.asset b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy_Atlas.asset similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy_Atlas.asset rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy_Atlas.asset diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy_Atlas.asset.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy_Atlas.asset.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy_Atlas.asset.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy_Atlas.asset.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy_Material Fill.mat b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy_Material Fill.mat similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy_Material Fill.mat rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy_Material Fill.mat diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy_Material Fill.mat.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy_Material Fill.mat.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy_Material Fill.mat.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy_Material Fill.mat.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy_Material.mat b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy_Material.mat similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy_Material.mat rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy_Material.mat diff --git a/spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy_Material.mat.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy_Material.mat.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/spineboy-unity/spineboy_Material.mat.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/spineboy-unity/spineboy_Material.mat.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/square32.png b/spine-unity/Assets/Spine Examples/Spine Skeletons/square32.png similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/square32.png rename to spine-unity/Assets/Spine Examples/Spine Skeletons/square32.png diff --git a/spine-unity/Assets/Spine Examples/Spine/square32.png.meta b/spine-unity/Assets/Spine Examples/Spine Skeletons/square32.png.meta similarity index 100% rename from spine-unity/Assets/Spine Examples/Spine/square32.png.meta rename to spine-unity/Assets/Spine Examples/Spine Skeletons/square32.png.meta diff --git a/spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro_SkeletonData.asset b/spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro_SkeletonData.asset deleted file mode 100644 index 965ca4cb6..000000000 --- a/spine-unity/Assets/Spine Examples/Spine/Hero/hero-pro_SkeletonData.asset +++ /dev/null @@ -1,34 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: f1b3b4b945939a54ea0b23d3396115fb, type: 3} - m_Name: hero-pro_SkeletonData - m_EditorClassIdentifier: - atlasAssets: - - {fileID: 11400000, guid: 8384ab388a4037649a1f64fb2e1a8e7f, type: 2} - scale: 0.01 - skeletonJSON: {fileID: 4900000, guid: 33cbc24302a26c1438b20d9253eee469, type: 3} - fromAnimation: - - fall - - run-from fall - - fall - - idle - toAnimation: - - run-from fall - - run - - crouch - - crouch - duration: - - 0.05 - - 0 - - 0 - - 0 - defaultMix: 0.1 - controller: {fileID: 0} diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/AnimationReferenceAssetEditor.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/AnimationReferenceAssetEditor.cs index 596efbb42..15991bbcb 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/AnimationReferenceAssetEditor.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/AnimationReferenceAssetEditor.cs @@ -111,7 +111,7 @@ namespace Spine.Unity.Editor { EditorGUILayout.HelpBox(string.Format("Animation named {0} was not found for this Skeleton.", animationNameProperty.stringValue), MessageType.Warning); } else { using (new SpineInspectorUtility.BoxScope()) { - if (!string.Equals(SpineEditorUtilities.GetPathSafeName(animationName), ThisAnimationReferenceAsset.name, System.StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(SpineEditorUtilities.AssetUtility.GetPathSafeName(animationName), ThisAnimationReferenceAsset.name, System.StringComparison.OrdinalIgnoreCase)) EditorGUILayout.HelpBox("Animation name value does not match this asset's name. Inspectors using this asset may be misleading.", MessageType.None); EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(animationName, SpineEditorUtilities.Icons.animation)); diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonBaker.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonBaker.cs index 286149297..bbed3b657 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonBaker.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonBaker.cs @@ -30,7 +30,7 @@ // Contributed by: Mitch Thompson -#define SPINE_SKELETON_ANIMATOR +#define SPINE_SKELETONMECANIM using UnityEngine; using UnityEditor; @@ -71,7 +71,14 @@ namespace Spine.Unity.Editor { public static class SkeletonBaker { #region SkeletonAnimator's Mecanim Clips - #if SPINE_SKELETON_ANIMATOR + #if SPINE_SKELETONMECANIM + public static void UpdateMecanimClips (SkeletonDataAsset skeletonDataAsset) { + if (skeletonDataAsset.controller == null) + return; + + SkeletonBaker.GenerateMecanimAnimationClips(skeletonDataAsset); + } + public static void GenerateMecanimAnimationClips (SkeletonDataAsset skeletonDataAsset) { var data = skeletonDataAsset.GetSkeletonData(true); if (data == null) { @@ -80,7 +87,7 @@ namespace Spine.Unity.Editor { } string dataPath = AssetDatabase.GetAssetPath(skeletonDataAsset); - string controllerPath = dataPath.Replace(SpineEditorUtilities.SkeletonDataSuffix, "_Controller").Replace(".asset", ".controller"); + string controllerPath = dataPath.Replace(SpineEditorUtilities.AssetUtility.SkeletonDataSuffix, "_Controller").Replace(".asset", ".controller"); UnityEditor.Animations.AnimatorController controller; if (skeletonDataAsset.controller != null) { controller = (UnityEditor.Animations.AnimatorController)skeletonDataAsset.controller; @@ -1406,6 +1413,53 @@ namespace Spine.Unity.Editor { #endregion #endregion + #region Region Baking + public static GameObject BakeRegion (SpineAtlasAsset atlasAsset, AtlasRegion region, bool autoSave = true) { + atlasAsset.GetAtlas(); // Initializes atlasAsset. + + string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset); + string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath); + string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name); + string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.AssetUtility.GetPathSafeName(region.name) + ".prefab").Replace("\\", "/"); + + GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject)); + GameObject root; + Mesh mesh; + bool isNewPrefab = false; + + if (!Directory.Exists(bakedDirPath)) + Directory.CreateDirectory(bakedDirPath); + + if (prefab == null) { + root = new GameObject("temp", typeof(MeshFilter), typeof(MeshRenderer)); + prefab = PrefabUtility.CreatePrefab(bakedPrefabPath, root); + isNewPrefab = true; + Object.DestroyImmediate(root); + } + + mesh = (Mesh)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(Mesh)); + + Material mat = null; + mesh = atlasAsset.GenerateMesh(region.name, mesh, out mat); + if (isNewPrefab) { + AssetDatabase.AddObjectToAsset(mesh, prefab); + prefab.GetComponent().sharedMesh = mesh; + } + + EditorUtility.SetDirty(mesh); + EditorUtility.SetDirty(prefab); + + if (autoSave) { + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + } + + prefab.GetComponent().sharedMaterial = mat; + + return prefab; + } + #endregion + static string GetPath (BoneData b) { return GetPathRecurse(b).Substring(1); } diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDataAssetInspector.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDataAssetInspector.cs index 693aa25d6..d27348f48 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDataAssetInspector.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDataAssetInspector.cs @@ -28,7 +28,7 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -#define SPINE_SKELETON_ANIMATOR +#define SPINE_SKELETON_MECANIM using System; using System.Reflection; @@ -55,7 +55,7 @@ namespace Spine.Unity.Editor { SerializedProperty spriteCollection; #endif - #if SPINE_SKELETON_ANIMATOR + #if SPINE_SKELETON_MECANIM static bool isMecanimExpanded = false; SerializedProperty controller; #endif @@ -100,7 +100,7 @@ namespace Spine.Unity.Editor { duration = serializedObject.FindProperty("duration"); defaultMix = serializedObject.FindProperty("defaultMix"); - #if SPINE_SKELETON_ANIMATOR + #if SPINE_SKELETON_MECANIM controller = serializedObject.FindProperty("controller"); #endif @@ -238,7 +238,7 @@ namespace Spine.Unity.Editor { FieldInfo nameField = typeof(AnimationReferenceAsset).GetField("animationName", BindingFlags.NonPublic | BindingFlags.Instance); FieldInfo skeletonDataAssetField = typeof(AnimationReferenceAsset).GetField("skeletonDataAsset", BindingFlags.NonPublic | BindingFlags.Instance); foreach (var animation in targetSkeletonData.Animations) { - string assetPath = string.Format("{0}/{1}.asset", dataPath, SpineEditorUtilities.GetPathSafeName(animation.Name)); + string assetPath = string.Format("{0}/{1}.asset", dataPath, SpineEditorUtilities.AssetUtility.GetPathSafeName(animation.Name)); AnimationReferenceAsset existingAsset = AssetDatabase.LoadAssetAtPath(assetPath); if (existingAsset == null) { AnimationReferenceAsset newAsset = ScriptableObject.CreateInstance(); @@ -494,7 +494,7 @@ namespace Spine.Unity.Editor { } void DrawUnityTools () { - #if SPINE_SKELETON_ANIMATOR + #if SPINE_SKELETON_MECANIM using (new SpineInspectorUtility.BoxScope()) { isMecanimExpanded = EditorGUILayout.Foldout(isMecanimExpanded, SpineInspectorUtility.TempContent("SkeletonAnimator", SpineInspectorUtility.UnityIcon())); if (isMecanimExpanded) { @@ -538,8 +538,8 @@ namespace Spine.Unity.Editor { warnings.Add("Missing Skeleton JSON"); } else { var fieldValue = (TextAsset)skeletonJSON.objectReferenceValue; - if (!SpineEditorUtilities.SkeletonDataFileValidator.IsSpineData(fieldValue)) { - warnings.Add("Skeleton data file is not a valid JSON or binary file."); + if (!SpineEditorUtilities.AssetUtility.IsSpineData(fieldValue)) { + warnings.Add("Skeleton data file is not a valid Spine JSON or binary file."); } else { #if SPINE_TK2D bool searchForSpineAtlasAssets = true; @@ -569,7 +569,7 @@ namespace Spine.Unity.Editor { } else { List missingPaths = null; if (atlasAssets.arraySize > 0) { - missingPaths = SpineEditorUtilities.GetRequiredAtlasRegions(AssetDatabase.GetAssetPath(skeletonJSON.objectReferenceValue)); + missingPaths = SpineEditorUtilities.AssetUtility.GetRequiredAtlasRegions(AssetDatabase.GetAssetPath(skeletonJSON.objectReferenceValue)); foreach (var atlas in atlasList) { for (int i = 0; i < missingPaths.Count; i++) { @@ -587,8 +587,8 @@ namespace Spine.Unity.Editor { } if (missingPaths != null) { - foreach (string str in missingPaths) - warnings.Add("Missing Region: '" + str + "'"); + foreach (string missingRegion in missingPaths) + warnings.Add(string.Format("Missing Region: '{0}'", missingRegion)); } } @@ -599,7 +599,7 @@ namespace Spine.Unity.Editor { } void DoReimport () { - SpineEditorUtilities.ImportSpineContent(new [] { AssetDatabase.GetAssetPath(skeletonJSON.objectReferenceValue) }, true); + SpineEditorUtilities.AssetUtility.ImportSpineContent(new [] { AssetDatabase.GetAssetPath(skeletonJSON.objectReferenceValue) }, true); preview.Clear(); InitializeEditor(); EditorUtility.SetDirty(targetSkeletonDataAsset); @@ -769,7 +769,7 @@ namespace Spine.Unity.Editor { if (previewGameObject == null) { try { - previewGameObject = SpineEditorUtilities.InstantiateSkeletonAnimation(skeletonDataAsset, skinName).gameObject; + previewGameObject = SpineEditorUtilities.EditorInstantiation.InstantiateSkeletonAnimation(skeletonDataAsset, skinName).gameObject; if (previewGameObject != null) { previewGameObject.hideFlags = HideFlags.HideAndDontSave; diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDebugWindow.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDebugWindow.cs index cee6ecf9f..9373f93ad 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDebugWindow.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDebugWindow.cs @@ -229,9 +229,9 @@ namespace Spine.Unity.Editor { // Flip EditorGUILayout.BeginHorizontal(GUILayout.MaxWidth(160f)); - EditorGUILayout.LabelField("Flip", GUILayout.MaxWidth(EditorGUIUtility.labelWidth - 20f)); - skeleton.FlipX = EditorGUILayout.ToggleLeft(".FlipX", skeleton.FlipX, GUILayout.MaxWidth(70f)); - skeleton.FlipY = EditorGUILayout.ToggleLeft(".FlipY", skeleton.FlipY, GUILayout.MaxWidth(70f)); + EditorGUILayout.LabelField("Scale", GUILayout.MaxWidth(EditorGUIUtility.labelWidth - 20f)); + skeleton.ScaleX = EditorGUILayout.DelayedFloatField(".ScaleX", skeleton.ScaleX, GUILayout.MaxWidth(70f)); + skeleton.ScaleY = EditorGUILayout.DelayedFloatField(".ScaleY", skeleton.ScaleY, GUILayout.MaxWidth(70f)); GUILayout.EndHorizontal(); // Color diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineAtlasAssetInspector.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineAtlasAssetInspector.cs index 798392f86..de693f737 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineAtlasAssetInspector.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineAtlasAssetInspector.cs @@ -93,7 +93,7 @@ namespace Spine.Unity.Editor { string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name); for (int i = 0; i < regions.Count; i++) { AtlasRegion region = regions[i]; - string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(region) + ".prefab").Replace("\\", "/"); + string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.AssetUtility.GetPathSafeRegionName(region) + ".prefab").Replace("\\", "/"); GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject)); baked.Add(prefab != null); bakedObjects.Add(prefab); @@ -134,12 +134,12 @@ namespace Spine.Unity.Editor { } EditorGUILayout.Space(); - if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Set Mipmap Bias to " + SpineEditorUtilities.DEFAULT_MIPMAPBIAS))) { + if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Set Mipmap Bias to " + SpineEditorUtilities.Preferences.DEFAULT_MIPMAPBIAS))) { foreach (var m in atlasAsset.materials) { var texture = m.mainTexture; - texture.mipMapBias = SpineEditorUtilities.DEFAULT_MIPMAPBIAS; + texture.mipMapBias = SpineEditorUtilities.Preferences.DEFAULT_MIPMAPBIAS; } - Debug.Log("Texture mipmap bias set to " + SpineEditorUtilities.DEFAULT_MIPMAPBIAS); + Debug.Log("Texture mipmap bias set to " + SpineEditorUtilities.Preferences.DEFAULT_MIPMAPBIAS); } EditorGUILayout.Space(); @@ -285,7 +285,16 @@ namespace Spine.Unity.Editor { } } - EditorGUILayout.LabelField(new GUIContent(regions[i].name, SpineEditorUtilities.Icons.image)); + string regionName = regions[i].name; + Texture2D icon = SpineEditorUtilities.Icons.image; + if (regionName.EndsWith(" ")) { + regionName = string.Format("'{0}'", regions[i].name); + icon = SpineEditorUtilities.Icons.warning; + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(regionName, icon, "Region name ends with whitespace. This may cause errors. Please check your source image filenames.")); + } else { + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(regionName, icon)); + } + } EditorGUI.indentLevel = baseIndent; } diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs index 66804c332..d7ab79121 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs @@ -157,65 +157,27 @@ namespace Spine.Unity.Editor { public static string editorGUIPath = ""; public static bool initialized; - /// HACK: This list keeps the asset reference temporarily during importing. - /// - /// In cases of very large projects/sufficient RAM pressure, when AssetDatabase.SaveAssets is called, - /// Unity can mistakenly unload assets whose references are only on the stack. - /// This leads to MissingReferenceException and other errors. - static readonly List protectFromStackGarbageCollection = new List(); - static HashSet assetsImportedInWrongState = new HashSet(); + // Preferences entry point + [PreferenceItem("Spine")] + static void PreferencesGUI () { + Preferences.HandlePreferencesGUI(); + } - #if SPINE_TK2D - const float DEFAULT_DEFAULT_SCALE = 1f; - #else - const float DEFAULT_DEFAULT_SCALE = 0.01f; - #endif - const string DEFAULT_SCALE_KEY = "SPINE_DEFAULT_SCALE"; - public static float defaultScale = DEFAULT_DEFAULT_SCALE; + // Auto-import entry point + static void OnPostprocessAllAssets (string[] imported, string[] deleted, string[] moved, string[] movedFromAssetPaths) { + if (imported.Length == 0) + return; - const float DEFAULT_DEFAULT_MIX = 0.2f; - const string DEFAULT_MIX_KEY = "SPINE_DEFAULT_MIX"; - public static float defaultMix = DEFAULT_DEFAULT_MIX; - - const string DEFAULT_DEFAULT_SHADER = "Spine/Skeleton"; - const string DEFAULT_SHADER_KEY = "SPINE_DEFAULT_SHADER"; - public static string defaultShader = DEFAULT_DEFAULT_SHADER; - - const float DEFAULT_DEFAULT_ZSPACING = 0f; - const string DEFAULT_ZSPACING_KEY = "SPINE_DEFAULT_ZSPACING"; - public static float defaultZSpacing = DEFAULT_DEFAULT_ZSPACING; - - const bool DEFAULT_SHOW_HIERARCHY_ICONS = true; - const string SHOW_HIERARCHY_ICONS_KEY = "SPINE_SHOW_HIERARCHY_ICONS"; - public static bool showHierarchyIcons = DEFAULT_SHOW_HIERARCHY_ICONS; - - const bool DEFAULT_SET_TEXTUREIMPORTER_SETTINGS = true; - const string SET_TEXTUREIMPORTER_SETTINGS_KEY = "SPINE_SET_TEXTUREIMPORTER_SETTINGS"; - public static bool setTextureImporterSettings = DEFAULT_SET_TEXTUREIMPORTER_SETTINGS; - - internal const float DEFAULT_MIPMAPBIAS = -0.5f; - - public const float DEFAULT_SCENE_ICONS_SCALE = 1f; - public const string SCENE_ICONS_SCALE_KEY = "SPINE_SCENE_ICONS_SCALE"; + AssetUtility.HandleOnPostprocessAllAssets(imported); + } #region Initialization static SpineEditorUtilities () { Initialize(); } - static void LoadPreferences () { - defaultMix = EditorPrefs.GetFloat(DEFAULT_MIX_KEY, DEFAULT_DEFAULT_MIX); - defaultScale = EditorPrefs.GetFloat(DEFAULT_SCALE_KEY, DEFAULT_DEFAULT_SCALE); - defaultZSpacing = EditorPrefs.GetFloat(DEFAULT_ZSPACING_KEY, DEFAULT_DEFAULT_ZSPACING); - defaultShader = EditorPrefs.GetString(DEFAULT_SHADER_KEY, DEFAULT_DEFAULT_SHADER); - showHierarchyIcons = EditorPrefs.GetBool(SHOW_HIERARCHY_ICONS_KEY, DEFAULT_SHOW_HIERARCHY_ICONS); - setTextureImporterSettings = EditorPrefs.GetBool(SET_TEXTUREIMPORTER_SETTINGS_KEY, DEFAULT_SET_TEXTUREIMPORTER_SETTINGS); - SpineHandles.handleScale = EditorPrefs.GetFloat(SCENE_ICONS_SCALE_KEY, DEFAULT_SCENE_ICONS_SCALE); - preferencesLoaded = true; - } - static void Initialize () { - LoadPreferences(); + Preferences.Load(); DirectoryInfo rootDir = new DirectoryInfo(Application.dataPath); FileInfo[] files = rootDir.GetFiles("SpineEditorUtilities.cs", SearchOption.AllDirectories); @@ -225,20 +187,21 @@ namespace Spine.Unity.Editor { Icons.Initialize(); // Drag and Drop - SceneView.onSceneGUIDelegate -= SceneViewDragAndDrop; - SceneView.onSceneGUIDelegate += SceneViewDragAndDrop; - EditorApplication.hierarchyWindowItemOnGUI -= SpineEditorHierarchyHandler.HierarchyDragAndDrop; - EditorApplication.hierarchyWindowItemOnGUI += SpineEditorHierarchyHandler.HierarchyDragAndDrop; + SceneView.onSceneGUIDelegate -= DragAndDropInstantiation.SceneViewDragAndDrop; + SceneView.onSceneGUIDelegate += DragAndDropInstantiation.SceneViewDragAndDrop; + + EditorApplication.hierarchyWindowItemOnGUI -= HierarchyHandler.HandleDragAndDrop; + EditorApplication.hierarchyWindowItemOnGUI += HierarchyHandler.HandleDragAndDrop; // Hierarchy Icons #if UNITY_2017_2_OR_NEWER - EditorApplication.playModeStateChanged -= SpineEditorHierarchyHandler.HierarchyIconsOnPlaymodeStateChanged; - EditorApplication.playModeStateChanged += SpineEditorHierarchyHandler.HierarchyIconsOnPlaymodeStateChanged; - SpineEditorHierarchyHandler.HierarchyIconsOnPlaymodeStateChanged(PlayModeStateChange.EnteredEditMode); + EditorApplication.playModeStateChanged -= HierarchyHandler.IconsOnPlaymodeStateChanged; + EditorApplication.playModeStateChanged += HierarchyHandler.IconsOnPlaymodeStateChanged; + HierarchyHandler.IconsOnPlaymodeStateChanged(PlayModeStateChange.EnteredEditMode); #else - EditorApplication.playmodeStateChanged -= SpineEditorHierarchyHandler.HierarchyIconsOnPlaymodeStateChanged; - EditorApplication.playmodeStateChanged += SpineEditorHierarchyHandler.HierarchyIconsOnPlaymodeStateChanged; - SpineEditorHierarchyHandler.HierarchyIconsOnPlaymodeStateChanged(); + EditorApplication.playmodeStateChanged -= HierarchyHandler.IconsOnPlaymodeStateChanged; + EditorApplication.playmodeStateChanged += HierarchyHandler.IconsOnPlaymodeStateChanged; + HierarchyHandler.IconsOnPlaymodeStateChanged(); #endif initialized = true; @@ -250,1018 +213,618 @@ namespace Spine.Unity.Editor { } #endregion - #region Spine Preferences and Defaults - static bool preferencesLoaded = false; - - [PreferenceItem("Spine")] - static void PreferencesGUI () { - if (!preferencesLoaded) - LoadPreferences(); - - EditorGUI.BeginChangeCheck(); - showHierarchyIcons = EditorGUILayout.Toggle(new GUIContent("Show Hierarchy Icons", "Show relevant icons on GameObjects with Spine Components on them. Disable this if you have large, complex scenes."), showHierarchyIcons); - if (EditorGUI.EndChangeCheck()) { - EditorPrefs.SetBool(SHOW_HIERARCHY_ICONS_KEY, showHierarchyIcons); - #if UNITY_2017_2_OR_NEWER - SpineEditorHierarchyHandler.HierarchyIconsOnPlaymodeStateChanged(PlayModeStateChange.EnteredEditMode); - #else - SpineEditorHierarchyHandler.HierarchyIconsOnPlaymodeStateChanged(); - #endif - } - - EditorGUILayout.Separator(); - - EditorGUILayout.LabelField("Auto-Import Settings", EditorStyles.boldLabel); - - EditorGUI.BeginChangeCheck(); - defaultMix = EditorGUILayout.FloatField("Default Mix", defaultMix); - if (EditorGUI.EndChangeCheck()) - EditorPrefs.SetFloat(DEFAULT_MIX_KEY, defaultMix); - - EditorGUI.BeginChangeCheck(); - defaultScale = EditorGUILayout.FloatField("Default SkeletonData Scale", defaultScale); - if (EditorGUI.EndChangeCheck()) - EditorPrefs.SetFloat(DEFAULT_SCALE_KEY, defaultScale); - - EditorGUI.BeginChangeCheck(); - var shader = (EditorGUILayout.ObjectField("Default Shader", Shader.Find(defaultShader), typeof(Shader), false) as Shader); - defaultShader = shader != null ? shader.name : DEFAULT_DEFAULT_SHADER; - if (EditorGUI.EndChangeCheck()) - EditorPrefs.SetString(DEFAULT_SHADER_KEY, defaultShader); - - EditorGUI.BeginChangeCheck(); - setTextureImporterSettings = EditorGUILayout.Toggle(new GUIContent("Apply Atlas Texture Settings", "Apply the recommended settings for Texture Importers."), showHierarchyIcons); - if (EditorGUI.EndChangeCheck()) { - EditorPrefs.SetBool(SET_TEXTUREIMPORTER_SETTINGS_KEY, showHierarchyIcons); - } - - EditorGUILayout.Space(); - - EditorGUILayout.LabelField("Editor Instantiation", EditorStyles.boldLabel); - EditorGUI.BeginChangeCheck(); - defaultZSpacing = EditorGUILayout.Slider("Default Slot Z-Spacing", defaultZSpacing, -0.1f, 0f); - if (EditorGUI.EndChangeCheck()) - EditorPrefs.SetFloat(DEFAULT_ZSPACING_KEY, defaultZSpacing); - - - EditorGUILayout.Space(); - EditorGUILayout.LabelField("Handles and Gizmos", EditorStyles.boldLabel); - EditorGUI.BeginChangeCheck(); - SpineHandles.handleScale = EditorGUILayout.Slider("Editor Bone Scale", SpineHandles.handleScale, 0.01f, 2f); - SpineHandles.handleScale = Mathf.Max(0.01f, SpineHandles.handleScale); - if (EditorGUI.EndChangeCheck()) { - EditorPrefs.SetFloat(SCENE_ICONS_SCALE_KEY, SpineHandles.handleScale); - SceneView.RepaintAll(); - } - - - GUILayout.Space(20); - EditorGUILayout.LabelField("3rd Party Settings", EditorStyles.boldLabel); - using (new GUILayout.HorizontalScope()) { - EditorGUILayout.PrefixLabel("Define TK2D"); - if (GUILayout.Button("Enable", GUILayout.Width(64))) - SpineTK2DEditorUtility.EnableTK2D(); - if (GUILayout.Button("Disable", GUILayout.Width(64))) - SpineTK2DEditorUtility.DisableTK2D(); - } - } - #endregion - - #region Drag and Drop Instantiation - public delegate Component InstantiateDelegate (SkeletonDataAsset skeletonDataAsset); - - public struct SpawnMenuData { - public Vector3 spawnPoint; - public SkeletonDataAsset skeletonDataAsset; - public InstantiateDelegate instantiateDelegate; - public bool isUI; - } - - public class SkeletonComponentSpawnType { - public string menuLabel; - public InstantiateDelegate instantiateDelegate; - public bool isUI; - } - - internal static readonly List additionalSpawnTypes = new List(); - - static void SceneViewDragAndDrop (SceneView sceneview) { - var current = UnityEngine.Event.current; - var references = DragAndDrop.objectReferences; - if (current.type == EventType.Layout) return; - - // Allow drag and drop of one SkeletonDataAsset. - if (references.Length == 1) { - var skeletonDataAsset = references[0] as SkeletonDataAsset; - if (skeletonDataAsset != null) { - var mousePos = current.mousePosition; - - bool invalidSkeletonData = skeletonDataAsset.GetSkeletonData(true) == null; - if (invalidSkeletonData) { - DragAndDrop.visualMode = DragAndDropVisualMode.Rejected; - Handles.BeginGUI(); - GUI.Label(new Rect(mousePos + new Vector2(20f, 20f), new Vector2(400f, 40f)), new GUIContent(string.Format("{0} is invalid.\nCannot create new Spine GameObject.", skeletonDataAsset.name), SpineEditorUtilities.Icons.warning)); - Handles.EndGUI(); - return; - } else { - DragAndDrop.visualMode = DragAndDropVisualMode.Copy; - Handles.BeginGUI(); - GUI.Label(new Rect(mousePos + new Vector2(20f, 20f), new Vector2(400f, 20f)), new GUIContent(string.Format("Create Spine GameObject ({0})", skeletonDataAsset.skeletonJSON.name), SpineEditorUtilities.Icons.skeletonDataAssetIcon)); - Handles.EndGUI(); - - if (current.type == EventType.DragPerform) { - RectTransform rectTransform = (Selection.activeGameObject == null) ? null : Selection.activeGameObject.GetComponent(); - Plane plane = (rectTransform == null) ? new Plane(Vector3.back, Vector3.zero) : new Plane(-rectTransform.forward, rectTransform.position); - Vector3 spawnPoint = MousePointToWorldPoint2D(mousePos, sceneview.camera, plane); - ShowInstantiateContextMenu(skeletonDataAsset, spawnPoint); - DragAndDrop.AcceptDrag(); - current.Use(); - } - } - } - } - } - - public static void ShowInstantiateContextMenu (SkeletonDataAsset skeletonDataAsset, Vector3 spawnPoint) { - var menu = new GenericMenu(); - - // SkeletonAnimation - menu.AddItem(new GUIContent("SkeletonAnimation"), false, HandleSkeletonComponentDrop, new SpawnMenuData { - skeletonDataAsset = skeletonDataAsset, - spawnPoint = spawnPoint, - instantiateDelegate = (data) => InstantiateSkeletonAnimation(data), - isUI = false - }); - - // SkeletonGraphic - var skeletonGraphicInspectorType = System.Type.GetType("Spine.Unity.Editor.SkeletonGraphicInspector"); - if (skeletonGraphicInspectorType != null) { - var graphicInstantiateDelegate = skeletonGraphicInspectorType.GetMethod("SpawnSkeletonGraphicFromDrop", BindingFlags.Static | BindingFlags.Public); - if (graphicInstantiateDelegate != null) - menu.AddItem(new GUIContent("SkeletonGraphic (UI)"), false, HandleSkeletonComponentDrop, new SpawnMenuData { - skeletonDataAsset = skeletonDataAsset, - spawnPoint = spawnPoint, - instantiateDelegate = System.Delegate.CreateDelegate(typeof(InstantiateDelegate), graphicInstantiateDelegate) as InstantiateDelegate, - isUI = true - }); - } - - #if SPINE_SKELETONMECANIM - menu.AddSeparator(""); - // SkeletonMecanim - menu.AddItem(new GUIContent("SkeletonMecanim"), false, HandleSkeletonComponentDrop, new SpawnMenuData { - skeletonDataAsset = skeletonDataAsset, - spawnPoint = spawnPoint, - instantiateDelegate = (data) => InstantiateSkeletonMecanim(data) - }); - #endif - - menu.ShowAsContext(); - } - - public static void HandleSkeletonComponentDrop (object spawnMenuData) { - var data = (SpawnMenuData)spawnMenuData; - - if (data.skeletonDataAsset.GetSkeletonData(true) == null) { - EditorUtility.DisplayDialog("Invalid SkeletonDataAsset", "Unable to create Spine GameObject.\n\nPlease check your SkeletonDataAsset.", "Ok"); - return; - } - - bool isUI = data.isUI; - - Component newSkeletonComponent = data.instantiateDelegate.Invoke(data.skeletonDataAsset); - GameObject newGameObject = newSkeletonComponent.gameObject; - Transform newTransform = newGameObject.transform; - - var activeGameObject = Selection.activeGameObject; - if (isUI && activeGameObject != null) - newTransform.SetParent(activeGameObject.transform, false); - - newTransform.position = isUI ? data.spawnPoint : RoundVector(data.spawnPoint, 2); - - if (isUI && (activeGameObject == null || activeGameObject.GetComponent() == null)) - Debug.Log("Created a UI Skeleton GameObject not under a RectTransform. It may not be visible until you parent it to a canvas."); - - if (!isUI && activeGameObject != null && activeGameObject.transform.localScale != Vector3.one) - Debug.Log("New Spine GameObject was parented to a scaled Transform. It may not be the intended size."); - - Selection.activeGameObject = newGameObject; - //EditorGUIUtility.PingObject(newGameObject); // Doesn't work when setting activeGameObject. - Undo.RegisterCreatedObjectUndo(newGameObject, "Create Spine GameObject"); - } - - ///

- /// Rounds off vector components to a number of decimal digits. - /// - public static Vector3 RoundVector (Vector3 vector, int digits) { - vector.x = (float)System.Math.Round(vector.x, digits); - vector.y = (float)System.Math.Round(vector.y, digits); - vector.z = (float)System.Math.Round(vector.z, digits); - return vector; - } - - /// - /// Converts a mouse point to a world point on a plane. - /// - static Vector3 MousePointToWorldPoint2D (Vector2 mousePosition, Camera camera, Plane plane) { - var screenPos = new Vector3(mousePosition.x, camera.pixelHeight - mousePosition.y, 0f); - var ray = camera.ScreenPointToRay(screenPos); - float distance; - bool hit = plane.Raycast(ray, out distance); - return ray.GetPoint(distance); - } - #endregion - - #region Hierarchy - static class SpineEditorHierarchyHandler { - static Dictionary skeletonRendererTable = new Dictionary(); - static Dictionary skeletonUtilityBoneTable = new Dictionary(); - static Dictionary boundingBoxFollowerTable = new Dictionary(); - - #if UNITY_2017_2_OR_NEWER - internal static void HierarchyIconsOnPlaymodeStateChanged (PlayModeStateChange stateChange) { - #else - internal static void HierarchyIconsOnPlaymodeStateChanged () { - #endif - skeletonRendererTable.Clear(); - skeletonUtilityBoneTable.Clear(); - boundingBoxFollowerTable.Clear(); - - #if UNITY_2018 - EditorApplication.hierarchyChanged -= HierarchyIconsOnChanged; - #else - EditorApplication.hierarchyWindowChanged -= HierarchyIconsOnChanged; - #endif - EditorApplication.hierarchyWindowItemOnGUI -= HierarchyIconsOnGUI; - - if (!Application.isPlaying && showHierarchyIcons) { - #if UNITY_2018 - EditorApplication.hierarchyChanged += HierarchyIconsOnChanged; - #else - EditorApplication.hierarchyWindowChanged += HierarchyIconsOnChanged; - #endif - EditorApplication.hierarchyWindowItemOnGUI += HierarchyIconsOnGUI; - HierarchyIconsOnChanged(); - } - } - - internal static void HierarchyIconsOnChanged () { - skeletonRendererTable.Clear(); - skeletonUtilityBoneTable.Clear(); - boundingBoxFollowerTable.Clear(); - - SkeletonRenderer[] arr = Object.FindObjectsOfType(); - foreach (SkeletonRenderer r in arr) - skeletonRendererTable[r.gameObject.GetInstanceID()] = r.gameObject; - - SkeletonUtilityBone[] boneArr = Object.FindObjectsOfType(); - foreach (SkeletonUtilityBone b in boneArr) - skeletonUtilityBoneTable[b.gameObject.GetInstanceID()] = b; - - BoundingBoxFollower[] bbfArr = Object.FindObjectsOfType(); - foreach (BoundingBoxFollower bbf in bbfArr) - boundingBoxFollowerTable[bbf.gameObject.GetInstanceID()] = bbf; - } - - internal static void HierarchyIconsOnGUI (int instanceId, Rect selectionRect) { - Rect r = new Rect(selectionRect); - if (skeletonRendererTable.ContainsKey(instanceId)) { - r.x = r.width - 15; - r.width = 15; - GUI.Label(r, Icons.spine); - } else if (skeletonUtilityBoneTable.ContainsKey(instanceId)) { - r.x -= 26; - if (skeletonUtilityBoneTable[instanceId] != null) { - if (skeletonUtilityBoneTable[instanceId].transform.childCount == 0) - r.x += 13; - r.y += 2; - r.width = 13; - r.height = 13; - if (skeletonUtilityBoneTable[instanceId].mode == SkeletonUtilityBone.Mode.Follow) - GUI.DrawTexture(r, Icons.bone); - else - GUI.DrawTexture(r, Icons.poseBones); - } - } else if (boundingBoxFollowerTable.ContainsKey(instanceId)) { - r.x -= 26; - if (boundingBoxFollowerTable[instanceId] != null) { - if (boundingBoxFollowerTable[instanceId].transform.childCount == 0) - r.x += 13; - r.y += 2; - r.width = 13; - r.height = 13; - GUI.DrawTexture(r, Icons.boundingBox); - } - } - } - - internal static void HierarchyDragAndDrop (int instanceId, Rect selectionRect) { - // HACK: Uses EditorApplication.hierarchyWindowItemOnGUI. - // Only works when there is at least one item in the scene. - var current = UnityEngine.Event.current; - var eventType = current.type; - bool isDraggingEvent = eventType == EventType.DragUpdated; - bool isDropEvent = eventType == EventType.DragPerform; - if (isDraggingEvent || isDropEvent) { - var mouseOverWindow = EditorWindow.mouseOverWindow; - if (mouseOverWindow != null) { - - // One, existing, valid SkeletonDataAsset - var references = DragAndDrop.objectReferences; - if (references.Length == 1) { - var skeletonDataAsset = references[0] as SkeletonDataAsset; - if (skeletonDataAsset != null && skeletonDataAsset.GetSkeletonData(true) != null) { - - // Allow drag-and-dropping anywhere in the Hierarchy Window. - // HACK: string-compare because we can't get its type via reflection. - const string HierarchyWindow = "UnityEditor.SceneHierarchyWindow"; - if (HierarchyWindow.Equals(mouseOverWindow.GetType().ToString(), System.StringComparison.Ordinal)) { - if (isDraggingEvent) { - DragAndDrop.visualMode = DragAndDropVisualMode.Copy; - current.Use(); - } else if (isDropEvent) { - ShowInstantiateContextMenu(skeletonDataAsset, Vector3.zero); - DragAndDrop.AcceptDrag(); - current.Use(); - return; - } - } - - } - } - } - } - - } - } - #endregion - - #region Auto-Import Entry Point - static void OnPostprocessAllAssets (string[] imported, string[] deleted, string[] moved, string[] movedFromAssetPaths) { - if (imported.Length == 0) - return; - - // In case user used "Assets -> Reimport All", during the import process, - // asset database is not initialized until some point. During that period, - // all attempts to load any assets using API (i.e. AssetDatabase.LoadAssetAtPath) - // will return null, and as result, assets won't be loaded even if they actually exists, - // which may lead to numerous importing errors. - // This situation also happens if Library folder is deleted from the project, which is a pretty - // common case, since when using version control systems, the Library folder must be excluded. - // - // So to avoid this, in case asset database is not available, we delay loading the assets - // until next time. - // - // Unity *always* reimports some internal assets after the process is done, so this method - // is always called once again in a state when asset database is available. - // - // Checking whether AssetDatabase is initialized is done by attempting to load - // a known "marker" asset that should always be available. Failing to load this asset - // means that AssetDatabase is not initialized. - assetsImportedInWrongState.UnionWith(imported); - if (AssetDatabaseAvailabilityDetector.IsAssetDatabaseAvailable()) { - string[] combinedAssets = assetsImportedInWrongState.ToArray(); - assetsImportedInWrongState.Clear(); - ImportSpineContent(combinedAssets); - } - } - - public static void ImportSpineContent (string[] imported, bool reimport = false) { - var atlasPaths = new List(); - var imagePaths = new List(); - var skeletonPaths = new List(); - - foreach (string str in imported) { - string extension = Path.GetExtension(str).ToLower(); - switch (extension) { - case ".txt": - if (str.EndsWith(".atlas.txt", System.StringComparison.Ordinal)) - atlasPaths.Add(str); - break; - case ".png": - case ".jpg": - imagePaths.Add(str); - break; - case ".json": - var jsonAsset = (TextAsset)AssetDatabase.LoadAssetAtPath(str, typeof(TextAsset)); - if (jsonAsset != null && SkeletonDataFileValidator.IsSpineData(jsonAsset)) - skeletonPaths.Add(str); - break; - case ".bytes": - if (str.ToLower().EndsWith(".skel.bytes", System.StringComparison.Ordinal)) { - if (SkeletonDataFileValidator.IsSpineData((TextAsset)AssetDatabase.LoadAssetAtPath(str, typeof(TextAsset)))) - skeletonPaths.Add(str); - } - break; - } - } - - // Import atlases first. - var atlases = new List(); - foreach (string ap in atlasPaths) { - TextAsset atlasText = (TextAsset)AssetDatabase.LoadAssetAtPath(ap, typeof(TextAsset)); - AtlasAssetBase atlas = IngestSpineAtlas(atlasText); - atlases.Add(atlas); - } - - // Import skeletons and match them with atlases. - bool abortSkeletonImport = false; - foreach (string sp in skeletonPaths) { - if (!reimport && SkeletonDataFileValidator.CheckForValidSkeletonData(sp)) { - ReloadSkeletonData(sp); - continue; - } - - string dir = Path.GetDirectoryName(sp); - - #if SPINE_TK2D - IngestSpineProject(AssetDatabase.LoadAssetAtPath(sp, typeof(TextAsset)) as TextAsset, null); - #else - var localAtlases = FindAtlasesAtPath(dir); - var requiredPaths = GetRequiredAtlasRegions(sp); - var atlasMatch = GetMatchingAtlas(requiredPaths, localAtlases); - if (atlasMatch != null || requiredPaths.Count == 0) { - IngestSpineProject(AssetDatabase.LoadAssetAtPath(sp, typeof(TextAsset)) as TextAsset, atlasMatch); - } else { - bool resolved = false; - while (!resolved) { - - string filename = Path.GetFileNameWithoutExtension(sp); - int result = EditorUtility.DisplayDialogComplex( - string.Format("AtlasAsset for \"{0}\"", filename), - string.Format("Could not automatically set the AtlasAsset for \"{0}\". You may set it manually.", filename), - "Choose AtlasAssets...", "Skip this", "Stop importing all" - ); - - switch (result) { - case -1: - //Debug.Log("Select Atlas"); - AtlasAssetBase selectedAtlas = GetAtlasDialog(Path.GetDirectoryName(sp)); - if (selectedAtlas != null) { - localAtlases.Clear(); - localAtlases.Add(selectedAtlas); - atlasMatch = GetMatchingAtlas(requiredPaths, localAtlases); - if (atlasMatch != null) { - resolved = true; - IngestSpineProject(AssetDatabase.LoadAssetAtPath(sp, typeof(TextAsset)) as TextAsset, atlasMatch); - } - } - break; - case 0: // Choose AtlasAssets... - var atlasList = MultiAtlasDialog(requiredPaths, Path.GetDirectoryName(sp), Path.GetFileNameWithoutExtension(sp)); - if (atlasList != null) - IngestSpineProject(AssetDatabase.LoadAssetAtPath(sp, typeof(TextAsset)) as TextAsset, atlasList.ToArray()); - - resolved = true; - break; - case 1: // Skip - Debug.Log("Skipped importing: " + Path.GetFileName(sp)); - resolved = true; - break; - case 2: // Stop importing all - abortSkeletonImport = true; - resolved = true; - break; - } - } - } - - if (abortSkeletonImport) - break; - #endif - } - // Any post processing of images - } - - static void ReloadSkeletonData (string skeletonJSONPath) { - string dir = Path.GetDirectoryName(skeletonJSONPath); - TextAsset textAsset = (TextAsset)AssetDatabase.LoadAssetAtPath(skeletonJSONPath, typeof(TextAsset)); - DirectoryInfo dirInfo = new DirectoryInfo(dir); - FileInfo[] files = dirInfo.GetFiles("*.asset"); - - foreach (var f in files) { - string localPath = dir + "/" + f.Name; - var obj = AssetDatabase.LoadAssetAtPath(localPath, typeof(Object)); - var skeletonDataAsset = obj as SkeletonDataAsset; - if (skeletonDataAsset != null) { - if (skeletonDataAsset.skeletonJSON == textAsset) { - if (Selection.activeObject == skeletonDataAsset) - Selection.activeObject = null; - - Debug.LogFormat("Changes to '{0}' detected. Clearing SkeletonDataAsset: {1}", skeletonJSONPath, localPath); - skeletonDataAsset.Clear(); - - string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(skeletonDataAsset)); - string lastHash = EditorPrefs.GetString(guid + "_hash"); - - // For some weird reason sometimes Unity loses the internal Object pointer, - // and as a result, all comparisons with null returns true. - // But the C# wrapper is still alive, so we can "restore" the object - // by reloading it from its Instance ID. - AtlasAssetBase[] skeletonDataAtlasAssets = skeletonDataAsset.atlasAssets; - if (skeletonDataAtlasAssets != null) { - for (int i = 0; i < skeletonDataAtlasAssets.Length; i++) { - if (!ReferenceEquals(null, skeletonDataAtlasAssets[i]) && - skeletonDataAtlasAssets[i].Equals(null) && - skeletonDataAtlasAssets[i].GetInstanceID() != 0 - ) { - skeletonDataAtlasAssets[i] = EditorUtility.InstanceIDToObject(skeletonDataAtlasAssets[i].GetInstanceID()) as AtlasAssetBase; - } - } - } - - SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(true); - string currentHash = skeletonData != null ? skeletonData.Hash : null; - - #if SPINE_SKELETONMECANIM - if (currentHash == null || lastHash != currentHash) - UpdateMecanimClips(skeletonDataAsset); - #endif - - // if (currentHash == null || lastHash != currentHash) - // Do any upkeep on synchronized assets - - if (currentHash != null) - EditorPrefs.SetString(guid + "_hash", currentHash); - } - } - } - } - #endregion - - #region Match SkeletonData with Atlases - static readonly AttachmentType[] AtlasTypes = { AttachmentType.Region, AttachmentType.Linkedmesh, AttachmentType.Mesh }; - - static List MultiAtlasDialog (List requiredPaths, string initialDirectory, string filename = "") { - List atlasAssets = new List(); - bool resolved = false; - string lastAtlasPath = initialDirectory; - while (!resolved) { - - // Build dialog box message. - var missingRegions = new List(requiredPaths); - var dialogText = new StringBuilder(); - { - dialogText.AppendLine(string.Format("SkeletonDataAsset for \"{0}\"", filename)); - dialogText.AppendLine("has missing regions."); - dialogText.AppendLine(); - dialogText.AppendLine("Current Atlases:"); - - if (atlasAssets.Count == 0) - dialogText.AppendLine("\t--none--"); - - for (int i = 0; i < atlasAssets.Count; i++) - dialogText.AppendLine("\t" + atlasAssets[i].name); - - dialogText.AppendLine(); - dialogText.AppendLine("Missing Regions:"); - - foreach (var atlasAsset in atlasAssets) { - var atlas = atlasAsset.GetAtlas(); - for (int i = 0; i < missingRegions.Count; i++) { - if (atlas.FindRegion(missingRegions[i]) != null) { - missingRegions.RemoveAt(i); - i--; - } - } - } - - int n = missingRegions.Count; - if (n == 0) break; - - const int MaxListLength = 15; - for (int i = 0; (i < n && i < MaxListLength); i++) - dialogText.AppendLine("\t" + missingRegions[i]); - - if (n > MaxListLength) dialogText.AppendLine(string.Format("\t... {0} more...", n - MaxListLength)); - } - - // Show dialog box. - int result = EditorUtility.DisplayDialogComplex( - "SkeletonDataAsset has missing Atlas.", - dialogText.ToString(), - "Browse...", "Import anyway", "Cancel" - ); - - switch (result) { - case 0: // Browse... - AtlasAssetBase selectedAtlasAsset = GetAtlasDialog(lastAtlasPath); - if (selectedAtlasAsset != null) { - var atlas = selectedAtlasAsset.GetAtlas(); - bool hasValidRegion = false; - foreach (string str in missingRegions) { - if (atlas.FindRegion(str) != null) { - hasValidRegion = true; - break; - } - } - atlasAssets.Add(selectedAtlasAsset); - } - break; - case 1: // Import anyway - resolved = true; - break; - case 2: // Cancel - atlasAssets = null; - resolved = true; - break; - } - } - - return atlasAssets; - } - - static AtlasAssetBase GetAtlasDialog (string dirPath) { - string path = EditorUtility.OpenFilePanel("Select AtlasAsset...", dirPath, "asset"); - if (path == "") return null; // Canceled or closed by user. - - int subLen = Application.dataPath.Length - 6; - string assetRelativePath = path.Substring(subLen, path.Length - subLen).Replace("\\", "/"); - - Object obj = AssetDatabase.LoadAssetAtPath(assetRelativePath, typeof(AtlasAssetBase)); - - if (obj == null || obj.GetType() != typeof(AtlasAssetBase)) - return null; - - return (AtlasAssetBase)obj; - } - - static void AddRequiredAtlasRegionsFromBinary (string skeletonDataPath, List requiredPaths) { - SkeletonBinary binary = new SkeletonBinary(new AtlasRequirementLoader(requiredPaths)); - TextAsset data = (TextAsset)AssetDatabase.LoadAssetAtPath(skeletonDataPath, typeof(TextAsset)); - MemoryStream input = new MemoryStream(data.bytes); - binary.ReadSkeletonData(input); - binary = null; - } - - public static List GetRequiredAtlasRegions (string skeletonDataPath) { - List requiredPaths = new List(); - - if (skeletonDataPath.Contains(".skel")) { - AddRequiredAtlasRegionsFromBinary(skeletonDataPath, requiredPaths); - return requiredPaths; - } - - TextAsset spineJson = (TextAsset)AssetDatabase.LoadAssetAtPath(skeletonDataPath, typeof(TextAsset)); - - StringReader reader = new StringReader(spineJson.text); - var root = Json.Deserialize(reader) as Dictionary; - - if (!root.ContainsKey("skins")) - return requiredPaths; - - foreach (KeyValuePair entry in (Dictionary)root["skins"]) { - foreach (KeyValuePair slotEntry in (Dictionary)entry.Value) { - - foreach (KeyValuePair attachmentEntry in ((Dictionary)slotEntry.Value)) { - var data = ((Dictionary)attachmentEntry.Value); - - // Ignore non-atlas-requiring types. - if (data.ContainsKey("type")) { - AttachmentType attachmentType; - string typeString = (string)data["type"]; - try { - attachmentType = (AttachmentType)System.Enum.Parse(typeof(AttachmentType), typeString, true); - } catch (System.ArgumentException e) { - // For more info, visit: http://esotericsoftware.com/forum/Spine-editor-and-runtime-version-management-6534 - Debug.LogWarning(string.Format("Unidentified Attachment type: \"{0}\". Skeleton may have been exported from an incompatible Spine version.", typeString)); - throw e; - } - - if (!AtlasTypes.Contains(attachmentType)) - continue; - } - - if (data.ContainsKey("path")) - requiredPaths.Add((string)data["path"]); - else if (data.ContainsKey("name")) - requiredPaths.Add((string)data["name"]); - else - requiredPaths.Add(attachmentEntry.Key); - } - } - } - - return requiredPaths; - } - - static AtlasAssetBase GetMatchingAtlas (List requiredPaths, List atlasAssets) { - AtlasAssetBase atlasAssetMatch = null; - - foreach (AtlasAssetBase a in atlasAssets) { - Atlas atlas = a.GetAtlas(); - bool failed = false; - foreach (string regionPath in requiredPaths) { - if (atlas.FindRegion(regionPath) == null) { - failed = true; - break; - } - } - - if (!failed) { - atlasAssetMatch = a; - break; - } - } - - return atlasAssetMatch; - } - - public class AtlasRequirementLoader : AttachmentLoader { - List requirementList; - - public AtlasRequirementLoader (List requirementList) { - this.requirementList = requirementList; - } - - public RegionAttachment NewRegionAttachment (Skin skin, string name, string path) { - requirementList.Add(path); - return new RegionAttachment(name); - } - - public MeshAttachment NewMeshAttachment (Skin skin, string name, string path) { - requirementList.Add(path); - return new MeshAttachment(name); - } - - public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, string name) { - return new BoundingBoxAttachment(name); - } - - public PathAttachment NewPathAttachment (Skin skin, string name) { - return new PathAttachment(name); - } - - public PointAttachment NewPointAttachment (Skin skin, string name) { - return new PointAttachment(name); - } - - public ClippingAttachment NewClippingAttachment (Skin skin, string name) { - return new ClippingAttachment(name); - } - } - #endregion - - #region Import Atlases - static List FindAtlasesAtPath (string path) { - List arr = new List(); - DirectoryInfo dir = new DirectoryInfo(path); - FileInfo[] assetInfoArr = dir.GetFiles("*.asset"); - - int subLen = Application.dataPath.Length - 6; - foreach (var f in assetInfoArr) { - string assetRelativePath = f.FullName.Substring(subLen, f.FullName.Length - subLen).Replace("\\", "/"); - Object obj = AssetDatabase.LoadAssetAtPath(assetRelativePath, typeof(AtlasAssetBase)); - if (obj != null) - arr.Add(obj as AtlasAssetBase); - } - - return arr; - } - - static AtlasAssetBase IngestSpineAtlas (TextAsset atlasText) { - if (atlasText == null) { - Debug.LogWarning("Atlas source cannot be null!"); - return null; - } - - string primaryName = Path.GetFileNameWithoutExtension(atlasText.name).Replace(".atlas", ""); - string assetPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(atlasText)); - - string atlasPath = assetPath + "/" + primaryName + "_Atlas.asset"; - - SpineAtlasAsset atlasAsset = (SpineAtlasAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(SpineAtlasAsset)); - - List vestigialMaterials = new List(); - - if (atlasAsset == null) - atlasAsset = SpineAtlasAsset.CreateInstance(); - else { - foreach (Material m in atlasAsset.materials) - vestigialMaterials.Add(m); - } - - protectFromStackGarbageCollection.Add(atlasAsset); - atlasAsset.atlasFile = atlasText; - - //strip CR - string atlasStr = atlasText.text; - atlasStr = atlasStr.Replace("\r", ""); - - string[] atlasLines = atlasStr.Split('\n'); - List pageFiles = new List(); - for (int i = 0; i < atlasLines.Length - 1; i++) { - if (atlasLines[i].Trim().Length == 0) - pageFiles.Add(atlasLines[i + 1].Trim()); - } - - var populatingMaterials = new List(pageFiles.Count);//atlasAsset.materials = new Material[pageFiles.Count]; - - for (int i = 0; i < pageFiles.Count; i++) { - string texturePath = assetPath + "/" + pageFiles[i]; - Texture2D texture = (Texture2D)AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D)); - - if (setTextureImporterSettings) { - TextureImporter texImporter = (TextureImporter)TextureImporter.GetAtPath(texturePath); - if (texImporter == null) { - Debug.LogWarning(string.Format("{0} ::: Texture asset \"{1}\" not found. Skipping. Please check your atlas file for renamed files.", atlasAsset.name, texturePath)); - continue; - } - - texImporter.textureCompression = TextureImporterCompression.Uncompressed; - texImporter.alphaSource = TextureImporterAlphaSource.FromInput; - texImporter.mipmapEnabled = false; - texImporter.alphaIsTransparency = false; // Prevent the texture importer from applying bleed to the transparent parts for PMA. - texImporter.spriteImportMode = SpriteImportMode.None; - texImporter.maxTextureSize = 2048; - - EditorUtility.SetDirty(texImporter); - AssetDatabase.ImportAsset(texturePath); - AssetDatabase.SaveAssets(); - } - - string pageName = Path.GetFileNameWithoutExtension(pageFiles[i]); - - //because this looks silly - if (pageName == primaryName && pageFiles.Count == 1) - pageName = "Material"; - - string materialPath = assetPath + "/" + primaryName + "_" + pageName + ".mat"; - Material mat = (Material)AssetDatabase.LoadAssetAtPath(materialPath, typeof(Material)); - - if (mat == null) { - mat = new Material(Shader.Find(defaultShader)); - AssetDatabase.CreateAsset(mat, materialPath); - } else { - vestigialMaterials.Remove(mat); - } - - mat.mainTexture = texture; - EditorUtility.SetDirty(mat); - AssetDatabase.SaveAssets(); - - populatingMaterials.Add(mat); //atlasAsset.materials[i] = mat; - } - - atlasAsset.materials = populatingMaterials.ToArray(); - - for (int i = 0; i < vestigialMaterials.Count; i++) - AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(vestigialMaterials[i])); - - if (AssetDatabase.GetAssetPath(atlasAsset) == "") - AssetDatabase.CreateAsset(atlasAsset, atlasPath); - else - atlasAsset.Clear(); - - EditorUtility.SetDirty(atlasAsset); - AssetDatabase.SaveAssets(); - - if (pageFiles.Count != atlasAsset.materials.Length) - Debug.LogWarning(string.Format("{0} ::: Not all atlas pages were imported. If you rename your image files, please make sure you also edit the filenames specified in the atlas file.", atlasAsset.name)); - else - Debug.Log(string.Format("{0} ::: Imported with {1} material", atlasAsset.name, atlasAsset.materials.Length)); - - // Iterate regions and bake marked. - Atlas atlas = atlasAsset.GetAtlas(); - FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic); - List regions = (List)field.GetValue(atlas); - string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset); - string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath); - string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name); - - bool hasBakedRegions = false; - for (int i = 0; i < regions.Count; i++) { - AtlasRegion region = regions[i]; - string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeName(region.name) + ".prefab").Replace("\\", "/"); - GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject)); - if (prefab != null) { - BakeRegion(atlasAsset, region, false); - hasBakedRegions = true; - } - } - - if (hasBakedRegions) { - AssetDatabase.SaveAssets(); - AssetDatabase.Refresh(); - } - - protectFromStackGarbageCollection.Remove(atlasAsset); - return (AtlasAssetBase)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(AtlasAssetBase)); - } - #endregion - - #region Bake Atlas Region - public static GameObject BakeRegion (SpineAtlasAsset atlasAsset, AtlasRegion region, bool autoSave = true) { - Atlas atlas = atlasAsset.GetAtlas(); - string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset); - string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath); - string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name); - string bakedPrefabPath = Path.Combine(bakedDirPath, GetPathSafeName(region.name) + ".prefab").Replace("\\", "/"); - - GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject)); - GameObject root; - Mesh mesh; - bool isNewPrefab = false; - - if (!Directory.Exists(bakedDirPath)) - Directory.CreateDirectory(bakedDirPath); - - if (prefab == null) { - root = new GameObject("temp", typeof(MeshFilter), typeof(MeshRenderer)); - prefab = PrefabUtility.CreatePrefab(bakedPrefabPath, root); - isNewPrefab = true; - Object.DestroyImmediate(root); - } - - mesh = (Mesh)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(Mesh)); - - Material mat = null; - mesh = atlasAsset.GenerateMesh(region.name, mesh, out mat); - if (isNewPrefab) { - AssetDatabase.AddObjectToAsset(mesh, prefab); - prefab.GetComponent().sharedMesh = mesh; - } - - EditorUtility.SetDirty(mesh); - EditorUtility.SetDirty(prefab); - - if (autoSave) { - AssetDatabase.SaveAssets(); - AssetDatabase.Refresh(); - } - - prefab.GetComponent().sharedMaterial = mat; - - return prefab; - } - #endregion - - #region Import SkeletonData (json or binary) - public const string SkeletonDataSuffix = "_SkeletonData"; - static SkeletonDataAsset IngestSpineProject (TextAsset spineJson, params AtlasAssetBase[] atlasAssets) { - string primaryName = Path.GetFileNameWithoutExtension(spineJson.name); - string assetPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(spineJson)); - string filePath = assetPath + "/" + primaryName + SkeletonDataSuffix + ".asset"; - + public static class Preferences { #if SPINE_TK2D - if (spineJson != null) { - SkeletonDataAsset skeletonDataAsset = (SkeletonDataAsset)AssetDatabase.LoadAssetAtPath(filePath, typeof(SkeletonDataAsset)); - if (skeletonDataAsset == null) { - skeletonDataAsset = SkeletonDataAsset.CreateInstance(); - skeletonDataAsset.skeletonJSON = spineJson; - skeletonDataAsset.fromAnimation = new string[0]; - skeletonDataAsset.toAnimation = new string[0]; - skeletonDataAsset.duration = new float[0]; - skeletonDataAsset.defaultMix = defaultMix; - skeletonDataAsset.scale = defaultScale; - - AssetDatabase.CreateAsset(skeletonDataAsset, filePath); - AssetDatabase.SaveAssets(); - } else { - skeletonDataAsset.Clear(); - skeletonDataAsset.GetSkeletonData(true); - } - - return skeletonDataAsset; - } else { - EditorUtility.DisplayDialog("Error!", "Tried to ingest null Spine data.", "OK"); - return null; - } - + const float DEFAULT_DEFAULT_SCALE = 1f; #else - if (spineJson != null && atlasAssets != null) { - SkeletonDataAsset skeletonDataAsset = (SkeletonDataAsset)AssetDatabase.LoadAssetAtPath(filePath, typeof(SkeletonDataAsset)); - if (skeletonDataAsset == null) { - skeletonDataAsset = ScriptableObject.CreateInstance(); { - skeletonDataAsset.atlasAssets = atlasAssets; - skeletonDataAsset.skeletonJSON = spineJson; - skeletonDataAsset.defaultMix = defaultMix; - skeletonDataAsset.scale = defaultScale; - } + const float DEFAULT_DEFAULT_SCALE = 0.01f; + #endif + const string DEFAULT_SCALE_KEY = "SPINE_DEFAULT_SCALE"; + public static float defaultScale = DEFAULT_DEFAULT_SCALE; - AssetDatabase.CreateAsset(skeletonDataAsset, filePath); - AssetDatabase.SaveAssets(); - } else { - skeletonDataAsset.atlasAssets = atlasAssets; - skeletonDataAsset.Clear(); - skeletonDataAsset.GetSkeletonData(true); + const float DEFAULT_DEFAULT_MIX = 0.2f; + const string DEFAULT_MIX_KEY = "SPINE_DEFAULT_MIX"; + public static float defaultMix = DEFAULT_DEFAULT_MIX; + + const string DEFAULT_DEFAULT_SHADER = "Spine/Skeleton"; + const string DEFAULT_SHADER_KEY = "SPINE_DEFAULT_SHADER"; + public static string defaultShader = DEFAULT_DEFAULT_SHADER; + + const float DEFAULT_DEFAULT_ZSPACING = 0f; + const string DEFAULT_ZSPACING_KEY = "SPINE_DEFAULT_ZSPACING"; + public static float defaultZSpacing = DEFAULT_DEFAULT_ZSPACING; + + const bool DEFAULT_SHOW_HIERARCHY_ICONS = true; + const string SHOW_HIERARCHY_ICONS_KEY = "SPINE_SHOW_HIERARCHY_ICONS"; + public static bool showHierarchyIcons = DEFAULT_SHOW_HIERARCHY_ICONS; + + const bool DEFAULT_SET_TEXTUREIMPORTER_SETTINGS = true; + const string SET_TEXTUREIMPORTER_SETTINGS_KEY = "SPINE_SET_TEXTUREIMPORTER_SETTINGS"; + public static bool setTextureImporterSettings = DEFAULT_SET_TEXTUREIMPORTER_SETTINGS; + + internal const float DEFAULT_MIPMAPBIAS = -0.5f; + + public const float DEFAULT_SCENE_ICONS_SCALE = 1f; + public const string SCENE_ICONS_SCALE_KEY = "SPINE_SCENE_ICONS_SCALE"; + + static bool preferencesLoaded = false; + + public static void Load () { + defaultMix = EditorPrefs.GetFloat(DEFAULT_MIX_KEY, DEFAULT_DEFAULT_MIX); + defaultScale = EditorPrefs.GetFloat(DEFAULT_SCALE_KEY, DEFAULT_DEFAULT_SCALE); + defaultZSpacing = EditorPrefs.GetFloat(DEFAULT_ZSPACING_KEY, DEFAULT_DEFAULT_ZSPACING); + defaultShader = EditorPrefs.GetString(DEFAULT_SHADER_KEY, DEFAULT_DEFAULT_SHADER); + showHierarchyIcons = EditorPrefs.GetBool(SHOW_HIERARCHY_ICONS_KEY, DEFAULT_SHOW_HIERARCHY_ICONS); + setTextureImporterSettings = EditorPrefs.GetBool(SET_TEXTUREIMPORTER_SETTINGS_KEY, DEFAULT_SET_TEXTUREIMPORTER_SETTINGS); + SpineHandles.handleScale = EditorPrefs.GetFloat(SCENE_ICONS_SCALE_KEY, DEFAULT_SCENE_ICONS_SCALE); + preferencesLoaded = true; + } + + public static void HandlePreferencesGUI () { + if (!preferencesLoaded) + Load(); + + EditorGUI.BeginChangeCheck(); + showHierarchyIcons = EditorGUILayout.Toggle(new GUIContent("Show Hierarchy Icons", "Show relevant icons on GameObjects with Spine Components on them. Disable this if you have large, complex scenes."), showHierarchyIcons); + if (EditorGUI.EndChangeCheck()) { + EditorPrefs.SetBool(SHOW_HIERARCHY_ICONS_KEY, showHierarchyIcons); + #if UNITY_2017_2_OR_NEWER + HierarchyHandler.IconsOnPlaymodeStateChanged(PlayModeStateChange.EnteredEditMode); + #else + HierarchyHandler.IconsOnPlaymodeStateChanged(); + #endif } - return skeletonDataAsset; - } else { - EditorUtility.DisplayDialog("Error!", "Must specify both Spine JSON and AtlasAsset array", "OK"); - return null; - } - #endif - } - #endregion + EditorGUILayout.Separator(); + + EditorGUILayout.LabelField("Auto-Import Settings", EditorStyles.boldLabel); + + EditorGUI.BeginChangeCheck(); + defaultMix = EditorGUILayout.FloatField("Default Mix", defaultMix); + if (EditorGUI.EndChangeCheck()) + EditorPrefs.SetFloat(DEFAULT_MIX_KEY, defaultMix); + + EditorGUI.BeginChangeCheck(); + defaultScale = EditorGUILayout.FloatField("Default SkeletonData Scale", defaultScale); + if (EditorGUI.EndChangeCheck()) + EditorPrefs.SetFloat(DEFAULT_SCALE_KEY, defaultScale); + + EditorGUI.BeginChangeCheck(); + var shader = (EditorGUILayout.ObjectField("Default Shader", Shader.Find(defaultShader), typeof(Shader), false) as Shader); + defaultShader = shader != null ? shader.name : DEFAULT_DEFAULT_SHADER; + if (EditorGUI.EndChangeCheck()) + EditorPrefs.SetString(DEFAULT_SHADER_KEY, defaultShader); + + EditorGUI.BeginChangeCheck(); + setTextureImporterSettings = EditorGUILayout.Toggle(new GUIContent("Apply Atlas Texture Settings", "Apply the recommended settings for Texture Importers."), showHierarchyIcons); + if (EditorGUI.EndChangeCheck()) { + EditorPrefs.SetBool(SET_TEXTUREIMPORTER_SETTINGS_KEY, showHierarchyIcons); + } + + EditorGUILayout.Space(); + + EditorGUILayout.LabelField("Editor Instantiation", EditorStyles.boldLabel); + EditorGUI.BeginChangeCheck(); + defaultZSpacing = EditorGUILayout.Slider("Default Slot Z-Spacing", defaultZSpacing, -0.1f, 0f); + if (EditorGUI.EndChangeCheck()) + EditorPrefs.SetFloat(DEFAULT_ZSPACING_KEY, defaultZSpacing); + + + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Handles and Gizmos", EditorStyles.boldLabel); + EditorGUI.BeginChangeCheck(); + SpineHandles.handleScale = EditorGUILayout.Slider("Editor Bone Scale", SpineHandles.handleScale, 0.01f, 2f); + SpineHandles.handleScale = Mathf.Max(0.01f, SpineHandles.handleScale); + if (EditorGUI.EndChangeCheck()) { + EditorPrefs.SetFloat(SCENE_ICONS_SCALE_KEY, SpineHandles.handleScale); + SceneView.RepaintAll(); + } + + + GUILayout.Space(20); + EditorGUILayout.LabelField("3rd Party Settings", EditorStyles.boldLabel); + using (new GUILayout.HorizontalScope()) { + EditorGUILayout.PrefixLabel("Define TK2D"); + if (GUILayout.Button("Enable", GUILayout.Width(64))) + SpineTK2DEditorUtility.EnableTK2D(); + if (GUILayout.Button("Disable", GUILayout.Width(64))) + SpineTK2DEditorUtility.DisableTK2D(); + } + } + } + + public static class AssetUtility { + public const string SkeletonDataSuffix = "_SkeletonData"; + public const string AtlasSuffix = "_Atlas"; - #region SkeletonDataFileValidator - internal static class SkeletonDataFileValidator { static readonly int[][] compatibleBinaryVersions = { new[] { 3, 7, 0 } }; static readonly int[][] compatibleJsonVersions = { new[] { 3, 7, 0 }, new[] { 3, 6, 0 }, new[] { 3, 5, 0 } }; //static bool isFixVersionRequired = false; + /// HACK: This list keeps the asset reference temporarily during importing. + /// + /// In cases of very large projects/sufficient RAM pressure, when AssetDatabase.SaveAssets is called, + /// Unity can mistakenly unload assets whose references are only on the stack. + /// This leads to MissingReferenceException and other errors. + public static readonly List protectFromStackGarbageCollection = new List(); + public static HashSet assetsImportedInWrongState = new HashSet(); + + public static void HandleOnPostprocessAllAssets (string[] imported) { + // In case user used "Assets -> Reimport All", during the import process, + // asset database is not initialized until some point. During that period, + // all attempts to load any assets using API (i.e. AssetDatabase.LoadAssetAtPath) + // will return null, and as result, assets won't be loaded even if they actually exists, + // which may lead to numerous importing errors. + // This situation also happens if Library folder is deleted from the project, which is a pretty + // common case, since when using version control systems, the Library folder must be excluded. + // + // So to avoid this, in case asset database is not available, we delay loading the assets + // until next time. + // + // Unity *always* reimports some internal assets after the process is done, so this method + // is always called once again in a state when asset database is available. + // + // Checking whether AssetDatabase is initialized is done by attempting to load + // a known "marker" asset that should always be available. Failing to load this asset + // means that AssetDatabase is not initialized. + AssetUtility.assetsImportedInWrongState.UnionWith(imported); + if (AssetDatabaseAvailabilityDetector.IsAssetDatabaseAvailable()) { + string[] combinedAssets = AssetUtility.assetsImportedInWrongState.ToArray(); + AssetUtility.assetsImportedInWrongState.Clear(); + AssetUtility.ImportSpineContent(combinedAssets); + } + } + + #region Match SkeletonData with Atlases + static readonly AttachmentType[] AtlasTypes = { AttachmentType.Region, AttachmentType.Linkedmesh, AttachmentType.Mesh }; + + public static List GetRequiredAtlasRegions (string skeletonDataPath) { + List requiredPaths = new List(); + + if (skeletonDataPath.Contains(".skel")) { + AddRequiredAtlasRegionsFromBinary(skeletonDataPath, requiredPaths); + return requiredPaths; + } + + TextAsset spineJson = (TextAsset)AssetDatabase.LoadAssetAtPath(skeletonDataPath, typeof(TextAsset)); + + StringReader reader = new StringReader(spineJson.text); + var root = Json.Deserialize(reader) as Dictionary; + + if (!root.ContainsKey("skins")) + return requiredPaths; + + foreach (var skin in (Dictionary)root["skins"]) { + foreach (var slot in (Dictionary)skin.Value) { + + foreach (var attachment in ((Dictionary)slot.Value)) { + var data = ((Dictionary)attachment.Value); + + // Ignore non-atlas-requiring types. + if (data.ContainsKey("type")) { + AttachmentType attachmentType; + string typeString = (string)data["type"]; + try { + attachmentType = (AttachmentType)System.Enum.Parse(typeof(AttachmentType), typeString, true); + } catch (System.ArgumentException e) { + // For more info, visit: http://esotericsoftware.com/forum/Spine-editor-and-runtime-version-management-6534 + Debug.LogWarning(string.Format("Unidentified Attachment type: \"{0}\". Skeleton may have been exported from an incompatible Spine version.", typeString)); + throw e; + } + + if (!AtlasTypes.Contains(attachmentType)) + continue; + } + + if (data.ContainsKey("path")) + requiredPaths.Add((string)data["path"]); + else if (data.ContainsKey("name")) + requiredPaths.Add((string)data["name"]); + //else + // requiredPaths.Add(attachment.Key); + } + } + } + + return requiredPaths; + } + + internal static void AddRequiredAtlasRegionsFromBinary (string skeletonDataPath, List requiredPaths) { + SkeletonBinary binary = new SkeletonBinary(new AtlasRequirementLoader(requiredPaths)); + TextAsset data = (TextAsset)AssetDatabase.LoadAssetAtPath(skeletonDataPath, typeof(TextAsset)); + MemoryStream input = new MemoryStream(data.bytes); + binary.ReadSkeletonData(input); + binary = null; + } + + internal static AtlasAssetBase GetMatchingAtlas (List requiredPaths, List atlasAssets) { + AtlasAssetBase atlasAssetMatch = null; + + foreach (AtlasAssetBase a in atlasAssets) { + Atlas atlas = a.GetAtlas(); + bool failed = false; + foreach (string regionPath in requiredPaths) { + if (atlas.FindRegion(regionPath) == null) { + failed = true; + break; + } + } + + if (!failed) { + atlasAssetMatch = a; + break; + } + } + + return atlasAssetMatch; + } + + public class AtlasRequirementLoader : AttachmentLoader { + List requirementList; + + public AtlasRequirementLoader (List requirementList) { + this.requirementList = requirementList; + } + + public RegionAttachment NewRegionAttachment (Skin skin, string name, string path) { + requirementList.Add(path); + return new RegionAttachment(name); + } + + public MeshAttachment NewMeshAttachment (Skin skin, string name, string path) { + requirementList.Add(path); + return new MeshAttachment(name); + } + + public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, string name) { + return new BoundingBoxAttachment(name); + } + + public PathAttachment NewPathAttachment (Skin skin, string name) { + return new PathAttachment(name); + } + + public PointAttachment NewPointAttachment (Skin skin, string name) { + return new PointAttachment(name); + } + + public ClippingAttachment NewClippingAttachment (Skin skin, string name) { + return new ClippingAttachment(name); + } + } + #endregion + + public static void ImportSpineContent (string[] imported, bool reimport = false) { + var atlasPaths = new List(); + var imagePaths = new List(); + var skeletonPaths = new List(); + + foreach (string str in imported) { + string extension = Path.GetExtension(str).ToLower(); + switch (extension) { + case ".txt": + if (str.EndsWith(".atlas.txt", System.StringComparison.Ordinal)) + atlasPaths.Add(str); + break; + case ".png": + case ".jpg": + imagePaths.Add(str); + break; + case ".json": + var jsonAsset = (TextAsset)AssetDatabase.LoadAssetAtPath(str, typeof(TextAsset)); + if (jsonAsset != null && IsSpineData(jsonAsset)) + skeletonPaths.Add(str); + break; + case ".bytes": + if (str.ToLower().EndsWith(".skel.bytes", System.StringComparison.Ordinal)) { + if (IsSpineData((TextAsset)AssetDatabase.LoadAssetAtPath(str, typeof(TextAsset)))) + skeletonPaths.Add(str); + } + break; + } + } + + // Import atlases first. + var atlases = new List(); + foreach (string ap in atlasPaths) { + TextAsset atlasText = (TextAsset)AssetDatabase.LoadAssetAtPath(ap, typeof(TextAsset)); + AtlasAssetBase atlas = IngestSpineAtlas(atlasText); + atlases.Add(atlas); + } + + // Import skeletons and match them with atlases. + bool abortSkeletonImport = false; + foreach (string skeletonPath in skeletonPaths) { + if (!reimport && CheckForValidSkeletonData(skeletonPath)) { + ReloadSkeletonData(skeletonPath); + continue; + } + + string dir = Path.GetDirectoryName(skeletonPath); + + #if SPINE_TK2D + IngestSpineProject(AssetDatabase.LoadAssetAtPath(sp, typeof(TextAsset)) as TextAsset, null); + #else + var localAtlases = FindAtlasesAtPath(dir); + var requiredPaths = GetRequiredAtlasRegions(skeletonPath); + var atlasMatch = GetMatchingAtlas(requiredPaths, localAtlases); + if (atlasMatch != null || requiredPaths.Count == 0) { + IngestSpineProject(AssetDatabase.LoadAssetAtPath(skeletonPath, typeof(TextAsset)) as TextAsset, atlasMatch); + } else { + SkeletonImportDialog(skeletonPath, localAtlases, requiredPaths, ref abortSkeletonImport); + } + + if (abortSkeletonImport) + break; + #endif + } + // Any post processing of images + } + + static void ReloadSkeletonData (string skeletonJSONPath) { + string dir = Path.GetDirectoryName(skeletonJSONPath); + TextAsset textAsset = (TextAsset)AssetDatabase.LoadAssetAtPath(skeletonJSONPath, typeof(TextAsset)); + DirectoryInfo dirInfo = new DirectoryInfo(dir); + FileInfo[] files = dirInfo.GetFiles("*.asset"); + + foreach (var f in files) { + string localPath = dir + "/" + f.Name; + var obj = AssetDatabase.LoadAssetAtPath(localPath, typeof(Object)); + var skeletonDataAsset = obj as SkeletonDataAsset; + if (skeletonDataAsset != null) { + if (skeletonDataAsset.skeletonJSON == textAsset) { + if (Selection.activeObject == skeletonDataAsset) + Selection.activeObject = null; + + Debug.LogFormat("Changes to '{0}' detected. Clearing SkeletonDataAsset: {1}", skeletonJSONPath, localPath); + skeletonDataAsset.Clear(); + + string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(skeletonDataAsset)); + string lastHash = EditorPrefs.GetString(guid + "_hash"); + + // For some weird reason sometimes Unity loses the internal Object pointer, + // and as a result, all comparisons with null returns true. + // But the C# wrapper is still alive, so we can "restore" the object + // by reloading it from its Instance ID. + AtlasAssetBase[] skeletonDataAtlasAssets = skeletonDataAsset.atlasAssets; + if (skeletonDataAtlasAssets != null) { + for (int i = 0; i < skeletonDataAtlasAssets.Length; i++) { + if (!ReferenceEquals(null, skeletonDataAtlasAssets[i]) && + skeletonDataAtlasAssets[i].Equals(null) && + skeletonDataAtlasAssets[i].GetInstanceID() != 0 + ) { + skeletonDataAtlasAssets[i] = EditorUtility.InstanceIDToObject(skeletonDataAtlasAssets[i].GetInstanceID()) as AtlasAssetBase; + } + } + } + + SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(true); + string currentHash = skeletonData != null ? skeletonData.Hash : null; + + #if SPINE_SKELETONMECANIM + if (currentHash == null || lastHash != currentHash) + SkeletonBaker.UpdateMecanimClips(skeletonDataAsset); + #endif + + // if (currentHash == null || lastHash != currentHash) + // Do any upkeep on synchronized assets + + if (currentHash != null) + EditorPrefs.SetString(guid + "_hash", currentHash); + } + } + } + } + + #region Import Atlases + static List FindAtlasesAtPath (string path) { + List arr = new List(); + DirectoryInfo dir = new DirectoryInfo(path); + FileInfo[] assetInfoArr = dir.GetFiles("*.asset"); + + int subLen = Application.dataPath.Length - 6; + foreach (var f in assetInfoArr) { + string assetRelativePath = f.FullName.Substring(subLen, f.FullName.Length - subLen).Replace("\\", "/"); + Object obj = AssetDatabase.LoadAssetAtPath(assetRelativePath, typeof(AtlasAssetBase)); + if (obj != null) + arr.Add(obj as AtlasAssetBase); + } + + return arr; + } + + static AtlasAssetBase IngestSpineAtlas (TextAsset atlasText) { + if (atlasText == null) { + Debug.LogWarning("Atlas source cannot be null!"); + return null; + } + + string primaryName = Path.GetFileNameWithoutExtension(atlasText.name).Replace(".atlas", ""); + string assetPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(atlasText)); + + string atlasPath = assetPath + "/" + primaryName + AtlasSuffix + ".asset"; + + SpineAtlasAsset atlasAsset = (SpineAtlasAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(SpineAtlasAsset)); + + List vestigialMaterials = new List(); + + if (atlasAsset == null) + atlasAsset = SpineAtlasAsset.CreateInstance(); + else { + foreach (Material m in atlasAsset.materials) + vestigialMaterials.Add(m); + } + + protectFromStackGarbageCollection.Add(atlasAsset); + atlasAsset.atlasFile = atlasText; + + //strip CR + string atlasStr = atlasText.text; + atlasStr = atlasStr.Replace("\r", ""); + + string[] atlasLines = atlasStr.Split('\n'); + List pageFiles = new List(); + for (int i = 0; i < atlasLines.Length - 1; i++) { + if (atlasLines[i].Trim().Length == 0) + pageFiles.Add(atlasLines[i + 1].Trim()); + } + + var populatingMaterials = new List(pageFiles.Count);//atlasAsset.materials = new Material[pageFiles.Count]; + + for (int i = 0; i < pageFiles.Count; i++) { + string texturePath = assetPath + "/" + pageFiles[i]; + Texture2D texture = (Texture2D)AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D)); + + if (SpineEditorUtilities.Preferences.setTextureImporterSettings) { + TextureImporter texImporter = (TextureImporter)TextureImporter.GetAtPath(texturePath); + if (texImporter == null) { + Debug.LogWarning(string.Format("{0} ::: Texture asset \"{1}\" not found. Skipping. Please check your atlas file for renamed files.", atlasAsset.name, texturePath)); + continue; + } + + texImporter.textureCompression = TextureImporterCompression.Uncompressed; + texImporter.alphaSource = TextureImporterAlphaSource.FromInput; + texImporter.mipmapEnabled = false; + texImporter.alphaIsTransparency = false; // Prevent the texture importer from applying bleed to the transparent parts for PMA. + texImporter.spriteImportMode = SpriteImportMode.None; + texImporter.maxTextureSize = 2048; + + EditorUtility.SetDirty(texImporter); + AssetDatabase.ImportAsset(texturePath); + AssetDatabase.SaveAssets(); + } + + string pageName = Path.GetFileNameWithoutExtension(pageFiles[i]); + + //because this looks silly + if (pageName == primaryName && pageFiles.Count == 1) + pageName = "Material"; + + string materialPath = assetPath + "/" + primaryName + "_" + pageName + ".mat"; + Material mat = (Material)AssetDatabase.LoadAssetAtPath(materialPath, typeof(Material)); + + if (mat == null) { + mat = new Material(Shader.Find(SpineEditorUtilities.Preferences.defaultShader)); + AssetDatabase.CreateAsset(mat, materialPath); + } else { + vestigialMaterials.Remove(mat); + } + + mat.mainTexture = texture; + EditorUtility.SetDirty(mat); + AssetDatabase.SaveAssets(); + + populatingMaterials.Add(mat); //atlasAsset.materials[i] = mat; + } + + atlasAsset.materials = populatingMaterials.ToArray(); + + for (int i = 0; i < vestigialMaterials.Count; i++) + AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(vestigialMaterials[i])); + + if (AssetDatabase.GetAssetPath(atlasAsset) == "") + AssetDatabase.CreateAsset(atlasAsset, atlasPath); + else + atlasAsset.Clear(); + + EditorUtility.SetDirty(atlasAsset); + AssetDatabase.SaveAssets(); + + if (pageFiles.Count != atlasAsset.materials.Length) + Debug.LogWarning(string.Format("{0} :: Not all atlas pages were imported. If you rename your image files, please make sure you also edit the filenames specified in the atlas file.", atlasAsset.name)); + else + Debug.Log(string.Format("{0} :: Imported with {1} material", atlasAsset.name, atlasAsset.materials.Length)); + + // Iterate regions and bake marked. + Atlas atlas = atlasAsset.GetAtlas(); + FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic); + List regions = (List)field.GetValue(atlas); + string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset); + string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath); + string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name); + + bool hasBakedRegions = false; + for (int i = 0; i < regions.Count; i++) { + AtlasRegion region = regions[i]; + string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.AssetUtility.GetPathSafeName(region.name) + ".prefab").Replace("\\", "/"); + GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject)); + if (prefab != null) { + SkeletonBaker.BakeRegion(atlasAsset, region, false); + hasBakedRegions = true; + } + } + + if (hasBakedRegions) { + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + } + + protectFromStackGarbageCollection.Remove(atlasAsset); + return (AtlasAssetBase)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(AtlasAssetBase)); + } + #endregion + + #region Import SkeletonData (json or binary) + internal static SkeletonDataAsset IngestSpineProject (TextAsset spineJson, params AtlasAssetBase[] atlasAssets) { + string primaryName = Path.GetFileNameWithoutExtension(spineJson.name); + string assetPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(spineJson)); + string filePath = assetPath + "/" + primaryName + SkeletonDataSuffix + ".asset"; + + #if SPINE_TK2D + if (spineJson != null) { + SkeletonDataAsset skeletonDataAsset = (SkeletonDataAsset)AssetDatabase.LoadAssetAtPath(filePath, typeof(SkeletonDataAsset)); + if (skeletonDataAsset == null) { + skeletonDataAsset = SkeletonDataAsset.CreateInstance(); + skeletonDataAsset.skeletonJSON = spineJson; + skeletonDataAsset.fromAnimation = new string[0]; + skeletonDataAsset.toAnimation = new string[0]; + skeletonDataAsset.duration = new float[0]; + skeletonDataAsset.defaultMix = defaultMix; + skeletonDataAsset.scale = defaultScale; + + AssetDatabase.CreateAsset(skeletonDataAsset, filePath); + AssetDatabase.SaveAssets(); + } else { + skeletonDataAsset.Clear(); + skeletonDataAsset.GetSkeletonData(true); + } + + return skeletonDataAsset; + } else { + EditorUtility.DisplayDialog("Error!", "Tried to ingest null Spine data.", "OK"); + return null; + } + + #else + if (spineJson != null && atlasAssets != null) { + SkeletonDataAsset skeletonDataAsset = (SkeletonDataAsset)AssetDatabase.LoadAssetAtPath(filePath, typeof(SkeletonDataAsset)); + if (skeletonDataAsset == null) { + skeletonDataAsset = ScriptableObject.CreateInstance(); + { + skeletonDataAsset.atlasAssets = atlasAssets; + skeletonDataAsset.skeletonJSON = spineJson; + skeletonDataAsset.defaultMix = SpineEditorUtilities.Preferences.defaultMix; + skeletonDataAsset.scale = SpineEditorUtilities.Preferences.defaultScale; + } + + AssetDatabase.CreateAsset(skeletonDataAsset, filePath); + AssetDatabase.SaveAssets(); + } else { + skeletonDataAsset.atlasAssets = atlasAssets; + skeletonDataAsset.Clear(); + skeletonDataAsset.GetSkeletonData(true); + } + + return skeletonDataAsset; + } else { + EditorUtility.DisplayDialog("Error!", "Must specify both Spine JSON and AtlasAsset array", "OK"); + return null; + } + #endif + } + #endregion + + #region Spine Skeleton Data File Validation public static bool CheckForValidSkeletonData (string skeletonJSONPath) { string dir = Path.GetDirectoryName(skeletonJSONPath); TextAsset textAsset = (TextAsset)AssetDatabase.LoadAssetAtPath(skeletonJSONPath, typeof(TextAsset)); @@ -1348,157 +911,572 @@ namespace Spine.Unity.Editor { return isSpineData; } + #endregion + + #region Dialogs + public static void SkeletonImportDialog (string skeletonPath, List localAtlases, List requiredPaths, ref bool abortSkeletonImport) { + bool resolved = false; + while (!resolved) { + + string filename = Path.GetFileNameWithoutExtension(skeletonPath); + int result = EditorUtility.DisplayDialogComplex( + string.Format("AtlasAsset for \"{0}\"", filename), + string.Format("Could not automatically set the AtlasAsset for \"{0}\".\n\n (You may resolve this manually later.)", filename), + "Resolve atlases...", "Import without atlases", "Stop importing" + ); + + switch (result) { + case -1: + //Debug.Log("Select Atlas"); + AtlasAssetBase selectedAtlas = BrowseAtlasDialog(Path.GetDirectoryName(skeletonPath)); + if (selectedAtlas != null) { + localAtlases.Clear(); + localAtlases.Add(selectedAtlas); + var atlasMatch = AssetUtility.GetMatchingAtlas(requiredPaths, localAtlases); + if (atlasMatch != null) { + resolved = true; + AssetUtility.IngestSpineProject(AssetDatabase.LoadAssetAtPath(skeletonPath, typeof(TextAsset)) as TextAsset, atlasMatch); + } + } + break; + case 0: // Resolve AtlasAssets... + var atlasList = MultiAtlasDialog(requiredPaths, Path.GetDirectoryName(skeletonPath), Path.GetFileNameWithoutExtension(skeletonPath)); + if (atlasList != null) + AssetUtility.IngestSpineProject(AssetDatabase.LoadAssetAtPath(skeletonPath, typeof(TextAsset)) as TextAsset, atlasList.ToArray()); + + resolved = true; + break; + case 1: // Import without atlas + Debug.LogWarning("Imported with missing atlases. Skeleton will not render: " + Path.GetFileName(skeletonPath)); + AssetUtility.IngestSpineProject(AssetDatabase.LoadAssetAtPath(skeletonPath, typeof(TextAsset)) as TextAsset, new AtlasAssetBase[] { }); + resolved = true; + break; + case 2: // Stop importing all + abortSkeletonImport = true; + resolved = true; + break; + } + } + } + + public static List MultiAtlasDialog (List requiredPaths, string initialDirectory, string filename = "") { + List atlasAssets = new List(); + bool resolved = false; + string lastAtlasPath = initialDirectory; + while (!resolved) { + + // Build dialog box message. + var missingRegions = new List(requiredPaths); + var dialogText = new StringBuilder(); + { + dialogText.AppendLine(string.Format("SkeletonDataAsset for \"{0}\"", filename)); + dialogText.AppendLine("has missing regions."); + dialogText.AppendLine(); + dialogText.AppendLine("Current Atlases:"); + + if (atlasAssets.Count == 0) + dialogText.AppendLine("\t--none--"); + + for (int i = 0; i < atlasAssets.Count; i++) + dialogText.AppendLine("\t" + atlasAssets[i].name); + + dialogText.AppendLine(); + dialogText.AppendLine("Missing Regions:"); + + foreach (var atlasAsset in atlasAssets) { + var atlas = atlasAsset.GetAtlas(); + for (int i = 0; i < missingRegions.Count; i++) { + if (atlas.FindRegion(missingRegions[i]) != null) { + missingRegions.RemoveAt(i); + i--; + } + } + } + + int n = missingRegions.Count; + if (n == 0) + break; + + const int MaxListLength = 15; + for (int i = 0; (i < n && i < MaxListLength); i++) + dialogText.AppendLine(string.Format("\t {0}", missingRegions[i])); + + if (n > MaxListLength) + dialogText.AppendLine(string.Format("\t... {0} more...", n - MaxListLength)); + } + + // Show dialog box. + int result = EditorUtility.DisplayDialogComplex( + "SkeletonDataAsset has missing Atlas.", + dialogText.ToString(), + "Browse Atlas...", "Import anyway", "Cancel import" + ); + + switch (result) { + case 0: // Browse... + AtlasAssetBase selectedAtlasAsset = BrowseAtlasDialog(lastAtlasPath); + if (selectedAtlasAsset != null) { + if (!atlasAssets.Contains(selectedAtlasAsset)) { + var atlas = selectedAtlasAsset.GetAtlas(); + bool hasValidRegion = false; + foreach (string str in missingRegions) { + if (atlas.FindRegion(str) != null) { + hasValidRegion = true; + break; + } + } + atlasAssets.Add(selectedAtlasAsset); + } + } + break; + case 1: // Import anyway + resolved = true; + break; + case 2: // Cancel + atlasAssets = null; + resolved = true; + break; + } + } + + return atlasAssets; + } + + public static AtlasAssetBase BrowseAtlasDialog (string dirPath) { + string path = EditorUtility.OpenFilePanel("Select AtlasAsset...", dirPath, "asset"); + if (path == "") + return null; // Canceled or closed by user. + + int subLen = Application.dataPath.Length - 6; + string assetRelativePath = path.Substring(subLen, path.Length - subLen).Replace("\\", "/"); + + var obj = AssetDatabase.LoadAssetAtPath(assetRelativePath, typeof(AtlasAssetBase)); + if (obj == null || !(obj is AtlasAssetBase)) { + Debug.Log("Chosen asset was not of type AtlasAssetBase"); + return null; + } + + return (AtlasAssetBase)obj; + } + #endregion + + public static string GetPathSafeName (string name) { + foreach (char c in System.IO.Path.GetInvalidFileNameChars()) { // Doesn't handle more obscure file name limitations. + name = name.Replace(c, '_'); + } + return name; + } } - #endregion + public static class EditorInstantiation { + public delegate Component InstantiateDelegate (SkeletonDataAsset skeletonDataAsset); - #region SkeletonAnimation Menu - public static void IngestAdvancedRenderSettings (SkeletonRenderer skeletonRenderer) { - const string PMAShaderQuery = "Spine/Skeleton"; - const string TintBlackShaderQuery = "Tint Black"; + public class SkeletonComponentSpawnType { + public string menuLabel; + public InstantiateDelegate instantiateDelegate; + public bool isUI; + } - if (skeletonRenderer == null) return; - var skeletonDataAsset = skeletonRenderer.skeletonDataAsset; - if (skeletonDataAsset == null) return; + internal static readonly List additionalSpawnTypes = new List(); - bool pmaVertexColors = false; - bool tintBlack = false; - foreach (var atlasAsset in skeletonDataAsset.atlasAssets) { - if (!pmaVertexColors) { - foreach (Material m in atlasAsset.Materials) { - if (m.shader.name.Contains(PMAShaderQuery)) { - pmaVertexColors = true; - break; + public static void IngestAdvancedRenderSettings (SkeletonRenderer skeletonRenderer) { + const string PMAShaderQuery = "Spine/Skeleton"; + const string TintBlackShaderQuery = "Tint Black"; + + if (skeletonRenderer == null) + return; + var skeletonDataAsset = skeletonRenderer.skeletonDataAsset; + if (skeletonDataAsset == null) + return; + + bool pmaVertexColors = false; + bool tintBlack = false; + foreach (SpineAtlasAsset atlasAsset in skeletonDataAsset.atlasAssets) { + if (!pmaVertexColors) { + foreach (Material m in atlasAsset.materials) { + if (m.shader.name.Contains(PMAShaderQuery)) { + pmaVertexColors = true; + break; + } + } + } + + if (!tintBlack) { + foreach (Material m in atlasAsset.materials) { + if (m.shader.name.Contains(TintBlackShaderQuery)) { + tintBlack = true; + break; + } } } } - if (!tintBlack) { - foreach (Material m in atlasAsset.Materials) { - if (m.shader.name.Contains(TintBlackShaderQuery)) { - tintBlack = true; - break; + skeletonRenderer.pmaVertexColors = pmaVertexColors; + skeletonRenderer.tintBlack = tintBlack; + } + + public static SkeletonAnimation InstantiateSkeletonAnimation (SkeletonDataAsset skeletonDataAsset, string skinName, bool destroyInvalid = true) { + var skeletonData = skeletonDataAsset.GetSkeletonData(true); + var skin = skeletonData != null ? skeletonData.FindSkin(skinName) : null; + return InstantiateSkeletonAnimation(skeletonDataAsset, skin, destroyInvalid); + } + + public static SkeletonAnimation InstantiateSkeletonAnimation (SkeletonDataAsset skeletonDataAsset, Skin skin = null, bool destroyInvalid = true) { + SkeletonData data = skeletonDataAsset.GetSkeletonData(true); + + if (data == null) { + for (int i = 0; i < skeletonDataAsset.atlasAssets.Length; i++) { + string reloadAtlasPath = AssetDatabase.GetAssetPath(skeletonDataAsset.atlasAssets[i]); + skeletonDataAsset.atlasAssets[i] = (AtlasAssetBase)AssetDatabase.LoadAssetAtPath(reloadAtlasPath, typeof(AtlasAssetBase)); + } + data = skeletonDataAsset.GetSkeletonData(false); + } + + if (data == null) { + Debug.LogWarning("InstantiateSkeletonAnimation tried to instantiate a skeleton from an invalid SkeletonDataAsset."); + return null; + } + + string spineGameObjectName = string.Format("Spine GameObject ({0})", skeletonDataAsset.name.Replace("_SkeletonData", "")); + GameObject go = new GameObject(spineGameObjectName, typeof(MeshFilter), typeof(MeshRenderer), typeof(SkeletonAnimation)); + SkeletonAnimation newSkeletonAnimation = go.GetComponent(); + newSkeletonAnimation.skeletonDataAsset = skeletonDataAsset; + IngestAdvancedRenderSettings(newSkeletonAnimation); + + try { + newSkeletonAnimation.Initialize(false); + } catch (System.Exception e) { + if (destroyInvalid) { + Debug.LogWarning("Editor-instantiated SkeletonAnimation threw an Exception. Destroying GameObject to prevent orphaned GameObject."); + GameObject.DestroyImmediate(go); + } + throw e; + } + + // Set Defaults + bool noSkins = data.DefaultSkin == null && (data.Skins == null || data.Skins.Count == 0); // Support attachmentless/skinless SkeletonData. + skin = skin ?? data.DefaultSkin ?? (noSkins ? null : data.Skins.Items[0]); + if (skin != null) { + newSkeletonAnimation.initialSkinName = skin.Name; + newSkeletonAnimation.skeleton.SetSkin(skin); + } + + newSkeletonAnimation.zSpacing = SpineEditorUtilities.Preferences.defaultZSpacing; + + newSkeletonAnimation.skeleton.Update(0); + newSkeletonAnimation.state.Update(0); + newSkeletonAnimation.state.Apply(newSkeletonAnimation.skeleton); + newSkeletonAnimation.skeleton.UpdateWorldTransform(); + + return newSkeletonAnimation; + } + + #region SkeletonMecanim + #if SPINE_SKELETONMECANIM + public static SkeletonMecanim InstantiateSkeletonMecanim (SkeletonDataAsset skeletonDataAsset, string skinName) { + return InstantiateSkeletonMecanim(skeletonDataAsset, skeletonDataAsset.GetSkeletonData(true).FindSkin(skinName)); + } + + public static SkeletonMecanim InstantiateSkeletonMecanim (SkeletonDataAsset skeletonDataAsset, Skin skin = null) { + string spineGameObjectName = string.Format("Spine Mecanim GameObject ({0})", skeletonDataAsset.name.Replace("_SkeletonData", "")); + GameObject go = new GameObject(spineGameObjectName, typeof(MeshFilter), typeof(MeshRenderer), typeof(Animator), typeof(SkeletonMecanim)); + + if (skeletonDataAsset.controller == null) { + SkeletonBaker.GenerateMecanimAnimationClips(skeletonDataAsset); + Debug.Log(string.Format("Mecanim controller was automatically generated and assigned for {0}", skeletonDataAsset.name)); + } + + go.GetComponent().runtimeAnimatorController = skeletonDataAsset.controller; + + SkeletonMecanim anim = go.GetComponent(); + anim.skeletonDataAsset = skeletonDataAsset; + IngestAdvancedRenderSettings(anim); + + SkeletonData data = skeletonDataAsset.GetSkeletonData(true); + if (data == null) { + for (int i = 0; i < skeletonDataAsset.atlasAssets.Length; i++) { + string reloadAtlasPath = AssetDatabase.GetAssetPath(skeletonDataAsset.atlasAssets[i]); + skeletonDataAsset.atlasAssets[i] = (AtlasAssetBase)AssetDatabase.LoadAssetAtPath(reloadAtlasPath, typeof(AtlasAssetBase)); + } + data = skeletonDataAsset.GetSkeletonData(true); + } + + // Set defaults + skin = skin ?? data.DefaultSkin ?? data.Skins.Items[0]; + anim.zSpacing = SpineEditorUtilities.Preferences.defaultZSpacing; + + anim.Initialize(false); + anim.skeleton.SetSkin(skin); + anim.initialSkinName = skin.Name; + + anim.skeleton.Update(0); + anim.skeleton.UpdateWorldTransform(); + anim.LateUpdate(); + + return anim; + } + #endif + #endregion + } + + public static class DragAndDropInstantiation { + public struct SpawnMenuData { + public Vector3 spawnPoint; + public SkeletonDataAsset skeletonDataAsset; + public EditorInstantiation.InstantiateDelegate instantiateDelegate; + public bool isUI; + } + + public static void SceneViewDragAndDrop (SceneView sceneview) { + var current = UnityEngine.Event.current; + var references = DragAndDrop.objectReferences; + if (current.type == EventType.Layout) + return; + + // Allow drag and drop of one SkeletonDataAsset. + if (references.Length == 1) { + var skeletonDataAsset = references[0] as SkeletonDataAsset; + if (skeletonDataAsset != null) { + var mousePos = current.mousePosition; + + bool invalidSkeletonData = skeletonDataAsset.GetSkeletonData(true) == null; + if (invalidSkeletonData) { + DragAndDrop.visualMode = DragAndDropVisualMode.Rejected; + Handles.BeginGUI(); + GUI.Label(new Rect(mousePos + new Vector2(20f, 20f), new Vector2(400f, 40f)), new GUIContent(string.Format("{0} is invalid.\nCannot create new Spine GameObject.", skeletonDataAsset.name), SpineEditorUtilities.Icons.warning)); + Handles.EndGUI(); + return; + } else { + DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + Handles.BeginGUI(); + GUI.Label(new Rect(mousePos + new Vector2(20f, 20f), new Vector2(400f, 20f)), new GUIContent(string.Format("Create Spine GameObject ({0})", skeletonDataAsset.skeletonJSON.name), SpineEditorUtilities.Icons.skeletonDataAssetIcon)); + Handles.EndGUI(); + + if (current.type == EventType.DragPerform) { + RectTransform rectTransform = (Selection.activeGameObject == null) ? null : Selection.activeGameObject.GetComponent(); + Plane plane = (rectTransform == null) ? new Plane(Vector3.back, Vector3.zero) : new Plane(-rectTransform.forward, rectTransform.position); + Vector3 spawnPoint = MousePointToWorldPoint2D(mousePos, sceneview.camera, plane); + ShowInstantiateContextMenu(skeletonDataAsset, spawnPoint); + DragAndDrop.AcceptDrag(); + current.Use(); + } } } } } - skeletonRenderer.pmaVertexColors = pmaVertexColors; - skeletonRenderer.tintBlack = tintBlack; - } + public static void ShowInstantiateContextMenu (SkeletonDataAsset skeletonDataAsset, Vector3 spawnPoint) { + var menu = new GenericMenu(); - public static SkeletonAnimation InstantiateSkeletonAnimation (SkeletonDataAsset skeletonDataAsset, string skinName, bool destroyInvalid = true) { - var skeletonData = skeletonDataAsset.GetSkeletonData(true); - var skin = skeletonData != null ? skeletonData.FindSkin(skinName) : null; - return InstantiateSkeletonAnimation(skeletonDataAsset, skin, destroyInvalid); - } + // SkeletonAnimation + menu.AddItem(new GUIContent("SkeletonAnimation"), false, HandleSkeletonComponentDrop, new SpawnMenuData { + skeletonDataAsset = skeletonDataAsset, + spawnPoint = spawnPoint, + instantiateDelegate = (data) => EditorInstantiation.InstantiateSkeletonAnimation(data), + isUI = false + }); - public static SkeletonAnimation InstantiateSkeletonAnimation (SkeletonDataAsset skeletonDataAsset, Skin skin = null, bool destroyInvalid = true) { - SkeletonData data = skeletonDataAsset.GetSkeletonData(true); - - if (data == null) { - for (int i = 0; i < skeletonDataAsset.atlasAssets.Length; i++) { - string reloadAtlasPath = AssetDatabase.GetAssetPath(skeletonDataAsset.atlasAssets[i]); - skeletonDataAsset.atlasAssets[i] = (AtlasAssetBase)AssetDatabase.LoadAssetAtPath(reloadAtlasPath, typeof(AtlasAssetBase)); + // SkeletonGraphic + var skeletonGraphicInspectorType = System.Type.GetType("Spine.Unity.Editor.SkeletonGraphicInspector"); + if (skeletonGraphicInspectorType != null) { + var graphicInstantiateDelegate = skeletonGraphicInspectorType.GetMethod("SpawnSkeletonGraphicFromDrop", BindingFlags.Static | BindingFlags.Public); + if (graphicInstantiateDelegate != null) + menu.AddItem(new GUIContent("SkeletonGraphic (UI)"), false, HandleSkeletonComponentDrop, new SpawnMenuData { + skeletonDataAsset = skeletonDataAsset, + spawnPoint = spawnPoint, + instantiateDelegate = System.Delegate.CreateDelegate(typeof(EditorInstantiation.InstantiateDelegate), graphicInstantiateDelegate) as EditorInstantiation.InstantiateDelegate, + isUI = true + }); } - data = skeletonDataAsset.GetSkeletonData(false); + + #if SPINE_SKELETONMECANIM + menu.AddSeparator(""); + // SkeletonMecanim + menu.AddItem(new GUIContent("SkeletonMecanim"), false, HandleSkeletonComponentDrop, new SpawnMenuData { + skeletonDataAsset = skeletonDataAsset, + spawnPoint = spawnPoint, + instantiateDelegate = (data) => EditorInstantiation.InstantiateSkeletonMecanim(data) + }); + #endif + + menu.ShowAsContext(); } - if (data == null) { - Debug.LogWarning("InstantiateSkeletonAnimation tried to instantiate a skeleton from an invalid SkeletonDataAsset."); - return null; - } + public static void HandleSkeletonComponentDrop (object spawnMenuData) { + var data = (SpawnMenuData)spawnMenuData; - string spineGameObjectName = string.Format("Spine GameObject ({0})", skeletonDataAsset.name.Replace("_SkeletonData", "")); - GameObject go = new GameObject(spineGameObjectName, typeof(MeshFilter), typeof(MeshRenderer), typeof(SkeletonAnimation)); - SkeletonAnimation newSkeletonAnimation = go.GetComponent(); - newSkeletonAnimation.skeletonDataAsset = skeletonDataAsset; - IngestAdvancedRenderSettings(newSkeletonAnimation); - - try { - newSkeletonAnimation.Initialize(false); - } catch (System.Exception e) { - if (destroyInvalid) { - Debug.LogWarning("Editor-instantiated SkeletonAnimation threw an Exception. Destroying GameObject to prevent orphaned GameObject."); - GameObject.DestroyImmediate(go); + if (data.skeletonDataAsset.GetSkeletonData(true) == null) { + EditorUtility.DisplayDialog("Invalid SkeletonDataAsset", "Unable to create Spine GameObject.\n\nPlease check your SkeletonDataAsset.", "Ok"); + return; } - throw e; + + bool isUI = data.isUI; + + Component newSkeletonComponent = data.instantiateDelegate.Invoke(data.skeletonDataAsset); + GameObject newGameObject = newSkeletonComponent.gameObject; + Transform newTransform = newGameObject.transform; + + var activeGameObject = Selection.activeGameObject; + if (isUI && activeGameObject != null) + newTransform.SetParent(activeGameObject.transform, false); + + newTransform.position = isUI ? data.spawnPoint : RoundVector(data.spawnPoint, 2); + + if (isUI && (activeGameObject == null || activeGameObject.GetComponent() == null)) + Debug.Log("Created a UI Skeleton GameObject not under a RectTransform. It may not be visible until you parent it to a canvas."); + + if (!isUI && activeGameObject != null && activeGameObject.transform.localScale != Vector3.one) + Debug.Log("New Spine GameObject was parented to a scaled Transform. It may not be the intended size."); + + Selection.activeGameObject = newGameObject; + //EditorGUIUtility.PingObject(newGameObject); // Doesn't work when setting activeGameObject. + Undo.RegisterCreatedObjectUndo(newGameObject, "Create Spine GameObject"); } - // Set Defaults - bool noSkins = data.DefaultSkin == null && (data.Skins == null || data.Skins.Count == 0); // Support attachmentless/skinless SkeletonData. - skin = skin ?? data.DefaultSkin ?? (noSkins ? null : data.Skins.Items[0]); - if (skin != null) { - newSkeletonAnimation.initialSkinName = skin.Name; - newSkeletonAnimation.skeleton.SetSkin(skin); + /// + /// Rounds off vector components to a number of decimal digits. + /// + public static Vector3 RoundVector (Vector3 vector, int digits) { + vector.x = (float)System.Math.Round(vector.x, digits); + vector.y = (float)System.Math.Round(vector.y, digits); + vector.z = (float)System.Math.Round(vector.z, digits); + return vector; } - newSkeletonAnimation.zSpacing = defaultZSpacing; - - newSkeletonAnimation.skeleton.Update(0); - newSkeletonAnimation.state.Update(0); - newSkeletonAnimation.state.Apply(newSkeletonAnimation.skeleton); - newSkeletonAnimation.skeleton.UpdateWorldTransform(); - - return newSkeletonAnimation; - } - #endregion - - #region SkeletonMecanim - #if SPINE_SKELETONMECANIM - static void UpdateMecanimClips (SkeletonDataAsset skeletonDataAsset) { - if (skeletonDataAsset.controller == null) - return; - - SkeletonBaker.GenerateMecanimAnimationClips(skeletonDataAsset); - } - - public static SkeletonMecanim InstantiateSkeletonMecanim (SkeletonDataAsset skeletonDataAsset, string skinName) { - return InstantiateSkeletonMecanim(skeletonDataAsset, skeletonDataAsset.GetSkeletonData(true).FindSkin(skinName)); - } - - public static SkeletonMecanim InstantiateSkeletonMecanim (SkeletonDataAsset skeletonDataAsset, Skin skin = null) { - string spineGameObjectName = string.Format("Spine Mecanim GameObject ({0})", skeletonDataAsset.name.Replace("_SkeletonData", "")); - GameObject go = new GameObject(spineGameObjectName, typeof(MeshFilter), typeof(MeshRenderer), typeof(Animator), typeof(SkeletonMecanim)); - - if (skeletonDataAsset.controller == null) { - SkeletonBaker.GenerateMecanimAnimationClips(skeletonDataAsset); - Debug.Log(string.Format("Mecanim controller was automatically generated and assigned for {0}", skeletonDataAsset.name)); + /// + /// Converts a mouse point to a world point on a plane. + /// + static Vector3 MousePointToWorldPoint2D (Vector2 mousePosition, Camera camera, Plane plane) { + var screenPos = new Vector3(mousePosition.x, camera.pixelHeight - mousePosition.y, 0f); + var ray = camera.ScreenPointToRay(screenPos); + float distance; + bool hit = plane.Raycast(ray, out distance); + return ray.GetPoint(distance); } + } - go.GetComponent().runtimeAnimatorController = skeletonDataAsset.controller; + static class HierarchyHandler { + static Dictionary skeletonRendererTable = new Dictionary(); + static Dictionary skeletonUtilityBoneTable = new Dictionary(); + static Dictionary boundingBoxFollowerTable = new Dictionary(); - SkeletonMecanim anim = go.GetComponent(); - anim.skeletonDataAsset = skeletonDataAsset; - IngestAdvancedRenderSettings(anim); + #if UNITY_2017_2_OR_NEWER + internal static void IconsOnPlaymodeStateChanged (PlayModeStateChange stateChange) { + #else + internal static void IconsOnPlaymodeStateChanged () { + #endif + skeletonRendererTable.Clear(); + skeletonUtilityBoneTable.Clear(); + boundingBoxFollowerTable.Clear(); - SkeletonData data = skeletonDataAsset.GetSkeletonData(true); - if (data == null) { - for (int i = 0; i < skeletonDataAsset.atlasAssets.Length; i++) { - string reloadAtlasPath = AssetDatabase.GetAssetPath(skeletonDataAsset.atlasAssets[i]); - skeletonDataAsset.atlasAssets[i] = (AtlasAssetBase)AssetDatabase.LoadAssetAtPath(reloadAtlasPath, typeof(AtlasAssetBase)); + #if UNITY_2018 + EditorApplication.hierarchyChanged -= IconsOnChanged; + #else + EditorApplication.hierarchyWindowChanged -= IconsOnChanged; + #endif + EditorApplication.hierarchyWindowItemOnGUI -= IconsOnGUI; + + if (!Application.isPlaying && Preferences.showHierarchyIcons) { + #if UNITY_2018 + EditorApplication.hierarchyChanged += IconsOnChanged; + #else + EditorApplication.hierarchyWindowChanged += IconsOnChanged; + #endif + EditorApplication.hierarchyWindowItemOnGUI += IconsOnGUI; + IconsOnChanged(); } - data = skeletonDataAsset.GetSkeletonData(true); } - // Set defaults - skin = skin ?? data.DefaultSkin ?? data.Skins.Items[0]; - anim.zSpacing = defaultZSpacing; + internal static void IconsOnChanged () { + skeletonRendererTable.Clear(); + skeletonUtilityBoneTable.Clear(); + boundingBoxFollowerTable.Clear(); - anim.Initialize(false); - anim.skeleton.SetSkin(skin); - anim.initialSkinName = skin.Name; + SkeletonRenderer[] arr = Object.FindObjectsOfType(); + foreach (SkeletonRenderer r in arr) + skeletonRendererTable[r.gameObject.GetInstanceID()] = r.gameObject; - anim.skeleton.Update(0); - anim.skeleton.UpdateWorldTransform(); - anim.LateUpdate(); + SkeletonUtilityBone[] boneArr = Object.FindObjectsOfType(); + foreach (SkeletonUtilityBone b in boneArr) + skeletonUtilityBoneTable[b.gameObject.GetInstanceID()] = b; - return anim; + BoundingBoxFollower[] bbfArr = Object.FindObjectsOfType(); + foreach (BoundingBoxFollower bbf in bbfArr) + boundingBoxFollowerTable[bbf.gameObject.GetInstanceID()] = bbf; + } + + internal static void IconsOnGUI (int instanceId, Rect selectionRect) { + Rect r = new Rect(selectionRect); + if (skeletonRendererTable.ContainsKey(instanceId)) { + r.x = r.width - 15; + r.width = 15; + GUI.Label(r, Icons.spine); + } else if (skeletonUtilityBoneTable.ContainsKey(instanceId)) { + r.x -= 26; + if (skeletonUtilityBoneTable[instanceId] != null) { + if (skeletonUtilityBoneTable[instanceId].transform.childCount == 0) + r.x += 13; + r.y += 2; + r.width = 13; + r.height = 13; + if (skeletonUtilityBoneTable[instanceId].mode == SkeletonUtilityBone.Mode.Follow) + GUI.DrawTexture(r, Icons.bone); + else + GUI.DrawTexture(r, Icons.poseBones); + } + } else if (boundingBoxFollowerTable.ContainsKey(instanceId)) { + r.x -= 26; + if (boundingBoxFollowerTable[instanceId] != null) { + if (boundingBoxFollowerTable[instanceId].transform.childCount == 0) + r.x += 13; + r.y += 2; + r.width = 13; + r.height = 13; + GUI.DrawTexture(r, Icons.boundingBox); + } + } + } + + internal static void HandleDragAndDrop (int instanceId, Rect selectionRect) { + // HACK: Uses EditorApplication.hierarchyWindowItemOnGUI. + // Only works when there is at least one item in the scene. + var current = UnityEngine.Event.current; + var eventType = current.type; + bool isDraggingEvent = eventType == EventType.DragUpdated; + bool isDropEvent = eventType == EventType.DragPerform; + if (isDraggingEvent || isDropEvent) { + var mouseOverWindow = EditorWindow.mouseOverWindow; + if (mouseOverWindow != null) { + + // One, existing, valid SkeletonDataAsset + var references = UnityEditor.DragAndDrop.objectReferences; + if (references.Length == 1) { + var skeletonDataAsset = references[0] as SkeletonDataAsset; + if (skeletonDataAsset != null && skeletonDataAsset.GetSkeletonData(true) != null) { + + // Allow drag-and-dropping anywhere in the Hierarchy Window. + // HACK: string-compare because we can't get its type via reflection. + const string HierarchyWindow = "UnityEditor.SceneHierarchyWindow"; + if (HierarchyWindow.Equals(mouseOverWindow.GetType().ToString(), System.StringComparison.Ordinal)) { + if (isDraggingEvent) { + UnityEditor.DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + current.Use(); + } else if (isDropEvent) { + DragAndDropInstantiation.ShowInstantiateContextMenu(skeletonDataAsset, Vector3.zero); + UnityEditor.DragAndDrop.AcceptDrag(); + current.Use(); + return; + } + } + + } + } + } + } + + } } -#endif - #endregion - #region SpineTK2DEditorUtility internal static class SpineTK2DEditorUtility { const string SPINE_TK2D_DEFINE = "SPINE_TK2D"; @@ -1561,14 +1539,6 @@ namespace Spine.Unity.Editor { } } } - #endregion - - public static string GetPathSafeName (string name) { - foreach (char c in System.IO.Path.GetInvalidFileNameChars()) { // Doesn't handle more obscure file name limitations. - name = name.Replace(c, '_'); - } - return name; - } } public static class SpineHandles { diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Modules/SkeletonGraphic/Editor/SkeletonGraphicInspector.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Modules/SkeletonGraphic/Editor/SkeletonGraphicInspector.cs index bf6bda947..12ab21d20 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Modules/SkeletonGraphic/Editor/SkeletonGraphicInspector.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Modules/SkeletonGraphic/Editor/SkeletonGraphicInspector.cs @@ -193,7 +193,7 @@ namespace Spine.Unity.Editor { } skin = skin ?? data.DefaultSkin ?? data.Skins.Items[0]; - graphic.MeshGenerator.settings.zSpacing = SpineEditorUtilities.defaultZSpacing; + graphic.MeshGenerator.settings.zSpacing = SpineEditorUtilities.Preferences.defaultZSpacing; graphic.Initialize(false); if (skin != null) graphic.Skeleton.SetSkin(skin); diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/BoneFollower.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/BoneFollower.cs index 6ce6f147c..c462b262c 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/BoneFollower.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/BoneFollower.cs @@ -164,19 +164,14 @@ namespace Spine.Unity { if (followBoneRotation) { Vector3 worldRotation = skeletonTransform.rotation.eulerAngles; if (followLocalScale && bone.scaleX < 0) boneWorldRotation += 180f; - #if UNITY_5_6_OR_NEWER thisTransform.SetPositionAndRotation(targetWorldPosition, Quaternion.Euler(worldRotation.x, worldRotation.y, worldRotation.z + boneWorldRotation)); - #else - thisTransform.position = targetWorldPosition; - thisTransform.rotation = Quaternion.Euler(worldRotation.x, worldRotation.y, worldRotation.z + bone.WorldRotationX); - #endif } else { thisTransform.position = targetWorldPosition; } } Vector3 localScale = followLocalScale ? new Vector3(bone.scaleX, bone.scaleY, 1f) : new Vector3(1f, 1f, 1f); - if (followSkeletonFlip) localScale.y *= bone.skeleton.flipX ^ bone.skeleton.flipY ? -1f : 1f; + if (followSkeletonFlip) localScale.y *= Mathf.Sign(bone.skeleton.scaleX * bone.skeleton.scaleY); thisTransform.localScale = localScale; } } diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/PointFollower.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/PointFollower.cs index f3702beb5..e75309356 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/PointFollower.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/PointFollower.cs @@ -145,7 +145,7 @@ namespace Spine.Unity { if (followSkeletonFlip) { Vector3 localScale = thisTransform.localScale; - localScale.y = Mathf.Abs(localScale.y) * (bone.skeleton.flipX ^ bone.skeleton.flipY ? -1f : 1f); + localScale.y = Mathf.Abs(localScale.y) * Mathf.Sign(bone.skeleton.scaleX * bone.skeleton.scaleY); thisTransform.localScale = localScale; } } diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs index 21907bb7f..e4e25d464 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs @@ -207,8 +207,8 @@ namespace Spine.Unity { rendererBuffers.Initialize(); skeleton = new Skeleton(skeletonData) { - flipX = initialFlipX, - flipY = initialFlipY + scaleX = initialFlipX ? -1 : 1, + scaleY = initialFlipY ? -1 : 1 }; if (!string.IsNullOrEmpty(initialSkinName) && !string.Equals(initialSkinName, "default", System.StringComparison.Ordinal)) diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/SpineMesh.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/SpineMesh.cs index 9d4b12032..9b76040c5 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/SpineMesh.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/SpineMesh.cs @@ -308,10 +308,10 @@ namespace Spine.Unity { #if SPINE_TRIANGLECHECK var clippingAttachment = attachment as ClippingAttachment; if (clippingAttachment != null) { - clippingEndSlot = clippingAttachment.endSlot; - clippingAttachmentSource = i; - current.hasClipping = true; - skeletonHasClipping = true; + clippingEndSlot = clippingAttachment.endSlot; + clippingAttachmentSource = i; + current.hasClipping = true; + skeletonHasClipping = true; } #endif noRender = true; diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Ragdoll/SkeletonRagdoll.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Ragdoll/SkeletonRagdoll.cs index d43fb19ac..da7248f36 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Ragdoll/SkeletonRagdoll.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Ragdoll/SkeletonRagdoll.cs @@ -313,8 +313,8 @@ namespace Spine.Unity.Modules { } void UpdateSpineSkeleton (ISkeletonAnimation skeletonRenderer) { - bool flipX = skeleton.flipX; - bool flipY = skeleton.flipY; + bool flipX = skeleton.ScaleX < 0; + bool flipY = skeleton.ScaleY < 0; bool flipXOR = flipX ^ flipY; bool flipOR = flipX || flipY; diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Ragdoll/SkeletonRagdoll2D.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Ragdoll/SkeletonRagdoll2D.cs index 0e9c0aba2..f66015a74 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Ragdoll/SkeletonRagdoll2D.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Ragdoll/SkeletonRagdoll2D.cs @@ -311,8 +311,8 @@ namespace Spine.Unity.Modules { /// Performed every skeleton animation update to translate Unity Transforms positions into Spine bone transforms. void UpdateSpineSkeleton (ISkeletonAnimation animatedSkeleton) { - bool flipX = skeleton.flipX; - bool flipY = skeleton.flipY; + bool flipX = skeleton.ScaleX < 0; + bool flipY = skeleton.ScaleY < 0; bool flipXOR = flipX ^ flipY; bool flipOR = flipX || flipY; var startingBone = this.StartingBone; diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Spine-Skeleton-Fill.shader b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Spine-Skeleton-Fill.shader index 161b03b59..f331ada19 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Spine-Skeleton-Fill.shader +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Shaders/Spine-Skeleton-Fill.shader @@ -1,4 +1,4 @@ -// - Unlit + no shadow +// - Unlit // - Premultiplied Alpha Blending (Optional straight alpha input) // - Double-sided, no depth @@ -7,6 +7,7 @@ Shader "Spine/Skeleton Fill" { _FillColor ("FillColor", Color) = (1,1,1,1) _FillPhase ("FillPhase", Range(0, 1)) = 0 [NoScaleOffset] _MainTex ("MainTex", 2D) = "white" {} + _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1 [Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0 } SubShader { @@ -59,6 +60,46 @@ Shader "Spine/Skeleton Fill" { } ENDCG } + + Pass { + Name "Caster" + Tags { "LightMode"="ShadowCaster" } + Offset 1, 1 + ZWrite On + ZTest LEqual + + Fog { Mode Off } + Cull Off + Lighting Off + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_shadowcaster + #pragma fragmentoption ARB_precision_hint_fastest + #include "UnityCG.cginc" + sampler2D _MainTex; + fixed _Cutoff; + + struct VertexOutput { + V2F_SHADOW_CASTER; + float2 uv : TEXCOORD1; + }; + + VertexOutput vert (appdata_base v) { + VertexOutput o; + o.uv = v.texcoord; + TRANSFER_SHADOW_CASTER(o) + return o; + } + + float4 frag (VertexOutput i) : COLOR { + fixed4 texcol = tex2D(_MainTex, i.uv); + clip(texcol.a - _Cutoff); + SHADOW_CASTER_FRAGMENT(i) + } + ENDCG + } } FallBack "Diffuse" -} \ No newline at end of file +} diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/BoneFollowerGraphic.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/BoneFollowerGraphic.cs index f399e9bc2..e833c4453 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/BoneFollowerGraphic.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/BoneFollowerGraphic.cs @@ -123,7 +123,7 @@ namespace Spine.Unity { } Vector3 localScale = followLocalScale ? new Vector3(bone.scaleX, bone.scaleY, 1f) : new Vector3(1f, 1f, 1f); - if (followSkeletonFlip) localScale.y *= bone.skeleton.flipX ^ bone.skeleton.flipY ? -1f : 1f; + if (followSkeletonFlip) localScale.y *= Mathf.Sign(bone.skeleton.scaleX * bone.skeleton.scaleY); thisTransform.localScale = localScale; } diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs index 43519c3d2..d76021a58 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs @@ -82,8 +82,8 @@ namespace Spine.Unity { // Only provide visual feedback to inspector changes in Unity Editor Edit mode. if (!Application.isPlaying) { - skeleton.flipX = this.initialFlipX; - skeleton.flipY = this.initialFlipY; + skeleton.scaleX = this.initialFlipX ? -1 : 1; + skeleton.scaleY = this.initialFlipY ? -1 : 1; skeleton.SetToSetupPose(); if (!string.IsNullOrEmpty(startingAnimation)) @@ -233,8 +233,8 @@ namespace Spine.Unity { } this.skeleton = new Skeleton(skeletonData) { - flipX = this.initialFlipX, - flipY = this.initialFlipY + scaleX = this.initialFlipX ? -1 : 1, + scaleY = this.initialFlipY ? -1 : 1 }; meshBuffers = new DoubleBuffered(); diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineAnimationState/SpineAnimationStateMixerBehaviour.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineAnimationState/SpineAnimationStateMixerBehaviour.cs index 2b593e1fb..a4994157c 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineAnimationState/SpineAnimationStateMixerBehaviour.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineAnimationState/SpineAnimationStateMixerBehaviour.cs @@ -40,6 +40,7 @@ namespace Spine.Unity.Playables { public class SpineAnimationStateMixerBehaviour : PlayableBehaviour { float[] lastInputWeights; + public int trackIndex; // NOTE: This function is called at runtime and edit time. Keep that in mind when setting the values of properties. public override void ProcessFrame (Playable playable, FrameData info, object playerData) { @@ -80,10 +81,10 @@ namespace Spine.Unity.Playables { if (clipData.animationReference == null) { float mixDuration = clipData.customDuration ? clipData.mixDuration : state.Data.DefaultMix; - state.SetEmptyAnimation(0, mixDuration); + state.SetEmptyAnimation(trackIndex, mixDuration); } else { if (clipData.animationReference.Animation != null) { - Spine.TrackEntry trackEntry = state.SetAnimation(0, clipData.animationReference.Animation, clipData.loop); + Spine.TrackEntry trackEntry = state.SetAnimation(trackIndex, clipData.animationReference.Animation, clipData.loop); //trackEntry.TrackTime = (float)inputPlayable.GetTime(); // More accurate time-start? trackEntry.EventThreshold = clipData.eventThreshold; diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineAnimationState/SpineAnimationStateTrack.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineAnimationState/SpineAnimationStateTrack.cs index 3bce9be06..4c51e7d4e 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineAnimationState/SpineAnimationStateTrack.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineAnimationState/SpineAnimationStateTrack.cs @@ -38,8 +38,13 @@ namespace Spine.Unity.Playables { [TrackClipType(typeof(SpineAnimationStateClip))] [TrackBindingType(typeof(SkeletonAnimation))] public class SpineAnimationStateTrack : TrackAsset { + public int trackIndex = 0; + public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount) { - return ScriptPlayable.Create (graph, inputCount); + var scriptPlayable = ScriptPlayable.Create(graph, inputCount); + var mixerBehaviour = scriptPlayable.GetBehaviour(); + mixerBehaviour.trackIndex = this.trackIndex; + return scriptPlayable; } } } diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineSkeletonFlip/SpineSkeletonFlipMixerBehaviour.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineSkeletonFlip/SpineSkeletonFlipMixerBehaviour.cs index 2330aae56..1ce745d12 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineSkeletonFlip/SpineSkeletonFlipMixerBehaviour.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Timeline/SpineSkeletonFlip/SpineSkeletonFlipMixerBehaviour.cs @@ -52,8 +52,8 @@ namespace Spine.Unity.Playables { var skeleton = playableHandle.Skeleton; if (!m_FirstFrameHappened) { - defaultFlipX = skeleton.flipX; - defaultFlipY = skeleton.flipY; + defaultFlipX = skeleton.FlipX; + defaultFlipY = skeleton.FlipY; m_FirstFrameHappened = true; } @@ -71,8 +71,8 @@ namespace Spine.Unity.Playables { totalWeight += inputWeight; if (inputWeight > greatestWeight) { - skeleton.flipX = input.flipX; - skeleton.flipY = input.flipY; + skeleton.FlipX = input.flipX; + skeleton.FlipY = input.flipY; greatestWeight = inputWeight; } @@ -81,8 +81,8 @@ namespace Spine.Unity.Playables { } if (currentInputs != 1 && 1f - totalWeight > greatestWeight) { - skeleton.flipX = defaultFlipX; - skeleton.flipY = defaultFlipY; + skeleton.FlipX = defaultFlipX; + skeleton.FlipY = defaultFlipY; } } @@ -93,8 +93,8 @@ namespace Spine.Unity.Playables { return; var skeleton = playableHandle.Skeleton; - skeleton.flipX = defaultFlipX; - skeleton.flipY = defaultFlipY; + skeleton.FlipX = defaultFlipX; + skeleton.FlipY = defaultFlipY; } } diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonExtensions.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonExtensions.cs index 06c2f57f0..6044c6d55 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonExtensions.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonExtensions.cs @@ -194,9 +194,8 @@ namespace Spine.Unity { public static Material GetMaterial (this Attachment a) { object rendererObject = null; var renderableAttachment = a as IHasRendererObject; - if (renderableAttachment != null) { - rendererObject = renderableAttachment.RendererObject; - } + if (renderableAttachment != null) + rendererObject = renderableAttachment.RendererObject; if (rendererObject == null) return null; diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonUtility/SkeletonUtility.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonUtility/SkeletonUtility.cs index a46959fbc..d48234ffd 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonUtility/SkeletonUtility.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonUtility/SkeletonUtility.cs @@ -123,10 +123,10 @@ namespace Spine.Unity { var skeleton = skeletonRenderer.skeleton; if (boneRoot != null && skeleton != null) { Vector3 flipScale = Vector3.one; - if (skeleton.FlipX) + if (skeleton.scaleX < 0) flipScale.x = -1; - if (skeleton.FlipY) + if (skeleton.scaleY < 0) flipScale.y = -1; boneRoot.localScale = flipScale; diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonUtility/SkeletonUtilityBone.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonUtility/SkeletonUtilityBone.cs index 1cec0264b..771045010 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonUtility/SkeletonUtilityBone.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonUtility/SkeletonUtilityBone.cs @@ -119,7 +119,7 @@ namespace Spine.Unity { } var thisTransform = cachedTransform; - float skeletonFlipRotation = (skeleton.flipX ^ skeleton.flipY) ? -1f : 1f; + float skeletonFlipRotation = Mathf.Sign(skeleton.scaleX * skeleton.scaleY); if (mode == Mode.Follow) { switch (phase) { case UpdatePhase.Local: