Jelajahi Sumber

[cpp] Sequence and SequenceTimeline support in SkeletonBinary.

Mario Zechner 3 tahun lalu
induk
melakukan
9fda6dcd3b

+ 2 - 2
spine-cpp/spine-cpp/include/spine/LinkedMesh.h

@@ -43,14 +43,14 @@ namespace spine {
 
 	public:
 		LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent,
-				   bool inheritDeform);
+				   bool inheritTimeline);
 
 	private:
 		MeshAttachment *_mesh;
 		String _skin;
 		size_t _slotIndex;
 		String _parent;
-		bool _inheritDeform;
+		bool _inheritTimeline;
 	};
 }
 

+ 6 - 2
spine-cpp/spine-cpp/include/spine/Sequence.h

@@ -39,12 +39,16 @@ namespace spine {
 
 	class Attachment;
 
-	class SP_API Sequence : public SpineObject {
+	class SkeletonBinary;
+	class SkeletonJson;
 
+	class SP_API Sequence : public SpineObject {
+		friend class SkeletonBinary;
+		friend class SkeletonJson;
 	public:
 		explicit Sequence();
 
-		Sequence(int id, const Vector<TextureRegion *> &regions, int start, int digits, int setupIndex);
+		Sequence(int count);
 
 		~Sequence();
 

+ 8 - 1
spine-cpp/spine-cpp/include/spine/SkeletonBinary.h

@@ -61,6 +61,8 @@ namespace spine {
 
 	class CurveTimeline2;
 
+	class Sequence;
+
 	class SP_API SkeletonBinary : public SpineObject {
 	public:
 		static const int BONE_ROTATE = 0;
@@ -81,6 +83,9 @@ namespace spine {
 		static const int SLOT_RGB2 = 4;
 		static const int SLOT_ALPHA = 5;
 
+		static const int ATTACHMENT_DEFORM = 0;
+		static const int ATTACHMENT_SEQUENCE = 1;
+
 		static const int PATH_POSITION = 0;
 		static const int PATH_SPACING = 1;
 		static const int PATH_MIX = 2;
@@ -137,10 +142,12 @@ namespace spine {
 
 		Skin *readSkin(DataInput *input, bool defaultSkin, SkeletonData *skeletonData, bool nonessential);
 
+		Sequence *readSequence(DataInput *input);
+
 		Attachment *readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName,
 								   SkeletonData *skeletonData, bool nonessential);
 
-		void readVertices(DataInput *input, VertexAttachment *attachment, int vertexCount);
+		void readVertices(DataInput *input, Vector<float> &vertices, Vector<size_t> &bones, int vertexCount);
 
 		void readFloatArray(DataInput *input, int n, float scale, Vector<float> &array);
 

+ 5 - 5
spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp

@@ -38,9 +38,9 @@
 using namespace spine;
 
 LinkedMesh::LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent,
-					   bool inheritDeform) : _mesh(mesh),
-											 _skin(skin),
-											 _slotIndex(slotIndex),
-											 _parent(parent),
-											 _inheritDeform(inheritDeform) {
+					   bool inheritTimeline) : _mesh(mesh),
+											   _skin(skin),
+											   _slotIndex(slotIndex),
+											   _parent(parent),
+											   _inheritTimeline(inheritTimeline) {
 }

+ 6 - 5
spine-cpp/spine-cpp/src/spine/Sequence.cpp

@@ -35,11 +35,12 @@
 
 using namespace spine;
 
-Sequence::Sequence() : _id(Sequence::getNextID()),
-					   _regions(),
-					   _start(0),
-					   _digits(0),
-					   _setupIndex(0) {
+Sequence::Sequence(int count) : _id(Sequence::getNextID()),
+								_regions(),
+								_start(0),
+								_digits(0),
+								_setupIndex(0) {
+	_regions.setSize(count, NULL);
 }
 
 Sequence::~Sequence() {

+ 160 - 94
spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp

@@ -72,6 +72,7 @@
 #include <spine/TransformConstraintData.h>
 #include <spine/TransformConstraintTimeline.h>
 #include <spine/TranslateTimeline.h>
+#include "spine/SequenceTimeline.h"
 
 using namespace spine;
 
@@ -298,10 +299,10 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
 			setError("Parent mesh not found: ", linkedMesh->_parent.buffer());
 			return NULL;
 		}
-		linkedMesh->_mesh->_timelineAttachment = linkedMesh->_inheritDeform ? static_cast<VertexAttachment *>(parent)
-																			: linkedMesh->_mesh;
+		linkedMesh->_mesh->_timelineAttachment = linkedMesh->_inheritTimeline ? static_cast<VertexAttachment *>(parent)
+																			  : linkedMesh->_mesh;
 		linkedMesh->_mesh->setParentMesh(static_cast<MeshAttachment *>(parent));
-		linkedMesh->_mesh->updateRegion();
+		if (linkedMesh->_mesh->_region) linkedMesh->_mesh->updateRegion();
 		_attachmentLoader->configureAttachment(linkedMesh->_mesh);
 	}
 	ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes);
@@ -478,6 +479,15 @@ Skin *SkeletonBinary::readSkin(DataInput *input, bool defaultSkin, SkeletonData
 	return skin;
 }
 
+Sequence *SkeletonBinary::readSequence(DataInput *input) {
+	if (!readBoolean(input)) return NULL;
+	Sequence *sequence = new (__FILE__, __LINE__) Sequence(readVarint(input, true));
+	sequence->_start = readVarint(input, true);
+	sequence->_digits = readVarint(input, true);
+	sequence->_setupIndex = readVarint(input, true);
+	return sequence;
+}
+
 Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName,
 										   SkeletonData *skeletonData, bool nonessential) {
 	String name(readStringRef(input, skeletonData));
@@ -488,21 +498,32 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
 		case AttachmentType_Region: {
 			String path(readStringRef(input, skeletonData));
 			if (path.isEmpty()) path = name;
-			RegionAttachment *region = _attachmentLoader->newRegionAttachment(*skin, String(name), String(path));
+			float rotation = readFloat(input);
+			float x = readFloat(input) * _scale;
+			float y = readFloat(input) * _scale;
+			float scaleX = readFloat(input);
+			float scaleY = readFloat(input);
+			float width = readFloat(input) * _scale;
+			float height = readFloat(input) * _scale;
+			Color color;
+			readColor(input, color);
+			Sequence *sequence = readSequence(input);
+			RegionAttachment *region = _attachmentLoader->newRegionAttachment(*skin, String(name), String(path), sequence);
 			if (!region) {
 				setError("Error reading attachment: ", name.buffer());
 				return nullptr;
 			}
 			region->_path = path;
-			region->_rotation = readFloat(input);
-			region->_x = readFloat(input) * _scale;
-			region->_y = readFloat(input) * _scale;
-			region->_scaleX = readFloat(input);
-			region->_scaleY = readFloat(input);
-			region->_width = readFloat(input) * _scale;
-			region->_height = readFloat(input) * _scale;
-			readColor(input, region->getColor());
-			region->updateRegion();
+			region->_rotation = rotation;
+			region->_x = x;
+			region->_y = y;
+			region->_scaleX = scaleX;
+			region->_scaleY = scaleY;
+			region->_width = width;
+			region->_height = height;
+			region->getColor().set(color);
+			region->_sequence = sequence;
+			if (sequence == NULL) region->updateRegion();
 			_attachmentLoader->configureAttachment(region);
 			return region;
 		}
@@ -513,7 +534,8 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
 				setError("Error reading attachment: ", name.buffer());
 				return nullptr;
 			}
-			readVertices(input, static_cast<VertexAttachment *>(box), vertexCount);
+			readVertices(input, box->getVertices(), box->getBones(), vertexCount);
+			box->setWorldVerticesLength(vertexCount << 1);
 			if (nonessential) {
 				readColor(input, box->getColor());
 			}
@@ -521,31 +543,51 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
 			return box;
 		}
 		case AttachmentType_Mesh: {
+			Color color;
 			int vertexCount;
-			MeshAttachment *mesh;
+			Vector<float> uvs;
+			Vector<unsigned short> triangles;
+			Vector<float> vertices;
+			Vector<size_t> bones;
+			int hullLength;
+			Sequence *sequence;
+			float width = 0;
+			float height = 0;
+			Vector<unsigned short> edges;
+
 			String path(readStringRef(input, skeletonData));
 			if (path.isEmpty()) path = name;
+			readColor(input, color);
+			vertexCount = readVarint(input, true);
+			readFloatArray(input, vertexCount << 1, 1, uvs);
+			readShortArray(input, triangles);
+			readVertices(input, vertices, bones, vertexCount);
+			hullLength = readVarint(input, true) << 1;
+			sequence = readSequence(input);
+			if (nonessential) {
+				readShortArray(input, edges);
+				width = readFloat(input) * _scale;
+				height = readFloat(input) * _scale;
+			}
 
-			mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path));
+			MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path), sequence);
 			if (!mesh) {
 				setError("Error reading attachment: ", name.buffer());
 				return nullptr;
 			}
 			mesh->_path = path;
-			readColor(input, mesh->getColor());
-			vertexCount = readVarint(input, true);
-			readFloatArray(input, vertexCount << 1, 1, mesh->getRegionUVs());
-			readShortArray(input, mesh->getTriangles());
-			readVertices(input, static_cast<VertexAttachment *>(mesh), vertexCount);
-			mesh->updateRegion();
-			mesh->_hullLength = readVarint(input, true) << 1;
+			mesh->_color.set(color);
+			mesh->_vertices.addAll(vertices);
+			mesh->setWorldVerticesLength(vertexCount << 1);
+			mesh->_triangles.addAll(triangles);
+			mesh->_regionUVs.addAll(uvs);
+			if (sequence == NULL) mesh->updateRegion();
+			mesh->_hullLength = hullLength;
+			mesh->_sequence = sequence;
 			if (nonessential) {
-				readShortArray(input, mesh->getEdges());
-				mesh->_width = readFloat(input) * _scale;
-				mesh->_height = readFloat(input) * _scale;
-			} else {
-				mesh->_width = 0;
-				mesh->_height = 0;
+				mesh->_edges.addAll(edges);
+				mesh->_width = width;
+				mesh->_height = height;
 			}
 			_attachmentLoader->configureAttachment(mesh);
 			return mesh;
@@ -554,23 +596,33 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
 			String path(readStringRef(input, skeletonData));
 			if (path.isEmpty()) path = name;
 
-			MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path));
+			Color color;
+			float width, height;
+			readColor(input, color);
+			String skinName(readStringRef(input, skeletonData));
+			String parent(readStringRef(input, skeletonData));
+			bool inheritTimelines = readBoolean(input);
+			Sequence *sequence = readSequence(input);
+			if (nonessential) {
+				width = readFloat(input) * _scale;
+				height = readFloat(input) * _scale;
+			}
+
+			MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path), sequence);
 			if (!mesh) {
 				setError("Error reading attachment: ", name.buffer());
 				return nullptr;
 			}
 			mesh->_path = path;
-			readColor(input, mesh->getColor());
-			String skinName(readStringRef(input, skeletonData));
-			String parent(readStringRef(input, skeletonData));
-			bool inheritDeform = readBoolean(input);
+			mesh->_color.set(color);
+			mesh->_sequence = sequence;
 			if (nonessential) {
-				mesh->_width = readFloat(input) * _scale;
-				mesh->_height = readFloat(input) * _scale;
+				mesh->_width = width;
+				mesh->_height = height;
 			}
 
 			LinkedMesh *linkedMesh = new (__FILE__, __LINE__) LinkedMesh(mesh, String(skinName), slotIndex,
-																		 String(parent), inheritDeform);
+																		 String(parent), inheritTimelines);
 			_linkedMeshes.add(linkedMesh);
 			return mesh;
 		}
@@ -583,7 +635,8 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
 			path->_closed = readBoolean(input);
 			path->_constantSpeed = readBoolean(input);
 			int vertexCount = readVarint(input, true);
-			readVertices(input, static_cast<VertexAttachment *>(path), vertexCount);
+			readVertices(input, path->getVertices(), path->getBones(), vertexCount);
+			path->setWorldVerticesLength(vertexCount << 1);
 			int lengthsLength = vertexCount / 3;
 			path->_lengths.setSize(lengthsLength, 0);
 			for (int i = 0; i < lengthsLength; ++i) {
@@ -619,7 +672,8 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
 				setError("Error reading attachment: ", name.buffer());
 				return nullptr;
 			}
-			readVertices(input, static_cast<VertexAttachment *>(clip), vertexCount);
+			readVertices(input, clip->getVertices(), clip->getBones(), vertexCount);
+			clip->setWorldVerticesLength(vertexCount << 1);
 			clip->_endSlot = skeletonData->_slots[endSlotIndex];
 			if (nonessential) {
 				readColor(input, clip->getColor());
@@ -631,18 +685,15 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
 	return nullptr;
 }
 
-void SkeletonBinary::readVertices(DataInput *input, VertexAttachment *attachment, int vertexCount) {
+void SkeletonBinary::readVertices(DataInput *input, Vector<float> &vertices, Vector<size_t> &bones, int vertexCount) {
 	float scale = _scale;
 	int verticesLength = vertexCount << 1;
-	attachment->setWorldVerticesLength(vertexCount << 1);
 
 	if (!readBoolean(input)) {
-		readFloatArray(input, verticesLength, scale, attachment->getVertices());
+		readFloatArray(input, verticesLength, scale, vertices);
 		return;
 	}
 
-	Vector<float> &vertices = attachment->getVertices();
-	Vector<size_t> &bones = attachment->getBones();
 	vertices.ensureCapacity(verticesLength * 3 * 3);
 	bones.ensureCapacity(verticesLength * 3);
 
@@ -1176,69 +1227,84 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
 			for (int iii = 0, nnn = readVarint(input, true); iii < nnn; iii++) {
 				const char *attachmentName = readStringRef(input, skeletonData);
 				Attachment *baseAttachment = skin->getAttachment(slotIndex, String(attachmentName));
-
 				if (!baseAttachment) {
 					ContainerUtil::cleanUpVectorOfPointers(timelines);
 					setError("Attachment not found: ", attachmentName);
 					return NULL;
 				}
-
 				VertexAttachment *attachment = static_cast<VertexAttachment *>(baseAttachment);
-
-				bool weighted = attachment->_bones.size() > 0;
-				Vector<float> &vertices = attachment->_vertices;
-				int deformLength = weighted ? vertices.size() / 3 * 2 : vertices.size();
-
+				unsigned int timelineType = readByte(input);
 				int frameCount = readVarint(input, true);
 				int frameLast = frameCount - 1;
-				int bezierCount = readVarint(input, true);
-				DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(frameCount, bezierCount, slotIndex,
-																				   attachment);
-
-				float time = readFloat(input);
-				for (int frame = 0, bezier = 0;; ++frame) {
-					Vector<float> deform;
-					size_t end = (size_t) readVarint(input, true);
-					if (end == 0) {
-						if (weighted) {
-							deform.setSize(deformLength, 0);
-							for (int iiii = 0; iiii < deformLength; ++iiii)
-								deform[iiii] = 0;
-						} else {
-							deform.clearAndAddAll(vertices);
-						}
-					} else {
-						deform.setSize(deformLength, 0);
-						size_t start = (size_t) readVarint(input, true);
-						end += start;
-						if (scale == 1) {
-							for (size_t v = start; v < end; ++v)
-								deform[v] = readFloat(input);
-						} else {
-							for (size_t v = start; v < end; ++v)
-								deform[v] = readFloat(input) * scale;
-						}
 
-						if (!weighted) {
-							for (size_t v = 0, vn = deform.size(); v < vn; ++v)
-								deform[v] += vertices[v];
+				switch (timelineType) {
+					case ATTACHMENT_DEFORM: {
+						bool weighted = attachment->_bones.size() > 0;
+						Vector<float> &vertices = attachment->_vertices;
+						int deformLength = weighted ? vertices.size() / 3 * 2 : vertices.size();
+
+						int bezierCount = readVarint(input, true);
+						DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(frameCount, bezierCount, slotIndex,
+																						   attachment);
+
+						float time = readFloat(input);
+						for (int frame = 0, bezier = 0;; ++frame) {
+							Vector<float> deform;
+							size_t end = (size_t) readVarint(input, true);
+							if (end == 0) {
+								if (weighted) {
+									deform.setSize(deformLength, 0);
+									for (int iiii = 0; iiii < deformLength; ++iiii)
+										deform[iiii] = 0;
+								} else {
+									deform.clearAndAddAll(vertices);
+								}
+							} else {
+								deform.setSize(deformLength, 0);
+								size_t start = (size_t) readVarint(input, true);
+								end += start;
+								if (scale == 1) {
+									for (size_t v = start; v < end; ++v)
+										deform[v] = readFloat(input);
+								} else {
+									for (size_t v = start; v < end; ++v)
+										deform[v] = readFloat(input) * scale;
+								}
+
+								if (!weighted) {
+									for (size_t v = 0, vn = deform.size(); v < vn; ++v)
+										deform[v] += vertices[v];
+								}
+							}
+
+							timeline->setFrame(frame, time, deform);
+							if (frame == frameLast) break;
+							float time2 = readFloat(input);
+							switch (readSByte(input)) {
+								case CURVE_STEPPED:
+									timeline->setStepped(frame);
+									break;
+								case CURVE_BEZIER:
+									setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1);
+							}
+							time = time2;
 						}
-					}
 
-					timeline->setFrame(frame, time, deform);
-					if (frame == frameLast) break;
-					float time2 = readFloat(input);
-					switch (readSByte(input)) {
-						case CURVE_STEPPED:
-							timeline->setStepped(frame);
-							break;
-						case CURVE_BEZIER:
-							setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1);
+						timelines.add(timeline);
+						break;
+					}
+					case ATTACHMENT_SEQUENCE: {
+						SequenceTimeline *timeline = new (__FILE__, __LINE__) SequenceTimeline(frameCount, slotIndex, attachment);
+						for (int frame = 0; frame < frameCount; frame++) {
+							float time = readFloat(input);
+							int modeAndIndex = readInt(input);
+							float delay = readFloat(input);
+							timeline->setFrame(frame, time, (spine::SequenceMode)(modeAndIndex & 0xf), modeAndIndex >> 4, delay);
+						}
+						timelines.add(timeline);
+						break;
 					}
-					time = time2;
 				}
-
-				timelines.add(timeline);
 			}
 		}
 	}