Alex Szpakowski avatar Alex Szpakowski committed 3efe7a8

Replaced luax_newtype with luax_pushtype (and added luax_rawnewtype for the old functionality of luax_newtype.)

luax_pushtype keeps the object in a weak table and checks the table before creating a new userdata, so it re-uses the object's existing wrapper userdata if it can, whenever the object is pushed to Lua.

This fixes some subtle issues with love objects, where using them as keys in tables would not always work as expected (https://love2d.org/forums/viewtopic.php?f=4&t=39398&p=112388#p112415). It also decreases the amount of new Lua objects created, saving the garbage collector some work.

Comments (0)

Files changed (26)

src/common/Variant.cpp

 			const char *name = NULL;
 			love::types.find(udatatype, name);
 			((love::Object *) data.userdata)->retain();
-			luax_newtype(L, name, flags, data.userdata);
+			luax_pushtype(L, name, flags, (love::Object *) data.userdata);
 		}
 		else
 			lua_pushlightuserdata(L, data.userdata);

src/common/runtime.cpp

  * 3. This notice may not be removed or altered from any source distribution.
  **/
 
+#include "config.h"
 #include "runtime.h"
 
 // LOVE
 
 static thread::Mutex *gcmutex = 0;
 void *_gcmutex = 0;
+
 /**
  * Called when an object is collected. The object is released
  * once in this function, possibly deleting it.
 		gcmutex = thread::newMutex();
 		_gcmutex = (void *) gcmutex;
 	}
+
 	Proxy *p = (Proxy *)lua_touserdata(L, 1);
 	Object *t = (Object *)p->data;
-	if (p->own)
-	{
-		thread::Lock lock(gcmutex);
+
+	thread::Lock lock(gcmutex);
+
+	int numretains = p->retains;
+	if (numretains >= 0)
+		numretains = std::min(numretains, t->getReferenceCount());
+
+	for (int i = numretains; i > 0; i--)
 		t->release();
-	}
+
+	// Signal that this Proxy is dead.
+	p->retains = -1;
 	return 0;
 }
 
 int luax_register_module(lua_State *L, const WrappedModule &m)
 {
 	// Put a reference to the C++ module in Lua.
-	luax_getregistry(L, REGISTRY_MODULES);
+	luax_insistregistry(L, REGISTRY_MODULES);
 
 	Proxy *p = (Proxy *)lua_newuserdata(L, sizeof(Proxy));
-	p->own = true;
+	p->retains = 1;
 	p->data = m.module;
 	p->flags = m.flags;
 
 	if (!love::getType(tname, ltype))
 		printf("Missing type entry for type name: %s\n", tname);
 
+	// Get the place for storing and re-using instantiated love types.
+	luax_getregistry(L, REGISTRY_TYPES);
+
+	// Create registry._lovetypes if it doesn't exist yet.
+	if (!lua_istable(L, -1))
+	{
+		lua_newtable(L);
+		lua_replace(L, -2);
+
+		// Create a metatable.
+		lua_newtable(L);
+
+		// metatable.__mode = "v". Weak userdata values.
+		lua_pushliteral(L, "v");
+		lua_setfield(L, -2, "__mode");
+
+		// setmetatable(newtable, metatable)
+		lua_setmetatable(L, -2);
+
+		// registry._lovetypes = newtable
+		lua_setfield(L, LUA_REGISTRYINDEX, "_lovetypes");
+	}
+	else
+		lua_pop(L, 1);
+
 	luaL_newmetatable(L, tname);
 
 	// m.__index = m
 	return 0;
 }
 
-void luax_newtype(lua_State *L, const char *name, bits flags, void *data, bool own)
+void luax_rawnewtype(lua_State *L, const char *name, bits flags, love::Object *data, bool own)
 {
 	Proxy *u = (Proxy *)lua_newuserdata(L, sizeof(Proxy));
 
-	u->data = data;
+	u->data = (void *) data;
 	u->flags = flags;
-	u->own = own;
+	u->retains = own ? 1 : 0;
 
 	luaL_newmetatable(L, name);
 	lua_setmetatable(L, -2);
 }
 
+void luax_pushtype(lua_State *L, const char *name, bits flags, love::Object *data, bool own)
+{
+	// Fetch the registry table of instantiated types.
+	luax_getregistry(L, REGISTRY_TYPES);
+
+	// The table might not exist - it should be insisted in luax_register_type.
+	if (!lua_istable(L, -1))
+	{
+		lua_pop(L, 1);
+		return luax_rawnewtype(L, name, flags, data, own);
+	}
+
+	// Get the value of lovetypes[data] on the stack.
+	lua_pushlightuserdata(L, (void *) data);
+	lua_gettable(L, -2);
+
+	// If the Proxy userdata isn't in the instantiated types table yet, add it.
+	if (lua_type(L, -1) != LUA_TUSERDATA)
+	{
+		lua_pop(L, 1);
+
+		luax_rawnewtype(L, name, flags, data, own);
+
+		lua_pushlightuserdata(L, (void *) data);
+		lua_pushvalue(L, -2);
+
+		// lovetypes[data] = Proxy.
+		lua_settable(L, -4);
+
+		// Remove the lovetypes table from the stack.
+		lua_remove(L, -2);
+
+		// The Proxy userdata remains at the top of the stack.
+		return;
+	}
+
+	// Remove the lovetypes table from the stack.
+	lua_remove(L, -2);
+
+	// If the object should be released on GC and we already have a stored
+	// Proxy, we should tell the Proxy that the object was retained again.
+	if (own)
+	{
+		Proxy *p = (Proxy *) lua_touserdata(L, -1);
+
+		thread::EmptyLock lock;
+		if (gcmutex)
+			lock.setLock(gcmutex);
+
+		if (p->retains >= 0)
+			++(p->retains);
+	}
+
+	// Keep the Proxy userdata on the stack.
+}
+
 bool luax_istype(lua_State *L, int idx, love::bits type)
 {
 	if (lua_isuserdata(L, idx) == 0)
 	return 1;
 }
 
-int luax_getregistry(lua_State *L, Registry r)
+int luax_getlove(lua_State *L, const char *k)
+{
+	lua_getglobal(L, "love");
+
+	if (!lua_isnil(L, -1))
+	{
+		lua_getfield(L, -1, k);
+		lua_replace(L, -2);
+	}
+
+	return 1;
+}
+
+int luax_insistregistry(lua_State *L, Registry r)
 {
 	switch (r)
 	{
 		return luax_insistlove(L, "_gc");
 	case REGISTRY_MODULES:
 		return luax_insistlove(L, "_modules");
+	case REGISTRY_TYPES:
+		return luax_insist(L, LUA_REGISTRYINDEX, "_lovetypes");
+	default:
+		return luaL_error(L, "Attempted to use invalid registry.");
+	}
+}
+
+int luax_getregistry(lua_State *L, Registry r)
+{
+	switch (r)
+	{
+	case REGISTRY_GC:
+		return luax_getlove(L, "_gc");
+	case REGISTRY_MODULES:
+		return luax_getlove(L, "_modules");
+	case REGISTRY_TYPES:
+		lua_getfield(L, LUA_REGISTRYINDEX, "_lovetypes");
+		return 1;
 	default:
 		return luaL_error(L, "Attempted to use invalid registry.");
 	}

src/common/runtime.h

 
 // LOVE
 #include "types.h"
+#include "Object.h"
 
 // Lua
 extern "C" {
 
 // Exposed mutex of the GC
 extern void *_gcmutex;
-extern unsigned int _gcthread;
 
 /**
  * Registries represent special tables which can be accessed with
- * luax_getregistry.
+ * luax_insistregistry and luax_getregistry.
  **/
 enum Registry
 {
 	REGISTRY_GC = 1,
-	REGISTRY_MODULES
+	REGISTRY_MODULES,
+	REGISTRY_TYPES
 };
 
 /**
 	// Holds type information (see types.h).
 	bits flags;
 
-	// The light userdata.
+	// The light userdata (pointer to the love::Object).
 	void *data;
 
-	// True if Lua should delete on GC.
-	bool own;
+	// The number of times release() should be called on GC.
+	int retains;
 };
 
 /**
  *
  * In any case, the top stack element is popped, regardless of its type.
  **/
-Reference *luax_refif (lua_State *L, int type);
+Reference *luax_refif(lua_State *L, int type);
 
 /**
  * Prints the current contents of the stack. Only useful for debugging.
 int luax_register_searcher(lua_State *L, lua_CFunction f, int pos = -1);
 
 /**
- * Creates a new Lua-accessible object of the given type, and put it on the stack.
+ * Pushes a Lua representation of the given object onto the stack, creating and
+ * storing the Lua representation in a weak table if it doesn't exist yet.
  * @param L The Lua state.
- * @param name The name of the type. This must match the used earlier with luax_register_type.
- * @param flags The type information.
+ * @param name The name of the type. This must match the name used with luax_register_type.
+ * @param flags The type information of the object.
  * @param data The pointer to the actual object.
- * @own Set this to true (default) if the object should be released upon garbage collection.
+ * @param own Set this to true (default) if the object should be released upon garbage collection.
  **/
-void luax_newtype(lua_State *L, const char *name, bits flags, void *data, bool own = true);
+void luax_pushtype(lua_State *L, const char *name, bits flags, love::Object *data, bool own = true);
+
+/**
+ * Creates a new Lua representation of the given object *without* checking if it
+ * exists yet, and *without* storing it in a weak table.
+ * This should only be used when performance is an extreme concern and the
+ * object is not ever expected to be pushed to Lua again, as it prevents the
+ * Lua-side objects from working in all cases when used as keys in tables.
+ * @param L The Lua state.
+ * @param name The name of the type. This must match the name used with luax_register_type.
+ * @param flags The type information of the object.
+ * @param data The pointer to the actual object.
+ * @param own Set this to true (default) if the object should be released upon garbage collection.
+ **/
+void luax_rawnewtype(lua_State *L, const char *name, bits flags, love::Object *data, bool own = true);
 
 /**
  * Checks whether the value at idx is a certain type.
 int luax_insistlove(lua_State *L, const char *k);
 
 /**
- * Gets (creates if needed) the specified Registry, and puts it on top
- * of the stack.
+ * Pushes the table 'k' in the love table onto the stack. Pushes nil if the
+ * table doesn't exist.
+ * @param k The name of the table we want to get.
+ **/
+int luax_getlove(lua_State *L, const char *k);
+
+/**
+ * Gets (creates if needed) the specified Registry, and pushes it into the
+ * stack.
+ * @param L The Lua state.
+ * @param r The Registry to get.
+ **/
+int luax_insistregistry(lua_State *L, Registry r);
+
+/**
+ * Gets the specified Registry, and pushes it onto the stack. Pushes nil if the
+ * registry hasn't been created (see luax_insistregistry.)
  * @param L The Lua state.
  * @param r The Registry to get.
  **/
 template <typename T>
 T *luax_getmodule(lua_State *L, const char *k, love::bits type)
 {
-	luax_getregistry(L, REGISTRY_MODULES);
+	luax_insistregistry(L, REGISTRY_MODULES);
 	lua_getfield(L, -1, k);
 
 	if (!lua_isuserdata(L, -1))
 template <typename T>
 T *luax_optmodule(lua_State *L, const char *k, love::bits type)
 {
-	luax_getregistry(L, REGISTRY_MODULES);
+	luax_insistregistry(L, REGISTRY_MODULES);
 	lua_getfield(L, -1, k);
 
 	if (!lua_isuserdata(L, -1))

src/modules/audio/wrap_Audio.cpp

 
 	if (t)
 	{
-		luax_newtype(L, "Source", AUDIO_SOURCE_T, (void *)t);
+		luax_pushtype(L, "Source", AUDIO_SOURCE_T, t);
 		return 1;
 	}
 	else
 	if (!sd)
 		lua_pushnil(L);
 	else
-		luax_newtype(L, "SoundData", SOUND_SOUND_DATA_T, (void *)sd);
+		luax_pushtype(L, "SoundData", SOUND_SOUND_DATA_T, sd);
 	return 1;
 }
 
 	{
 		love::sound::SoundData *sd = instance->stopRecording(true);
 		if (!sd) lua_pushnil(L);
-		else luax_newtype(L, "SoundData", SOUND_SOUND_DATA_T, (void *)sd);
+		else luax_pushtype(L, "SoundData", SOUND_SOUND_DATA_T, sd);
 		return 1;
 	}
 	instance->stopRecording(false);

src/modules/filesystem/physfs/wrap_Filesystem.cpp

 		}
 	}
 
-	luax_newtype(L, "File", FILESYSTEM_FILE_T, (void *)t);
+	luax_pushtype(L, "File", FILESYSTEM_FILE_T, t);
 	return 1;
 }
 
 			{
 				return ioError(L, "%s", e.what());
 			}
-			luax_newtype(L, "FileData", FILESYSTEM_FILE_DATA_T, (void *) data);
+			luax_pushtype(L, "FileData", FILESYSTEM_FILE_DATA_T, data);
 			return 1;
 		}
 		else
 		return luaL_error(L, "Invalid FileData decoder: %s", decstr);
 	}
 
-	luax_newtype(L, "FileData", FILESYSTEM_FILE_DATA_T, (void *)t);
+	luax_pushtype(L, "FileData", FILESYSTEM_FILE_DATA_T, t);
 	return 1;
 }
 
 		{
 			return luaL_error(L, "%s", e.what());
 		}
-		luax_newtype(L, "File", FILESYSTEM_FILE_T, file);
+		luax_pushtype(L, "File", FILESYSTEM_FILE_T, file);
 	}
 	else
 		return luaL_error(L, "Expected filename.");

src/modules/font/freetype/wrap_Font.cpp

 		return luaL_error(L, "%s", e.what());
 	}
 
-	luax_newtype(L, "Rasterizer", FONT_RASTERIZER_T, t);
+	luax_pushtype(L, "Rasterizer", FONT_RASTERIZER_T, t);
 	return 1;
 }
 
 		t = instance->newGlyphData(r, g);
 	}
 
-	luax_newtype(L, "GlyphData", FONT_GLYPH_DATA_T, t);
+	luax_pushtype(L, "GlyphData", FONT_GLYPH_DATA_T, t);
 	return 1;
 }
 

src/modules/font/wrap_Rasterizer.cpp

 		return luaL_error(L, "%s", e.what());
 	}
 
-	luax_newtype(L, "GlyphData", FONT_GLYPH_DATA_T, (void *) g);
+	luax_pushtype(L, "GlyphData", FONT_GLYPH_DATA_T, g);
 	return 1;
 }
 

src/modules/graphics/opengl/wrap_Canvas.cpp

 	Canvas *canvas = luax_checkcanvas(L, 1);
 	love::image::Image *image = luax_getmodule<love::image::Image>(L, "image", MODULE_IMAGE_T);
 	love::image::ImageData *img = canvas->getImageData(image);
-	luax_newtype(L, "ImageData", IMAGE_IMAGE_DATA_T, (void *)img);
+	luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, img);
 	return 1;
 }
 

src/modules/graphics/opengl/wrap_Graphics.cpp

 
 
 	// Push the type.
-	luax_newtype(L, "Image", GRAPHICS_IMAGE_T, (void *)image);
+	luax_pushtype(L, "Image", GRAPHICS_IMAGE_T, image);
 
 	return 1;
 }
 
 	geom->setVertexColors(hasvertexcolors);
 
-	luax_newtype(L, "Geometry", GRAPHICS_GEOMETRY_T, (void *) geom);
+	// Note: This should be changed to luax_pushtype if the new Geometry is ever
+	// expected to be pushed to Lua from another C++ function!
+	luax_rawnewtype(L, "Geometry", GRAPHICS_GEOMETRY_T, geom);
 	return 1;
 }
 
 
 	Geometry *quad = instance->newQuad(x, y, w, h, sw, sh);
 
-	luax_newtype(L, "Geometry", GRAPHICS_GEOMETRY_T, (void *)quad);
+	// Note: This should be changed to luax_pushtype if the new Geometry is ever
+	// expected to be pushed to Lua from another C++ function!
+	luax_rawnewtype(L, "Geometry", GRAPHICS_GEOMETRY_T, quad);
 	return 1;
 }
 
 		return luaL_error(L, "Could not load font.");
 
 	// Push the type.
-	luax_newtype(L, "Font", GRAPHICS_FONT_T, (void *)font);
+	luax_pushtype(L, "Font", GRAPHICS_FONT_T, font);
 
 	return 1;
 }
 		love::image::ImageData *id = i->getImageData();
 		if (!id)
 			return luaL_argerror(L, 1, "Image cannot be compressed.");
-		luax_newtype(L, "ImageData", IMAGE_IMAGE_DATA_T, (void *)id, false);
+		luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, id, false);
 		lua_replace(L, 1);
 	}
 
 		return luaL_error(L, "Could not load font.");
 
 	// Push the type.
-	luax_newtype(L, "Font", GRAPHICS_FONT_T, (void *)font);
+	luax_pushtype(L, "Font", GRAPHICS_FONT_T, font);
 
 	return 1;
 }
 	{
 		return luaL_error(L, e.what());
 	}
-	luax_newtype(L, "SpriteBatch", GRAPHICS_SPRITE_BATCH_T, (void *)t);
+	luax_pushtype(L, "SpriteBatch", GRAPHICS_SPRITE_BATCH_T, t);
 	return 1;
 }
 
 	{
 		return luaL_error(L, "%s", e.what());
 	}
-	luax_newtype(L, "ParticleSystem", GRAPHICS_PARTICLE_SYSTEM_T, (void *) t);
+	luax_pushtype(L, "ParticleSystem", GRAPHICS_PARTICLE_SYSTEM_T, t);
 	return 1;
 }
 
 	if (NULL == canvas)
 		return luaL_error(L, "Canvas not created, but no error thrown. I don't even...");
 
-	luax_newtype(L, "Canvas", GRAPHICS_CANVAS_T, (void *)canvas);
+	luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, canvas);
 	return 1;
 }
 
 	try
 	{
 		Shader *shader = instance->newShader(sources);
-		luax_newtype(L, "Shader", GRAPHICS_SHADER_T, (void *)shader);
+		luax_pushtype(L, "Shader", GRAPHICS_SHADER_T, shader);
 	}
 	catch (const love::Exception &e)
 	{
 		return 0;
 
 	f->retain();
-	luax_newtype(L, "Font", GRAPHICS_FONT_T, (void *)f);
+	luax_pushtype(L, "Font", GRAPHICS_FONT_T, f);
 	return 1;
 }
 
 	{
 		return luaL_error(L, "%s", e.what());
 	}
-	luax_newtype(L, "ImageData", IMAGE_IMAGE_DATA_T, (void *)i);
+	luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, i);
 	return 1;
 }
 
 	if (canvas)
 	{
 		canvas->retain();
-		luax_newtype(L, "Canvas", GRAPHICS_CANVAS_T, (void *) canvas);
+		luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, canvas);
 
 		const std::vector<Canvas *> &attachments = canvas->getAttachedCanvases();
 		for (size_t i = 0; i < attachments.size(); i++)
 		{
 			attachments[i]->retain();
-			luax_newtype(L, "Canvas", GRAPHICS_CANVAS_T, (void *) attachments[i]);
+			luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, attachments[i]);
 			n++;
 		}
 	}
 	if (shader)
 	{
 		shader->retain();
-		luax_newtype(L, "Shader", GRAPHICS_SHADER_T, (void *) shader);
+		luax_pushtype(L, "Shader", GRAPHICS_SHADER_T, shader);
 	}
 	else
 		lua_pushnil(L);

src/modules/graphics/opengl/wrap_Image.cpp

 		if (t)
 		{
 			t->retain();
-			luax_newtype(L, "CompressedData", IMAGE_COMPRESSED_DATA_T, (void *) t);
+			luax_pushtype(L, "CompressedData", IMAGE_COMPRESSED_DATA_T, t);
 		}
 		else
 			lua_pushnil(L);
 		if (t)
 		{
 			t->retain();
-			luax_newtype(L, "ImageData", IMAGE_IMAGE_DATA_T, (void *) t);
+			luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, t);
 		}
 		else
 			lua_pushnil(L);

src/modules/graphics/opengl/wrap_ParticleSystem.cpp

 	ParticleSystem *t = luax_checkparticlesystem(L, 1);
 	Image *i = t->getImage();
 	i->retain();
-	luax_newtype(L, "Image", GRAPHICS_IMAGE_T, (void *) i);
+	luax_pushtype(L, "Image", GRAPHICS_IMAGE_T, i);
 	return 1;
 }
 

src/modules/graphics/opengl/wrap_SpriteBatch.cpp

 	SpriteBatch *t = luax_checkspritebatch(L, 1);
 	Image *image = t->getImage();
 	image->retain();
-	luax_newtype(L, "Image", GRAPHICS_IMAGE_T, (void *)image);
+	luax_pushtype(L, "Image", GRAPHICS_IMAGE_T, image);
 	return 1;
 }
 

src/modules/image/wrap_Image.cpp

 		{
 			return luaL_error(L, "%s", e.what());
 		}
-		luax_newtype(L, "ImageData", IMAGE_IMAGE_DATA_T, (void *)t);
+		luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, t);
 		return 1;
 	}
 
 		return luaL_error(L, "%s", e.what());
 	}
 
-	luax_newtype(L, "ImageData", IMAGE_IMAGE_DATA_T, (void *) t);
+	luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, t);
 
 	return 1;
 }
 		return luaL_error(L, "%s", e.what());
 	}
 
-	luax_newtype(L, "CompressedData", IMAGE_COMPRESSED_DATA_T, (void *) t);
+	luax_pushtype(L, "CompressedData", IMAGE_COMPRESSED_DATA_T, t);
 
 	return 1;
 }

src/modules/joystick/sdl/wrap_JoystickModule.cpp

 	{
 		love::joystick::Joystick *stick = instance->getJoystick(i);
 		stick->retain();
-		luax_newtype(L, "Joystick", JOYSTICK_JOYSTICK_T, (void *) stick);
+		luax_pushtype(L, "Joystick", JOYSTICK_JOYSTICK_T, stick);
 		lua_rawseti(L, -2, i + 1);
 	}
 

src/modules/math/wrap_BezierCurve.cpp

 {
 	BezierCurve *curve = luax_checkbeziercurve(L, 1);
 	BezierCurve *deriv = new BezierCurve(curve->getDerivative());
-	luax_newtype(L, "BezierCurve", MATH_BEZIER_CURVE_T, (void *)deriv);
+	luax_pushtype(L, "BezierCurve", MATH_BEZIER_CURVE_T, deriv);
 	return 1;
 }
 

src/modules/math/wrap_Math.cpp

 		}
 	}
 
-	luax_newtype(L, "RandomGenerator", MATH_RANDOM_GENERATOR_T, (void *) t);
+	luax_pushtype(L, "RandomGenerator", MATH_RANDOM_GENERATOR_T, t);
 	return 1;
 }
 
 	}
 
 	BezierCurve *curve = Math::instance.newBezierCurve(points);
-	luax_newtype(L, "BezierCurve", MATH_BEZIER_CURVE_T, (void *)curve);
+	luax_pushtype(L, "BezierCurve", MATH_BEZIER_CURVE_T, curve);
 	return 1;
 }
 

src/modules/mouse/wrap_Mouse.cpp

 		}
 	}
 
-	luax_newtype(L, "Cursor", MOUSE_CURSOR_T, (void *) cursor);
+	luax_pushtype(L, "Cursor", MOUSE_CURSOR_T, cursor);
 	return 1;
 }
 
 	if (cursor)
 	{
 		cursor->retain();
-		luax_newtype(L, "Cursor", MOUSE_CURSOR_T, (void *) cursor);
+		luax_pushtype(L, "Cursor", MOUSE_CURSOR_T, cursor);
 	}
 	else
 		lua_pushnil(L);

src/modules/physics/box2d/Body.cpp

 		if (!fixture)
 			throw love::Exception("A fixture has escaped Memoizer!");
 		fixture->retain();
-		luax_newtype(L, "Fixture", PHYSICS_FIXTURE_T, (void *)fixture);
+		luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, fixture);
 		lua_rawseti(L, -2, i);
 		i++;
 	}

src/modules/physics/box2d/Physics.cpp

 	s->Set(vecs, vcount);
 	PolygonShape *p = new PolygonShape(s);
 
-	luax_newtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, (void *)p);
+	luax_pushtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, p);
 	return 1;
 }
 
 	ChainShape *c = new ChainShape(s);
 	delete[] vecs;
 
-	luax_newtype(L, "ChainShape", PHYSICS_CHAIN_SHAPE_T, (void *)c);
+	luax_pushtype(L, "ChainShape", PHYSICS_CHAIN_SHAPE_T, c);
 
 	return 1;
 }

src/modules/physics/box2d/World.cpp

 			if (a != 0)
 			{
 				a->retain();
-				luax_newtype(L, "Fixture", PHYSICS_FIXTURE_T, (void *)a);
+				luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, a);
 			}
 			else
 				throw love::Exception("A fixture has escaped Memoizer!");
 			if (b != 0)
 			{
 				b->retain();
-				luax_newtype(L, "Fixture", PHYSICS_FIXTURE_T, (void *)b);
+				luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, b);
 			}
 			else
 				throw love::Exception("A fixture has escaped Memoizer!");
 		else
 			cobj->retain();
 
-		luax_newtype(L, "Contact", (PHYSICS_CONTACT_T), (void *)cobj);
+		luax_pushtype(L, "Contact", (PHYSICS_CONTACT_T), cobj);
 
 		int args = 3;
 		if (impulse)
 	{
 		lua_State *L = ref->getL();
 		ref->push();
-		luax_newtype(L, "Fixture", PHYSICS_FIXTURE_T, (void *)a);
-		luax_newtype(L, "Fixture", PHYSICS_FIXTURE_T, (void *)b);
+		luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, a);
+		luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, b);
 		lua_call(L, 2, 1);
 		return luax_toboolean(L, -1);
 	}
 		if (!f)
 			throw love::Exception("A fixture has escaped Memoizer!");
 		f->retain();
-		luax_newtype(L, "Fixture", PHYSICS_FIXTURE_T, (void *)f);
+		luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, f);
 		lua_call(L, 1, 1);
 		return luax_toboolean(L, -1);
 	}
 		if (!f)
 			throw love::Exception("A fixture has escaped Memoizer!");
 		f->retain();
-		luax_newtype(L, "Fixture", PHYSICS_FIXTURE_T, (void *)f);
+		luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, f);
 		b2Vec2 scaledPoint = Physics::scaleUp(point);
 		lua_pushnumber(L, scaledPoint.x);
 		lua_pushnumber(L, scaledPoint.y);
 		if (!body)
 			throw love::Exception("A body has escaped Memoizer!");
 		body->retain();
-		luax_newtype(L, "Body", PHYSICS_BODY_T, (void *)body);
+		luax_pushtype(L, "Body", PHYSICS_BODY_T, body);
 		lua_rawseti(L, -2, i);
 		i++;
 	}
 		Joint *joint = (Joint *)Memoizer::find(j);
 		if (!joint) throw love::Exception("A joint has escaped Memoizer!");
 		joint->retain();
-		luax_newtype(L, "Joint", PHYSICS_JOINT_T, (void *)joint);
+		luax_pushtype(L, "Joint", PHYSICS_JOINT_T, joint);
 		lua_rawseti(L, -2, i);
 		i++;
 	}
 			contact = new Contact(c);
 		else
 			contact->retain();
-		luax_newtype(L, "Contact", PHYSICS_CONTACT_T, (void *)contact);
+		luax_pushtype(L, "Contact", PHYSICS_CONTACT_T, contact);
 		lua_rawseti(L, -2, i);
 		i++;
 	}

src/modules/physics/box2d/wrap_ChainShape.cpp

 	int index = luaL_checkint(L, 2) - 1; // Convert from 1-based index
 	EdgeShape *e = 0;
 	ASSERT_GUARD(e = c->getChildEdge(index);)
-	luax_newtype(L, "EdgeShape", PHYSICS_EDGE_SHAPE_T, e);
+	luax_pushtype(L, "EdgeShape", PHYSICS_EDGE_SHAPE_T, e);
 	return 1;
 }
 

src/modules/physics/box2d/wrap_Fixture.cpp

 	if (body == 0)
 		return 0;
 	body->retain();
-	luax_newtype(L, "Body", PHYSICS_BODY_T, (void *)body);
+	luax_pushtype(L, "Body", PHYSICS_BODY_T, body);
 	return 1;
 }
 
 	switch (shape->getType())
 	{
 	case Shape::SHAPE_EDGE:
-		luax_newtype(L, "EdgeShape", PHYSICS_EDGE_SHAPE_T, (void *)shape);
+		luax_pushtype(L, "EdgeShape", PHYSICS_EDGE_SHAPE_T, shape);
 		break;
 	case Shape::SHAPE_CHAIN:
-		luax_newtype(L, "ChainShape", PHYSICS_CHAIN_SHAPE_T, (void *)shape);
+		luax_pushtype(L, "ChainShape", PHYSICS_CHAIN_SHAPE_T, shape);
 		break;
 	case Shape::SHAPE_CIRCLE:
-		luax_newtype(L, "CircleShape", PHYSICS_CIRCLE_SHAPE_T, (void *)shape);
+		luax_pushtype(L, "CircleShape", PHYSICS_CIRCLE_SHAPE_T, shape);
 		break;
 	case Shape::SHAPE_POLYGON:
-		luax_newtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, (void *)shape);
+		luax_pushtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, shape);
 		break;
 	default:
-		luax_newtype(L, "Shape", PHYSICS_SHAPE_T, (void *)shape);
+		luax_pushtype(L, "Shape", PHYSICS_SHAPE_T, shape);
 		break;
 	}
 	return 1;

src/modules/physics/box2d/wrap_Physics.cpp

 
 	World *w;
 	ASSERT_GUARD(w = instance->newWorld(gx, gy, sleep);)
-	luax_newtype(L, "World", PHYSICS_WORLD_T, (void *)w);
+	luax_pushtype(L, "World", PHYSICS_WORLD_T, w);
 
 	return 1;
 }
 
 	Body *body;
 	ASSERT_GUARD(body = instance->newBody(world, x, y, btype);)
-	luax_newtype(L, "Body", PHYSICS_BODY_T, (void *)body);
+	luax_pushtype(L, "Body", PHYSICS_BODY_T, body);
 	return 1;
 }
 
 	float density = (float)luaL_optnumber(L, 3, 1.0f);
 	Fixture *fixture;
 	ASSERT_GUARD(fixture = instance->newFixture(body, shape, density);)
-	luax_newtype(L, "Fixture", PHYSICS_FIXTURE_T, (void *)fixture);
+	luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, fixture);
 	return 1;
 }
 
 		float radius = (float)luaL_checknumber(L, 1);
 		CircleShape *shape;
 		ASSERT_GUARD(shape = instance->newCircleShape(radius);)
-		luax_newtype(L, "CircleShape", PHYSICS_CIRCLE_SHAPE_T, (void *)shape);
+		luax_pushtype(L, "CircleShape", PHYSICS_CIRCLE_SHAPE_T, shape);
 		return 1;
 	}
 	else if (top == 3)
 		float radius = (float)luaL_checknumber(L, 3);
 		CircleShape *shape;
 		ASSERT_GUARD(shape = instance->newCircleShape(x, y, radius);)
-		luax_newtype(L, "CircleShape", PHYSICS_CIRCLE_SHAPE_T, (void *)shape);
+		luax_pushtype(L, "CircleShape", PHYSICS_CIRCLE_SHAPE_T, shape);
 		return 1;
 	}
 	else
 		float h = (float)luaL_checknumber(L, 2);
 		PolygonShape *shape;
 		ASSERT_GUARD(shape = instance->newRectangleShape(w, h);)
-		luax_newtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, (void *)shape);
+		luax_pushtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, shape);
 		return 1;
 	}
 	else if (top == 4 || top == 5)
 		float angle = (float)luaL_optnumber(L, 5, 0);
 		PolygonShape *shape;
 		ASSERT_GUARD(shape = instance->newRectangleShape(x, y, w, h, angle);)
-		luax_newtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, (void *)shape);
+		luax_pushtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, shape);
 		return 1;
 	}
 	else
 	float y2 = (float)luaL_checknumber(L, 4);
 	EdgeShape *shape;
 	ASSERT_GUARD(shape = instance->newEdgeShape(x1, y1, x2, y2);)
-	luax_newtype(L, "EdgeShape", PHYSICS_EDGE_SHAPE_T, (void *)shape);
+	luax_pushtype(L, "EdgeShape", PHYSICS_EDGE_SHAPE_T, shape);
 	return 1;
 }
 
 	bool collideConnected = luax_optboolean(L, 7, false);
 	DistanceJoint *j;
 	ASSERT_GUARD(j = instance->newDistanceJoint(body1, body2, x1, y1, x2, y2, collideConnected);)
-	luax_newtype(L, "DistanceJoint", PHYSICS_DISTANCE_JOINT_T, (void *)j);
+	luax_pushtype(L, "DistanceJoint", PHYSICS_DISTANCE_JOINT_T, j);
 	return 1;
 }
 
 	float y = (float)luaL_checknumber(L, 3);
 	MouseJoint *j;
 	ASSERT_GUARD(j = instance->newMouseJoint(body, x, y);)
-	luax_newtype(L, "MouseJoint", PHYSICS_MOUSE_JOINT_T, (void *)j);
+	luax_pushtype(L, "MouseJoint", PHYSICS_MOUSE_JOINT_T, j);
 	return 1;
 }
 
 	bool collideConnected = luax_optboolean(L, 5, false);
 	RevoluteJoint *j;
 	ASSERT_GUARD(j = instance->newRevoluteJoint(body1, body2, x, y, collideConnected);)
-	luax_newtype(L, "RevoluteJoint", PHYSICS_REVOLUTE_JOINT_T, (void *)j);
+	luax_pushtype(L, "RevoluteJoint", PHYSICS_REVOLUTE_JOINT_T, j);
 	return 1;
 }
 
 	}
 	PrismaticJoint *j;
 	ASSERT_GUARD(j = instance->newPrismaticJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);)
-	luax_newtype(L, "PrismaticJoint", PHYSICS_PRISMATIC_JOINT_T, (void *)j);
+	luax_pushtype(L, "PrismaticJoint", PHYSICS_PRISMATIC_JOINT_T, j);
 	return 1;
 }
 
 
 	PulleyJoint *j;
 	ASSERT_GUARD(j = instance->newPulleyJoint(body1, body2, b2Vec2(gx1,gy1), b2Vec2(gx2,gy2), b2Vec2(x1,y1), b2Vec2(x2,y2), ratio, collideConnected);)
-	luax_newtype(L, "PulleyJoint", PHYSICS_PULLEY_JOINT_T, (void *)j);
+	luax_pushtype(L, "PulleyJoint", PHYSICS_PULLEY_JOINT_T, j);
 	return 1;
 }
 
 
 	GearJoint *j;
 	ASSERT_GUARD(j = instance->newGearJoint(joint1, joint2, ratio, collideConnected);)
-	luax_newtype(L, "GearJoint", PHYSICS_GEAR_JOINT_T, (void *)j);
+	luax_pushtype(L, "GearJoint", PHYSICS_GEAR_JOINT_T, j);
 	return 1;
 }
 
 	}
 	FrictionJoint *j;
 	ASSERT_GUARD(j = instance->newFrictionJoint(body1, body2, xA, yA, xB, yB, collideConnected);)
-	luax_newtype(L, "FrictionJoint", PHYSICS_FRICTION_JOINT_T, (void *)j);
+	luax_pushtype(L, "FrictionJoint", PHYSICS_FRICTION_JOINT_T, j);
 	return 1;
 }
 
 	}
 	WeldJoint *j;
 	ASSERT_GUARD(j = instance->newWeldJoint(body1, body2, xA, yA, xB, yB, collideConnected);)
-	luax_newtype(L, "WeldJoint", PHYSICS_WELD_JOINT_T, (void *)j);
+	luax_pushtype(L, "WeldJoint", PHYSICS_WELD_JOINT_T, j);
 	return 1;
 }
 
 
 	WheelJoint *j;
 	ASSERT_GUARD(j = instance->newWheelJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);)
-	luax_newtype(L, "WheelJoint", PHYSICS_WHEEL_JOINT_T, (void *)j);
+	luax_pushtype(L, "WheelJoint", PHYSICS_WHEEL_JOINT_T, j);
 	return 1;
 }
 
 	bool collideConnected = luax_optboolean(L, 8, false);
 	RopeJoint *j;
 	ASSERT_GUARD(j = instance->newRopeJoint(body1, body2, x1, y1, x2, y2, maxLength, collideConnected);)
-	luax_newtype(L, "RopeJoint", PHYSICS_ROPE_JOINT_T, (void *)j);
+	luax_pushtype(L, "RopeJoint", PHYSICS_ROPE_JOINT_T, j);
 	return 1;
 }
 

src/modules/sound/wrap_Sound.cpp

 		}
 	}
 
-	luax_newtype(L, "SoundData", SOUND_SOUND_DATA_T, (void *)t);
-
+	luax_pushtype(L, "SoundData", SOUND_SOUND_DATA_T, t);
 	return 1;
 }
 
 		Decoder *t = instance->newDecoder(data, bufferSize);
 		if (t == 0)
 			return luaL_error(L, "Extension \"%s\" not supported.", data->getExtension().c_str());
-		luax_newtype(L, "Decoder", SOUND_DECODER_T, (void *)t);
+		luax_pushtype(L, "Decoder", SOUND_DECODER_T, t);
 	}
 	catch(love::Exception &e)
 	{

src/modules/thread/wrap_ThreadModule.cpp

 	}
 
 	LuaThread *t = instance->newThread(name, data);
-	luax_newtype(L, "Thread", THREAD_THREAD_T, (void *)t);
+	luax_pushtype(L, "Thread", THREAD_THREAD_T, t);
 	return 1;
 }
 
 int w_newChannel(lua_State *L)
 {
 	Channel *c = instance->newChannel();
-	luax_newtype(L, "Channel", THREAD_CHANNEL_T, (void *)c);
+	luax_pushtype(L, "Channel", THREAD_CHANNEL_T, c);
 	return 1;
 }
 
 {
 	std::string name = luax_checkstring(L, 1);
 	Channel *c = instance->getChannel(name);
-	luax_newtype(L, "Channel", THREAD_CHANNEL_T, (void *)c);
+	luax_pushtype(L, "Channel", THREAD_CHANNEL_T, c);
 	return 1;
 }
 

src/modules/window/wrap_Window.cpp

 	if (i)
 	{
 		i->retain();
-		luax_newtype(L, "ImageData", IMAGE_IMAGE_DATA_T, (void*) i);
+		luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, i);
 	}
 	else
 		lua_pushnil(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.