Browse Source

Add Mesh:getAttachedAttributes.

Alex Szpakowski 5 years ago
parent
commit
d77dabaa6b

+ 9 - 17
src/modules/graphics/Mesh.cpp

@@ -121,10 +121,13 @@ Mesh::Mesh(const std::vector<Mesh::BufferAttribute> &attributes, PrimitiveType d
 
 
 	attachedAttributes = attributes;
 	attachedAttributes = attributes;
 
 
-	vertexCount = LOVE_UINT32_MAX;
+	vertexCount = attachedAttributes.size() > 0 ? LOVE_UINT32_MAX : 0;
 
 
 	for (const auto &attrib : attachedAttributes)
 	for (const auto &attrib : attachedAttributes)
 	{
 	{
+		if ((attrib.buffer->getTypeFlags() & Buffer::TYPEFLAG_VERTEX) == 0)
+			throw love::Exception("Buffer must be created with vertex buffer support to be used as a Mesh vertex attribute.");
+
 		if (getAttachedAttributeIndex(attrib.name) != -1)
 		if (getAttachedAttributeIndex(attrib.name) != -1)
 			throw love::Exception("Duplicate vertex attribute name: %s", attrib.name.c_str());
 			throw love::Exception("Duplicate vertex attribute name: %s", attrib.name.c_str());
 
 
@@ -268,17 +271,6 @@ const std::vector<Buffer::DataMember> &Mesh::getVertexFormat() const
 	return vertexFormat;
 	return vertexFormat;
 }
 }
 
 
-int Mesh::getAttributeIndex(const std::string &name) const
-{
-	for (int i = 0; i < (int) vertexFormat.size(); i++)
-	{
-		if (vertexFormat[i].decl.name == name)
-			return i;
-	}
-
-	return -1;
-}
-
 void Mesh::setAttributeEnabled(const std::string &name, bool enable)
 void Mesh::setAttributeEnabled(const std::string &name, bool enable)
 {
 {
 	int index = getAttachedAttributeIndex(name);
 	int index = getAttachedAttributeIndex(name);
@@ -317,10 +309,10 @@ void Mesh::attachAttribute(const std::string &name, Buffer *buffer, const std::s
 
 
 	newattrib.buffer = buffer;
 	newattrib.buffer = buffer;
 	newattrib.enabled = oldattrib.buffer.get() ? oldattrib.enabled : true;
 	newattrib.enabled = oldattrib.buffer.get() ? oldattrib.enabled : true;
-	newattrib.index = buffer->getDataMemberIndex(attachname);
+	newattrib.indexInBuffer = buffer->getDataMemberIndex(attachname);
 	newattrib.step = step;
 	newattrib.step = step;
 
 
-	if (newattrib.index < 0)
+	if (newattrib.indexInBuffer < 0)
 		throw love::Exception("The specified vertex buffer does not have a vertex attribute named '%s'", attachname.c_str());
 		throw love::Exception("The specified vertex buffer does not have a vertex attribute named '%s'", attachname.c_str());
 
 
 	if (oldindex != -1)
 	if (oldindex != -1)
@@ -337,7 +329,7 @@ bool Mesh::detachAttribute(const std::string &name)
 
 
 	attachedAttributes.erase(attachedAttributes.begin() + index);
 	attachedAttributes.erase(attachedAttributes.begin() + index);
 
 
-	if (getAttributeIndex(name) != -1)
+	if (vertexBuffer.get() && vertexBuffer->getDataMemberIndex(name) != -1)
 		attachAttribute(name, vertexBuffer, name);
 		attachAttribute(name, vertexBuffer, name);
 
 
 	return true;
 	return true;
@@ -594,9 +586,9 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount)
 			// Make sure the buffer isn't mapped (sends data to GPU if needed.)
 			// Make sure the buffer isn't mapped (sends data to GPU if needed.)
 			buffer->unmap();
 			buffer->unmap();
 
 
-			const auto &member = buffer->getDataMember(attrib.index);
+			const auto &member = buffer->getDataMember(attrib.indexInBuffer);
 
 
-			uint16 offset = (uint16) buffer->getMemberOffset(attrib.index);
+			uint16 offset = (uint16) member.offset;
 			uint16 stride = (uint16) buffer->getArrayStride();
 			uint16 stride = (uint16) buffer->getArrayStride();
 
 
 			attributes.set(attributeindex, member.decl.format, offset, activebuffers);
 			attributes.set(attributeindex, member.decl.format, offset, activebuffers);

+ 1 - 2
src/modules/graphics/Mesh.h

@@ -54,7 +54,7 @@ public:
 	{
 	{
 		std::string name;
 		std::string name;
 		StrongRef<Buffer> buffer;
 		StrongRef<Buffer> buffer;
-		int index;
+		int indexInBuffer;
 		AttributeStep step;
 		AttributeStep step;
 		bool enabled;
 		bool enabled;
 	};
 	};
@@ -101,7 +101,6 @@ public:
 	 * Gets the format of each vertex attribute stored in the Mesh.
 	 * Gets the format of each vertex attribute stored in the Mesh.
 	 **/
 	 **/
 	const std::vector<Buffer::DataMember> &getVertexFormat() const;
 	const std::vector<Buffer::DataMember> &getVertexFormat() const;
-	int getAttributeIndex(const std::string &name) const;
 
 
 	/**
 	/**
 	 * Sets whether a specific vertex attribute is used when drawing the Mesh.
 	 * Sets whether a specific vertex attribute is used when drawing the Mesh.

+ 1 - 1
src/modules/graphics/wrap_Graphics.cpp

@@ -1557,7 +1557,7 @@ static Mesh *newStandardMesh(lua_State *L)
 	PrimitiveType drawmode = luax_optmeshdrawmode(L, 2, PRIMITIVE_TRIANGLE_FAN);
 	PrimitiveType drawmode = luax_optmeshdrawmode(L, 2, PRIMITIVE_TRIANGLE_FAN);
 	BufferUsage usage = luax_optmeshusage(L, 3, BUFFERUSAGE_DYNAMIC);
 	BufferUsage usage = luax_optmeshusage(L, 3, BUFFERUSAGE_DYNAMIC);
 
 
-	auto format = Mesh::getDefaultVertexFormat();
+	std::vector<Buffer::DataDeclaration> format = Mesh::getDefaultVertexFormat();
 
 
 	// First argument is a table of standard vertices, or the number of
 	// First argument is a table of standard vertices, or the number of
 	// standard vertices.
 	// standard vertices.

+ 38 - 0
src/modules/graphics/wrap_Mesh.cpp

@@ -298,6 +298,8 @@ int w_Mesh_attachAttribute(lua_State *L)
 	{
 	{
 		Mesh *mesh = luax_checkmesh(L, 3);
 		Mesh *mesh = luax_checkmesh(L, 3);
 		buffer = mesh->getVertexBuffer();
 		buffer = mesh->getVertexBuffer();
+		if (buffer == nullptr)
+			return luaL_error(L, "Mesh does not have its own vertex buffer.");
 	}
 	}
 
 
 	AttributeStep step = STEP_PER_VERTEX;
 	AttributeStep step = STEP_PER_VERTEX;
@@ -321,6 +323,41 @@ int w_Mesh_detachAttribute(lua_State *L)
 	return 1;
 	return 1;
 }
 }
 
 
+int w_Mesh_getAttachedAttributes(lua_State *L)
+{
+	Mesh *t = luax_checkmesh(L, 1);
+	const auto &attributes = t->getAttachedAttributes();
+
+	lua_createtable(L, (int) attributes.size(), 0);
+
+	for (int i = 0; i < (int) attributes.size(); i++)
+	{
+		const auto &attrib = attributes[i];
+
+		lua_createtable(L, 4, 0);
+
+		luax_pushstring(L, attrib.name);
+		lua_rawseti(L, -1, 1);
+
+		luax_pushtype(L, attrib.buffer.get());
+		lua_rawseti(L, -1, 2);
+
+		const char *stepstr = nullptr;
+		if (!getConstant(attrib.step, stepstr))
+			return luaL_error(L, "Invalid vertex attribute step.");
+		lua_pushstring(L, stepstr);
+		lua_rawseti(L, -1, 3);
+
+		const Buffer::DataMember &member = attrib.buffer->getDataMember(attrib.indexInBuffer);
+		luax_pushstring(L, member.decl.name);
+		lua_rawseti(L, -1, 4);
+
+		lua_rawseti(L, -1, i + 1);
+	}
+
+	return 1;
+}
+
 int w_Mesh_flush(lua_State *L)
 int w_Mesh_flush(lua_State *L)
 {
 {
 	Mesh *t = luax_checkmesh(L, 1);
 	Mesh *t = luax_checkmesh(L, 1);
@@ -507,6 +544,7 @@ static const luaL_Reg w_Mesh_functions[] =
 	{ "isAttributeEnabled", w_Mesh_isAttributeEnabled },
 	{ "isAttributeEnabled", w_Mesh_isAttributeEnabled },
 	{ "attachAttribute", w_Mesh_attachAttribute },
 	{ "attachAttribute", w_Mesh_attachAttribute },
 	{ "detachAttribute", w_Mesh_detachAttribute },
 	{ "detachAttribute", w_Mesh_detachAttribute },
+	{ "getAttachedAttributes", w_Mesh_getAttachedAttributes },
 	{ "flush", w_Mesh_flush },
 	{ "flush", w_Mesh_flush },
 	{ "setVertexMap", w_Mesh_setVertexMap },
 	{ "setVertexMap", w_Mesh_setVertexMap },
 	{ "getVertexMap", w_Mesh_getVertexMap },
 	{ "getVertexMap", w_Mesh_getVertexMap },