Index: trunk/src/lua/lua_area.cc
===================================================================
--- trunk/src/lua/lua_area.cc	(revision 494)
+++ trunk/src/lua/lua_area.cc	(revision 503)
@@ -459,9 +459,9 @@
 }
 
-void nv::lua::register_area( lua_State* L )
-{
-	int stack = lua_gettop( L );
-	nlua_requiref(L, "area", luaopen_area, 1);
-	lua_settop( L, stack );
-}
-
+void nv::lua::register_area( lua::state* state )
+{
+	int stack = lua_gettop( state->get_raw() );
+	nlua_requiref( state->get_raw(), "area", luaopen_area, 1);
+	lua_settop( state->get_raw(), stack );
+}
+
Index: trunk/src/lua/lua_aux.cc
===================================================================
--- trunk/src/lua/lua_aux.cc	(revision 494)
+++ trunk/src/lua/lua_aux.cc	(revision 503)
@@ -137,8 +137,8 @@
 };
 
-void nv::lua::register_aux( lua_State* L )
+void nv::lua::register_aux( lua::state* state )
 {
-	nlua_register( L, "table", nluaaux_table_aux_f );
-	nlua_register( L, "math", nluaaux_math_aux_f );
+	nlua_register( state->get_raw(), "table", nluaaux_table_aux_f );
+	nlua_register( state->get_raw(), "math", nluaaux_math_aux_f );
 }
 
Index: trunk/src/lua/lua_map_area.cc
===================================================================
--- trunk/src/lua/lua_map_area.cc	(revision 494)
+++ trunk/src/lua/lua_map_area.cc	(revision 503)
@@ -223,16 +223,17 @@
 }
 
-void nv::lua::register_map_area_interface( lua_State* L, int index )
-{
-	nlua_register( L, nlua_map_area_f, index );
-}
-
-void nv::lua::register_map_area( lua_State* L )
-{
-	luaopen_map_area(L);
-}
-
-void nv::lua::register_map_area_instance( lua_State* L, ref object_index, map_area* area )
-{
+void nv::lua::register_map_area_interface( lua::state* state, int index )
+{
+	nlua_register( state->get_raw(), nlua_map_area_f, index );
+}
+
+void nv::lua::register_map_area( lua::state* state )
+{
+	luaopen_map_area( state->get_raw() );
+}
+
+void nv::lua::register_map_area_instance( lua::state* state, ref object_index, map_area* area )
+{
+	lua_State* L = state->get_raw();
 	lua_rawgeti( L, LUA_REGISTRYINDEX, object_index.get() );
 	lua_pushliteral( L, "__map_area_ptr" );
Index: trunk/src/lua/lua_map_tile.cc
===================================================================
--- trunk/src/lua/lua_map_tile.cc	(revision 494)
+++ trunk/src/lua/lua_map_tile.cc	(revision 503)
@@ -366,7 +366,8 @@
 };
 
-void nv::lua::register_map_tile( lua_State * L )
+void nv::lua::register_map_tile( lua::state* state )
 {
 	// TODO: check if __gc is used!
+	lua_State* L = state->get_raw();
 	luaL_newmetatable( L, NLUA_MAP_TILE_METATABLE );
 	lua_pushvalue( L, -1 );
Index: trunk/src/lua/lua_math.cc
===================================================================
--- trunk/src/lua/lua_math.cc	(revision 494)
+++ trunk/src/lua/lua_math.cc	(revision 503)
@@ -359,5 +359,33 @@
 }
 
-void nv::lua::register_math( lua_State* L )
+template < typename T >
+void nlua_rtti_vec_push( nv::lua::state* state, const nv::type_entry*, void* object )
+{
+	T* value = reinterpret_cast<T*>( object );
+	push_vec<T>( state->get_raw(), *value );
+}
+
+template < typename T >
+bool nlua_rtti_vec_read( nv::lua::state* state, const nv::type_entry*, void* object, int index )
+{
+	T* value = reinterpret_cast<T*>( object );
+	int type = lua_type( state->get_raw(), index );
+	if ( type == LUA_TUSERDATA )
+	{
+		T* from = to_pvec<T>( state->get_raw(), index );
+		if ( !from ) return false;
+		*value = *from;
+	}
+// 	else if ( type == LUA_TTABLE )
+// 	{
+// 
+// 	}
+	else
+		return false;
+	int todo; int table_constructor;
+	return true;
+}
+
+void nv::lua::register_math( lua::state* state )
 { 
 	for (size_t i = 0; i < 256; ++i ) nlua_swizzel_lookup[i] = 255;
@@ -379,4 +407,6 @@
 	nlua_swizzel_lookup[uchar8( 'v' )] = 0;
 	nlua_swizzel_lookup[uchar8( '3' )] = 3;
+
+	lua_State* L = state->get_raw();
 	int stack = lua_gettop( L );
 
@@ -389,4 +419,11 @@
 	nlua_requiref(L, "vec4", luaopen_vec<nv::vec4>, 1);
 	lua_settop( L, stack );
-}
-
+
+	state->register_rtti_type< nv::ivec2 >( nlua_rtti_vec_push<nv::ivec2>, nlua_rtti_vec_read<nv::ivec2> );
+	state->register_rtti_type< nv::ivec3 >( nlua_rtti_vec_push<nv::ivec3>, nlua_rtti_vec_read<nv::ivec3> );
+	state->register_rtti_type< nv::ivec4 >( nlua_rtti_vec_push<nv::ivec4>, nlua_rtti_vec_read<nv::ivec4> );
+	state->register_rtti_type< nv::vec2 > ( nlua_rtti_vec_push<nv::vec2>,  nlua_rtti_vec_read<nv::vec2> );
+	state->register_rtti_type< nv::vec3 > ( nlua_rtti_vec_push<nv::vec3>,  nlua_rtti_vec_read<nv::vec3> );
+	state->register_rtti_type< nv::vec4 > ( nlua_rtti_vec_push<nv::vec4>,  nlua_rtti_vec_read<nv::vec4> );
+}
+
Index: trunk/src/lua/lua_state.cc
===================================================================
--- trunk/src/lua/lua_state.cc	(revision 494)
+++ trunk/src/lua/lua_state.cc	(revision 503)
@@ -9,4 +9,5 @@
 #include "nv/lua/lua_raw.hh"
 #include "nv/lua/lua_nova.hh"
+#include "nv/lua/lua_types.hh"
 #include "nv/core/logging.hh"
 #include "nv/stl/string.hh"
@@ -143,5 +144,5 @@
 
 lua::table_guard::table_guard( lua::state* lstate, const path& p, bool global )
-	: state_wrapper( lstate->get_raw(), false ), m_level(0)
+	: state_wrapper( lstate->get_raw(), lstate->m_lua_types, false ), m_parent( lstate ), m_level(0)
 {
 	m_global = false;
@@ -155,5 +156,5 @@
 
 lua::table_guard::table_guard( const table_guard& parent, const path& p )
-	: state_wrapper( parent.m_state, false ), m_level(0)
+	: state_wrapper( parent.m_state, parent.m_lua_types, false ), m_parent( parent.m_parent ), m_level(0)
 {
 	m_global = false;
@@ -350,12 +351,32 @@
 
 
+bool nv::lua::table_guard::read( const string_view& element, const type_entry* entry, void* object )
+{
+	NV_ASSERT_ALWAYS( m_lua_types->get_type_database() == entry->type_db, "Type database mismatch between Lua and entry!" );
+	lua_getfield( m_state, -1, element.data() );
+	if ( lua_type( m_state, -1 ) != LUA_TTABLE )
+	{
+		lua_pop( m_state, 1 );
+		return false;
+	}
+	if ( !nv::lua::read_rtti_type( m_parent, entry, object, -1 ) )
+	{
+		lua_pop( m_state, 1 );
+		return false;
+	}
+	lua_pop( m_state, 1 );
+	return true;
+}
+
 // state
 
-lua::state::state( lua_State* state ) : state_wrapper( state, false )
-{
-
-}
-
-lua::state::state( bool load_libs /*= false*/ ) : state_wrapper( nullptr, true )
+lua::state::state( lua_State* state, type_database* types )
+	: state_wrapper( state, new type_data( types ), false )
+{
+
+}
+
+lua::state::state( bool load_libs /*= false*/, type_database* types )
+	: state_wrapper( nullptr, new type_data( types ), true )
 {
 	load_lua_library();
@@ -575,4 +596,9 @@
 }
 
+void nv::lua::state::register_rtti_type( thash64 tid, lua_rtti_push_function p, lua_rtti_read_function r )
+{
+	m_lua_types->insert( tid, p, r );
+}
+
 nv::lua::ref nv::lua::state::register_handle_component_impl( string_view id, bool empty )
 {
@@ -626,2 +652,103 @@
 }
 
+nv::lua::state::~state()
+{
+	delete m_lua_types;
+	m_lua_types = nullptr;
+}
+
+template < typename T >
+void nlua_rtti_signed_push( nv::lua::state* state, const type_entry*, void* object )
+{
+	T* value = reinterpret_cast<T*>( object );
+	lua_pushinteger( state->get_raw(), lua_Integer( *value ) );
+}
+
+template < typename T >
+void nlua_rtti_unsigned_push( nv::lua::state* state, const type_entry*, void* object )
+{
+	T* value = reinterpret_cast<T*>( object );
+	lua_pushinteger( state->get_raw(), lua_Unsigned( *value ) );
+}
+
+template < typename T >
+void nlua_rtti_floating_push( nv::lua::state* state, const type_entry*, void* object )
+{
+	T* value = reinterpret_cast< T* >( object );
+	lua_pushnumber( state->get_raw(), lua_Number( *value ) );
+}
+
+static void nlua_rtti_boolean_push( nv::lua::state* state, const type_entry*, void* object )
+{
+	bool* value = reinterpret_cast<bool*>( object );
+	lua_pushboolean( state->get_raw(), *value );
+}
+
+template < typename T >
+bool nlua_rtti_signed_read( nv::lua::state* state, const type_entry*, void* object, int index )
+{
+	T* value = reinterpret_cast<T*>( object );
+	if ( lua_type( state->get_raw(), index ) == LUA_TNUMBER )
+	{
+		*value = T( lua_tointeger( state->get_raw(), index ) );
+		return true;
+	}
+	return false;
+}
+
+template < typename T >
+bool nlua_rtti_unsigned_read( nv::lua::state* state, const type_entry*, void* object, int index )
+{
+	T* value = reinterpret_cast<T*>( object );
+	if ( lua_type( state->get_raw(), index ) == LUA_TNUMBER )
+	{
+		*value = T( lua_tointeger( state->get_raw(), index ) );
+		return true;
+	}
+	return false;
+}
+
+template < typename T >
+bool nlua_rtti_floating_read( nv::lua::state* state, const type_entry*, void* object, int index )
+{
+	T* value = reinterpret_cast<T*>( object );
+	if ( lua_type( state->get_raw(), index ) == LUA_TNUMBER )
+	{
+		*value = T( lua_tonumber( state->get_raw(), index ) );
+		return true;
+	}
+	return false;
+}
+
+static bool nlua_rtti_boolean_read( nv::lua::state* state, const type_entry*, void* object, int index )
+{
+	bool* value = reinterpret_cast<bool*>( object );
+	if ( lua_type( state->get_raw(), index ) == LUA_TBOOLEAN )
+	{
+		*value = bool( lua_toboolean( state->get_raw(), index ) );
+		return true;
+	}
+	return false;
+}
+
+
+void nv::lua::type_data::insert( thash64 tid, lua_rtti_push_function p, lua_rtti_read_function r )
+{
+	m_type_read.assign( tid, r );
+	m_type_push.assign( tid, p );
+}
+
+void nv::lua::type_data::register_standard_types()
+{
+	insert<bool>( nlua_rtti_boolean_push, nlua_rtti_boolean_read );
+	insert<nv::sint8> ( nlua_rtti_signed_push<nv::sint8>,    nlua_rtti_signed_read<nv::sint8> );
+	insert<nv::sint16>( nlua_rtti_signed_push<nv::sint16>,   nlua_rtti_signed_read<nv::sint16> );
+	insert<nv::sint32>( nlua_rtti_signed_push<nv::sint32>,   nlua_rtti_signed_read<nv::sint32> );
+	insert<nv::uint8> ( nlua_rtti_unsigned_push<nv::uint8>,  nlua_rtti_unsigned_read<nv::uint8> );
+	insert<nv::uint16>( nlua_rtti_unsigned_push<nv::uint16>, nlua_rtti_unsigned_read<nv::uint16> );
+	insert<nv::uint32>( nlua_rtti_unsigned_push<nv::uint32>, nlua_rtti_unsigned_read<nv::uint32> );
+	insert<nv::f32>   ( nlua_rtti_floating_push<nv::f32>,    nlua_rtti_floating_read<nv::f32> );
+	insert<nv::f64>   ( nlua_rtti_floating_push<nv::f64>,    nlua_rtti_floating_read<nv::f64> );
+//	insert<nv::sint64>( nlua_rtti_floating_push<nv::sint64>, nlua_rtti_floating_read<nv::sint64> );
+//	insert<nv::uint64>( nlua_rtti_floating_push<nv::uint64>, nlua_rtti_floating_read<nv::uint64> );
+}
Index: trunk/src/lua/lua_types.cc
===================================================================
--- trunk/src/lua/lua_types.cc	(revision 503)
+++ trunk/src/lua/lua_types.cc	(revision 503)
@@ -0,0 +1,202 @@
+// Copyright (C) 2016-2016 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of Nova libraries. 
+// For conditions of distribution and use, see copying.txt file in root folder.
+
+#include "nv/lua/lua_types.hh"
+
+#include "nv/lua/lua_raw.hh"
+
+using namespace nv;
+
+bool nv::lua::read_rtti_type( lua::state* state, const type_entry* entry, void* object, int index )
+{
+	const lua::type_data* td = state->get_type_data();
+	const type_database*  db = td->get_type_database();
+	NV_ASSERT_ALWAYS( db == entry->type_db, "Type database mismatch between Lua and entry!" );
+
+	const lua::lua_rtti_read_function* read = td->get_read( entry->hash );
+	if ( read )
+	{
+		return (*read)( state, entry, object, index );
+	}
+
+	lua_State* lstate = state->get_raw();
+	int ltype = lua_type( lstate, index );
+	index = nlua_absindex( lstate, index );
+	int fcount = int( entry->field_list.size() );
+
+	if ( fcount > 0 && ltype == LUA_TTABLE )
+	{
+		// numerical assignment
+		if ( lua_objlen( lstate, index ) > 0 )
+		{
+			int i = 0;
+			for (;;)
+			{
+				i++;
+				lua_rawgeti( lstate, index, i );
+				if ( lua_isnil( lstate, -1 ) || i > fcount )
+				{
+					lua_pop( lstate, 1 );
+					break;
+				}
+				const type_field& f = entry->field_list[i - 1];
+				read_rtti_type( state, f.type, (char*)object + f.offset, -1 );
+				lua_pop( lstate, 1 );
+			};
+
+		}
+
+		// by name assignment
+		lua_pushnil( lstate );
+		while ( lua_next( lstate, index ) != 0 )
+		{
+			if ( lua_type( lstate, -2 ) == LUA_TSTRING )
+			{
+				string_view key = nlua_tostringview( lstate, -2 );
+				auto fit = entry->field_names.find(key);
+				if ( fit != entry->field_names.end() )
+				{
+					const type_field& f = entry->field_list[ fit->second ];
+					read_rtti_type( state, f.type, (char*)object + f.offset, -1 );
+				}
+			}
+			lua_pop( lstate, 1 );
+		}
+		return true;
+	}
+	int ecount = int( entry->enum_list.size() );
+	if ( ecount > 0 )
+	{
+		if ( ltype == LUA_TSTRING )
+		{
+			string_view key = nlua_tostringview( lstate, index );
+			auto eit = entry->enum_names.find( key );
+			if ( eit != entry->enum_names.end() )
+			{
+				int error; // proper type instead of sint32?
+				*(sint32*)object = entry->enum_list[eit->second].value;
+				return true;
+			}
+		}
+		if ( ltype == LUA_TNUMBER )
+		{
+			int error; // proper type instead of sint32?
+			*(sint32*)object = lua_tointeger( lstate, index );
+			return true;
+		}
+	}
+	return false;
+}
+
+static void nlua_rtti_proxy_push_field( lua_State * L, void* object, type_field& f )
+{
+	//throw std::logic_error( "The method or operation is not implemented." );
+}
+
+static void nlua_rtti_proxy_set_field( lua_State * L, void* object, type_field& f, int index )
+{
+	//throw std::logic_error( "The method or operation is not implemented." );
+}
+
+static int nlua_rtti_proxy_index( lua_State * L )
+{
+	type_entry* entry  = reinterpret_cast<type_entry*>( lua_touserdata( L, lua_upvalueindex( 1 ) ) );
+	void*       object = lua_touserdata( L, lua_upvalueindex( 2 ) );
+	nv::string_view index = nlua_tostringview( L, 2 );
+	auto f = entry->field_names.find( index );
+	if ( f != entry->field_names.end() )
+	{
+		nlua_rtti_proxy_push_field( L, object, entry->field_list[ f->second ] );
+	}
+	else
+	{
+		int error;
+		lua_pushnil( L );
+	}
+	return 1;
+}
+
+static int nlua_rtti_proxy_newindex( lua_State * L )
+{
+	type_entry* entry = reinterpret_cast<type_entry*>( lua_touserdata( L, lua_upvalueindex( 1 ) ) );
+	void*       object = lua_touserdata( L, lua_upvalueindex( 2 ) );
+	nv::string_view index = nlua_tostringview( L, 2 );
+	auto f = entry->field_names.find( index );
+	if ( f != entry->field_names.end() )
+	{
+		nlua_rtti_proxy_set_field( L, object, entry->field_list[f->second], 3 );
+	}
+	else
+	{
+		int error;
+	}
+	return 1;
+}
+
+/*
+
+static void nlua_push_function( lua_State* L, const type_entry* entry, lua_CFunction f )
+{
+	lua_pushlightuserdata( L, const_cast<type_entry*>( entry ) );
+	lua_pushcclosure( L, f, 1 );
+}
+
+static void nlua_rtti_requiref( lua_State *L, const type_entry* entry, const char *modname, lua_CFunction openf, int glb )
+{
+	int only_works_for_51;
+	nlua_push_function( L, entry, openf );
+	lua_pushstring( L, modname );
+	lua_call( L, 1, 1 );
+	if ( glb != 0 )
+	{
+		lua_pushvalue( L, LUA_GLOBALSINDEX );
+		lua_pushvalue( L, -2 );
+		lua_setfield( L, -2, modname );
+		lua_pop( L, 1 );
+	}
+}
+
+static void nlua_rtti_register( lua_State *L, const type_entry* entry, const luaL_Reg *l )
+{
+	int index = nlua_absindex( L, -1 );
+	for ( ; l->name != NULL; l++ )
+	{
+		lua_pushstring( L, l->name );
+		nlua_push_function( L, entry, l->func );
+		lua_rawset( L, index );
+	}
+}
+
+static int nlua_rtti_open( lua_State *L )
+{
+// 	type_entry* entry = reinterpret_cast<type_entry*>( lua_touserdata( L, lua_upvalueindex( 1 ) ) );
+// 
+// 	luaL_newmetatable( L, entry->type_db->resolve_name( entry ).data() );
+// 	nlua_register( L, nlua_vec_m, -1 );
+// 	lua_createtable( L, 0, 0 );
+// 	nlua_register( L, nlua_vec_f, -1 );
+// 	lua_setfield( L, -2, "__functions" );
+// 	lua_pop( L, 1 );
+// 
+// 	lua_createtable( L, 0, 0 );
+// 	nlua_register( L, nlua_vec_sf, -1 );
+// 	lua_createtable( L, 0, 0 );
+// 	nlua_register( L, nlua_vec_sm, -1 );
+// 	lua_setmetatable( L, -2 );
+	return 1;
+}
+
+void nv::lua::register_lua_rtti_type( const string_view& name, lua::state* state, const type_entry* entry )
+{
+	const type_database* db = state->get_type_db();
+	NV_ASSERT_ALWAYS( db == entry->type_db, "Type database mismatch between Lua and entry!" );
+	lua_pushlightuserdata( state->get_raw(), const_cast< type_entry* >( entry ) );
+	int lua_ref
+
+
+	
+}
+*/
