Index: trunk/nv/ecs/component.hh
===================================================================
--- trunk/nv/ecs/component.hh	(revision 539)
+++ trunk/nv/ecs/component.hh	(revision 540)
@@ -25,4 +25,8 @@
 namespace nv
 {
+	namespace lua
+	{
+		class stack_proxy;
+	}
 
 	namespace ecs
@@ -61,4 +65,6 @@
 				}
 			}
+
+			virtual void initialize( handle_type, lua::stack_proxy& ) {};
 
 			inline value_type& insert( handle_type h )
Index: trunk/nv/ecs/ecs.hh
===================================================================
--- trunk/nv/ecs/ecs.hh	(revision 539)
+++ trunk/nv/ecs/ecs.hh	(revision 540)
@@ -26,4 +26,9 @@
 {
 
+	namespace lua
+	{
+		class stack_proxy;
+	}
+
 	namespace ecs
 	{
@@ -65,4 +70,5 @@
 			{
 			public:
+				virtual void initialize( handle_type, lua::stack_proxy& ) = 0;
 				virtual void remove( handle_type h ) = 0;
 				virtual void* get_raw( handle_type h ) = 0;
@@ -109,4 +115,5 @@
 				register_receiver( name, c );
 				m_component_map[thash64::create<Component>()] = c;
+				m_component_map_by_name[name] = c;
 			}
 
@@ -249,4 +256,16 @@
 			}
 
+			component_interface* get_component( shash64 component_name )
+			{
+				auto it = m_component_map_by_name.find( component_name );
+				return it != m_component_map_by_name.end() ? it->second : nullptr;
+			}
+
+			const component_interface* get_component( shash64 component_name ) const
+			{
+				auto it = m_component_map_by_name.find( component_name );
+				return it != m_component_map_by_name.end() ? it->second : nullptr;
+			}
+
 			template < typename Component >
 			Component* get( handle_type h )
@@ -267,4 +286,5 @@
 			vector< receiver_interface* >               m_receivers;
 			hash_store< thash64, component_interface* > m_component_map;
+			hash_store< shash64, component_interface* > m_component_map_by_name;
 			time_type                                   m_time = time_type(0);
 			priority_queue< message, vector< message >, message_compare_type > m_pqueue;
Index: trunk/nv/lua/lua_proxy.hh
===================================================================
--- trunk/nv/lua/lua_proxy.hh	(revision 539)
+++ trunk/nv/lua/lua_proxy.hh	(revision 540)
@@ -9,4 +9,5 @@
 
 #include <nv/common.hh>
+#include <nv/core/types.hh>
 #include <nv/stl/string.hh>
 #include <nv/stl/string_table.hh>
@@ -56,4 +57,7 @@
 			bool is_bool() const;
 			bool is_string() const;
+			bool is_valid() const;
+			bool is_nil() const { return !is_valid(); }
+			operator bool() const { return is_valid(); }
 
 			const_string get_string() const { return const_string( get_string_view() ); }
@@ -80,4 +84,16 @@
 			}
 
+			template < typename T >
+			bool read( T& t ) const
+			{
+				NV_ASSERT( m_state->get_type_data(), "stack_proxy::read - type database not created!" );
+				const type_database* tdb = m_state->get_type_data()->get_type_database();
+				NV_ASSERT( tdb, "stack_proxy::read - type database not set!" );
+				const type_entry* entry = tdb->get_type<T>();
+				return read( entry, &t );
+			}
+			bool read( const type_entry* entry, void* object ) const;
+// bool write?
+
 			// TO FUCKING DO : non-copyable stringview
 //			string_view get_string_view() const;
@@ -91,4 +107,5 @@
 			state* m_state;
 			sint32 m_index;
+			friend class table_guard;
 		};
 
Index: trunk/nv/lua/lua_state.hh
===================================================================
--- trunk/nv/lua/lua_state.hh	(revision 539)
+++ trunk/nv/lua/lua_state.hh	(revision 540)
@@ -376,19 +376,20 @@
 		{
 		public:
+			table_guard( stack_proxy& proxy );
 			table_guard( state* lstate, const path& p, bool global = true );
 			table_guard( const table_guard& parent, const path& p );
 			virtual ~table_guard();
-			uint32 get_size();
+			uint32 size();
 			iterator_provider< kv_iterator > pairs()
 			{
-				return iterator_provider< kv_iterator >( m_parent, -1 );
+				return iterator_provider< kv_iterator >( m_parent, m_index );
 			}
 			iterator_provider< key_iterator > keys()
 			{
-				return iterator_provider< key_iterator >( m_parent, -1 );
+				return iterator_provider< key_iterator >( m_parent, m_index );
 			}
 			iterator_provider< value_iterator > values()
 			{
-				return iterator_provider< value_iterator >( m_parent, -1 );
+				return iterator_provider< value_iterator >( m_parent, m_index );
 			}
 
@@ -399,55 +400,8 @@
 //			temporary_proxy operator[]( sint32 key );
 
-
-			bool has_field( string_view element );
-			
-// 			shash64 get_string_hash_64( string_view element, uint64 defval = 0 );
-// 			shash64 get_string( string_view element, string_table* table, uint64 defval = 0 );
-// 			const_string get_string( string_view element, string_view defval = string_view() );
-// 			string128 get_string128( string_view element, string_view defval = string_view() );
-// 			string64 get_string64( string_view element, string_view defval = string_view() );
-// 			string32 get_string32( string_view element, string_view defval = string_view() );
-// 
-// 			char get_char( string_view element, char defval = ' ' );
-// 			int get_integer( string_view element, int defval = 0 );
-// 			unsigned get_unsigned( string_view element, unsigned defval = 0 );
-// 			double get_double( string_view element, double defval = 0.0 );
-// 			float get_float( string_view element, float defval = 0.0 );
-// 			bool get_boolean( string_view element, bool defval = false );
-// 
-// 			shash64 get_string_hash_64( int i, uint64 defval = 0 );
-// 			shash64 get_string( int i, string_table* table, uint64 defval = 0 );
-// 			const_string get_string( int i, string_view defval = string_view() );
-// 			string128 get_string128( int i, string_view defval = string_view() );
-// 
-// 			char get_char( int i, char defval = ' ' );
-// 			int get_integer( int i, int defval = 0 );
-// 			unsigned get_unsigned( int i, unsigned defval = 0 );
-// 			double get_double( int i, double defval = 0.0 );
-// 			float get_float( int i, float defval = 0.0 );
-// 			bool get_boolean( int i, bool defval = false );
-// 
-// 			bool is_table( string_view element );
-// 			bool is_number( string_view element );
-// 			bool is_boolean( string_view element );
-// 			bool is_string( string_view element );
-// 			bool is_table( int i );
-// 			bool is_number( int i );
-// 			bool is_boolean( int i );
-// 			bool is_string( int i );
-
-			template < typename T >
-			bool read( const string_view& element, T& t )
-			{
-				NV_ASSERT( m_lua_types, "table_guard::read - type database not created!" );
-				NV_ASSERT( m_lua_types->get_type_database(), "table_guard::read - type database not set!" );
-				const type_entry* entry = m_lua_types->get_type_database()->get_type<T>();
-				return read( element, entry, &t );
-			}
-			bool read( const string_view& element, const type_entry* entry, void* object );
-
 		private:
 			state* m_parent;
 			int m_level;
+			int m_index;
 		};
 
Index: trunk/nv/stl/string.hh
===================================================================
--- trunk/nv/stl/string.hh	(revision 539)
+++ trunk/nv/stl/string.hh	(revision 540)
@@ -153,3 +153,8 @@
 using nv::operator "" _sh64;
 
+NV_RTTI_DECLARE( nv::shash32 )
+NV_RTTI_DECLARE( nv::shash64 )
+
+
+
 #endif // NV_STL_STRING_HH
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> );
 }
