Browse Source

Maerge in default

--HG--
branch : minor
Bart van Strien 12 years ago
parent
commit
a67a23e10f

+ 6 - 0
changes.txt

@@ -9,6 +9,7 @@ LOVE 0.8.1 [Rubber Piggy]
   * Added basic support for the file:// uri scheme.
   * Added basic support for the file:// uri scheme.
   * Added love.mouse.setX/setY.
   * Added love.mouse.setX/setY.
   * Added love.filesystem.getIdentity.
   * Added love.filesystem.getIdentity.
+  * Added HDR canvas support.
   * OPTIONAL: Added support for GME.
   * OPTIONAL: Added support for GME.
 
 
   * Fixed crashes with font drawing on some ATI cards.
   * Fixed crashes with font drawing on some ATI cards.
@@ -21,6 +22,10 @@ LOVE 0.8.1 [Rubber Piggy]
   * Fixed 'random' hangs in audio.
   * Fixed 'random' hangs in audio.
   * Fixed love.graphics.getLineWidth returning incorrect values.
   * Fixed love.graphics.getLineWidth returning incorrect values.
   * Fixed possible memory leak in utf-8 decoder.
   * 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.
   * Moved love's startup to modules/love.
 
 
@@ -32,6 +37,7 @@ LOVE 0.8.1 [Rubber Piggy]
   * Updated Source:set* functions to default z to 0.
   * Updated Source:set* functions to default z to 0.
   * Updated the windows console, it now tries to re-use an active one first.
   * 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 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]
 LOVE 0.8.0 [Rubber Piggy]
 -------------------------
 -------------------------

+ 8 - 0
src/modules/audio/wrap_Source.cpp

@@ -210,6 +210,13 @@ int w_Source_isPaused(lua_State *L)
 	return 1;
 	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)
 int w_Source_isStatic(lua_State *L)
 {
 {
 	Source *t = luax_checksource(L, 1);
 	Source *t = luax_checksource(L, 1);
@@ -299,6 +306,7 @@ static const luaL_Reg functions[] =
 	{ "isLooping", w_Source_isLooping },
 	{ "isLooping", w_Source_isLooping },
 	{ "isStopped", w_Source_isStopped },
 	{ "isStopped", w_Source_isStopped },
 	{ "isPaused", w_Source_isPaused },
 	{ "isPaused", w_Source_isPaused },
+	{ "isPlaying", w_Source_isPlaying },
 	{ "isStatic", w_Source_isStatic },
 	{ "isStatic", w_Source_isStatic },
 
 
 	{ "setVolumeLimits", w_Source_setVolumeLimits },
 	{ "setVolumeLimits", w_Source_setVolumeLimits },

+ 1 - 0
src/modules/audio/wrap_Source.h

@@ -51,6 +51,7 @@ int w_Source_setLooping(lua_State *L);
 int w_Source_isLooping(lua_State *L);
 int w_Source_isLooping(lua_State *L);
 int w_Source_isStopped(lua_State *L);
 int w_Source_isStopped(lua_State *L);
 int w_Source_isPaused(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_isStatic(lua_State *L);
 int w_Source_setVolumeLimits(lua_State *L);
 int w_Source_setVolumeLimits(lua_State *L);
 int w_Source_getVolumeLimits(lua_State *L);
 int w_Source_getVolumeLimits(lua_State *L);

+ 1 - 1
src/modules/filesystem/physfs/Filesystem.cpp

@@ -236,7 +236,7 @@ const char *Filesystem::getAppdataDirectory()
 #ifdef LOVE_WINDOWS
 #ifdef LOVE_WINDOWS
 	if (appdata.empty())
 	if (appdata.empty())
 	{
 	{
-		wchar_t *w_appdata = _wgetenv(TEXT("APPDATA"));
+		wchar_t *w_appdata = _wgetenv(L"APPDATA");
 		appdata = to_utf8(w_appdata);
 		appdata = to_utf8(w_appdata);
 		replace_char(appdata, '\\', '/');
 		replace_char(appdata, '\\', '/');
 	}
 	}

+ 23 - 9
src/modules/graphics/opengl/Canvas.cpp

@@ -304,13 +304,13 @@ Canvas::Canvas(int width, int height, TextureType texture_type)
 
 
 	// texture coordinates
 	// texture coordinates
 	vertices[0].s = 0;
 	vertices[0].s = 0;
-	vertices[0].t = 1;
+	vertices[0].t = 0;
 	vertices[1].s = 0;
 	vertices[1].s = 0;
-	vertices[1].t = 0;
+	vertices[1].t = 1;
 	vertices[2].s = 1;
 	vertices[2].s = 1;
-	vertices[2].t = 0;
+	vertices[2].t = 1;
 	vertices[3].s = 1;
 	vertices[3].s = 1;
-	vertices[3].t = 1;
+	vertices[3].t = 0;
 
 
 	getStrategy();
 	getStrategy();
 
 
@@ -364,7 +364,7 @@ void Canvas::startGrab()
 	glLoadIdentity();
 	glLoadIdentity();
 
 
 	// Set up orthographic view (no depth)
 	// 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
 	// Switch back to modelview matrix
 	glMatrixMode(GL_MODELVIEW);
 	glMatrixMode(GL_MODELVIEW);
@@ -413,18 +413,26 @@ void Canvas::draw(float x, float y, float angle, float sx, float sy, float ox, f
 
 
 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
 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();
 	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);
 	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)
 love::image::ImageData *Canvas::getImageData(love::image::Image *image)
 {
 {
 	int row = 4 * width;
 	int row = 4 * width;
 	int size = row * height;
 	int size = row * height;
-	GLubyte *pixels = new GLubyte[size];
+	GLubyte *pixels  = new GLubyte[size];
+	GLubyte *flipped = new GLubyte[size];
 
 
 	strategy->bindFBO(fbo);
 	strategy->bindFBO(fbo);
 	glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
 	glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
@@ -433,7 +441,13 @@ love::image::ImageData *Canvas::getImageData(love::image::Image *image)
 	else
 	else
 		strategy->bindFBO(0);
 		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;
 	delete[] pixels;
 
 

+ 56 - 12
src/modules/graphics/opengl/ParticleSystem.cpp

@@ -62,6 +62,7 @@ ParticleSystem::ParticleSystem(Image *sprite, unsigned int buffer)
 	: pStart(0)
 	: pStart(0)
 	, pLast(0)
 	, pLast(0)
 	, pEnd(0)
 	, pEnd(0)
+	, particleVerts(0)
 	, active(true)
 	, active(true)
 	, emissionRate(0)
 	, emissionRate(0)
 	, emitCounter(0)
 	, emitCounter(0)
@@ -104,6 +105,9 @@ ParticleSystem::~ParticleSystem()
 
 
 	if (pStart != 0)
 	if (pStart != 0)
 		delete [] pStart;
 		delete [] pStart;
+	
+	if (particleVerts != 0)
+		delete [] particleVerts;
 }
 }
 
 
 void ParticleSystem::add()
 void ParticleSystem::add()
@@ -197,11 +201,18 @@ void ParticleSystem::setSprite(Image *image)
 void ParticleSystem::setBufferSize(unsigned int size)
 void ParticleSystem::setBufferSize(unsigned int size)
 {
 {
 	// delete previous data
 	// delete previous data
-	delete [] pStart;
+	if (pStart != 0)
+		delete [] pStart;
 
 
 	pLast = pStart = new particle[size];
 	pLast = pStart = new particle[size];
 
 
 	pEnd = pStart + 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::setEmissionRate(int rate)
@@ -457,25 +468,58 @@ bool ParticleSystem::isFull() const
 void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
 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
 	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();
 	glPushMatrix();
 	glPushAttrib(GL_CURRENT_BIT);
 	glPushAttrib(GL_CURRENT_BIT);
 
 
-	Matrix t;
+	static Matrix t;
 	t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
 	t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
 	glMultMatrixf((const GLfloat *)t.getElements());
 	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();
 	glPopAttrib();
 	glPopMatrix();
 	glPopMatrix();

+ 3 - 0
src/modules/graphics/opengl/ParticleSystem.h

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

+ 6 - 3
src/modules/graphics/opengl/VertexBuffer.cpp

@@ -139,9 +139,12 @@ void *VBO::map()
 
 
 void VBO::unmap()
 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()
 void VBO::bind()

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

@@ -647,7 +647,7 @@ int w_setDefaultImageFilter(lua_State *L)
 	Image::FilterMode min;
 	Image::FilterMode min;
 	Image::FilterMode mag;
 	Image::FilterMode mag;
 	const char *minstr = luaL_checkstring(L, 1);
 	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))
 	if (!Image::getConstant(minstr, min))
 		return luaL_error(L, "Invalid filter mode: %s", minstr);
 		return luaL_error(L, "Invalid filter mode: %s", minstr);
 	if (!Image::getConstant(magstr, mag))
 	if (!Image::getConstant(magstr, mag))

+ 2 - 2
src/modules/graphics/opengl/wrap_Image.cpp

@@ -54,7 +54,7 @@ int w_Image_setFilter(lua_State *L)
 	Image::FilterMode min;
 	Image::FilterMode min;
 	Image::FilterMode mag;
 	Image::FilterMode mag;
 	const char *minstr = luaL_checkstring(L, 2);
 	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))
 	if (!Image::getConstant(minstr, min))
 		return luaL_error(L, "Invalid filter mode: %s", minstr);
 		return luaL_error(L, "Invalid filter mode: %s", minstr);
 	if (!Image::getConstant(magstr, mag))
 	if (!Image::getConstant(magstr, mag))
@@ -88,7 +88,7 @@ int w_Image_setWrap(lua_State *L)
 	Image::WrapMode s;
 	Image::WrapMode s;
 	Image::WrapMode t;
 	Image::WrapMode t;
 	const char *sstr = luaL_checkstring(L, 2);
 	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))
 	if (!Image::getConstant(sstr, s))
 		return luaL_error(L, "Invalid wrap mode: %s", sstr);
 		return luaL_error(L, "Invalid wrap mode: %s", sstr);
 	if (!Image::getConstant(tstr, t))
 	if (!Image::getConstant(tstr, t))

+ 8 - 1
src/modules/graphics/opengl/wrap_SpriteBatch.cpp

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

+ 2 - 1
src/scripts/boot.lua

@@ -324,6 +324,7 @@ function love.init()
 	end
 	end
 
 
 	-- Setup screen here.
 	-- Setup screen here.
+	local has_window = false
 	if c.screen and c.modules.graphics then
 	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
 		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,
 			assert(love.graphics.setMode(c.screen.width, c.screen.height,
@@ -376,7 +377,7 @@ function love.init()
 				"The game might still work, but it is not guaranteed.\n" ..
 				"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."
 				"Furthermore, this means one should not judge this game or the engine if not."
 			print(msg)
 			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.event.pump()
 				love.graphics.setBackgroundColor(89, 157, 220)
 				love.graphics.setBackgroundColor(89, 157, 220)
 				love.graphics.clear()
 				love.graphics.clear()

+ 5 - 3
src/scripts/boot.lua.h

@@ -528,6 +528,8 @@ const unsigned char boot_lua[] =
 	0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x2d, 0x2d, 0x20, 0x53, 0x65, 0x74, 0x75, 0x70, 0x20, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x68, 
 	0x09, 0x2d, 0x2d, 0x20, 0x53, 0x65, 0x74, 0x75, 0x70, 0x20, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x68, 
 	0x65, 0x72, 0x65, 0x2e, 0x0a,
 	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, 
 	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, 
 	0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x20, 
 	0x74, 0x68, 0x65, 0x6e, 0x0a,
 	0x74, 0x68, 0x65, 0x6e, 0x0a,
@@ -651,9 +653,9 @@ const unsigned char boot_lua[] =
 	0x20, 0x67, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x67, 0x69, 0x6e, 
 	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,
 	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, 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, 
 	0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x75, 0x6d, 
 	0x70, 0x28, 0x29, 0x0a,
 	0x70, 0x28, 0x29, 0x0a,
 	0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 
 	0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e,