Index: trunk/src/lua/lua_area.cc
===================================================================
--- trunk/src/lua/lua_area.cc	(revision 204)
+++ trunk/src/lua/lua_area.cc	(revision 206)
@@ -150,5 +150,5 @@
 static int nlua_area_coords( lua_State* L )
 {
-	nv::rectangle* a( nlua_to_parea( L, lua_upvalueindex(1) ) );
+	nv::rectangle* a( nlua_to_parea( L, 1 ) );
 	nv::ivec2      c( a->ul );
 	c.x--;
@@ -184,5 +184,5 @@
 static int nlua_area_edges( lua_State* L )
 {
-	nv::rectangle*   a( nlua_to_parea( L, lua_upvalueindex(1) ) );
+	nv::rectangle*   a( nlua_to_parea( L, 1 ) );
 	nv::ivec2 c( a->ul );
 	c.x--;
Index: trunk/src/lua/lua_map_area.cc
===================================================================
--- trunk/src/lua/lua_map_area.cc	(revision 204)
+++ trunk/src/lua/lua_map_area.cc	(revision 206)
@@ -9,4 +9,5 @@
 #include "nv/lua/lua_area.hh"
 #include "nv/lua/lua_glm.hh"
+#include "nv/lua/lua_values.hh"
 #include "nv/lua/lua_raw.hh"
 
@@ -53,5 +54,23 @@
 nv::map_area* nlua_to_map_area( lua_State* L, int index )
 {
-	return *(nv::map_area**)luaL_checkudata( L, index, NLUA_MAP_AREA_METATABLE );
+	if ( lua_type( L, index ) == LUA_TTABLE )
+	{
+		nv::map_area* o = nullptr;
+		if ( lua_istable( L , index ) )
+		{
+			lua_pushstring( L, "__map_area_ptr" );
+			lua_rawget( L, index );
+			if ( lua_isuserdata( L, -1 ) )
+			{
+				o = static_cast<nv::map_area*>( lua_touserdata( L, -1 ) );
+			} 
+			lua_pop( L, 1 );
+		}
+		return o;
+	}
+	else
+	{
+		return *(nv::map_area**)luaL_checkudata( L, index, NLUA_MAP_AREA_METATABLE );
+	}
 }
 
@@ -83,5 +102,8 @@
 {
 	nv::map_area* ma = nlua_to_map_area( L, 1 );
-	nlua_push_area( L, ma->get_rectangle() );
+	nv::rectangle r  = ma->get_rectangle();
+	r.lr.x -= 1;
+	r.lr.y -= 1;
+	nlua_push_area( L, r );
 	return 1;
 }
Index: trunk/src/lua/lua_state.cc
===================================================================
--- trunk/src/lua/lua_state.cc	(revision 204)
+++ trunk/src/lua/lua_state.cc	(revision 206)
@@ -16,5 +16,5 @@
 
 lua::stack_guard::stack_guard( lua::state* aL )
-	: L(aL), m_level( lua_gettop(aL->L) )
+	: L(aL), m_level( lua_gettop(aL->m_state) )
 {
 
@@ -22,5 +22,5 @@
 
 lua::stack_guard::stack_guard( lua::state& aL )
-	: L(&aL), m_level( lua_gettop(aL.L) )
+	: L(&aL), m_level( lua_gettop(aL.m_state) )
 {
 
@@ -29,16 +29,21 @@
 lua::stack_guard::~stack_guard()
 {
-	lua_settop( L->L, m_level );
-}
-
-lua::state::state( bool load_libs /*= false*/ )
+	lua_settop( L->m_state, m_level );
+}
+
+lua::state::state( lua_State* state ) : state_wrapper( state, false )
+{
+
+}
+
+lua::state::state( bool load_libs /*= false*/ ) : state_wrapper( nullptr, true )
 {
 	load_lua_library();
 	m_owner = true;
-	L = luaL_newstate( );
-
-	lua_pushcfunction(L, luaopen_base);
-	lua_pushliteral(L, LUA_TABLIBNAME);
-	lua_call(L, 1, 0);
+	m_state = luaL_newstate( );
+
+	lua_pushcfunction(m_state, luaopen_base);
+	lua_pushliteral(m_state, LUA_TABLIBNAME);
+	lua_call(m_state, 1, 0);
 
 	if ( load_libs )
@@ -55,5 +60,5 @@
 		for(; lib->func != NULL; lib++)
 		{
-			lib->func( L );
+			lib->func( m_state );
 		}
 	}
@@ -65,5 +70,5 @@
 {
 	NV_LOG( nv::LOG_TRACE, "Loading Lua string '" << name << "'");
-	return luaL_loadbuffer( L, code.c_str(), code.length(), name.c_str() );
+	return luaL_loadbuffer( m_state, code.c_str(), code.length(), name.c_str() );
 }
 
@@ -79,5 +84,5 @@
 {
 	NV_LOG( nv::LOG_NOTICE, "Loading Lua file '" << filename << "'");
-	return luaL_loadfile( L, filename.c_str() );
+	return luaL_loadfile( m_state, filename.c_str() );
 }
 
@@ -88,5 +93,5 @@
 	if (result)
 	{
-		NV_LOG( nv::LOG_WARNING, "Failed to load string " << name << ": " << lua_tostring(L, -1));
+		NV_LOG( nv::LOG_WARNING, "Failed to load string " << name << ": " << lua_tostring(m_state, -1));
 		return false;
 	}
@@ -100,5 +105,5 @@
 	if (result)
 	{
-		NV_LOG( nv::LOG_WARNING, "Failed to open stream " << name << ": " << lua_tostring(L, -1));
+		NV_LOG( nv::LOG_WARNING, "Failed to open stream " << name << ": " << lua_tostring(m_state, -1));
 		return false;
 	}
@@ -112,5 +117,5 @@
 	if (result) 
 	{
-		NV_LOG( nv::LOG_WARNING, "Failed to open file " << filename << ": " << lua_tostring(L, -1));
+		NV_LOG( nv::LOG_WARNING, "Failed to open file " << filename << ": " << lua_tostring(m_state, -1));
 		return false;
 	}
@@ -120,18 +125,18 @@
 int lua::state::do_current( const std::string& name, int rvalues )
 {
-	int result = lua_pcall(L, 0, rvalues, 0);
+	int result = lua_pcall(m_state, 0, rvalues, 0);
 	if (result) 
 	{
-		NV_LOG( nv::LOG_WARNING, "Failed to run script " << name << ": " << lua_tostring(L, -1));
-		lua_pop( L, 1 );
-	}
-	return result;
-}
-
-lua::state::~state()
+		NV_LOG( nv::LOG_WARNING, "Failed to run script " << name << ": " << lua_tostring(m_state, -1));
+		lua_pop( m_state, 1 );
+	}
+	return result;
+}
+
+lua::state_wrapper::~state_wrapper()
 {
 	if (m_owner)
 	{
-		lua_close( L );
+		lua_close( m_state );
 	}
 }
@@ -145,11 +150,11 @@
 		if (global)
 		{
-			lua_getglobal( L, path.c_str() );
+			lua_getglobal( m_state, path.c_str() );
 		}
 		else
 		{
-			lua_getfield( L, -1, path.c_str() );
-		}
-		return !lua_isnil( L, -1 );
+			lua_getfield( m_state, -1, path.c_str() );
+		}
+		return !lua_isnil( m_state, -1 );
 	}
 
@@ -163,24 +168,24 @@
 			if (global)
 			{
-				lua_getglobal( L, path.substr(start,point-start).c_str() );
+				lua_getglobal( m_state, path.substr(start,point-start).c_str() );
 			}
 			else
 			{
-				lua_getfield( L, -1, path.substr(start,point-start).c_str() );
+				lua_getfield( m_state, -1, path.substr(start,point-start).c_str() );
 			}
 		}
 		else
 		{
-			if ( lua_istable( L, -1 ) )
+			if ( lua_istable( m_state, -1 ) )
 			{
-				lua_pushstring( L, path.substr(start,point-start).c_str() );
-				lua_gettable( L, -2 );
-				lua_insert( L, -2 );
-				lua_pop( L, 1 );
+				lua_pushstring( m_state, path.substr(start,point-start).c_str() );
+				lua_gettable( m_state, -2 );
+				lua_insert( m_state, -2 );
+				lua_pop( m_state, 1 );
 			}
 			else
 			{
-				lua_pop(L, 1);
-				lua_pushnil(L);
+				lua_pop(m_state, 1);
+				lua_pushnil(m_state);
 				return false;
 			}
@@ -195,11 +200,13 @@
 int lua::state::get_stack_size()
 {
-	return lua_gettop( L );
+	return lua_gettop( m_state );
 }
 
 lua::table_guard::table_guard( lua::state* lstate, const path& p, bool global )
-	: L(lstate), m_guard(lstate)
-{
-	if ( !p.resolve( L->get_raw(), global ) )
+	: state_wrapper( lstate->get_raw(), false ), m_level(0)
+{
+	m_global = false;
+	m_level  = lua_gettop( m_state );
+	if ( !p.resolve( m_state, global ) )
 	{
 		// TODO : error handling
@@ -208,7 +215,9 @@
 
 lua::table_guard::table_guard( const table_guard& parent, const path& p )
-	: L( parent.L ), m_guard( parent.L )
-{
-	if ( !p.resolve( L->get_raw(), false ) )
+	: state_wrapper( parent.m_state, false ), m_level(0)
+{
+	m_global = false;
+	m_level  = lua_gettop( m_state );
+	if ( !p.resolve( m_state, false ) )
 	{
 		// TODO : error handling
@@ -218,5 +227,5 @@
 size_t lua::table_guard::get_size()
 {
-	return lua_rawlen( L->get_raw(), -1 );
+	return lua_rawlen( m_state, -1 );
 }
 
@@ -224,7 +233,7 @@
 bool lua::table_guard::has_field( const string& element )
 {
-	lua_getfield( L->L, -1, element.c_str() );
-	bool result = lua_isnil( L->L, -1 );
-	lua_pop( L->L, 1 );
+	lua_getfield( m_state, -1, element.c_str() );
+	bool result = lua_isnil( m_state, -1 );
+	lua_pop( m_state, 1 );
 	return result;
 }
@@ -232,7 +241,7 @@
 string lua::table_guard::get_string( const string& element, const string& defval /*= "" */ )
 {
-	lua_getfield( L->L, -1, element.c_str() );
-	string result( ( lua_type( L->L, -1 ) == LUA_TSTRING ) ? lua_tostring( L->L, -1 ) : defval );
-	lua_pop( L->L, 1 );
+	lua_getfield( m_state, -1, element.c_str() );
+	string result( ( lua_type( m_state, -1 ) == LUA_TSTRING ) ? lua_tostring( m_state, -1 ) : defval );
+	lua_pop( m_state, 1 );
 	return result;
 }
@@ -240,7 +249,7 @@
 char lua::table_guard::get_char( const string& element, char defval /*= "" */ )
 {
-	lua_getfield( L->L, -1, element.c_str() );
-	char result = ( lua_type( L->L, -1 ) == LUA_TSTRING && lua_rawlen( L->L, -1 ) > 0 ) ? lua_tostring( L->L, -1 )[0] : defval;
-	lua_pop( L->L, 1 );
+	lua_getfield( m_state, -1, element.c_str() );
+	char result = ( lua_type( m_state, -1 ) == LUA_TSTRING && lua_rawlen( m_state, -1 ) > 0 ) ? lua_tostring( m_state, -1 )[0] : defval;
+	lua_pop( m_state, 1 );
 	return result;
 }
@@ -248,7 +257,7 @@
 int lua::table_guard::get_integer( const string& element, int defval /*= "" */ )
 {
-	lua_getfield( L->L, -1, element.c_str() );
-	lua_Integer result = lua_type( L->L, -1 ) == LUA_TNUMBER ? lua_tointeger( L->L, -1 ) : defval;
-	lua_pop( L->L, 1 );
+	lua_getfield( m_state, -1, element.c_str() );
+	lua_Integer result = lua_type( m_state, -1 ) == LUA_TNUMBER ? lua_tointeger( m_state, -1 ) : defval;
+	lua_pop( m_state, 1 );
 	return static_cast< int >( result );
 }
@@ -256,7 +265,7 @@
 unsigned lua::table_guard::get_unsigned( const string& element, unsigned defval /*= "" */ )
 {
-	lua_getfield( L->L, -1, element.c_str() );
-	unsigned result = lua_type( L->L, -1 ) == LUA_TNUMBER ? lua_tounsigned( L->L, -1 ) : defval;
-	lua_pop( L->L, 1 );
+	lua_getfield( m_state, -1, element.c_str() );
+	unsigned result = lua_type( m_state, -1 ) == LUA_TNUMBER ? lua_tounsigned( m_state, -1 ) : defval;
+	lua_pop( m_state, 1 );
 	return result;
 }
@@ -264,7 +273,7 @@
 double lua::table_guard::get_double( const string& element, double defval /*= "" */ )
 {
-	lua_getfield( L->L, -1, element.c_str() );
-	double result = lua_type( L->L, -1 ) == LUA_TNUMBER ? lua_tonumber( L->L, -1 ) : defval;
-	lua_pop( L->L, 1 );
+	lua_getfield( m_state, -1, element.c_str() );
+	double result = lua_type( m_state, -1 ) == LUA_TNUMBER ? lua_tonumber( m_state, -1 ) : defval;
+	lua_pop( m_state, 1 );
 	return result;
 }
@@ -272,35 +281,40 @@
 bool lua::table_guard::get_boolean( const string& element, bool defval /*= "" */ )
 {
-	lua_getfield( L->L, -1, element.c_str() );
-	bool result = lua_type( L->L, -1 ) == LUA_TBOOLEAN ? lua_toboolean( L->L, -1 ) != 0 : defval;
-	lua_pop( L->L, 1 );
-	return result;
-}
-
-void lua::table_guard::call_get()
-{
-	lua_gettable( L->L, -2 );
-}
-
-void lua::table_guard::call_get_raw()
-{
-	lua_rawget( L->L, -2 );
-}
-
-bool nv::lua::table_guard::is_defined( const path& p )
-{
-	return L->is_defined( p, false );
+	lua_getfield( m_state, -1, element.c_str() );
+	bool result = lua_type( m_state, -1 ) == LUA_TBOOLEAN ? lua_toboolean( m_state, -1 ) != 0 : defval;
+	lua_pop( m_state, 1 );
+	return result;
+}
+
+void nv::lua::state_wrapper::push_global_table()
+{
+	lua_pushglobaltable( m_state );
+}
+
+void nv::lua::state_wrapper::pop_global_table()
+{
+	lua_replace( m_state, -2 );
+}
+
+void lua::state_wrapper::call_get()
+{
+	lua_gettable( m_state, -2 );
+}
+
+void lua::state_wrapper::call_get_raw()
+{
+	lua_rawget( m_state, -2 );
 }
 
 void lua::table_guard::get_raw_flags( const std::string& element, uint8* data, uint32 count )
 {
-	lua_getfield( L->L, -1, element.c_str() );
-	if ( lua_type( L->L, -1 ) != LUA_TTABLE )
-	{
-		lua_pop( L->L, 1 );
+	lua_getfield( m_state, -1, element.c_str() );
+	if ( lua_type( m_state, -1 ) != LUA_TTABLE )
+	{
+		lua_pop( m_state, 1 );
 		return;
 	}
-	nlua_toflags( L->L, -1, data, count );
-	lua_pop( L->L, 1 );
+	nlua_toflags( m_state, -1, data, count );
+	lua_pop( m_state, 1 );
 }
 
@@ -308,9 +322,9 @@
 void lua::state::log_stack()
 {
-	int top = lua_gettop(L);
+	int top = lua_gettop(m_state);
 	NV_LOG( LOG_DEBUG, "Stack dump (" << top << ")");
 	for ( int i = 0; i < top; ++i )
 	{
-		NV_LOG( LOG_DEBUG, "#" << i+1 << " - " << lua_typename(L, lua_type(L, i+1) ) << " = " << nlua_typecontent(L, i+1) );
+		NV_LOG( LOG_DEBUG, "#" << i+1 << " - " << lua_typename(m_state, lua_type(m_state, i+1) ) << " = " << nlua_typecontent(m_state, i+1) );
 	}
 }
@@ -318,5 +332,5 @@
 lua_State* lua::state::get_raw()
 {
-	return L;
+	return m_state;
 }
 
@@ -325,11 +339,11 @@
 	if ( o == nullptr ) return ref_none;
 	stack_guard guard( this );
-	lua_getglobal( L, lua_name );
-	if ( lua_isnil( L, -1 ) )
+	lua_getglobal( m_state, lua_name );
+	if ( lua_isnil( m_state, -1 ) )
 	{
 		NV_THROW( runtime_error, std::string( lua_name ) + " type not registered!" );
 	}
 	deep_pointer_copy( -1, o );
-	return luaL_ref( L, LUA_REGISTRYINDEX );
+	return luaL_ref( m_state, LUA_REGISTRYINDEX );
 }
 
@@ -348,38 +362,38 @@
 	if (!o) return;
 	stack_guard guard( this );
-	lua_rawgeti( L, LUA_REGISTRYINDEX, o->get_lua_index() );
-	lua_pushstring( L, "__ptr" );
-	lua_pushboolean( L, false );
-	lua_rawset( L, -3 );
-	lua_pop( L, 1 );
-	luaL_unref( L, LUA_REGISTRYINDEX, o->get_lua_index() );
+	lua_rawgeti( m_state, LUA_REGISTRYINDEX, o->get_lua_index() );
+	lua_pushstring( m_state, "__ptr" );
+	lua_pushboolean( m_state, false );
+	lua_rawset( m_state, -3 );
+	lua_pop( m_state, 1 );
+	luaL_unref( m_state, LUA_REGISTRYINDEX, o->get_lua_index() );
 }
 
 void lua::state::deep_pointer_copy( int index, void* obj )
 {
-	index = lua_absindex( L, index );
-	lua_newtable( L );
-	lua_pushnil( L );
+	index = lua_absindex( m_state, index );
+	lua_newtable( m_state );
+	lua_pushnil( m_state );
 	bool has_functions = false;
 	bool has_metatable = false;
 
-	while ( lua_next( L, index ) != 0 )
-	{
-		if ( lua_isfunction( L, -1 ) ) 
+	while ( lua_next( m_state, index ) != 0 )
+	{
+		if ( lua_isfunction( m_state, -1 ) ) 
 			has_functions = true;
-		else if ( lua_istable( L, -1 ) )
+		else if ( lua_istable( m_state, -1 ) )
 		{
 			deep_pointer_copy( -1, obj );
-			lua_insert( L, -2 );
-			lua_pop( L, 1 );
-		}
-		lua_pushvalue( L, -2 );
-		lua_insert( L, -2 );
-		lua_settable( L, -4 );
-	}
-
-	if ( lua_getmetatable( L, -2 ) )
-	{
-		lua_setmetatable( L, -2 );
+			lua_insert( m_state, -2 );
+			lua_pop( m_state, 1 );
+		}
+		lua_pushvalue( m_state, -2 );
+		lua_insert( m_state, -2 );
+		lua_settable( m_state, -4 );
+	}
+
+	if ( lua_getmetatable( m_state, -2 ) )
+	{
+		lua_setmetatable( m_state, -2 );
 		has_metatable = true;
 	}
@@ -387,7 +401,7 @@
 	if ( has_functions || has_metatable )
 	{
-		lua_pushstring( L, "__ptr" );
-		lua_pushlightuserdata( L, obj );
-		lua_rawset( L, -3 );
+		lua_pushstring( m_state, "__ptr" );
+		lua_pushlightuserdata( m_state, obj );
+		lua_rawset( m_state, -3 );
 	}
 }
@@ -399,35 +413,62 @@
 	for ( const auto& entry : et->enum_list )
 	{
-		lua_pushinteger( L, entry.value );
+		lua_pushinteger( m_state, entry.value );
 		if ( prefix.empty() )
 		{
-			lua_setglobal( L, entry.name.c_str() );
+			lua_setglobal( m_state, entry.name.c_str() );
 		}
 		else
 		{
-			lua_setglobal( L, ( prefix + entry.name ).c_str() );
-		}
-	}
-}
-
-
-bool nv::lua::state::is_defined( const path& p, bool global )
-{
-	if ( !p.resolve( L, global ) )
-	{
-		return false;
-	}
-	bool result = !lua_isnil( L, -1 );
-	lua_pop( L, 1 );
-	return result;
-}
-
-int lua::state::call_function( int nargs, int nresults )
-{
-	int status = lua_pcall( L, nargs, nresults, 0 );
+			lua_setglobal( m_state, ( prefix + entry.name ).c_str() );
+		}
+	}
+}
+
+void nv::lua::state::store_metadata( object* o, const std::string& metaname, void* pointer )
+{
+	if (!o) return;
+	stack_guard guard( this );
+	lua_rawgeti( m_state, LUA_REGISTRYINDEX, o->get_lua_index() );
+	lua_pushstring( m_state, metaname.c_str() );
+	lua_pushlightuserdata( m_state, pointer );
+	lua_rawset( m_state, -3 );
+	lua_pop( m_state, 1 );
+}
+
+bool nv::lua::state_wrapper::is_defined( const path& p, bool global )
+{
+	if ( !p.resolve( m_state, global ) )
+	{
+		return false;
+	}
+	bool result = !lua_isnil( m_state, -1 );
+	lua_pop( m_state, 1 );
+	return result;
+}
+
+bool nv::lua::state_wrapper::push_function( const path& p, bool global )
+{
+	if ( !p.resolve( m_state, global ) )
+	{
+		NV_LOG( LOG_ERROR, "Lua error : not a valid path - " + p.to_string() );
+		return false;
+	}
+
+	if ( !lua_isfunction( m_state, -1 ) ) 
+	{
+		lua_pop( m_state, 1 );
+		NV_LOG( LOG_ERROR, "Lua error : not a valid function - " + p.to_string() );
+		return false;
+	}
+	return true;
+}
+
+int nv::lua::state_wrapper::call_function( int nargs, int nresults )
+{
+	int status = lua_pcall( m_state, nargs, nresults, 0 );
 	if ( status != 0 )
 	{
-		std::string error = lua_tostring( L, -1 );
-		lua_pop( L, 1 );
+		std::string error = lua_tostring( m_state, -1 );
+		lua_pop( m_state, 1 );
 		NV_LOG( LOG_ERROR, "Lua error : " << error )
 	}
@@ -435,19 +476,6 @@
 }
 
-bool lua::state::push_function( const path& p, bool global )
-{
-	if ( !p.resolve( L, global ) )
-	{
-		NV_LOG( LOG_ERROR, "Lua error : not a valid path - " + p.to_string() );
-		return false;
-	}
-
-	if ( !lua_isfunction( L, -1 ) ) 
-	{
-		lua_pop( L, 1 );
-		NV_LOG( LOG_ERROR, "Lua error : not a valid function - " + p.to_string() );
-		return false;
-	}
-	return true;
-}
-
+lua::table_guard::~table_guard()
+{
+	lua_settop( m_state, m_level );
+}
Index: trunk/src/lua/lua_values.cc
===================================================================
--- trunk/src/lua/lua_values.cc	(revision 204)
+++ trunk/src/lua/lua_values.cc	(revision 206)
@@ -52,4 +52,10 @@
 }
 
+void nv::lua::detail::pop_value( lua_State *L, int& n )
+{
+	n = lua_tointeger( L, -1 );
+	lua_pop( L, 1 );
+}
+
 void nv::lua::detail::pop_value( lua_State *L, long& n )
 {
