Index: /trunk/nv/lua/lua_area.hh
===================================================================
--- /trunk/nv/lua/lua_area.hh	(revision 207)
+++ /trunk/nv/lua/lua_area.hh	(revision 208)
@@ -39,4 +39,5 @@
 			static void push( lua_State *L, const rectangle& p ) { detail::push_area( L, p ); }
 			static void pop( lua_State *L, rectangle& p ) { p = detail::to_area( L, -1 ); detail::pop_and_discard( L, 1 ); }
+			static rectangle to( lua_State *L, int index ) { return detail::to_area( L, index ); }
 		};
 	}
Index: /trunk/nv/lua/lua_glm.hh
===================================================================
--- /trunk/nv/lua/lua_glm.hh	(revision 207)
+++ /trunk/nv/lua/lua_glm.hh	(revision 208)
@@ -41,4 +41,10 @@
 
 			template< typename T >
+			T to_vec( lua_State* L, int index, const T& def )
+			{
+				return ( is_vec<T>( L, index ) ? *(T*)to_pointer( L, index ) : def );
+			}
+
+			template< typename T >
 			T* to_pvec( lua_State* L, int index )
 			{
@@ -58,5 +64,6 @@
 			typedef glm::detail::tvec2<T> value_type;
 			static void push( lua_State *L, const value_type& p ) { detail::push_vec< value_type >( L, p ); }
-			static void pop( lua_State *L, value_type& p ) { p = detail::to_vec< value_type >( L, -1 ); detail::pop_and_discard( L, 1 ); }
+			static value_type to( lua_State *L, int index ) { return detail::to_vec< value_type >( L, index ); }
+			static value_type to( lua_State *L, int index, const value_type& def ) { return detail::to_vec< value_type >( L, index, def ); }
 		};
 
@@ -66,5 +73,6 @@
 			typedef glm::detail::tvec3<T> value_type;
 			static void push( lua_State *L, const value_type& p ) { detail::push_vec< value_type >( L, p ); }
-			static void pop( lua_State *L, value_type& p ) { p = detail::to_vec< value_type >( L, -1 ); detail::pop_and_discard( L, 1 ); }
+			static value_type to( lua_State *L, int index ) { return detail::to_vec< value_type >( L, index ); }
+			static value_type to( lua_State *L, int index, const value_type& def ) { return detail::to_vec< value_type >( L, index, def ); }
 		};
 
@@ -74,5 +82,6 @@
 			typedef glm::detail::tvec4<T> value_type;
 			static void push( lua_State *L, const value_type& p ) { detail::push_vec< value_type >( L, p ); }
-			static void pop( lua_State *L, value_type& p ) { p = detail::to_vec< value_type >( L, -1 ); detail::pop_and_discard( L, 1 ); }
+			static value_type to( lua_State *L, int index ) { return detail::to_vec< value_type >( L, index ); }
+			static value_type to( lua_State *L, int index, const value_type& def ) { return detail::to_vec< value_type >( L, index, def ); }
 		};
 	}
Index: /trunk/nv/lua/lua_values.hh
===================================================================
--- /trunk/nv/lua/lua_values.hh	(revision 207)
+++ /trunk/nv/lua/lua_values.hh	(revision 208)
@@ -8,6 +8,6 @@
 #define NV_LUA_VALUES_HH
 
-#include <type_traits>
 #include <nv/common.hh>
+#include <nv/type_traits.hh>
 #include <nv/string.hh>
 
@@ -18,5 +18,9 @@
 	namespace lua
 	{
-		struct passer
+		typedef ptrdiff_t     linteger;
+		typedef unsigned long lunsigned;
+		typedef double        lnumber;
+
+ 		struct passer
 		{
 			virtual void push( lua_State *L ) const = 0;
@@ -24,15 +28,14 @@
 		};
 
-		struct returner_base
-		{
-			virtual void pop( lua_State *L ) = 0;
-			virtual ~returner_base(){}
-		};
-
 		template < typename T >
-		struct returner : public returner_base
-		{
+		struct returner
+		{
+			returner( lua_State *, int ) : value() {}
+			returner( lua_State *, int, const T& ) : value() {}
 			operator T() { return value; }
 			operator const T() const { return value; }
+			virtual returner<T> to( lua_State *L, int index ) = 0;
+			virtual returner<T> to( lua_State *L, int index, const T& def ) = 0;
+			virtual ~returner(){}
 		protected:
 			T value;
@@ -43,28 +46,160 @@
 		{
 			static void push( lua_State *L, const T& p ) { p.push( L ); }
-			static void pop( lua_State *L, T& p ) { p.pop( L ); }
+			static T to( lua_State *L, int index ) { return T( L, index ); }
+			static T to( lua_State *L, int index, const T& def ) { return T( L, index, def ); }
 		};
 
 		namespace detail
 		{
-			void push_value( lua_State *L, long n );
-			void push_value( lua_State *L, double n );
-			void push_value( lua_State *L, bool n );
-			void push_value( lua_State *L, const std::string& s );
-			void push_value( lua_State *L, const char* s );
-			void push_value( lua_State *L, object* o );
-			void push_value( lua_State *L, void* p );
-
-			template< typename D >
-			typename std::enable_if<std::is_base_of<object, D>::value>::type
-				push_value( lua_State *L, D* o )
-			{
-				push_value( L, (object*)o );
-			}
+			void push_unsigned( lua_State *L, lunsigned v );
+			void push_integer ( lua_State *L, linteger v );
+			void push_number  ( lua_State *L, lnumber v );
+			void push_bool    ( lua_State *L, bool v );
+			void push_string  ( lua_State *L, const std::string& s );
+			void push_cstring ( lua_State *L, const char* s );
+			void push_object  ( lua_State *L, object* o );
+			void push_pointer ( lua_State *L, void* p );
+
+			lunsigned   to_unsigned( lua_State *L, int index );
+			linteger    to_integer ( lua_State *L, int index );
+			lnumber     to_number  ( lua_State *L, int index );
+			bool        to_bool    ( lua_State *L, int index );
+			std::string to_string  ( lua_State *L, int index );
+			const char* to_cstring ( lua_State *L, int index );
+			object*     to_object  ( lua_State *L, int index );
+			void*       to_pointer ( lua_State *L, int index );
+
+			lunsigned   to_unsigned( lua_State *L, int index, lunsigned def );
+			linteger    to_integer ( lua_State *L, int index, linteger def );
+			lnumber     to_number  ( lua_State *L, int index, lnumber def );
+			bool        to_bool    ( lua_State *L, int index, bool def );
+			std::string to_string  ( lua_State *L, int index, const std::string& def );
+			const char* to_cstring ( lua_State *L, int index, const char* def );
+			object*     to_object  ( lua_State *L, int index, object* def );
+			void*       to_pointer ( lua_State *L, int index, void* def );
+
+			void pop_and_discard( lua_State *L, int count );
+			bool is_userdata( lua_State *L, int index, const char* metatable );
+			void* check_userdata( lua_State *L, int index, const char* metatable );
+			void* allocate_userdata( lua_State *L, size_t size, const char* metatable );
+			template <typename T>
+			void push_userdata( lua_State *L, const T& v, const char* metatable )
+			{
+				new (allocate_userdata(L, sizeof(T), metatable)) T(v);
+			}
+		}
+
+		template <>
+		struct pass_traits<linteger>
+		{
+			static void push( lua_State *L, linteger s ) { detail::push_integer( L, s ); }
+			static linteger to( lua_State *L, int index ) { return detail::to_integer( L, index ); }
+			static linteger to( lua_State *L, int index, linteger def ) { return detail::to_integer( L, index, def ); }
+		};
+
+		template <>
+		struct pass_traits<lunsigned>
+		{
+			static void push( lua_State *L, lunsigned s ) { detail::push_unsigned( L, s ); }
+			static lunsigned to( lua_State *L, int index ) { return detail::to_unsigned( L, index ); }
+			static lunsigned to( lua_State *L, int index, lunsigned def ) { return detail::to_unsigned( L, index, def ); }
+		};
+
+		template <>
+		struct pass_traits<lnumber>
+		{
+			static void push( lua_State *L, lnumber s ) { detail::push_number( L, s ); }
+			static lnumber to( lua_State *L, int index ) { return detail::to_number( L, index ); }
+			static lnumber to( lua_State *L, int index, lnumber def ) { return detail::to_number( L, index, def ); }
+		};
+
+		template <>
+		struct pass_traits<bool>
+		{
+			static void push( lua_State *L, bool s ) { detail::push_bool( L, s ); }
+			static bool to( lua_State *L, int index ) { return detail::to_bool( L, index ); }
+			static bool to( lua_State *L, int index, bool def ) { return detail::to_bool( L, index, def ); }
+		};
+
+		template <>
+		struct pass_traits<const char*>
+		{
+			static void push( lua_State *L, const char* s ) { detail::push_cstring( L, s ); }
+			static const char* to( lua_State *L, int index ) { return detail::to_cstring( L, index ); }
+			static const char* to( lua_State *L, int index, const char* def ) { return detail::to_cstring( L, index, def ); }
+		};
+
+		template <>
+		struct pass_traits<std::string>
+		{
+			static void push( lua_State *L, const std::string& s ) { detail::push_string( L, s ); }
+			static std::string to( lua_State *L, int index ) { return detail::to_string( L, index ); }
+			static std::string to( lua_State *L, int index, const std::string& def ) { return detail::to_string( L, index, def ); }
+		};
+
+		template <>
+		struct pass_traits<object*>
+		{
+			static void push( lua_State *L, object* o ) { detail::push_object( L, o ); }
+			static object* to( lua_State *L, int index ) { return detail::to_object( L, index ); }
+			static object* to( lua_State *L, int index, object* def ) { return detail::to_object( L, index, def ); }
+		};
+
+		namespace detail
+		{
+
+			template <typename T, class ENABLE = void >
+			struct type_degrade
+			{
+				typedef T type;
+			};
+
+			template <typename T>
+			struct type_degrade< T, typename std::enable_if< std::is_floating_point< T >::value >::type >
+			{
+				typedef lnumber type;
+			};
+
+			template <typename T>
+			struct type_degrade< T, typename std::enable_if< std::is_integral< T >::value && std::is_signed< T >::value >::type >
+			{
+				typedef linteger type;
+			};
+
+			template <typename T>
+			struct type_degrade< T, typename std::enable_if< std::is_integral< T >::value && std::is_unsigned< T >::value >::type >
+			{
+				typedef lunsigned type;
+			};
+
+			template <typename T>
+			struct type_degrade< T, typename std::enable_if< is_cstring< T >::value >::type >
+			{
+				typedef const char* type;
+			};
+
+			template <typename T>
+			struct type_degrade< T, typename std::enable_if< is_stdstring< T >::value >::type >
+			{
+				typedef std::string type;
+			};
+
+			template <typename T>
+			struct type_degrade< T*, typename std::enable_if< std::is_base_of<object, T >::value >::type >
+			{
+				typedef object* type;
+			};
+
+			template <>
+			struct type_degrade< bool >
+			{
+				typedef bool type;
+			};
 
  			template < typename T >
  			void push_value( lua_State *L, const T& p )
  			{
- 				pass_traits<T>::push( L, p );
+				typedef typename type_degrade<T>::type degraded;
+ 				pass_traits<degraded>::push( L, p );
  			}
 
@@ -80,21 +215,18 @@
 			void push_values( lua_State *L, const T1& p1, const T2& p2, const T3& p3, const T4& p4, const T5& p5 ) { push_value( L, p1 ); push_value( L, p2 ); push_value( L, p3 ); push_value( L, p4 ); push_value( L, p5 ); }
 
-			void pop_value( lua_State *L, int& n );
-			void pop_value( lua_State *L, long& n );
-			void pop_value( lua_State *L, double& n );
-			void pop_value( lua_State *L, bool& n );
-			void pop_value( lua_State *L, std::string& s );
-			void pop_value( lua_State *L, object*& o );
-			void pop_value( lua_State *L, void*& p );
 			template < typename T >
 			inline void pop_value( lua_State *L, T& p )
 			{
-				pass_traits<T>::pop( L, p );
+				typedef typename type_degrade<T>::type degraded;
+				p = pass_traits<degraded>::to( L, -1 );
+				detail::pop_and_discard(L, 1);
 			}
 			template < typename T >
 			inline T pop_return_value( lua_State *L )
 			{
+				typedef typename type_degrade<T>::type degraded;
 				T ret;
-				pop_value( L, ret );
+				ret = pass_traits<degraded>::to( L, -1 );
+				detail::pop_and_discard(L, 1);
 				return ret;
 			}
@@ -106,4 +238,18 @@
 
 			template < typename T >
+			inline T get_value( lua_State *L, int index )
+			{
+				typedef typename type_degrade<T>::type degraded;
+				return pass_traits<degraded>::to( L, index );
+			}
+
+			template < typename T >
+			inline T get_value( lua_State *L, int index, const T& def )
+			{
+				typedef typename type_degrade<T>::type degraded;
+				return pass_traits<degraded>::to( L, index, def );
+			}
+
+			template < typename T >
 			struct return_count
 			{
@@ -117,14 +263,4 @@
 			};
 
-
-			void pop_and_discard( lua_State *L, int count );
-			bool is_userdata( lua_State *L, int index, const char* metatable );
-			void* check_userdata( lua_State *L, int index, const char* metatable );
-			void* allocate_userdata( lua_State *L, size_t size, const char* metatable );
-			template <typename T>
-			void push_userdata( lua_State *L, const T& v, const char* metatable )
-			{
-				new (allocate_userdata(L, sizeof(T), metatable)) T(v);
-			}
 		}
 
Index: /trunk/nv/type_traits.hh
===================================================================
--- /trunk/nv/type_traits.hh	(revision 207)
+++ /trunk/nv/type_traits.hh	(revision 208)
@@ -18,4 +18,21 @@
 namespace nv
 {
+
+	// These could be done much better
+	template <typename T>
+	struct is_cstring
+		: public std::integral_constant<bool,
+		std::is_same<       char *, typename std::decay< T >::type >::value ||
+		std::is_same< const char *, typename std::decay< T >::type >::value >
+		{};
+
+	template <typename T>
+	struct is_stdstring
+		: public std::integral_constant<bool,
+		std::is_same< std::string, typename std::remove_cv< std::remove_reference< T > >::type >::value 
+		>
+	{};
+
+	template < typename T > struct is_string : public std::integral_constant<bool, is_stdstring<T>::value || is_cstring<T>::value> {};
 
 	// Just for once, MSVC is the good guy, and everybody else sucks.
Index: /trunk/src/lua/lua_values.cc
===================================================================
--- /trunk/src/lua/lua_values.cc	(revision 207)
+++ /trunk/src/lua/lua_values.cc	(revision 208)
@@ -10,97 +10,7 @@
 #include "nv/object.hh"
 
-void nv::lua::detail::push_value( lua_State *L, long n )
-{
-	lua_pushinteger( L, n );
-}
-
-void nv::lua::detail::push_value( lua_State *L, double d )
-{
-	lua_pushnumber( L, d );
-}
-
-void nv::lua::detail::push_value( lua_State *L, bool n )
-{
-	lua_pushboolean( L, n );
-}
-
-void nv::lua::detail::push_value( lua_State *L, const char* s )
-{
-	lua_pushstring( L, s );
-}
-
-void nv::lua::detail::push_value( lua_State *L, const std::string& s )
-{
-	lua_pushstring( L, s.c_str() );
-}
-
-void nv::lua::detail::push_value( lua_State *L, object* o )
-{
-	if ( o == nullptr )
-	{
-		lua_pushnil( L );
-	}
-	else
-	{
-		lua_rawgeti( L, LUA_REGISTRYINDEX, o->get_lua_index() );
-	}
-}
-
-void nv::lua::detail::push_value( lua_State *L, void* p )
-{
-	lua_pushlightuserdata( L, p );
-}
-
-void nv::lua::detail::pop_value( lua_State *L, int& n )
-{
-	n = lua_tointeger( L, -1 );
-	lua_pop( L, 1 );
-}
-
-void nv::lua::detail::pop_value( lua_State *L, long& n )
-{
-	n = lua_tointeger( L, -1 );
-	lua_pop( L, 1 );
-}
-
-void nv::lua::detail::pop_value( lua_State *L, double& d )
-{
-	d = lua_tonumber( L, -1 );
-	lua_pop( L, 1 );
-}
-
-void nv::lua::detail::pop_value( lua_State *L, bool& n )
-{
-	n = lua_toboolean( L, -1 ) != 0;
-	lua_pop( L, 1 );
-}
-
-void nv::lua::detail::pop_value( lua_State *L, std::string& s )
-{
-	s = lua_tostring( L, -1 ); 
-	lua_pop( L, 1 );
-}
-
-void nv::lua::detail::pop_value( lua_State *L, object*& o )
-{
-	o = nullptr;
-	if ( lua_istable( L , -1 ) )
-	{
-		lua_pushstring( L, "__ptr" );
-		lua_rawget( L, -1 );
-		if ( lua_isuserdata( L, -1 ) )
-		{
-			o = (object*)( lua_touserdata( L, -1 ) );
-		} 
-		lua_pop( L, 1 );
-	}
-	lua_pop( L, 1 );
-}
-
-void nv::lua::detail::pop_value( lua_State *L, void*& p )
-{
-	p = lua_touserdata( L, -1 );
-	lua_pop( L, 1 );
-}
+using nv::lua::linteger;
+using nv::lua::lnumber;
+using nv::lua::lunsigned;
 
 bool nv::lua::detail::is_userdata( lua_State *L, int index, const char* metatable )
@@ -126,2 +36,150 @@
 }
 
+void nv::lua::detail::push_unsigned( lua_State *L, lunsigned v )
+{
+	lua_pushunsigned( L, v );
+}
+
+void nv::lua::detail::push_integer ( lua_State *L, linteger v )
+{
+	lua_pushinteger( L, v );
+}
+
+void nv::lua::detail::push_number  ( lua_State *L, lnumber v )
+{
+	lua_pushnumber( L, v );
+}
+
+void nv::lua::detail::push_bool    ( lua_State *L, bool v )
+{
+	lua_pushboolean( L, v );
+}
+
+void nv::lua::detail::push_string  ( lua_State *L, const std::string& s )
+{
+	lua_pushlstring( L, s.c_str(), s.size() );
+}
+
+void nv::lua::detail::push_cstring ( lua_State *L, const char* s )
+{
+	lua_pushstring( L, s );
+}
+
+void nv::lua::detail::push_object  ( lua_State *L, object* o )
+{
+	if ( o == nullptr )
+	{
+		lua_pushnil( L );
+	}
+	else
+	{
+		lua_rawgeti( L, LUA_REGISTRYINDEX, o->get_lua_index() );
+	}
+}
+
+void nv::lua::detail::push_pointer ( lua_State *L, void* p )
+{
+	lua_pushlightuserdata( L, p );
+}
+
+lunsigned   nv::lua::detail::to_unsigned( lua_State *L, int index )
+{
+	return lua_tounsigned( L, index );
+}
+
+linteger    nv::lua::detail::to_integer ( lua_State *L, int index )
+{
+	return lua_tointeger( L, index );
+}
+
+lnumber     nv::lua::detail::to_number  ( lua_State *L, int index )
+{
+	return lua_tonumber( L, index );
+}
+
+bool        nv::lua::detail::to_bool    ( lua_State *L, int index )
+{
+	return lua_toboolean( L, index ) != 0;
+}
+
+std::string nv::lua::detail::to_string  ( lua_State *L, int index )
+{
+	return lua_tostring( L, index );
+}
+
+const char* nv::lua::detail::to_cstring ( lua_State *L, int index )
+{
+	return lua_tostring( L, index );
+}
+
+nv::object* nv::lua::detail::to_object  ( lua_State *L, int index )
+{
+	object* o = nullptr;
+	if ( lua_istable( L , index ) )
+	{
+		lua_pushstring( L, "__ptr" );
+		lua_rawget( L, index );
+		if ( lua_isuserdata( L, -1 ) )
+		{
+			o = static_cast<object*>( lua_touserdata( L, -1 ) );
+		} 
+		lua_pop( L, 1 );
+	}
+	return o;
+}
+
+void*       nv::lua::detail::to_pointer ( lua_State *L, int index )
+{
+	return lua_touserdata( L, index );
+}
+
+lunsigned   nv::lua::detail::to_unsigned( lua_State *L, int index, lunsigned def )
+{
+	return ( lua_type( L, index ) == LUA_TNUMBER ? lua_tounsigned( L, index ) : def );
+}
+
+linteger    nv::lua::detail::to_integer ( lua_State *L, int index, linteger def )
+{
+	return ( lua_type( L, index ) == LUA_TNUMBER ? lua_tointeger( L, index ) : def );
+}
+
+lnumber     nv::lua::detail::to_number  ( lua_State *L, int index, lnumber def )
+{
+	return ( lua_type( L, index ) == LUA_TNUMBER ? lua_tonumber( L, index ) : def );
+}
+
+bool        nv::lua::detail::to_bool    ( lua_State *L, int index, bool def )
+{
+	return ( lua_type( L, index ) == LUA_TBOOLEAN ? lua_toboolean( L, index ) != 0 : def );
+}
+
+std::string nv::lua::detail::to_string  ( lua_State *L, int index, const std::string& def )
+{
+	return ( lua_type( L, index ) == LUA_TSTRING ? lua_tostring( L, index ) : def );
+}
+
+const char* nv::lua::detail::to_cstring ( lua_State *L, int index, const char* def )
+{
+	return ( lua_type( L, index ) == LUA_TSTRING ? lua_tostring( L, index ) : def );
+}
+
+nv::object* nv::lua::detail::to_object  ( lua_State *L, int index, nv::object* def )
+{
+	object* o = def;
+	if ( lua_istable( L , index ) )
+	{
+		lua_pushstring( L, "__ptr" );
+		lua_rawget( L, index );
+		if ( lua_isuserdata( L, -1 ) )
+		{
+			o = static_cast<object*>( lua_touserdata( L, -1 ) );
+		}
+		lua_pop( L, 1 );
+	}
+	return o;
+}
+
+void*       nv::lua::detail::to_pointer ( lua_State *L, int index, void* def )
+{
+	return ( lua_type( L, index ) == LUA_TUSERDATA ? lua_touserdata( L, index ) : def );
+}
