void SSpineWidget::UpdateMesh(int32 LayerId, FSlateWindowElementList& OutDrawElements, const FGeometry& AllottedGeometry, Skeleton* Skeleton) { TArray<FVector> vertices; TArray<int32> indices; TArray<FVector2D> uvs; TArray<FColor> colors; TArray<FVector> darkColors; int idx = 0; int meshSection = 0; UMaterialInstanceDynamic* lastMaterial = nullptr; SkeletonClipping &clipper = widget->clipper; Vector<float> &worldVertices = widget->worldVertices; float depthOffset = 0; unsigned short quadIndices[] = { 0, 1, 2, 0, 2, 3 }; for (int i = 0; i < (int)Skeleton->getSlots().size(); ++i) { Vector<float> &attachmentVertices = worldVertices; unsigned short* attachmentIndices = nullptr; int numVertices; int numIndices; AtlasRegion* attachmentAtlasRegion = nullptr; Color attachmentColor; attachmentColor.set(1, 1, 1, 1); float* attachmentUvs = nullptr; Slot* slot = Skeleton->getDrawOrder()[i]; Attachment* attachment = slot->getAttachment(); if (!attachment) continue; if (!attachment->getRTTI().isExactly(RegionAttachment::rtti) && !attachment->getRTTI().isExactly(MeshAttachment::rtti) && !attachment->getRTTI().isExactly(ClippingAttachment::rtti)) continue; if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) { RegionAttachment* regionAttachment = (RegionAttachment*)attachment; attachmentColor.set(regionAttachment->getColor()); attachmentAtlasRegion = (AtlasRegion*)regionAttachment->getRendererObject(); regionAttachment->computeWorldVertices(slot->getBone(), attachmentVertices, 0, 2); attachmentIndices = quadIndices; attachmentUvs = regionAttachment->getUVs().buffer(); numVertices = 4; numIndices = 6; } else if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) { MeshAttachment* mesh = (MeshAttachment*)attachment; attachmentColor.set(mesh->getColor()); attachmentAtlasRegion = (AtlasRegion*)mesh->getRendererObject(); mesh->computeWorldVertices(*slot, 0, mesh->getWorldVerticesLength(), attachmentVertices, 0, 2); attachmentIndices = mesh->getTriangles().buffer(); attachmentUvs = mesh->getUVs().buffer(); numVertices = mesh->getWorldVerticesLength() >> 1; numIndices = mesh->getTriangles().size(); } else /* clipping */ {
void PathConstraint::update() { Attachment *baseAttachment = _target->getAttachment(); if (baseAttachment == NULL || !baseAttachment->getRTTI().instanceOf(PathAttachment::rtti)) { return; } PathAttachment *attachment = static_cast<PathAttachment *>(baseAttachment); float rotateMix = _rotateMix; float translateMix = _translateMix; bool translate = translateMix > 0; bool rotate = rotateMix > 0; if (!translate && !rotate) { return; } PathConstraintData &data = _data; bool percentSpacing = data._spacingMode == SpacingMode_Percent; RotateMode rotateMode = data._rotateMode; bool tangents = rotateMode == RotateMode_Tangent, scale = rotateMode == RotateMode_ChainScale; size_t boneCount = _bones.size(); size_t spacesCount = tangents ? boneCount : boneCount + 1; _spaces.setSize(spacesCount, 0); float spacing = _spacing; if (scale || !percentSpacing) { if (scale) { _lengths.setSize(boneCount, 0); } bool lengthSpacing = data._spacingMode == SpacingMode_Length; for (size_t i = 0, n = spacesCount - 1; i < n;) { Bone *boneP = _bones[i]; Bone &bone = *boneP; float setupLength = bone._data.getLength(); if (setupLength < PathConstraint::EPSILON) { if (scale) { _lengths[i] = 0; } _spaces[++i] = 0; } else if (percentSpacing) { if (scale) { float x = setupLength * bone._a, y = setupLength * bone._c; float length = MathUtil::sqrt(x * x + y * y); _lengths[i] = length; } _spaces[++i] = spacing; } else { float x = setupLength * bone._a; float y = setupLength * bone._c; float length = MathUtil::sqrt(x * x + y * y); if (scale) { _lengths[i] = length; } _spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; } } } else { for (size_t i = 1; i < spacesCount; ++i) { _spaces[i] = spacing; } } Vector<float>& positions = computeWorldPositions(*attachment, spacesCount, tangents, data.getPositionMode() == PositionMode_Percent, percentSpacing); float boneX = positions[0]; float boneY = positions[1]; float offsetRotation = data.getOffsetRotation(); bool tip; if (offsetRotation == 0) { tip = rotateMode == RotateMode_Chain; } else { tip = false; Bone &p = _target->getBone(); offsetRotation *= p.getA() * p.getD() - p.getB() * p.getC() > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad; } for (size_t i = 0, p = 3; i < boneCount; i++, p += 3) { Bone *boneP = _bones[i]; Bone &bone = *boneP; bone._worldX += (boneX - bone._worldX) * translateMix; bone._worldY += (boneY - bone._worldY) * translateMix; float x = positions[p]; float y = positions[p + 1]; float dx = x - boneX; float dy = y - boneY; if (scale) { float length = _lengths[i]; if (length >= PathConstraint::EPSILON) { float s = (MathUtil::sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1; bone._a *= s; bone._c *= s; } } boneX = x; boneY = y; if (rotate) { float a = bone._a, b = bone._b, c = bone._c, d = bone._d, r, cos, sin; if (tangents) { r = positions[p - 1]; } else if (_spaces[i + 1] < PathConstraint::EPSILON) { r = positions[p + 2]; } else { r = MathUtil::atan2(dy, dx); } r -= MathUtil::atan2(c, a); if (tip) { cos = MathUtil::cos(r); sin = MathUtil::sin(r); float length = bone._data.getLength(); boneX += (length * (cos * a - sin * c) - dx) * rotateMix; boneY += (length * (sin * a + cos * c) - dy) * rotateMix; } else { r += offsetRotation; } if (r > MathUtil::Pi) { r -= MathUtil::Pi_2; } else if (r < -MathUtil::Pi) { r += MathUtil::Pi_2; } r *= rotateMix; cos = MathUtil::cos(r); sin = MathUtil::sin(r); bone._a = cos * a - sin * c; bone._b = cos * b - sin * d; bone._c = sin * a + cos * c; bone._d = sin * b + cos * d; } bone._appliedValid = false; } }