Alex Szpakowski avatar Alex Szpakowski committed 2ca82dd

Added SpriteBatch:remove(id)

Comments (0)

Files changed (7)

platform/macosx/Info-Framework.plist

 	<key>CFBundleInfoDictionaryVersion</key>
 	<string>6.0</string>
 	<key>CFBundleName</key>
-	<string>${PRODUCT_NAME}</string>
+	<string>LÖVE</string>
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
 	<string>0.8.0</string>
 	<key>CFBundleSignature</key>
-	<string>????</string>
+	<string>LoVe</string>
 	<key>CFBundleVersion</key>
 	<string>0.8.0</string>
 	<key>NSPrincipalClass</key>

platform/macosx/love-framework.xcodeproj/project.pbxproj

 		FA577A8C16C71D3600860150 /* auto.lua */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = auto.lua; sourceTree = "<group>"; };
 		FA577A8D16C71D3600860150 /* boot.lua */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = boot.lua; sourceTree = "<group>"; };
 		FA577A8E16C71D3600860150 /* graphics.lua */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = graphics.lua; sourceTree = "<group>"; };
-		FA577AAF16C7507900860150 /* love framework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = "love framework.framework"; sourceTree = BUILT_PRODUCTS_DIR; };
+		FA577AAF16C7507900860150 /* love.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "love.framework"; path = love.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
 		2F654C0235EB60C744A22507 /* Products */ = {
 			isa = PBXGroup;
 			children = (
-				FA577AAF16C7507900860150 /* love framework.framework */,
+				FA577AAF16C7507900860150 /* love.framework */,
 			);
 			name = Products;
 			sourceTree = "<group>";
 /* End PBXHeadersBuildPhase section */
 
 /* Begin PBXNativeTarget section */
-		FA577AAE16C7507900860150 /* love framework */ = {
+		FA577AAE16C7507900860150 /* Framework */ = {
 			isa = PBXNativeTarget;
-			buildConfigurationList = FA577ABF16C7507900860150 /* Build configuration list for PBXNativeTarget "love framework" */;
+			buildConfigurationList = FA577ABF16C7507900860150 /* Build configuration list for PBXNativeTarget "Framework" */;
 			buildPhases = (
 				FA577AAA16C7507900860150 /* Sources */,
 				FA577AAB16C7507900860150 /* Frameworks */,
 			);
 			dependencies = (
 			);
-			name = "love framework";
+			name = Framework;
 			productName = love;
-			productReference = FA577AAF16C7507900860150 /* love framework.framework */;
+			productReference = FA577AAF16C7507900860150 /* love.framework */;
 			productType = "com.apple.product-type.framework";
 		};
 /* End PBXNativeTarget section */
 			projectDirPath = "";
 			projectRoot = "";
 			targets = (
-				FA577AAE16C7507900860150 /* love framework */,
+				FA577AAE16C7507900860150 /* Framework */,
 			);
 		};
 /* End PBXProject section */
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Debug;
 		};
-		FA577ABF16C7507900860150 /* Build configuration list for PBXNativeTarget "love framework" */ = {
+		FA577ABF16C7507900860150 /* Build configuration list for PBXNativeTarget "Framework" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
 				FA577AC016C7507900860150 /* Debug */,

platform/macosx/love.xcodeproj/project.pbxproj

 		FA08F69716C766E700F007B5 /* love.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = FA08F69116C765A200F007B5 /* love.framework */; };
 /* End PBXBuildFile section */
 
+/* Begin PBXContainerItemProxy section */
+		FA08F6A616C77A4300F007B5 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = FA577A9316C7217800860150 /* love-framework.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = FA577AAF16C7507900860150;
+			remoteInfo = "love framework";
+		};
+/* End PBXContainerItemProxy section */
+
 /* Begin PBXCopyFilesBuildPhase section */
 		A9255DDE1043185300BA1496 /* Copy Frameworks */ = {
 			isa = PBXCopyFilesBuildPhase;
 			name = Resources;
 			sourceTree = "<group>";
 		};
+		FA08F6A316C77A4300F007B5 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				FA08F6A716C77A4300F007B5 /* love.framework */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
 		FA577A9D16C7262E00860150 /* Source */ = {
 			isa = PBXGroup;
 			children = (
 			);
 			mainGroup = 29B97314FDCFA39411CA2CEA /* love */;
 			projectDirPath = "";
+			projectReferences = (
+				{
+					ProductGroup = FA08F6A316C77A4300F007B5 /* Products */;
+					ProjectRef = FA577A9316C7217800860150 /* love-framework.xcodeproj */;
+				},
+			);
 			projectRoot = "";
 			targets = (
 				8D1107260486CEB800E47090 /* love */,
 		};
 /* End PBXProject section */
 
+/* Begin PBXReferenceProxy section */
+		FA08F6A716C77A4300F007B5 /* love.framework */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.framework;
+			name = "love.framework";
+			path = love.framework;
+			remoteRef = FA08F6A616C77A4300F007B5 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+/* End PBXReferenceProxy section */
+
 /* Begin PBXResourcesBuildPhase section */
 		8D1107290486CEB800E47090 /* Resources */ = {
 			isa = PBXResourcesBuildPhase;

src/modules/graphics/opengl/SpriteBatch.cpp

 int SpriteBatch::add(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky, int index /*= -1*/)
 {
 	// Only do this if there's a free slot.
-	if ((index == -1 && next >= size) || index < -1 || index >= size)
+	if ((index == -1 && next >= size && gaps.size() == 0) || index < -1 || index >= size)
 		return -1;
 
+	// Determine where in the vertex buffer to insert into, using the gap list
+	// if possible.
+	int realindex;
+	if (index == -1 && gaps.size() > 0)
+	{
+		realindex = gaps.front();
+		gaps.pop_front();
+	}
+	else
+	{
+		realindex = (index == -1) ? next : index;
+		std::deque<int>::iterator it = std::find(gaps.begin(), gaps.end(), realindex);
+		if (it != gaps.end())
+			gaps.erase(it); // This index is no longer a gap.
+	}
+
 	// Needed for colors.
 	memcpy(sprite, image->getVertices(), sizeof(vertex)*4);
 
 
 	if (color)
 		setColorv(sprite, *color);
+	
 
-	addv(sprite, (index == -1 ? next : index));
+	addv(sprite, realindex);
 
 	// Increment counter.
-	if (index == -1)
+	if (index == -1 && realindex == next)
 		return next++;
-	return index;
+
+	return realindex;
 }
 
 int SpriteBatch::addq(Quad *quad, float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky, int index /*= -1*/)
 {
 	// Only do this if there's a free slot.
-	if ((index == -1 && next >= size) || index < -1 || index >= next)
+	if ((index == -1 && next >= size && gaps.size() == 0) || index < -1 || index >= next)
 		return -1;
 
+	// Determine where in the vertex buffer to insert into, using the gap list
+	// if possible.
+	int realindex;
+	if (index == -1 && gaps.size() > 0)
+	{
+		realindex = gaps.front();
+		gaps.pop_front();
+	}
+	else
+	{
+		realindex = (index == -1) ? next : index;
+		std::deque<int>::iterator it = std::find(gaps.begin(), gaps.end(), realindex);
+		if (it != gaps.end())
+			gaps.erase(it); // This index is no longer a gap.
+	}
+
 	// Needed for colors.
 	memcpy(sprite, quad->getVertices(), sizeof(vertex)*4);
 
 	if (color)
 		setColorv(sprite, *color);
 
-	addv(sprite, (index == -1 ? next : index));
+	addv(sprite, realindex);
 
 	// Increment counter.
-	if (index == -1)
+	if (index == -1 && realindex == next)
 		return next++;
-	return index;
+
+	return realindex;
+}
+
+void SpriteBatch::remove(int index)
+{
+	if (index < 0 || index >= next || next <= 0)
+		return;
+
+	// If this is the last index in the sprite list, decrease the total sprite
+	// count instead of adding a dummy sprite.
+	if (index == next - 1)
+	{
+		int spritecount = index;
+
+		// Remove all consecutive gaps at the end of the sprite list.
+		std::deque<int>::iterator it;
+		while ((it = std::find(gaps.begin(), gaps.end(), --spritecount)) != gaps.end())
+			gaps.erase(it);
+
+		next = spritecount + 1;
+		return;
+	}
+	else if (std::find(gaps.begin(), gaps.end(), index) != gaps.end())
+		return; // Don't add the same index to the gap list twice.
+
+
+	// OpenGL won't render any primitive whose vertices are all identical.
+	for (int i = 0; i < 4; i++)
+		sprite[i].x = sprite[i].y = 0;
+
+	// Replace the existing sprite at this index with the dummy sprite.
+	addv(sprite, index);
+
+	gaps.push_back(index);
 }
 
 void SpriteBatch::clear()
 {
 	// Reset the position of the next index.
 	next = 0;
+	gaps.clear();
 }
 
 void *SpriteBatch::lock()

src/modules/graphics/opengl/SpriteBatch.h

 
 // C
 #include <cstring>
+#include <deque>
 
 // LOVE
 #include "common/math.h"
 
 	int add(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky, int index = -1);
 	int addq(Quad *quad, float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky, int index = -1);
+	void remove(int index);
 	void clear();
 
 	void *lock();
 	VertexBuffer *array_buf;
 	VertexIndex *element_buf;
 
+	// List of gaps in the SpriteBatch. Checked when adding sprites, and added
+	// to when removing them.
+	std::deque<int> gaps;
+
 }; // SpriteBatch
 
 } // opengl

src/modules/graphics/opengl/wrap_SpriteBatch.cpp

 	return 0;
 }
 
+int w_SpriteBatch_remove(lua_State *L)
+{
+	SpriteBatch *t = luax_checkspritebatch(L, 1);
+	int id = luaL_checkinteger(L, 2);
+	t->remove(id);
+	return 0;
+}
 
 int w_SpriteBatch_clear(lua_State *L)
 {
 	{ "addq", w_SpriteBatch_addq },
 	{ "set", w_SpriteBatch_set },
 	{ "setq", w_SpriteBatch_setq },
+	{ "remove", w_SpriteBatch_remove },
 	{ "clear", w_SpriteBatch_clear },
 	{ "bind", w_SpriteBatch_bind },
 	{ "unbind", w_SpriteBatch_unbind },

src/modules/graphics/opengl/wrap_SpriteBatch.h

 int w_SpriteBatch_addq(lua_State *L);
 int w_SpriteBatch_set(lua_State *L);
 int w_SpriteBatch_setq(lua_State *L);
+int w_SpriteBatch_remove(lua_State *L);
 int w_SpriteBatch_clear(lua_State *L);
 int w_SpriteBatch_lock(lua_State *L);
 int w_SpriteBatch_unlock(lua_State *L);
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.