Index: trunk/src/lua/lua_glm.cc
===================================================================
--- trunk/src/lua/lua_glm.cc	(revision 53)
+++ trunk/src/lua/lua_glm.cc	(revision 53)
@@ -0,0 +1,344 @@
+// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+
+#include "nv/lua/lua_glm.hh"
+#include "nv/types.hh"
+#include "nv/string.hh"
+#include <new>
+
+static size_t nlua_swizzel_lookup[256];
+
+inline bool nlua_is_swizzel( const char* str, size_t max )
+{
+	while (*str)
+	{
+		if (nlua_swizzel_lookup[*str] > max) return false;
+		str++;
+	}
+	return true;
+}
+
+template < typename T, size_t k >
+struct nlua_vec_constructor {
+	static inline T construct( lua_State* L, int index ) {
+		return T();
+	}
+};
+
+template < typename T > struct nlua_vec_constructor< T, 1 > {
+	static inline T construct( lua_State* L, int index ) {
+		return T( lua_tonumber( L, index ) );
+	}
+};
+
+template < typename T > struct nlua_vec_constructor< T, 2 > {
+	static inline T construct( lua_State* L, int index ) {
+		if ( lua_type( L, index ) == LUA_TUSERDATA )
+			return nlua_to_vec<T>( L, index );
+		else
+			return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ) );
+	}
+};
+
+template < typename T > struct nlua_vec_constructor< T, 3 > {
+	static inline T construct( lua_State* L, int index ) {
+		typedef glm::detail::tvec2<T::value_type> vec2;
+		if ( lua_type( L, index ) == LUA_TUSERDATA )
+		{
+			if ( nlua_is_vec<T>( L, index ) )
+				return nlua_to_vec<T>( L, index );
+			else
+				return T( nlua_to_vec<vec2>( L, index ), lua_tonumber( L, index + 1 ) );
+		}
+		else
+		{
+			if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
+				return T( lua_tonumber( L, index ), nlua_to_vec<vec2>( L, index+1 ) );
+			else
+				return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ), lua_tonumber( L, index + 2 ) );
+		}
+	}
+};
+
+template < typename T > struct nlua_vec_constructor< T, 4 > {
+	static inline T construct( lua_State* L, int index ) {
+		typedef glm::detail::tvec2<T::value_type> vec2;
+		typedef glm::detail::tvec3<T::value_type> vec3;
+		if ( lua_type( L, index ) == LUA_TUSERDATA )
+		{
+			if ( nlua_is_vec<T>( L, index ) )
+				return nlua_to_vec<T>( L, index );
+			else
+			{
+				if ( nlua_is_vec<vec3>( L, index ) )
+					return T( nlua_to_vec<vec3>( L, index ), lua_tonumber( L, index + 1 ) );
+				else
+				{
+					if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
+						return T( nlua_to_vec<vec2>( L, index ), nlua_to_vec<vec2>( L, index + 1 ) );
+					else
+						return T( nlua_to_vec<vec2>( L, index ), lua_tonumber( L, index + 1 ), lua_tonumber( L, index + 2 ) );
+				}
+			}
+		}
+		else
+		{
+			if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
+			{
+				if ( nlua_is_vec<vec3>( L, index+1 ) )
+					return T( lua_tonumber( L, index ), nlua_to_vec<vec3>( L, index+1 ) );
+				else
+					return T( lua_tonumber( L, index ), nlua_to_vec<vec2>( L, index+1 ), lua_tonumber( L, index + 2 ) );
+			}
+			else
+			{
+				if ( lua_type( L, index+2 ) == LUA_TUSERDATA )
+					return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ), nlua_to_vec<vec2>( L, index+2 ) );
+				else
+					return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ), lua_tonumber( L, index + 2 ), lua_tonumber( L, index + 3 ) );
+			}
+		}
+	}
+};
+
+template< typename T >
+int nlua_vec_new( lua_State* L )
+{
+	nlua_push_vec( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( T::value_type )>::construct( L, 1 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_call( lua_State* L )
+{
+	nlua_push_vec( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( T::value_type )>::construct( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+static int nlua_vec_unm( lua_State* L )
+{
+	nlua_push_vec<T>( L, -nlua_to_vec<T>( L, 1 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_add( lua_State* L )
+{
+	if ( lua_type( L, 1 ) == LUA_TNUMBER )
+		nlua_push_vec<T>( L, (T::value_type)(lua_tonumber( L, 1 )) + nlua_to_vec<T>( L, 2 ) );
+	else
+		if ( lua_type( L, 2 ) == LUA_TNUMBER )
+			nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) + (T::value_type)(lua_tonumber( L, 2 )) );
+		else
+			nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) + nlua_to_vec<T>( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_sub( lua_State* L )
+{
+	if ( lua_type( L, 1 ) == LUA_TNUMBER )
+		nlua_push_vec<T>( L, (T::value_type)(lua_tonumber( L, 1 )) - nlua_to_vec<T>( L, 2 ) );
+	else
+		if ( lua_type( L, 2 ) == LUA_TNUMBER )
+			nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) - (T::value_type)(lua_tonumber( L, 2 )) );
+		else
+			nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) - nlua_to_vec<T>( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_mul( lua_State* L )
+{
+	if ( lua_type( L, 1 ) == LUA_TNUMBER )
+		nlua_push_vec<T>( L, (T::value_type)(lua_tonumber( L, 1 )) * nlua_to_vec<T>( L, 2 ) );
+	else
+		if ( lua_type( L, 2 ) == LUA_TNUMBER )
+			nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) * (T::value_type)(lua_tonumber( L, 2 )) );
+		else
+			nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) * nlua_to_vec<T>( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_div( lua_State* L )
+{
+	if ( lua_type( L, 1 ) == LUA_TNUMBER )
+		nlua_push_vec<T>( L, (T::value_type)(lua_tonumber( L, 1 )) / nlua_to_vec<T>( L, 2 ) );
+	else
+		if ( lua_type( L, 2 ) == LUA_TNUMBER )
+			nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) / (T::value_type)(lua_tonumber( L, 2 )) );
+		else
+			nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) / nlua_to_vec<T>( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_eq( lua_State* L )
+{
+	lua_pushboolean( L, nlua_to_vec<T>( L, 1 ) == nlua_to_vec<T>( L, 2 ) );
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_get( lua_State* L )
+{
+	T v = nlua_to_vec<T>( L, 1 );
+	for ( size_t i = 0; i < v.length(); ++i )
+	{
+		lua_pushnumber( L, v[i] );
+	}
+	return v.length();
+}
+
+template< typename T >
+int nlua_vec_index( lua_State* L )
+{
+	T* v = nlua_to_pvec<T>( L, 1 );
+	size_t len  = 0;
+	size_t vlen = v->length();
+	const char * key = lua_tolstring( L, 2, &len );
+	size_t idx = 255;
+
+	if( len == 1 )
+	{
+		idx = nlua_swizzel_lookup[ key[ 0 ] ];
+		if ( idx < vlen )
+		{
+			lua_pushnumber( L, (*v)[idx] );
+			return 1;
+		}
+	}
+	else if ( len < 4 && nlua_is_swizzel(key,vlen-1) )
+	{
+		switch (len) {
+		case 2 : nlua_push_vec( L, glm::detail::tvec2<T::value_type>( (*v)[nlua_swizzel_lookup[key[0]]], (*v)[nlua_swizzel_lookup[key[1]]] ) ); return 1;
+		case 3 : nlua_push_vec( L, glm::detail::tvec3<T::value_type>( (*v)[nlua_swizzel_lookup[key[0]]], (*v)[nlua_swizzel_lookup[key[1]]], (*v)[nlua_swizzel_lookup[key[2]]] ) ); return 1;
+		case 4 : nlua_push_vec( L, glm::detail::tvec4<T::value_type>( (*v)[nlua_swizzel_lookup[key[0]]], (*v)[nlua_swizzel_lookup[key[1]]], (*v)[nlua_swizzel_lookup[key[2]]], (*v)[nlua_swizzel_lookup[key[3]]] ) ); return 1;
+		default: break;
+		}
+	}
+
+	lua_getglobal( L, nv::get_type_name<T>() );
+	lua_pushvalue( L, -2 );
+	lua_rawget( L, -2 );
+
+	return 1;
+}
+
+template< typename T >
+int nlua_vec_newindex( lua_State* L )
+{
+	typedef glm::detail::tvec2<T::value_type> vec2;
+	typedef glm::detail::tvec3<T::value_type> vec3;
+	typedef glm::detail::tvec4<T::value_type> vec4;
+
+	T* v = nlua_to_pvec<T>( L, 1 );
+	size_t len  = 0;
+	size_t vlen = v->length();
+	const char * key = lua_tolstring( L, 2, &len );
+	size_t idx = 255;
+	if( len == 1 )
+	{
+		idx = nlua_swizzel_lookup[ key[ 0 ] ];
+		if ( idx < vlen )
+		{
+			(*v)[idx] = (T::value_type)luaL_checknumber( L, 3 );
+			return 0;
+		}
+	}
+	else if ( len < 4 && nlua_is_swizzel(key,vlen-1) )
+	{
+ 		switch (len) {
+		case 2 : { vec2 v2 = nlua_to_vec<vec2>(L,3); for (size_t i = 0; i<len; ++i) (*v)[nlua_swizzel_lookup[key[i]]] = v2[i]; } return 0;
+		case 3 : { vec3 v3 = nlua_to_vec<vec3>(L,3); for (size_t i = 0; i<len; ++i) (*v)[nlua_swizzel_lookup[key[i]]] = v3[i]; } return 0;
+		case 4 : { vec4 v4 = nlua_to_vec<vec4>(L,3); for (size_t i = 0; i<len; ++i) (*v)[nlua_swizzel_lookup[key[i]]] = v4[i]; } return 0;
+ 		default: break;
+		}
+	}
+	return 0;
+}
+
+template< typename T >
+static int nlua_vec_tostring( lua_State* L )
+{
+	T v = nlua_to_vec<T>( L, 1 );
+	std::string s = "(";
+	for ( size_t i = 0; i < v.length(); ++i )
+	{
+		if (i > 0) s += ",";
+		s += nv::to_string(v[i]);
+	}
+	s+=")";
+	lua_pushstring( L, s.c_str() );
+	return 1;
+}
+
+template< typename T >
+int luaopen_vec( lua_State * L )
+{
+	static const struct luaL_Reg nlua_vec_f [] = {
+		{ "new",            nlua_vec_new<T> },
+		{ "get",            nlua_vec_get<T> },
+		{NULL, NULL}
+	};
+
+	static const struct luaL_Reg nlua_vec_fm [] = {
+		{ "__call",         nlua_vec_call<T> },
+		{NULL, NULL}
+	};
+
+	static const struct luaL_Reg nlua_vec_m [] = {
+		{ "__add",      nlua_vec_add<T> },
+		{ "__sub",      nlua_vec_sub<T> },
+		{ "__unm",      nlua_vec_unm<T> },
+		{ "__mul",      nlua_vec_mul<T> },
+		{ "__div",      nlua_vec_div<T> },
+		{ "__eq",       nlua_vec_eq<T> },
+		{ "__index",    nlua_vec_index<T> },
+		{ "__newindex", nlua_vec_newindex<T> },
+		{ "__tostring", nlua_vec_tostring<T> },
+		{NULL, NULL}
+	};
+
+	luaL_newmetatable( L, nv::get_type_name<T>() );
+	luaL_setfuncs( L, nlua_vec_m, 0 );
+	lua_pop(L,1);
+	luaL_newlib(L, nlua_vec_f);
+	lua_newtable( L );
+	luaL_setfuncs( L, nlua_vec_fm, 0 );
+	lua_setmetatable( L, -2 );
+	return 1;
+}
+
+void nlua_register_glm( lua_State* L )
+{ 
+	for (size_t i = 0; i < 256; ++i ) nlua_swizzel_lookup[i] = 255;
+	nlua_swizzel_lookup['x'] = 0;
+	nlua_swizzel_lookup['r'] = 0;
+	nlua_swizzel_lookup['s'] = 0;
+	nlua_swizzel_lookup['0'] = 0;
+	nlua_swizzel_lookup['y'] = 1;
+	nlua_swizzel_lookup['g'] = 1;
+	nlua_swizzel_lookup['t'] = 0;
+	nlua_swizzel_lookup['1'] = 1;
+	nlua_swizzel_lookup['z'] = 2;
+	nlua_swizzel_lookup['b'] = 2;
+	nlua_swizzel_lookup['u'] = 0;
+	nlua_swizzel_lookup['2'] = 2;
+	nlua_swizzel_lookup['w'] = 3;
+	nlua_swizzel_lookup['a'] = 3;
+	nlua_swizzel_lookup['v'] = 0;
+	nlua_swizzel_lookup['3'] = 3;
+	luaL_requiref(L, "ivec2", luaopen_vec<glm::ivec2>, 1);
+	luaL_requiref(L, "ivec3", luaopen_vec<glm::ivec3>, 1);
+	luaL_requiref(L, "ivec4", luaopen_vec<glm::ivec4>, 1);
+	luaL_requiref(L, "vec2", luaopen_vec<glm::vec2>, 1);
+	luaL_requiref(L, "vec3", luaopen_vec<glm::vec3>, 1);
+	luaL_requiref(L, "vec4", luaopen_vec<glm::vec4>, 1);
+}
+
