Index: trunk/src/core/types.cc
===================================================================
--- trunk/src/core/types.cc	(revision 539)
+++ trunk/src/core/types.cc	(revision 540)
@@ -28,4 +28,6 @@
 	db->create_type<ivec4>();
 	db->create_type<quat>();
+	db->create_type<shash32>();
+	db->create_type<shash64>();
 	db->create_type<string32>();
 	db->create_type<string64>();
Index: trunk/src/engine/animation.cc
===================================================================
--- trunk/src/engine/animation.cc	(revision 539)
+++ trunk/src/engine/animation.cc	(revision 540)
@@ -27,5 +27,5 @@
 nv::resource< animator_data > nv::animator_manager::load_animator( nv::lua::table_guard& table, nv::shash64 id, nv::pose_data_set* poses /*= nullptr */ )
 {
-	uint32 count = table.get_size();
+	uint32 count = table.size();
 	if ( count == 0 )
 	{
@@ -73,5 +73,5 @@
 		{
 			nv::lua::table_guard states_table( layer_table, "states" );
-			uint32 state_count = states_table.get_size();
+			uint32 state_count = states_table.size();
 			if ( state_count > 0 )
 			{
@@ -119,5 +119,5 @@
 					{
 						nv::lua::table_guard transitions_table( state_table, "transitions" );
-						uint32 transition_count = transitions_table.get_size();
+						uint32 transition_count = transitions_table.size();
 						if ( transition_count > 0 )
 						{
@@ -167,5 +167,5 @@
 	result.in = table["ease_in"].get_enum( result.in );
 	result.out = table["ease_out"].get_enum( nv::easing_type::NONE );
-	if ( table.has_field( "ease_in_out" ) )
+	if ( table[ "ease_in_out" ] )
 	{
 		result.in = result.out = table["ease_in_out"].get_enum( nv::easing_type::NONE );
Index: trunk/src/engine/model_manager.cc
===================================================================
--- trunk/src/engine/model_manager.cc	(revision 539)
+++ trunk/src/engine/model_manager.cc	(revision 540)
@@ -30,5 +30,5 @@
 		gm->ragdoll_id = table["ragdoll"].get_string32();
 	
-	if ( table.has_field( "animator" ) )
+	if ( table["animator"] )
 	{
 		gm->animator = m_rm->get< animator_data >( table["animator"].get_string() );
@@ -40,5 +40,5 @@
 	}
 
-	if ( table.has_field( "phx_mesh" ) )
+	if ( table[ "phx_mesh" ] )
 	{
 		nv::string128 cpath( table["phx_mesh"].get_string128() );
@@ -77,5 +77,5 @@
 		node->tag = table["tag"].get_string32();
 
-	if ( table.has_field( "path" ) )
+	if ( table[ "path" ] )
 	{
 		nv::string128 cpath( table["path"].get_string128() );
@@ -85,36 +85,36 @@
 	}
 
-	if ( table.has_field( "phx_hextents" ) )
+	if ( table[ "phx_hextents"] )
 		node->phx_hextents = table["phx_hextents"].as<vec3>();
-	if ( table.has_field( "phx_offset" ) )
+	if ( table[ "phx_offset"] )
 		node->phx_offset = table["phx_offset"].as<vec3>();
-	if ( table.has_field( "phx_mass" ) )
+	if ( table[ "phx_mass"] )
 		node->phx_mass = table["phx_mass"].as<float>( 0.0f );
-	if ( table.has_field( "phx_mass" ) )
+	if ( table["phx_mass"] )
 		node->phx_shape = nv::phx_shape( table["phx_shape"].as<int>( 0 ) );
 
-	if ( table.has_field( "local_position" ) )
+	if ( table["local_position"] )
 		node->local.set_position( table["local_position"].as<vec3>() );
-	if ( table.has_field( "local_orientation" ) )
+	if ( table["local_orientation"] )
 		node->local.set_orientation( vec4_to_quat( table["local_orientation"].as<vec4>( vec4( 0.0f, 0.0f, 0.0f, 1.0f ) ) ) );
 
-	if ( table.has_field( "position" ) )
+	if ( table["position"] )
 	{
 		node->position.min = table["position"].as<vec3>();
 		node->position.max = node->position.min;
 	}
-	if ( table.has_field( "rotation" ) )
+	if ( table["rotation"] )
 	{
 		node->rotation.min = table["rotation"].as<vec3>();
 		node->rotation.max = node->rotation.min;
 	}
-	if ( table.has_field( "position_min" ) )  node->position.min  = table["position_min"].as<vec3>();
-	if ( table.has_field( "position_max" ) )  node->position.max  = table["position_max"].as<vec3>();
-	if ( table.has_field( "position_dist" ) ) node->position.dist = random_dist( table["position_dist"].get_uint32() );
-	if ( table.has_field( "rotation_min" ) )  node->rotation.min  = table["rotation_min"].as<vec3>();
-	if ( table.has_field( "rotation_max" ) )  node->rotation.max  = table["rotation_max"].as<vec3>();
-	if ( table.has_field( "rotation_dist" ) ) node->rotation.dist = random_dist( table["rotation_dist"].get_uint32() );
+	if ( table["position_min"] )  node->position.min  = table["position_min"].as<vec3>();
+	if ( table["position_max"] )  node->position.max  = table["position_max"].as<vec3>();
+	if ( table["position_dist"] ) node->position.dist = random_dist( table["position_dist"].get_uint32() );
+	if ( table["rotation_min"] )  node->rotation.min  = table["rotation_min"].as<vec3>();
+	if ( table["rotation_max"] )  node->rotation.max  = table["rotation_max"].as<vec3>();
+	if ( table["rotation_dist"] ) node->rotation.dist = random_dist( table["rotation_dist"].get_uint32() );
 
-	if ( table.has_field( "attach" ) )
+	if ( table["attach"] )
 	{
 		if ( table["attach"].is_number() )
@@ -140,5 +140,5 @@
 	node->material  = cmaterial;
 
-	for ( uint32 i = 1; i <= table.get_size(); ++i )
+	for ( uint32 i = 1; i <= table.size(); ++i )
 	{
 		lua::table_guard child_table( table, i );
Index: trunk/src/engine/particle_manager.cc
===================================================================
--- trunk/src/engine/particle_manager.cc	(revision 539)
+++ trunk/src/engine/particle_manager.cc	(revision 540)
@@ -68,5 +68,5 @@
 
 	vec2 def_size        = table.get<vec2>("size", vec2(0.1,0.1) );
-	uint32 elements = table.get_size();
+	uint32 elements = table.size();
 	for ( uint32 i = 0; i < elements; ++i )
 	{
Index: trunk/src/engine/program_manager.cc
===================================================================
--- trunk/src/engine/program_manager.cc	(revision 539)
+++ trunk/src/engine/program_manager.cc	(revision 540)
@@ -68,5 +68,5 @@
 	{
 		lua::table_guard inctable( table, "files" );
-		uint32 count = inctable.get_size();
+		uint32 count = inctable.size();
 		for ( uint32 i = 1; i <= count; ++i )
 		{
Index: trunk/src/engine/ragdoll_manager.cc
===================================================================
--- trunk/src/engine/ragdoll_manager.cc	(revision 539)
+++ trunk/src/engine/ragdoll_manager.cc	(revision 540)
@@ -75,5 +75,5 @@
 		float radius = table["radius"].get_f32();
 		float length = 0.0f;
-		if ( table.has_field( "target" ) )
+		if ( table[ "target" ] )
 		{
 			const auto& of = bind_data->get_bone_transforms().m_offsets;
@@ -97,5 +97,5 @@
 			part.limits     = table["limits"].as< vec3 >();
 		}
-		uint32 child_count = table.get_size();
+		uint32 child_count = table.size();
 		bool   result = true;
 		if ( child_count > 0 )
Index: trunk/src/lua/lua_proxy.cc
===================================================================
--- trunk/src/lua/lua_proxy.cc	(revision 539)
+++ trunk/src/lua/lua_proxy.cc	(revision 540)
@@ -9,4 +9,5 @@
 #include "nv/lua/lua_raw.hh"
 #include "nv/lua/lua_state.hh"
+#include "nv/lua/lua_types.hh"
 
 using namespace nv;
@@ -58,4 +59,16 @@
 }
 
+bool nv::lua::stack_proxy::is_valid() const
+{
+	return !( lua_isnil( *m_state, m_index ) );
+}
+
+bool nv::lua::stack_proxy::read( const type_entry* entry, void* object ) const
+{
+	NV_ASSERT_ALWAYS( m_state->get_type_data()->get_type_database() == entry->type_db, "Type database mismatch between Lua and entry!" );
+	if ( lua_type( *m_state, m_index ) != LUA_TTABLE ) return false;
+	return nv::lua::read_rtti_type( m_state, entry, object, m_index );
+}
+
 bool nv::lua::stack_proxy::is_table() const
 {
Index: trunk/src/lua/lua_state.cc
===================================================================
--- trunk/src/lua/lua_state.cc	(revision 539)
+++ trunk/src/lua/lua_state.cc	(revision 540)
@@ -153,4 +153,5 @@
 		// TODO : error handling
 	}
+	m_index = -1;
 }
 
@@ -165,27 +166,28 @@
 		// TODO : error handling
 	}
+	m_index = -1;
 }
 
 lua::table_guard::~table_guard()
 {
-	lua_settop( m_state, m_level );
-}
-
-nv::uint32 lua::table_guard::get_size()
-{
-	return nlua_rawlen( m_state, -1 );
-}
-
-bool lua::table_guard::has_field( string_view element )
-{
-	lua_getfield( m_state, -1, element.data() );
-	bool result = !( lua_isnil( m_state, -1 ) );
-	lua_pop( m_state, 1 );
-	return result;
+	if ( m_index == -1 )
+		lua_settop( m_state, m_level );
+}
+
+nv::uint32 lua::table_guard::size()
+{
+	return nlua_rawlen( m_state, m_index );
+}
+
+nv::lua::table_guard::table_guard( stack_proxy& proxy )
+	: state_wrapper( *proxy.m_state, proxy.m_state->m_lua_types, false ), m_parent( proxy.m_state ), m_level( 0 )
+{
+	m_level = lua_gettop( m_state );
+	m_index = proxy.m_index;
 }
 
 const nv::lua::temporary_proxy nv::lua::table_guard::operator[]( const string_view& key ) const
 {
-	lua_getfield( m_state, -1, key.data() );
+	lua_getfield( m_state, m_index, key.data() );
 	return temporary_proxy( m_parent );
 }
@@ -193,24 +195,6 @@
 const nv::lua::temporary_proxy nv::lua::table_guard::operator[]( sint32 key ) const
 {
-	lua_rawgeti( m_state, -1, key );
+	lua_rawgeti( m_state, m_index, key );
 	return temporary_proxy( m_parent );
-}
-
-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;
 }
 
@@ -590,4 +574,16 @@
 }
 
+template < typename T >
+bool nlua_rtti_string_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_TSTRING )
+	{
+		*value = T( nlua_tostringview( 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 )
@@ -608,5 +604,10 @@
 	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::shash32>  ( nullptr, nlua_rtti_string_read<nv::shash32> );
+	insert<nv::shash64>  ( nullptr, nlua_rtti_string_read<nv::shash64> );
+	insert<nv::string32> ( nullptr, nlua_rtti_string_read<nv::string32> );
+	insert<nv::string64> ( nullptr, nlua_rtti_string_read<nv::string64> );
+	insert<nv::string128>( nullptr, nlua_rtti_string_read<nv::string128> );
+	//	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> );
 }
