Commits

Bart van Strien committed 56a408b Merge

Maerge in default

Comments (0)

Files changed (13)

   * Added basic support for the file:// uri scheme.
   * Added love.mouse.setX/setY.
   * Added love.filesystem.getIdentity.
+  * Added HDR canvas support.
   * OPTIONAL: Added support for GME.
 
   * Fixed crashes with font drawing on some ATI cards.
   * Fixed 'random' hangs in audio.
   * Fixed love.graphics.getLineWidth returning incorrect values.
   * Fixed possible memory leak in utf-8 decoder.
+  * Fixed love.sound.newDecoder not accepting FileData.
+  * Fixed multiplicative blend mode.
+  * Fixed Box2D exception in World:update.
+  * Fixed spacing for the last character in an ImageFont.
 
   * Moved love's startup to modules/love.
 
   * Updated Source:set* functions to default z to 0.
   * Updated the windows console, it now tries to re-use an active one first.
   * Updated love.image memory handling, improves errors and thread-safety.
+  * Updated order of sleep/present in love.run (now draws, *then* sleeps).
 
 LOVE 0.8.0 [Rubber Piggy]
 -------------------------

src/modules/audio/wrap_Source.cpp

 	return 1;
 }
 
+int w_Source_isPlaying(lua_State *L)
+{
+	Source *t = luax_checksource(L, 1);
+	luax_pushboolean(L, !t->isStopped() && !t->isPaused());
+	return 1;
+}
+
 int w_Source_isStatic(lua_State *L)
 {
 	Source *t = luax_checksource(L, 1);
 	{ "isLooping", w_Source_isLooping },
 	{ "isStopped", w_Source_isStopped },
 	{ "isPaused", w_Source_isPaused },
+	{ "isPlaying", w_Source_isPlaying },
 	{ "isStatic", w_Source_isStatic },
 
 	{ "setVolumeLimits", w_Source_setVolumeLimits },

src/modules/audio/wrap_Source.h

 int w_Source_isLooping(lua_State *L);
 int w_Source_isStopped(lua_State *L);
 int w_Source_isPaused(lua_State *L);
+int w_Source_isPlaying(lua_State *L);
 int w_Source_isStatic(lua_State *L);
 int w_Source_setVolumeLimits(lua_State *L);
 int w_Source_getVolumeLimits(lua_State *L);

src/modules/filesystem/physfs/Filesystem.cpp

 #ifdef LOVE_WINDOWS
 	if (appdata.empty())
 	{
-		wchar_t *w_appdata = _wgetenv(TEXT("APPDATA"));
+		wchar_t *w_appdata = _wgetenv(L"APPDATA");
 		appdata = to_utf8(w_appdata);
 		replace_char(appdata, '\\', '/');
 	}

src/modules/graphics/opengl/Canvas.cpp

 
 	// texture coordinates
 	vertices[0].s = 0;
-	vertices[0].t = 1;
+	vertices[0].t = 0;
 	vertices[1].s = 0;
-	vertices[1].t = 0;
+	vertices[1].t = 1;
 	vertices[2].s = 1;
-	vertices[2].t = 0;
+	vertices[2].t = 1;
 	vertices[3].s = 1;
-	vertices[3].t = 1;
+	vertices[3].t = 0;
 
 	getStrategy();
 
 	glLoadIdentity();
 
 	// Set up orthographic view (no depth)
-	glOrtho(0.0, width, 0.0, height, -1.0, 1.0);
+	glOrtho(0.0, width, height, 0.0, -1.0, 1.0);
 
 	// Switch back to modelview matrix
 	glMatrixMode(GL_MODELVIEW);
 
 void Canvas::drawq(love::graphics::Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
 {
-	static Matrix t;
 	const vertex *v = quad->getVertices();
 
+	// mirror quad on x axis
+	vertex w[4];
+	memcpy(w, v, sizeof(vertex)*4);
+	for (size_t i = 0; i < 4; ++i)
+		w[i].t = 1. - w[i].t;
+
+	static Matrix t;
 	t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
-	drawv(t, v);
+
+	drawv(t, w);
 }
 
 love::image::ImageData *Canvas::getImageData(love::image::Image *image)
 {
 	int row = 4 * width;
 	int size = row * height;
-	GLubyte *pixels = new GLubyte[size];
+	GLubyte *pixels  = new GLubyte[size];
+	GLubyte *flipped = new GLubyte[size];
 
 	strategy->bindFBO(fbo);
 	glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
 	else
 		strategy->bindFBO(0);
 
-	love::image::ImageData *img = image->newImageData(width, height, (void *)pixels);
+	GLubyte *src = pixels, *dst = flipped + size - row;
+	for (int i = 0; i < height; ++i, dst -= row, src += row)
+	{
+		memcpy(dst, src, row);
+	}
+
+	love::image::ImageData *img = image->newImageData(width, height, (void *)flipped);
 
 	delete[] pixels;
 

src/modules/graphics/opengl/ParticleSystem.cpp

 	: pStart(0)
 	, pLast(0)
 	, pEnd(0)
+	, particleVerts(0)
 	, active(true)
 	, emissionRate(0)
 	, emitCounter(0)
 
 	if (pStart != 0)
 		delete [] pStart;
+	
+	if (particleVerts != 0)
+		delete [] particleVerts;
 }
 
 void ParticleSystem::add()
 void ParticleSystem::setBufferSize(unsigned int size)
 {
 	// delete previous data
-	delete [] pStart;
+	if (pStart != 0)
+		delete [] pStart;
 
 	pLast = pStart = new particle[size];
 
 	pEnd = pStart + size;
+	
+	if (particleVerts != 0)
+		delete [] particleVerts;
+	
+	// each particle has 4 vertices
+	particleVerts = new vertex[size*4];
 }
 
 void ParticleSystem::setEmissionRate(int rate)
 void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
 {
 	if (sprite == 0) return;  // just in case of failure
+	
+	int numParticles = count();
+	if (numParticles == 0) return; // don't bother if there's nothing to do
 
 	glPushMatrix();
 	glPushAttrib(GL_CURRENT_BIT);
 
-	Matrix t;
+	static Matrix t;
 	t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
 	glMultMatrixf((const GLfloat *)t.getElements());
-
-	particle *p = pStart;
-	while (p != pLast)
+	
+	const vertex * imageVerts = sprite->getVertices();
+	
+	// set the vertex data for each particle (transformation, texcoords, color)
+	for (int i = 0; i < numParticles; i++)
 	{
-		glPushMatrix();
-
-		glColor4f(p->color.r, p->color.g, p->color.b, p->color.a);
-		sprite->draw(p->position[0], p->position[1], p->rotation, p->size, p->size, offsetX, offsetY, 0.0f, 0.0f);
-
-		glPopMatrix();
-		p++;
+		particle * p = pStart + i;
+		
+		// particle vertices are sprite vertices transformed by particle information 
+		t.setTransformation(p->position[0], p->position[1], p->rotation, p->size, p->size, offsetX, offsetY, 0.0f, 0.0f);
+		t.transform(&particleVerts[i*4], &imageVerts[0], 4);
+		
+		// set the texture coordinate and color data for particle vertices
+		for (int v = 0; v < 4; v++) {
+			int vi = (i * 4) + v; // current vertex index for particle
+			
+			particleVerts[vi].s = imageVerts[v].s;
+			particleVerts[vi].t = imageVerts[v].t;
+			
+			// particle colors are stored as floats (0-1) but vertex colors are stored as unsigned bytes (0-255)
+			particleVerts[vi].r = p->color.r*255;
+			particleVerts[vi].g = p->color.g*255;
+			particleVerts[vi].b = p->color.b*255;
+			particleVerts[vi].a = p->color.a*255;
+		}
 	}
+	
+	sprite->bind();
+	
+	glEnableClientState(GL_COLOR_ARRAY);
+	glEnableClientState(GL_VERTEX_ARRAY);
+	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+	
+	glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vertex), (GLvoid *)&particleVerts[0].r);
+	glVertexPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid *)&particleVerts[0].x);
+	glTexCoordPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid *)&particleVerts[0].s);
+	
+	glDrawArrays(GL_QUADS, 0, numParticles*4);
+	
+	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+	glDisableClientState(GL_VERTEX_ARRAY);
+	glDisableClientState(GL_COLOR_ARRAY);
 
 	glPopAttrib();
 	glPopMatrix();

src/modules/graphics/opengl/ParticleSystem.h

 
 	// Pointer to the end of the memory allocation.
 	particle *pEnd;
+	
+	// array of transformed vertex data for all particles, for drawing
+	vertex * particleVerts;
 
 	// The sprite to be drawn.
 	Image *sprite;

src/modules/graphics/opengl/VertexBuffer.cpp

 
 void VBO::unmap()
 {
-	glBufferSubDataARB(getTarget(), 0, getSize(), mapped);
-	free(mapped);
-	mapped = 0;
+	if (mapped)
+	{
+		glBufferSubDataARB(getTarget(), 0, getSize(), mapped);
+		free(mapped);
+		mapped = 0;
+	}
 }
 
 void VBO::bind()

src/modules/graphics/opengl/wrap_Graphics.cpp

 	Image::FilterMode min;
 	Image::FilterMode mag;
 	const char *minstr = luaL_checkstring(L, 1);
-	const char *magstr = luaL_checkstring(L, 2);
+	const char *magstr = luaL_optstring(L, 2, minstr);
 	if (!Image::getConstant(minstr, min))
 		return luaL_error(L, "Invalid filter mode: %s", minstr);
 	if (!Image::getConstant(magstr, mag))

src/modules/graphics/opengl/wrap_Image.cpp

 	Image::FilterMode min;
 	Image::FilterMode mag;
 	const char *minstr = luaL_checkstring(L, 2);
-	const char *magstr = luaL_checkstring(L, 3);
+	const char *magstr = luaL_optstring(L, 3, minstr);
 	if (!Image::getConstant(minstr, min))
 		return luaL_error(L, "Invalid filter mode: %s", minstr);
 	if (!Image::getConstant(magstr, mag))
 	Image::WrapMode s;
 	Image::WrapMode t;
 	const char *sstr = luaL_checkstring(L, 2);
-	const char *tstr = luaL_checkstring(L, 3);
+	const char *tstr = luaL_optstring(L, 3, sstr);
 	if (!Image::getConstant(sstr, s))
 		return luaL_error(L, "Invalid wrap mode: %s", sstr);
 	if (!Image::getConstant(tstr, t))

src/modules/graphics/opengl/wrap_SpriteBatch.cpp

 int w_SpriteBatch_bind(lua_State *L)
 {
 	SpriteBatch *t = luax_checkspritebatch(L, 1);
-	t->lock();
+	try
+	{
+		t->lock();
+	}
+	catch (love::Exception &e)
+	{
+		return luaL_error(L, "%s", e.what());
+	}
 	return 0;
 }
 

src/scripts/boot.lua

 	end
 
 	-- Setup screen here.
+	local has_window = false
 	if c.screen and c.modules.graphics then
 		if love.graphics.checkMode(c.screen.width, c.screen.height, c.screen.fullscreen) or (c.screen.width == 0 and c.screen.height == 0) then
 			assert(love.graphics.setMode(c.screen.width, c.screen.height,
 				"The game might still work, but it is not guaranteed.\n" ..
 				"Furthermore, this means one should not judge this game or the engine if not."
 			print(msg)
-			if love.graphics and love.timer and love.event then
+			if has_window and love.timer and love.event then
 				love.event.pump()
 				love.graphics.setBackgroundColor(89, 157, 220)
 				love.graphics.clear()

src/scripts/boot.lua.h

 	0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x2d, 0x2d, 0x20, 0x53, 0x65, 0x74, 0x75, 0x70, 0x20, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x68, 
 	0x65, 0x72, 0x65, 0x2e, 0x0a,
+	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x68, 0x61, 0x73, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 
+	0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x0a,
 	0x09, 0x69, 0x66, 0x20, 0x63, 0x2e, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 
 	0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x20, 
 	0x74, 0x68, 0x65, 0x6e, 0x0a,
 	0x20, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x67, 0x69, 0x6e, 
 	0x65, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x2e, 0x22, 0x0a,
 	0x09, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x6d, 0x73, 0x67, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 
-	0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x20, 0x61, 
-	0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x68, 0x61, 0x73, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x61, 
+	0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 
+	0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
 	0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x75, 0x6d, 
 	0x70, 0x28, 0x29, 0x0a,
 	0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 
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.