Example #1
0
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 */ {
Example #2
0
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;
	}
}