Index: trunk/nv/lua/lua_state.hh
===================================================================
--- trunk/nv/lua/lua_state.hh	(revision 340)
+++ trunk/nv/lua/lua_state.hh	(revision 341)
@@ -18,4 +18,5 @@
 #include <map>
 
+#include <nv/lua/lua_handle.hh>
 #include <nv/lua/lua_path.hh>
 #include <nv/lua/lua_values.hh>
@@ -24,7 +25,7 @@
 
 #ifdef NV_DEBUG
-#define NV_LUA_STACK_ASSERT( state, value ) nv::lua::stack_assert __lua_stack_assert( state, value );
+#define NV_LUA_STACK_ASSERT( state, value ) nv::lua::stack_assert __lua_stack_assert( (state), (value) );
 #else
-#define NV_LUA_STACK_ASSERT( state, value )
+#define NV_LUA_STACK_ASSERT( (state), (value) )
 #endif
 
@@ -248,4 +249,5 @@
 
 			void register_enum( const char* name, int value );
+			void register_singleton( const char* name, void* o );
 
 			void register_native_object_method( const char* lua_name, const char* name, lfunction f );
@@ -256,5 +258,117 @@
 			}
 			operator lua_State*() { return m_state; }
+
+			template < typename H >
+			void register_handle( const H& handle )
+			{
+				nv::lua::register_handle( m_state, handle, true );
+			}
+			template < typename H >
+			void unregister_handle( const H& handle )
+			{
+				nv::lua::unregister_handle( m_state, handle );
+			}
+			template < typename H >
+			ref register_handle_component( const H& handle, const std::string& id )
+			{
+				nv::lua::push_handle( m_state, handle );
+				return register_handle_component_impl( id, true );
+			}
+			template < typename H >
+			ref register_handle_component( const H& handle, const std::string& id, const path& proto )
+			{
+				if ( !proto.resolve( m_state, true ) )
+				{
+					return ref();
+				}
+				nv::lua::push_handle( m_state, handle );
+				return register_handle_component_impl( id, false );
+			}
+			template < typename H >
+			void unregister_handle_component( const H& handle, const std::string& id )
+			{
+				nv::lua::push_handle( m_state, handle );
+				unregister_handle_component_impl( id );
+			}
+
+			template < typename R >
+			R call( ref table, const path& p )
+			{
+				stack_guard guard( this ); // TODO: remove
+				detail::push_ref_object( m_state,table );
+				if ( push_function( p, false ) )
+				{
+					if ( call_function( 0, detail::return_count< R >::value ) == 0 )
+					{
+						return detail::pop_return_value<R>( m_state );
+					}
+				}
+				return R();
+			}
+			template < typename R, typename T1 >
+			R call( ref table, const path& p, const T1& p1 )
+			{
+				stack_guard guard( this ); // TODO: remove
+				detail::push_ref_object( m_state,table );
+				if ( push_function( p, false ) )
+				{
+					detail::push_value( m_state, p1 );
+					if ( call_function( 1, detail::return_count< R >::value ) == 0 )
+					{
+						return detail::pop_return_value<R>( m_state );
+					}
+				}
+				return R();
+			}
+			template < typename R, typename T1, typename T2 >
+			R call( ref table, const path& p, const T1& p1, const T2& p2 )
+			{
+				stack_guard guard( this ); // TODO: remove
+				detail::push_ref_object( m_state, table );
+				if ( push_function( p, false ) )
+				{
+					detail::push_values( m_state, p1, p2 );
+					if ( call_function( 2, detail::return_count< R >::value ) == 0 )
+					{
+						return detail::pop_return_value<R>( m_state );
+					}
+				}
+				return R();
+			}
+			template < typename R, typename T1, typename T2, typename T3 >
+			R call( ref table, const path& p, const T1& p1, const T2& p2, const T3& p3 )
+			{
+				stack_guard guard( this ); // TODO: remove
+				detail::push_ref_object( m_state, table );
+				if ( push_function( p, false ) )
+				{
+					detail::push_values( m_state, p1, p2, p3 );
+					if ( call_function( 3, detail::return_count< R >::value ) == 0 )
+					{
+						return detail::pop_return_value<R>( m_state );
+					}
+				}
+				return R();
+			}
+			template < typename R, typename T1, typename T2, typename T3, typename T4 >
+			R call( ref table, const path& p, const T1& p1, const T2& p2, const T3& p3, const T4& p4 )
+			{
+				stack_guard guard( this ); // TODO: remove
+				detail::push_ref_object( m_state, table );
+				if ( push_function( p, false ) )
+				{
+					detail::push_value( m_state, p1, p2, p3, p4 );
+					if ( call_function( 4, detail::return_count< R >::value ) == 0 )
+					{
+						return detail::pop_return_value<R>( m_state );
+					}
+				}
+				return R();
+			}
+
 		private:
+			ref register_handle_component_impl( const std::string& id, bool empty );
+			void unregister_handle_component_impl( const std::string& id );
+
 			int load_string( const std::string& code, const std::string& name );
 			int load_stream( std::istream& stream, const std::string& name );
Index: trunk/src/lua/lua_state.cc
===================================================================
--- trunk/src/lua/lua_state.cc	(revision 340)
+++ trunk/src/lua/lua_state.cc	(revision 341)
@@ -515,2 +515,53 @@
 }
 
+nv::lua::ref nv::lua::state::register_handle_component_impl( const std::string& id, bool empty )
+{
+	int args = empty ? 1 : 2;
+	NV_LUA_STACK_ASSERT( m_state, -args );
+
+	if ( lua_isnil( m_state, -1 ) || (!empty && lua_isnil( m_state, -2 )) )
+	{
+		lua_pop( m_state, args );
+		return ref();
+	}
+	if (empty)
+		lua_createtable( m_state, 0, 0 );
+	else
+		nlua_deepcopy( m_state, -2 );
+	lua_pushstring( m_state, id.c_str() );
+	lua_pushvalue( m_state, -2 );
+	lua_rawset( m_state, -4 );
+	lua_replace( m_state, -2 );
+	ref result = lua::ref( luaL_ref( m_state, LUA_REGISTRYINDEX ) );
+	if (!empty) lua_pop( m_state, 1 );
+	return result;
+}
+
+void nv::lua::state::unregister_handle_component_impl( const std::string& id )
+{
+	NV_LUA_STACK_ASSERT( m_state, -1 );
+
+	if ( lua_isnil( m_state, -1 ) )
+	{
+		lua_pop( m_state, 1 );
+		return;
+	}
+	lua_pushstring( m_state, id.c_str() );
+	lua_pushnil( m_state );
+	lua_rawset( m_state, -3 );
+	lua_pop( m_state, 1 );
+}
+
+void nv::lua::state::register_singleton( const char* name, void* o )
+{
+	if ( o == nullptr ) return;
+	stack_guard guard( this );
+	lua_getglobal( m_state, name );
+	if ( lua_isnil( m_state, -1 ) )
+	{
+		NV_THROW( runtime_error, std::string( name ) + " type not registered!" );
+	}
+	deep_pointer_copy( -1, o );
+	lua_setglobal( m_state, name );
+}
+
