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
+
+
+	
+}
+*/
