Index: trunk/nv/core/random.hh
===================================================================
--- trunk/nv/core/random.hh	(revision 502)
+++ trunk/nv/core/random.hh	(revision 503)
@@ -15,25 +15,29 @@
 {
 
-	class random
-	{
-	public:
-		static constexpr uint32 mersenne_n = 624;
-		static constexpr uint32 mersenne_m = 397;
-		static constexpr uint32 mersenne_static_seed = 5489;
-
-		typedef uint32 result_type; // mt19937::result_type
+	class random_base
+	{
+	public:
+		typedef uint32 result_type; 
 		typedef uint32 seed_type;
 
-		random( seed_type seed = 0 );
-		seed_type randomize() { return set_seed( 0 ); }
-		seed_type set_seed( seed_type seed = 0 );
-		static random& get();
-		result_type rand();
-		uint32 urand( uint32 val );
+		virtual seed_type set_seed( seed_type seed = 0 ) = 0;
+		virtual result_type rand() = 0;
+
+		seed_type randomize()
+		{
+			return set_seed( randomized_seed() );
+		}
+
+		uint32 urand( uint32 val )
+		{
+			uint32 x, max = 0xFFFFFFFFUL - ( 0xFFFFFFFFUL % val );
+			while ( ( x = rand() ) >= max );
+			return x / ( max / val );
+		}
 
 		sint32 srand( sint32 val )
 		{
 			NV_ASSERT( val >= 0, "Bad srand range!" );
-			return static_cast< sint32 >( urand( static_cast< uint32 >( val ) ) );
+			return static_cast<sint32>( urand( static_cast<uint32>( val ) ) );
 		}
 
@@ -53,5 +57,5 @@
 			// this method probably reduces range //
 			uint32 roll = urand( static_cast<uint32>( max - min ) + 1 );
-			return static_cast< sint32 >( roll ) + min;
+			return static_cast<sint32>( roll ) + min;
 		}
 
@@ -83,5 +87,5 @@
 		{
 			return math::tvec2<T>(
-				range_impl( min.x, max.x, is_floating_point<T>() ), 
+				range_impl( min.x, max.x, is_floating_point<T>() ),
 				range_impl( min.y, max.y, is_floating_point<T>() )
 				);
@@ -92,5 +96,5 @@
 		{
 			return math::tvec3<T>(
-				range_impl( min.x, max.x, is_floating_point<T>() ), 
+				range_impl( min.x, max.x, is_floating_point<T>() ),
 				range_impl( min.y, max.y, is_floating_point<T>() ),
 				range_impl( min.z, max.z, is_floating_point<T>() )
@@ -102,20 +106,22 @@
 		{
 			return math::tvec4<T>(
-				range_impl( min.x, max.x, is_floating_point<T>() ), 
+				range_impl( min.x, max.x, is_floating_point<T>() ),
 				range_impl( min.y, max.y, is_floating_point<T>() ),
-				range_impl( min.z, max.z, is_floating_point<T>() ), 
-				range_impl( min.w, max.w, is_floating_point<T>() ) 
+				range_impl( min.z, max.z, is_floating_point<T>() ),
+				range_impl( min.w, max.w, is_floating_point<T>() )
 				);
 		}
 
+
+
 		vec3 unit_vec3( bool = false )
 		{
 			return precise_unit_vec3();
-//			return precise ? precise_unit_vec3() : fast_unit_vec3();
+			//			return precise ? precise_unit_vec3() : fast_unit_vec3();
 		}
 		vec2 unit_vec2( bool = false )
 		{
 			return precise_unit_vec2();
-//			return precise ? precise_unit_vec2() : fast_unit_vec2();
+			//			return precise ? precise_unit_vec2() : fast_unit_vec2();
 		}
 
@@ -174,5 +180,5 @@
 		//vec3 fast_unit_vec3();
 		vec3 precise_unit_vec3();
-	
+
 		vec2 fast_disk_point();
 		vec2 precise_disk_point();
@@ -203,6 +209,5 @@
 		vec3 precise_hollow_ellipsoid_point( const vec3& iradii, const vec3& oradii );
 
-
-	private:
+	protected:
 		static seed_type randomized_seed();
 
@@ -218,18 +223,44 @@
 			return srange( min, max );
 		}
+	};
+
+	class random_mersenne : public random_base
+	{
+	public:
+		static constexpr uint32 mersenne_n = 624;
+		static constexpr uint32 mersenne_m = 397;
+		static constexpr uint32 mersenne_static_seed = 5489;
+
+		explicit random_mersenne( seed_type seed = randomized_seed() );
+		virtual seed_type set_seed( seed_type seed = 0 );
+		virtual result_type rand();
 	private:
 		void mt_init( uint32 seed );
 		void mt_update();
-		f64 mt_double();
 		uint32 mt_uint32();
 
-		uint32  m_state[ mersenne_n ];
+		uint32  m_state[mersenne_n];
 		uint32* m_next;
 		uint32  m_remaining;
 		uint32  m_seeded : 1;
 		uint32  m_static_system_seed : 1;
-
-		// temporary solution until we get rid of ::random
-		char m_data[16 * 1024];
+	};
+
+	class random_xor128 : public random_base
+	{
+	public:
+		explicit random_xor128( seed_type seed = randomized_seed() );
+		virtual seed_type set_seed( seed_type seed = 0 );
+		virtual result_type rand();
+	private:
+		uint32  m_state[4]; // xyzw
+	};
+
+
+	class random : public random_mersenne
+	{
+	public:
+		explicit random( seed_type seed = randomized_seed() ) : random_mersenne( seed ) {};
+		static random& get();
 	};
 
Index: trunk/nv/core/types.hh
===================================================================
--- trunk/nv/core/types.hh	(revision 502)
+++ trunk/nv/core/types.hh	(revision 503)
@@ -78,5 +78,5 @@
 		uint32      flags;    //!< flags 
 		uint32      offset;   //!< offset into parent
-		type_field* control;  //!< pointer to field control (in unions)
+		sint32      control;  //!< index to field control (in unions), -1 otherwise
 		sint32      enumidx;  //!< field index (in unions)
 	};
@@ -91,4 +91,5 @@
 	{
 		type_database*     type_db;     //!< Parent type database
+		thash64            hash;        //!< type hash
 		shash64            name;        //!< Scoped C++ name of the type
 		constructor_t      constructor; //!< Pointers to the constructor 
@@ -98,6 +99,6 @@
 		vector<type_field> field_list;  //!< Field list
 		vector<type_enum>  enum_list;   //!< Enum list
-		hash_store< shash64, type_field* > field_names;
-		hash_store< shash64, type_enum* >  enum_names;
+		hash_store< shash64, uint32 > field_names;
+		hash_store< shash64, uint32 > enum_names;
 	};
 
@@ -146,4 +147,5 @@
 			type_entry* i_type = new type_entry;
 			i_type->type_db = this;
+			i_type->hash = thash64::create< TYPE >();
 			i_type->name = m_names.insert( name );
 			i_type->size = sizeof( TYPE );
@@ -151,5 +153,5 @@
 			i_type->constructor = raw_construct_object < TYPE >;
 			i_type->destructor  = raw_destroy_object < TYPE >;
-			m_index_by_type[ thash64::create< TYPE >() ] = i_type;
+			m_index_by_type[ i_type->hash ] = i_type;
 			m_index_by_name[ i_type->name ] = i_type;
 			m_type_list.push_back( i_type );
@@ -176,7 +178,19 @@
 		}
 
-		string_view resolve_name( shash64 name_hash )
+		template< typename T >
+		const type_entry* get_type() const
+		{
+			auto it = m_index_by_type.find( thash64::create< T >() );
+			return it != m_index_by_type.end() ? it->second : nullptr;
+		}
+
+		string_view resolve_name( shash64 name_hash ) const
 		{
 			return m_names[name_hash];
+		}
+
+		string_view resolve_name( const type_entry* entry ) const
+		{
+			return m_names[entry->name];
 		}
 
@@ -211,8 +225,8 @@
 			( is_pod<field_type>::value ? TF_SIMPLETYPE : 0 );
 		f.offset = uint32( offset_of( field ) );
-		f.control = nullptr;
+		f.control = -1;
 		f.enumidx = 0;
 		m_entry->field_list.push_back( f );
-		m_entry->field_names[f.name] = &m_entry->field_list.back();
+		m_entry->field_names[f.name] = m_entry->field_list.size() - 1;
 		return *this;
 	}
@@ -229,8 +243,8 @@
 			( is_pod<TFIELD>::value ? TF_SIMPLETYPE : 0 );
 		f.offset = uint32( offset_of( field ) );
-		f.control = nullptr;
+		f.control = -1;
 		f.enumidx = 0;
 		m_entry->field_list.push_back( f );
-		m_entry->field_names[f.name] = &m_entry->field_list.back();
+		m_entry->field_names[f.name] = m_entry->field_list.size() - 1;
 		return *this;
 	}
@@ -248,8 +262,8 @@
 			( is_pod<field_type>::value ? TF_SIMPLETYPE : 0 );
 		f.offset = uint32( offset_of( field ) );
-		f.control = m_entry->field_names[ control_name ];
+		f.control = sint32( m_entry->field_names[ control_name ] );
 		f.enumidx = static_cast< sint32 >( control_value );
 		m_entry->field_list.push_back( f );
-		m_entry->field_names[f.name] = &m_entry->field_list.back();
+		m_entry->field_names[f.name] = m_entry->field_list.size() - 1;
 		return *this;
 	}
@@ -266,8 +280,8 @@
 			( is_pod<TFIELD>::value ? TF_SIMPLETYPE : 0 );
 		f.offset = uint32( offset_of( field ) );
-		f.control = m_entry->field_names[control_name];
+		f.control = sint32( m_entry->field_names[control_name] );
 		f.enumidx = static_cast<sint32>( control_value );
 		m_entry->field_list.push_back( f );
-		m_entry->field_names[f.name] = &m_entry->field_list.back();
+		m_entry->field_names[f.name] = m_entry->field_list.size() - 1;
 		return *this;
 	}
@@ -280,7 +294,9 @@
 		e.value = value;
 		m_entry->enum_list.push_back( e );
-		m_entry->enum_names[e.name] = &m_entry->enum_list.back();
-		return *this;
-	}
+		m_entry->enum_names[e.name] = m_entry->enum_list.size() - 1;
+		return *this;
+	}
+
+	void register_core_types( type_database* db );
 
 }
Index: trunk/nv/gfx/mesh_creator.hh
===================================================================
--- trunk/nv/gfx/mesh_creator.hh	(revision 502)
+++ trunk/nv/gfx/mesh_creator.hh	(revision 503)
@@ -24,5 +24,21 @@
 
 		// assumes that position and normal is vec3, tangent is vec4
-		void transform( float scale, const mat3& r33 );
+		void transform( const vec3& pos, const mat3& r33, float scale = 1.0f );
+		// assumes that position and normal is vec3, tangent is vec4
+		void transform( const vec3& pos, const quat& r, float scale = 1.0f )
+		{
+			transform( pos, mat3_cast(r), scale );
+		}
+		// assumes that position and normal is vec3, tangent is vec4
+		void transform( const nv::transform& tr, float scale = 1.0f )
+		{
+			transform( tr.get_position(), tr.get_orientation(), scale );
+		}
+		// assumes that position and normal is vec3, tangent is vec4
+		void transform( float scale, const mat3& r33 )
+		{
+			// remove this
+			transform( vec3(), r33, scale );
+		}
 		// TODO: this could generate normals too
 		void generate_tangents();
Index: trunk/nv/gl/gl_context.hh
===================================================================
--- trunk/nv/gl/gl_context.hh	(revision 502)
+++ trunk/nv/gl/gl_context.hh	(revision 503)
@@ -53,6 +53,6 @@
 		virtual void set_draw_buffer( output_slot slot );
 		virtual void set_read_buffer( output_slot slot );
-		virtual void blit( framebuffer f, clear_state::buffers_type mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 );
-		virtual void blit( framebuffer from, framebuffer to, clear_state::buffers_type mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 );
+		virtual void blit( framebuffer f, buffer_mask mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 );
+		virtual void blit( framebuffer from, framebuffer to, buffer_mask mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 );
 
 		virtual void attach( framebuffer f, output_slot slot, texture t, int layer = -1 );
Index: trunk/nv/gl/gl_enum.hh
===================================================================
--- trunk/nv/gl/gl_enum.hh	(revision 502)
+++ trunk/nv/gl/gl_enum.hh	(revision 503)
@@ -24,5 +24,5 @@
 
 	unsigned int texture_type_to_enum( texture_type type );
-	unsigned int clear_state_buffers_to_mask( clear_state::buffers_type type );
+	unsigned int clear_state_buffers_to_mask( buffer_mask type );
 	unsigned int depth_state_function_to_enum( depth_test::function_type type );
 	unsigned int polygon_mode_fill_to_enum( polygon_mode::fill_type type );
Index: trunk/nv/interface/clear_state.hh
===================================================================
--- trunk/nv/interface/clear_state.hh	(revision 502)
+++ trunk/nv/interface/clear_state.hh	(revision 503)
@@ -53,16 +53,16 @@
 	};
 
+	enum buffer_mask
+	{
+		NO_BUFFER = 0,
+		COLOR_BUFFER = 1,
+		DEPTH_BUFFER = 2,
+		STENCIL_BUFFER = 4,
+		COLOR_AND_DEPTH_BUFFER = COLOR_BUFFER | DEPTH_BUFFER,
+		ALL_BUFFERS = COLOR_BUFFER | DEPTH_BUFFER | STENCIL_BUFFER
+	};
+
 	struct clear_state
 	{
-		enum buffers_type
-		{
-			NONE = 0,
-			COLOR_BUFFER = 1,
-			DEPTH_BUFFER = 2,
-			STENCIL_BUFFER = 4,
-			COLOR_AND_DEPTH_BUFFER = COLOR_BUFFER | DEPTH_BUFFER, 
-			ALL = COLOR_BUFFER | DEPTH_BUFFER | STENCIL_BUFFER
-		};
-
 		nv::scissor_test scissor_test;
 		nv::color_mask color_mask;
@@ -71,5 +71,5 @@
 		uint32 back_stencil_mask;
 
-		buffers_type buffers;
+		buffer_mask buffers;
 		vec4 color;
 		float depth;
@@ -79,9 +79,14 @@
 			: scissor_test(), color_mask(), depth_mask( true ), 
 			  front_stencil_mask( uint32(-1) ), back_stencil_mask( uint32(-1) ),
-			  buffers( ALL ), color( vec4(0,0,0,1) ), depth( 1.0f ), stencil( 0 ) {}
+			  buffers( ALL_BUFFERS ), color( vec4(0,0,0,1) ), depth( 1.0f ), stencil( 0 ) {}
 	};
 
 } // namespace nv
 
+NV_RTTI_DECLARE( nv::color_mask )
+NV_RTTI_DECLARE( nv::scissor_test )
+NV_RTTI_DECLARE( nv::clear_state )
+NV_RTTI_DECLARE( nv::buffer_mask )
+
 
 #endif // NV_INTERFACE_CLEAR_STATE_HH
Index: trunk/nv/interface/context.hh
===================================================================
--- trunk/nv/interface/context.hh	(revision 502)
+++ trunk/nv/interface/context.hh	(revision 503)
@@ -185,6 +185,6 @@
 		virtual void set_draw_buffer( output_slot slot ) = 0;
 		virtual void set_read_buffer( output_slot slot ) = 0;
-		virtual void blit( framebuffer f, clear_state::buffers_type mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 ) = 0;
-		virtual void blit( framebuffer from, framebuffer to, clear_state::buffers_type mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 ) = 0;
+		virtual void blit( framebuffer f, buffer_mask mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 ) = 0;
+		virtual void blit( framebuffer from, framebuffer to, buffer_mask mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 ) = 0;
 
 		virtual void attach( framebuffer f, output_slot slot, texture t, int layer = -1 ) = 0;
Index: trunk/nv/interface/render_state.hh
===================================================================
--- trunk/nv/interface/render_state.hh	(revision 502)
+++ trunk/nv/interface/render_state.hh	(revision 503)
@@ -206,4 +206,20 @@
 } // namespace nv
 
+NV_RTTI_DECLARE( nv::depth_test )
+NV_RTTI_DECLARE( nv::depth_test::function_type )
+NV_RTTI_DECLARE( nv::polygon_mode )
+NV_RTTI_DECLARE( nv::polygon_mode::fill_type )
+NV_RTTI_DECLARE( nv::blending )
+NV_RTTI_DECLARE( nv::blending::factor )
+NV_RTTI_DECLARE( nv::blending::equation )
+NV_RTTI_DECLARE( nv::stencil_test_face )
+NV_RTTI_DECLARE( nv::stencil_test_face::operation )
+NV_RTTI_DECLARE( nv::stencil_test_face::function_type )
+NV_RTTI_DECLARE( nv::stencil_test )
+NV_RTTI_DECLARE( nv::culling )
+NV_RTTI_DECLARE( nv::culling::face_type )
+NV_RTTI_DECLARE( nv::culling::order_type )
+NV_RTTI_DECLARE( nv::depth_range )
+NV_RTTI_DECLARE( nv::render_state )
 
 #endif // NV_INTERFACE_RENDER_STATE_HH
Index: trunk/nv/lua/lua_area.hh
===================================================================
--- trunk/nv/lua/lua_area.hh	(revision 502)
+++ trunk/nv/lua/lua_area.hh	(revision 503)
@@ -18,5 +18,5 @@
 	namespace lua
 	{
-		void register_area( lua_State* L );
+		void register_area( lua::state* state );
 
 		template<>
Index: trunk/nv/lua/lua_aux.hh
===================================================================
--- trunk/nv/lua/lua_aux.hh	(revision 502)
+++ trunk/nv/lua/lua_aux.hh	(revision 503)
@@ -14,5 +14,5 @@
 	namespace lua
 	{
-		void register_aux( lua_State* L );
+		void register_aux( lua::state* state );
 	}
 }
Index: trunk/nv/lua/lua_map_area.hh
===================================================================
--- trunk/nv/lua/lua_map_area.hh	(revision 502)
+++ trunk/nv/lua/lua_map_area.hh	(revision 503)
@@ -20,7 +20,7 @@
 	namespace lua
 	{
-		void register_map_area( lua_State* L );
-		void register_map_area_interface( lua_State* L, int index );
-		void register_map_area_instance( lua_State* L, ref object_index, map_area* area );
+		void register_map_area( lua::state* state );
+		void register_map_area_interface( lua::state* state, int index );
+		void register_map_area_instance( lua::state* state, ref object_index, map_area* area );
 
 		namespace detail
Index: trunk/nv/lua/lua_map_tile.hh
===================================================================
--- trunk/nv/lua/lua_map_tile.hh	(revision 502)
+++ trunk/nv/lua/lua_map_tile.hh	(revision 503)
@@ -20,5 +20,5 @@
 	namespace lua
 	{
-		void register_map_tile( lua_State* L );
+		void register_map_tile( lua::state* state );
 	}
 }
Index: trunk/nv/lua/lua_math.hh
===================================================================
--- trunk/nv/lua/lua_math.hh	(revision 502)
+++ trunk/nv/lua/lua_math.hh	(revision 503)
@@ -10,4 +10,5 @@
 #include <nv/common.hh>
 #include <nv/stl/math.hh>
+#include <nv/lua/lua_state.hh>
 #include <nv/lua/lua_values.hh>
 
@@ -16,5 +17,5 @@
 	namespace lua
 	{
-		void register_math( lua_State* L );
+		void register_math( lua::state* state );
 
 		template<> struct pass_traits< vec2 >  : metatable_pass_traits< vec2 >  { static const char* metatable() { return "vec2"; } };
Index: trunk/nv/lua/lua_state.hh
===================================================================
--- trunk/nv/lua/lua_state.hh	(revision 502)
+++ trunk/nv/lua/lua_state.hh	(revision 503)
@@ -13,4 +13,5 @@
 
 #include <nv/common.hh>
+#include <nv/core/types.hh>
 #include <nv/stl/flags.hh>
 #include <nv/stl/handle.hh>
@@ -34,6 +35,61 @@
 	namespace lua
 	{
+
 		class state;
 
+		using lua_rtti_read_function  = bool(*)( state*, const type_entry*, void*, int index );
+		using lua_rtti_push_function  = void(*)( state*, const type_entry*, void* );
+		
+
+		class type_data
+		{
+			class entry
+			{
+
+			};
+		public:
+			explicit type_data( type_database* db ) : m_type_database( db )
+			{
+				register_standard_types();
+			}
+			const type_database* get_type_database() const { return m_type_database; }
+
+			template < typename T >
+			void insert( lua_rtti_push_function p, lua_rtti_read_function r )
+			{
+				insert( thash64::create<T>(), p, r );
+			}
+			void insert( thash64 tid, lua_rtti_push_function p, lua_rtti_read_function r );
+
+			template < typename T >
+			lua_rtti_read_function* get_push() const
+			{
+				return get_read( thash64::create<T>() );
+			}
+
+			template < typename T >
+			lua_rtti_push_function* get_push() const
+			{
+				return get_push( thash64::create<T>() );
+			}
+
+			const lua_rtti_read_function* get_read( thash64 h ) const
+			{
+				auto f = m_type_read.find( h );
+				return f != m_type_read.end() ? &f->second : nullptr;
+			}
+			const lua_rtti_push_function* get_push( thash64 h ) const
+			{
+				auto f = m_type_push.find( h );
+				return f != m_type_push.end() ? &f->second : nullptr;
+			}
+		protected:
+			void register_standard_types();
+
+			hash_store< thash64, lua_rtti_read_function >  m_type_read;
+			hash_store< thash64, lua_rtti_push_function >  m_type_push;
+			type_database*                                 m_type_database;
+		};
+
 		const int ret_multi = -1;
 
@@ -41,5 +97,5 @@
 		{
 		public:
-			state_wrapper( lua_State* a_state, bool a_owner ) : m_state( a_state ), m_owner( a_owner ), m_global( true ) {}
+			state_wrapper( lua_State* a_state, type_data* types, bool a_owner ) : m_state( a_state ), m_lua_types( types ), m_owner( a_owner ), m_global( true ) {}
 			virtual ~state_wrapper();
 
@@ -143,4 +199,6 @@
 				register_native_function( detail::object_method_wrapper< C, F, f >, name );
 			}
+
+			const type_data* get_type_data() const { return m_lua_types; }
 
 		protected:
@@ -155,4 +213,5 @@
 		protected:
 			lua_State* m_state;
+			type_data* m_lua_types;
 			bool m_owner;
 			bool m_global;
@@ -191,6 +250,6 @@
 
 		public:
-			explicit state( bool load_libs = false );
-			explicit state( lua_State* state );
+			explicit state( bool load_libs = false, type_database* types = nullptr );
+			explicit state( lua_State* state, type_database* types = nullptr );
 			bool do_string( string_view code, string_view name, int rvalues = 0 );
 			bool do_file( string_view filename );
@@ -279,5 +338,14 @@
 			}
 
+			virtual ~state();
+
+			template < typename T >
+			void register_rtti_type( lua_rtti_push_function p, lua_rtti_read_function r )
+			{
+				register_rtti_type( thash64::create< T >(), p, r );
+			}
+
 		private:
+			void register_rtti_type( thash64 tid, lua_rtti_push_function p, lua_rtti_read_function r );
 			ref register_handle_component_impl( string_view id, bool empty );
 			void unregister_handle_component_impl( string_view id );
@@ -313,5 +381,16 @@
 			bool is_boolean( string_view element );
 			bool is_string( string_view element );
+			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;
 		};
Index: trunk/nv/lua/lua_templates.hh
===================================================================
--- trunk/nv/lua/lua_templates.hh	(revision 503)
+++ trunk/nv/lua/lua_templates.hh	(revision 503)
@@ -0,0 +1,55 @@
+// 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.
+
+#ifndef NV_LUA_TEMPLATES_HH
+#define NV_LUA_TEMPLATES_HH
+
+#include <nv/common.hh>
+#include <nv/stl/math.hh>
+#include <nv/lua/lua_values.hh>
+
+namespace nv
+{
+	namespace lua
+	{
+
+		namespace detail
+		{
+			template < typename T >
+			int clone_impl( lua_State* L )
+			{
+				pass_traits<T>::push( L, pass_traits<T>::to( L, 1 ) );
+				return 1;
+			}
+
+			template < typename T >
+			int eq_impl( lua_State* L )
+			{
+				lua_pushboolean( L, pass_traits<T>::to( L, 1 ) == pass_traits<T>::to( L, 1 ) );
+				return 1;
+			}
+
+			template < typename T, typename Constructor >
+			int new_impl( lua_State* L )
+			{
+				pass_traits<T>::push( L, Constructor::construct( L, 1 ) );
+				return 1;
+			}
+
+			template < typename T, typename Constructor >
+			int call_impl( lua_State* L )
+			{
+				pass_traits<T>::push( L, Constructor::construct( L, 2 ) );
+				return 1;
+			}
+		}
+
+	}
+
+}
+
+
+#endif // NV_LUA_TEMPLATES_HH
Index: trunk/nv/lua/lua_types.hh
===================================================================
--- trunk/nv/lua/lua_types.hh	(revision 503)
+++ trunk/nv/lua/lua_types.hh	(revision 503)
@@ -0,0 +1,68 @@
+// 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.
+
+#ifndef NV_LUA_TYPES_HH
+#define NV_LUA_TYPES_HH
+
+#include <nv/common.hh>
+#include <nv/core/types.hh>
+#include <nv/stl/type_traits/properties.hh>
+#include <nv/lua/lua_values.hh>
+#include <nv/lua/lua_state.hh>
+
+/*
+#define NV_LUA_RTTI_DECLARE( type ) struct pass_traits< type > : nv::lua::lua_rtti_pass_traits< type > {}
+*/
+namespace nv
+{
+	namespace lua
+	{
+/*
+		template < typename T >
+		struct lua_rtti_pass_traits
+		{
+			typedef T value_type;
+			static const char* metatable()
+			{
+				return nv::rtti_type_hash<T>::name();
+			}
+			static void push( lua_State *L, const value_type& v )
+			{
+				detail::push_userdata< value_type >( L, v, metatable() );
+			}
+			static value_type to( lua_State *L, int index )
+			{
+				// TODO: ASSERT?
+				value_type* result = detail::to_userdata< value_type >( L, index, metatable() );
+				return result ? *result : value_type();
+			}
+			static value_type to( lua_State *L, int index, const value_type& def )
+			{
+				value_type* result = detail::to_userdata< value_type >( L, index, metatable() );
+				return result ? *result : def;
+			}
+		};
+
+		template < typename T >
+		void register_lua_rtti_type( const string_view& name, lua::state* state )
+		{
+			const type_database* db = state->get_type_db();
+			register_lua_rtti_type( name, state, db->get_type<T>() )
+		}
+
+
+		void register_lua_rtti_type( const string_view& name, lua::state* state, const type_entry* entry );
+		*/
+
+		bool read_rtti_type( lua::state* state, const type_entry* entry, void* object, int index );
+
+		template < typename T >
+		void push_rtti_proxy( lua::state* state, T* object );
+	}
+}
+
+#endif // NV_LUA_TYPES_HH
+
Index: trunk/src/core/random.cc
===================================================================
--- trunk/src/core/random.cc	(revision 502)
+++ trunk/src/core/random.cc	(revision 503)
@@ -19,5 +19,11 @@
 #define NV_MT_TWIST(u, v)  ( (NV_MT_MIXBITS(u, v) >> 1) ^ ( (v) & 1UL ? mt_matrix_a : 0UL) )
 
-void random::mt_init( uint32 seed )
+nv::random& random::get()
+{
+	static random default_rng;
+	return default_rng;
+}
+
+void random_mersenne::mt_init( uint32 seed )
 {
 	m_state[0] = static_cast<uint32>( seed & mt_full_mask );
@@ -34,5 +40,5 @@
 
 
-void random::mt_update()
+void random_mersenne::mt_update()
 {
 	uint32 *p = m_state;
@@ -51,5 +57,5 @@
 
 
-uint32 random::mt_uint32()
+uint32 random_mersenne::mt_uint32()
 {
 	uint32 r;
@@ -70,36 +76,22 @@
 }
 
-random::random( random::seed_type seed /*= 0 */ )
+random_mersenne::random_mersenne( random_mersenne::seed_type seed /*= 0 */ )
 	: m_next( nullptr ), m_remaining( 0 ), m_seeded( 0 )
 {
-	mt_init( seed == 0 ? randomized_seed() : seed );
-}
-
-random::seed_type random::set_seed( random::seed_type seed /*= 0 */ )
-{
-	if ( seed == 0 ) seed = randomized_seed();
+	mt_init( seed );
+}
+
+random_mersenne::seed_type random_mersenne::set_seed( random_mersenne::seed_type seed /*= 0 */ )
+{
 	mt_init( seed );
 	return seed;
 }
 
-nv::random& random::get()
-{
-	static random default_rng;
-	return default_rng;
-}
-
-random::result_type random::rand()
+random_mersenne::result_type random_mersenne::rand()
 {
 	return mt_uint32();
 }
 
-uint32 random::urand( uint32 val )
-{
-	uint32 x, max = mt_full_mask - ( mt_full_mask % val );
-	while ( ( x = rand() ) >= max );
-	return x / ( max / val );
-}
-
-random::seed_type random::randomized_seed()
+random_base::seed_type random_base::randomized_seed()
 {
 	// TODO: this seems off, as it might often seed the same, use general time 
@@ -108,5 +100,5 @@
 }
 
-nv::vec2 nv::random::precise_unit_vec2()
+nv::vec2 nv::random_base::precise_unit_vec2()
 {
 	f32 angle = frand( math::pi<f32>() * 2.f );
@@ -114,5 +106,5 @@
 }
 
-nv::vec3 nv::random::precise_unit_vec3()
+nv::vec3 nv::random_base::precise_unit_vec3()
 {
 	f32 cos_theta = frange( -1.0f, 1.0f );
@@ -126,5 +118,5 @@
 }
 
-nv::vec2 nv::random::fast_disk_point()
+nv::vec2 nv::random_base::fast_disk_point()
 {
 	f32 r1 = frand();
@@ -135,5 +127,5 @@
 }
 
-nv::vec2 nv::random::precise_disk_point()
+nv::vec2 nv::random_base::precise_disk_point()
 {
 	f32 r = sqrt( frand() );
@@ -142,5 +134,5 @@
 }
 
-nv::vec3 nv::random::fast_sphere_point()
+nv::vec3 nv::random_base::fast_sphere_point()
 {
 	f32 rad     = frand();
@@ -156,5 +148,5 @@
 }
 
-nv::vec3 nv::random::precise_sphere_point()
+nv::vec3 nv::random_base::precise_sphere_point()
 {
 	f32 radius = pow( frand(), 1.f/3.f );
@@ -169,5 +161,5 @@
 }
 
-nv::vec2 nv::random::precise_ellipse_point( const vec2& radii )
+nv::vec2 nv::random_base::precise_ellipse_point( const vec2& radii )
 {
 	vec2 p = range( -radii, radii );
@@ -184,5 +176,5 @@
 }
 
-nv::vec3 nv::random::precise_ellipsoid_point( const vec3& radii )
+nv::vec3 nv::random_base::precise_ellipsoid_point( const vec3& radii )
 {
 	vec3 p = range( -radii, radii );
@@ -199,5 +191,5 @@
 }
 
-nv::vec2 nv::random::fast_hollow_disk_point( f32 iradius, f32 oradius )
+nv::vec2 nv::random_base::fast_hollow_disk_point( f32 iradius, f32 oradius )
 {
 	f32 idist2 = iradius * iradius;
@@ -207,10 +199,10 @@
 }
 
-nv::vec2 nv::random::precise_hollow_disk_point( f32 iradius, f32 oradius )
+nv::vec2 nv::random_base::precise_hollow_disk_point( f32 iradius, f32 oradius )
 {
 	return fast_hollow_disk_point( iradius, oradius );
 }
 
-nv::vec3 nv::random::fast_hollow_sphere_point( f32 iradius, f32 oradius )
+nv::vec3 nv::random_base::fast_hollow_sphere_point( f32 iradius, f32 oradius )
 {
 	f32 idist3 = iradius * iradius * iradius;
@@ -220,5 +212,5 @@
 }
 
-nv::vec3 nv::random::precise_hollow_sphere_point( f32 iradius, f32 oradius )
+nv::vec3 nv::random_base::precise_hollow_sphere_point( f32 iradius, f32 oradius )
 {
 	return fast_hollow_sphere_point( iradius, oradius );
@@ -226,5 +218,5 @@
 
 
-nv::vec2 nv::random::fast_hollow_ellipse_point( const vec2& iradii, const vec2& oradii )
+nv::vec2 nv::random_base::fast_hollow_ellipse_point( const vec2& iradii, const vec2& oradii )
 {
 	vec2 iradii2 = iradii * iradii;
@@ -241,10 +233,10 @@
 }
 
-nv::vec2 nv::random::precise_hollow_ellipse_point( const vec2& iradii, const vec2& oradii )
+nv::vec2 nv::random_base::precise_hollow_ellipse_point( const vec2& iradii, const vec2& oradii )
 {
 	return fast_hollow_ellipse_point( iradii, oradii );
 }
 
-nv::vec3 nv::random::fast_hollow_ellipsoid_point( const vec3& iradii, const vec3& oradii )
+nv::vec3 nv::random_base::fast_hollow_ellipsoid_point( const vec3& iradii, const vec3& oradii )
 {
 	vec3 iradii2 = iradii * iradii;
@@ -267,7 +259,32 @@
 }
 
-nv::vec3 nv::random::precise_hollow_ellipsoid_point( const vec3& iradii, const vec3& oradii )
+nv::vec3 nv::random_base::precise_hollow_ellipsoid_point( const vec3& iradii, const vec3& oradii )
 {
 	return fast_hollow_ellipsoid_point( iradii, oradii );
 }
 
+nv::random_xor128::random_xor128( seed_type seed /*= randomized_seed() */ )
+{
+	set_seed( seed );
+}
+
+nv::random_base::seed_type nv::random_xor128::set_seed( seed_type seed /*= 0 */ )
+{
+	uint32 s = 4294967296 - seed;
+	m_state[0] = 123456789 * s;
+	m_state[1] = 362436069 * s;
+	m_state[2] = 521288629 * s;
+	m_state[3] = 88675123 * s;
+	return seed;
+}
+
+nv::random_base::result_type nv::random_xor128::rand()
+{
+	uint32 t = m_state[0];
+	t ^= t << 11;
+	t ^= t >> 8;
+	m_state[0] = m_state[1]; m_state[1] = m_state[2]; m_state[2] = m_state[3];
+	m_state[3] ^= m_state[3] >> 19;
+	m_state[3] ^= t;
+	return m_state[3];
+}
Index: trunk/src/core/types.cc
===================================================================
--- trunk/src/core/types.cc	(revision 503)
+++ trunk/src/core/types.cc	(revision 503)
@@ -0,0 +1,198 @@
+#include "nv/core/types.hh"
+
+#include "nv/interface/clear_state.hh"
+#include "nv/interface/render_state.hh"
+
+using namespace nv;
+
+void nv::register_core_types( type_database* db )
+{
+	db->create_type<bool>();
+	db->create_type<char>();
+	db->create_type<uint8>();
+	db->create_type<sint8>();
+	db->create_type<uint16>();
+	db->create_type<sint16>();
+	db->create_type<uint32>();
+	db->create_type<sint32>();
+	db->create_type<uint64>();
+	db->create_type<sint64>();
+	db->create_type<f32>();
+	db->create_type<f64>();
+	db->create_type<vec2>();
+	db->create_type<vec3>();
+	db->create_type<vec4>();
+	db->create_type<ivec2>();
+	db->create_type<ivec3>();
+	db->create_type<ivec4>();
+
+	db->create_type<color_mask>()
+		.field( "red",   &color_mask::red )
+		.field( "green", &color_mask::green )
+		.field( "blue",  &color_mask::blue )
+		.field( "alpha", &color_mask::alpha )
+		;
+
+	db->create_type<scissor_test>()
+		.field( "enabled", &scissor_test::enabled )
+		.field( "pos",     &scissor_test::pos )
+		.field( "dim",     &scissor_test::dim )
+		;
+
+	db->create_type<buffer_mask>()
+		.value( "NO_BUFFER",              buffer_mask::NO_BUFFER )
+		.value( "COLOR_BUFFER",           buffer_mask::COLOR_BUFFER )
+		.value( "DEPTH_BUFFER",           buffer_mask::DEPTH_BUFFER )
+		.value( "STENCIL_BUFFER",         buffer_mask::STENCIL_BUFFER )
+		.value( "COLOR_AND_DEPTH_BUFFER", buffer_mask::COLOR_AND_DEPTH_BUFFER )
+		.value( "ALL_BUFFERS",            buffer_mask::ALL_BUFFERS )
+		;
+
+	db->create_type<clear_state>()
+		.field( "scissor_test",              &clear_state::scissor_test )
+		.field( "color_mask",                &clear_state::color_mask )
+		.field( "depth_mask",                &clear_state::depth_mask )
+		.field( "front_stencil_mask",        &clear_state::front_stencil_mask )
+		.field( "back_stencil_mask",         &clear_state::back_stencil_mask )
+		.field( "buffers",                   &clear_state::buffers )
+		.field( "color",                     &clear_state::color )
+		.field( "depth",                     &clear_state::depth )
+		.field( "stencil",                   &clear_state::stencil )
+		;
+
+	db->create_type<depth_test::function_type>()
+		.value( "NEVER",            depth_test::function_type::NEVER )
+		.value( "LESS",             depth_test::function_type::LESS )
+		.value( "EQUAL",            depth_test::function_type::EQUAL )
+		.value( "LESS_OR_EQUAL",    depth_test::function_type::LESS_OR_EQUAL )
+		.value( "GREATER",          depth_test::function_type::GREATER )
+		.value( "NOT_EQUAL",        depth_test::function_type::NOT_EQUAL )
+		.value( "GREATER_OR_EQUAL", depth_test::function_type::GREATER_OR_EQUAL )
+		.value( "ALWAYS",           depth_test::function_type::ALWAYS )
+		;
+
+	db->create_type<depth_test>()
+		.field( "enabled", &depth_test::enabled )
+		.field( "function", &depth_test::function )
+		;
+
+	db->create_type<polygon_mode::fill_type>()
+		.value( "POINT", polygon_mode::fill_type::POINT )
+		.value( "LINE",  polygon_mode::fill_type::LINE )
+		.value( "FILL",  polygon_mode::fill_type::FILL )
+		;
+
+	db->create_type<polygon_mode>()
+		.field( "fill", &polygon_mode::fill )
+		;
+
+	db->create_type<blending::factor>()
+		.value( "ZERO",                     blending::factor::ZERO )
+		.value( "ONE",                      blending::factor::ONE )
+		.value( "SRC_COLOR",                blending::factor::SRC_COLOR )
+		.value( "SRC_ALPHA",                blending::factor::SRC_ALPHA )
+		.value( "DST_COLOR",                blending::factor::DST_COLOR )
+		.value( "DST_ALPHA",                blending::factor::DST_ALPHA )
+		.value( "CONSTANT_COLOR",           blending::factor::CONSTANT_COLOR )
+		.value( "CONSTANT_ALPHA",           blending::factor::CONSTANT_ALPHA )
+		.value( "ONE_MINUS_SRC_COLOR",      blending::factor::ONE_MINUS_SRC_COLOR )
+		.value( "ONE_MINUS_SRC_ALPHA",      blending::factor::ONE_MINUS_SRC_ALPHA )
+		.value( "ONE_MINUS_DST_COLOR",      blending::factor::ONE_MINUS_DST_COLOR )
+		.value( "ONE_MINUS_DST_ALPHA",      blending::factor::ONE_MINUS_DST_ALPHA )
+		.value( "ONE_MINUS_CONSTANT_COLOR", blending::factor::ONE_MINUS_CONSTANT_COLOR )
+		.value( "ONE_MINUS_CONSTANT_ALPHA", blending::factor::ONE_MINUS_CONSTANT_ALPHA )
+		.value( "SRC_ALPHA_SATURATE",       blending::factor::SRC_ALPHA_SATURATE )
+		;
+
+	db->create_type<blending::equation>()
+		.value( "ADD",              blending::equation::ADD )
+		.value( "MINIMUM",          blending::equation::MINIMUM )
+		.value( "MAXIMUM",          blending::equation::MAXIMUM )
+		.value( "SUBTRACT",         blending::equation::SUBTRACT )
+		.value( "REVERSE_SUBTRACT", blending::equation::REVERSE_SUBTRACT )
+		;
+
+	db->create_type<blending>()
+		.field( "enabled",          &blending::enabled )
+		.field( "src_rgb_factor",   &blending::src_rgb_factor )
+		.field( "src_alpha_factor", &blending::src_alpha_factor )
+		.field( "dst_rgb_factor",   &blending::dst_rgb_factor )
+		.field( "dst_alpha_factor", &blending::dst_alpha_factor )
+		.field( "rgb_equation",     &blending::rgb_equation )
+		.field( "alpha_equation",   &blending::alpha_equation )
+		.field( "color",            &blending::color )
+		;
+
+	db->create_type<stencil_test_face::operation>()
+		.value( "ZERO",           stencil_test_face::operation::ZERO )
+		.value( "INVERT",         stencil_test_face::operation::INVERT )
+		.value( "KEEP",           stencil_test_face::operation::KEEP )
+		.value( "REPLACE",        stencil_test_face::operation::REPLACE )
+		.value( "INCREMENT",      stencil_test_face::operation::INCREMENT )
+		.value( "DECREMENT",      stencil_test_face::operation::DECREMENT )
+		.value( "INCREMENT_WRAP", stencil_test_face::operation::INCREMENT_WRAP )
+		.value( "DECREMENT_WRAP", stencil_test_face::operation::DECREMENT_WRAP )
+		;
+
+	db->create_type<stencil_test_face::function_type>()
+		.value( "NEVER",            stencil_test_face::function_type::NEVER )
+		.value( "LESS",             stencil_test_face::function_type::LESS )
+		.value( "EQUAL",            stencil_test_face::function_type::EQUAL )
+		.value( "LESS_OR_EQUAL",    stencil_test_face::function_type::LESS_OR_EQUAL )
+		.value( "GREATER",          stencil_test_face::function_type::GREATER )
+		.value( "NOT_EQUAL",        stencil_test_face::function_type::NOT_EQUAL )
+		.value( "GREATER_OR_EQUAL", stencil_test_face::function_type::GREATER_OR_EQUAL )
+		.value( "ALWAYS",           stencil_test_face::function_type::ALWAYS )
+		;
+
+	db->create_type<stencil_test_face>()
+		.field( "op_fail",       &stencil_test_face::op_fail )
+		.field( "op_depth_pass", &stencil_test_face::op_depth_pass )
+		.field( "op_depth_fail", &stencil_test_face::op_depth_fail )
+		.field( "function",      &stencil_test_face::function )
+		.field( "ref_value",     &stencil_test_face::ref_value )
+		.field( "mask",          &stencil_test_face::mask )
+		;
+
+	db->create_type<stencil_test>()
+		.field( "enabled",       &stencil_test::enabled )
+		.field( "front_face",    &stencil_test::front_face )
+		.field( "back_face",     &stencil_test::back_face )
+		;
+
+	db->create_type<culling::face_type>()
+		.value( "FRONT",          culling::face_type::FRONT )
+		.value( "BACK",           culling::face_type::BACK )
+		.value( "FRONT_AND_BACK", culling::face_type::FRONT_AND_BACK )
+		;
+
+	db->create_type<culling::order_type>()
+		.value( "CW",  culling::order_type::CW )
+		.value( "CCW", culling::order_type::CCW )
+		;
+
+	db->create_type<culling>()
+		.field( "enabled", &culling::enabled )
+		.field( "face",    &culling::face )
+		.field( "order",   &culling::order )
+		;
+
+	db->create_type<depth_range>()
+		.field( "near", &depth_range::near )
+		.field( "far",  &depth_range::far )
+		;
+
+	db->create_type<render_state>()
+		.field( "stencil_test", &render_state::stencil_test )
+		.field( "depth_test",   &render_state::depth_test )
+		.field( "scissor_test", &render_state::scissor_test )
+		.field( "depth_range",  &render_state::depth_range )
+		.field( "blending",     &render_state::blending )
+		.field( "culling",      &render_state::culling )
+		.field( "color_mask",   &render_state::color_mask )
+		.field( "polygon_mode", &render_state::polygon_mode )
+		.field( "multisample",  &render_state::multisample )
+		.field( "depth_mask",   &render_state::depth_mask )
+		;
+}
+
Index: trunk/src/gfx/mesh_creator.cc
===================================================================
--- trunk/src/gfx/mesh_creator.cc	(revision 502)
+++ trunk/src/gfx/mesh_creator.cc	(revision 503)
@@ -88,14 +88,14 @@
 
 
-void nv::mesh_data_creator::transform( float scale, const mat3& r33 )
-{
-	vec3 vertex_offset     = vec3(); 
-	mat3 vertex_transform  = scale * r33;
-	mat3 normal_transform  = r33;
+void nv::mesh_data_creator::transform( const vec3& pos, const mat3& r33, float scale /*= 1.0f */ )
+{
+	vec3 vertex_offset = pos;
+	mat3 vertex_transform = scale * r33;
+	mat3 normal_transform = r33;
 
 	for ( uint32 c = 0; c < m_data->size(); ++c )
 	{
 		raw_data_channel_access channel( m_data, c );
-		const data_descriptor&  desc    = channel.descriptor();
+		const data_descriptor&  desc = channel.descriptor();
 		uint8* raw_data = channel.raw_data();
 		uint32 vtx_size = desc.element_size();
@@ -103,15 +103,15 @@
 		int n_offset = -1;
 		int t_offset = -1;
-		for ( const auto& cslot : desc  )
+		for ( const auto& cslot : desc )
 			switch ( cslot.vslot )
 			{
-				case slot::POSITION : if ( cslot.etype == FLOAT_VECTOR_3 ) p_offset = int( cslot.offset ); break;
-				case slot::NORMAL   : if ( cslot.etype == FLOAT_VECTOR_3 ) n_offset = int( cslot.offset ); break;
-				case slot::TANGENT  : if ( cslot.etype == FLOAT_VECTOR_4 ) t_offset = int( cslot.offset ); break;
-				default             : break;
+			case slot::POSITION: if ( cslot.etype == FLOAT_VECTOR_3 ) p_offset = int( cslot.offset ); break;
+			case slot::NORMAL: if ( cslot.etype == FLOAT_VECTOR_3 ) n_offset = int( cslot.offset ); break;
+			case slot::TANGENT: if ( cslot.etype == FLOAT_VECTOR_4 ) t_offset = int( cslot.offset ); break;
+			default: break;
 			}
 
 		if ( p_offset != -1 )
-			for ( uint32 i = 0; i < channel.size(); i++)
+			for ( uint32 i = 0; i < channel.size(); i++ )
 			{
 				vec3& p = *reinterpret_cast<vec3*>( raw_data + vtx_size*i + p_offset );
@@ -120,5 +120,5 @@
 
 		if ( n_offset != -1 )
-			for ( uint32 i = 0; i < channel.size(); i++)
+			for ( uint32 i = 0; i < channel.size(); i++ )
 			{
 				vec3& n = *reinterpret_cast<vec3*>( raw_data + vtx_size*i + n_offset );
@@ -126,11 +126,12 @@
 			}
 		if ( t_offset != -1 )
-			for ( uint32 i = 0; i < channel.size(); i++)
-			{
-				vec4& t = *reinterpret_cast<vec4*>(raw_data + vtx_size*i + t_offset );
-				t = vec4( math::normalize( normal_transform * vec3(t) ), t[3] );
-			}
-	}
-}
+			for ( uint32 i = 0; i < channel.size(); i++ )
+			{
+				vec4& t = *reinterpret_cast<vec4*>( raw_data + vtx_size*i + t_offset );
+				t = vec4( math::normalize( normal_transform * vec3( t ) ), t[3] );
+			}
+	}
+}
+
 
 struct vertex_g
Index: trunk/src/gl/gl_context.cc
===================================================================
--- trunk/src/gl/gl_context.cc	(revision 502)
+++ trunk/src/gl/gl_context.cc	(revision 503)
@@ -201,5 +201,5 @@
 }
 
-void nv::gl_context::blit( framebuffer f, clear_state::buffers_type mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 )
+void nv::gl_context::blit( framebuffer f, buffer_mask mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 )
 {
 	gl_framebuffer_info* info  = m_framebuffers.get( f );
@@ -207,5 +207,5 @@
 	{
 		glBindFramebuffer( GL_FRAMEBUFFER, info->glid );
-		unsigned filter = mask == clear_state::COLOR_BUFFER ? GL_LINEAR : GL_NEAREST;
+		unsigned filter = mask == buffer_mask::COLOR_BUFFER ? GL_LINEAR : GL_NEAREST;
 		glBlitFramebuffer( src1.x, src1.y, src2.x, src2.y, dst1.x, dst1.y, dst2.x, dst2.y, clear_state_buffers_to_mask( mask ), filter );
 	}
@@ -213,5 +213,5 @@
 
 
-void nv::gl_context::blit( framebuffer from, framebuffer to, clear_state::buffers_type mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 )
+void nv::gl_context::blit( framebuffer from, framebuffer to, buffer_mask mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 )
 {
 	gl_framebuffer_info* finfo = m_framebuffers.get( from );
@@ -221,5 +221,5 @@
 		glBindFramebuffer( GL_READ_FRAMEBUFFER, finfo->glid );
 		glBindFramebuffer( GL_DRAW_FRAMEBUFFER, tinfo ? tinfo->glid : 0 );
-		unsigned filter = mask == clear_state::COLOR_BUFFER ? GL_LINEAR : GL_NEAREST;
+		unsigned filter = mask == buffer_mask::COLOR_BUFFER ? GL_LINEAR : GL_NEAREST;
 		glBlitFramebuffer( src1.x, src1.y, src2.x, src2.y, dst1.x, dst1.y, dst2.x, dst2.y, clear_state_buffers_to_mask( mask ), filter );
 		glBindFramebuffer( GL_READ_FRAMEBUFFER, 0 );
Index: trunk/src/gl/gl_enum.cc
===================================================================
--- trunk/src/gl/gl_enum.cc	(revision 502)
+++ trunk/src/gl/gl_enum.cc	(revision 503)
@@ -28,10 +28,10 @@
 }
 
-unsigned int nv::clear_state_buffers_to_mask( clear_state::buffers_type type )
+unsigned int nv::clear_state_buffers_to_mask( buffer_mask type )
 {
 	unsigned int mask = 0;
-	if ( (type & clear_state::COLOR_BUFFER) != 0 )   mask |= GL_COLOR_BUFFER_BIT;
-	if ( (type & clear_state::DEPTH_BUFFER) != 0 )   mask |= GL_DEPTH_BUFFER_BIT;
-	if ( (type & clear_state::STENCIL_BUFFER) != 0 ) mask |= GL_STENCIL_BUFFER_BIT;
+	if ( (type & buffer_mask::COLOR_BUFFER) != 0 )   mask |= GL_COLOR_BUFFER_BIT;
+	if ( (type & buffer_mask::DEPTH_BUFFER) != 0 )   mask |= GL_DEPTH_BUFFER_BIT;
+	if ( (type & buffer_mask::STENCIL_BUFFER) != 0 ) mask |= GL_STENCIL_BUFFER_BIT;
 	return mask;
 }
Index: trunk/src/lua/lua_area.cc
===================================================================
--- trunk/src/lua/lua_area.cc	(revision 502)
+++ 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 502)
+++ 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 502)
+++ 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 502)
+++ 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 502)
+++ 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 502)
+++ 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
+
+
+	
+}
+*/
