Index: trunk/nv/ecs/component.hh
===================================================================
--- trunk/nv/ecs/component.hh	(revision 549)
+++ trunk/nv/ecs/component.hh	(revision 550)
@@ -59,23 +59,27 @@
 
 			component( ecs_type& a_ecs, string_view a_name, bool relational = false, uint32 reserve = 0 ) 
-				: m_ecs( a_ecs ), m_relational( relational )
-			{
+				: m_ecs( a_ecs ), m_relational( relational ), m_storage( nullptr )
+			{
+				m_storage = new storage_type;
 				m_ecs.register_component<component_type, Handler>( a_name, this );
-
 				if ( reserve != 0 )
 				{
-					m_data.reserve( reserve );
-				}
-			}
-
-			virtual void initialize( handle_type, lua::stack_proxy& ) {};
+					m_storage->reserve( reserve );
+				}
+			}
+
+			virtual uint32 temp_index( handle_type h ) const  final
+			{
+				return m_index.get( h );
+			}
+
 
 			inline value_type& insert( handle_type h )
 			{
 				index_type i = m_index.insert( h );
-				NV_ASSERT( i == index_type( m_data.size() ), "Fail!" );
+				NV_ASSERT( i == index_type( m_storage->size() ), "Fail!" );
 				NV_UNUSED( i );
-				m_data.emplace_back();
-				return m_data.back();
+				m_storage->emplace_back();
+				return m_storage->back();
 			}
 
@@ -84,9 +88,15 @@
 			{
 				index_type i = m_index.insert( h );
-				NV_ASSERT( i == index_type( m_data.size() ), "Fail!" );
+				NV_ASSERT( i == index_type( m_storage->size() ), "Fail!" );
 				NV_UNUSED( i );
-				m_data.emplace_back( nv::forward<Args>( args )... );
-				return m_data.back();
-			}
+				m_storage->emplace_back( nv::forward<Args>( args )... );
+				return m_storage->back();
+			}
+
+			virtual void* insert_raw( handle_type h ) final
+			{
+				return &insert( h );
+			}
+
 
 			bool exists( handle_type h )
@@ -95,15 +105,16 @@
 			}
 
-			virtual void update( time_type /*dtime*/ )
-			{
-				// no-op
-			}
-
-			virtual void clear()
-			{
- 				for ( uint32 i = 0; i < m_data.size(); ++i )
- 					destroy( &m_data[i] );
+			void call_destroy( value_type* data )
+			{
+				for ( auto dh : m_destroy )
+					dh( data );
+			}
+
+			virtual void clear_() final
+			{
+ 				for ( uint32 i = 0; i < m_storage->size(); ++i )
+ 					call_destroy( &(*m_storage)[i] );
 				m_index.clear();
- 				m_data.clear();
+				m_storage->clear();
 			}
 
@@ -111,10 +122,10 @@
 			{
 				index_type i = m_index.get( h );
-				return i >= 0 ? &( m_data[unsigned( i )] ) : nullptr;
+				return i >= 0 ? &( ( *m_storage )[unsigned( i )] ) : nullptr;
 			}
 			const value_type* get( handle_type h ) const
 			{
 				index_type i = m_index.get( h );
-				return i >= 0 ? &( m_data[unsigned( i )] ) : nullptr;
+				return i >= 0 ? &( ( *m_storage )[unsigned( i )] ) : nullptr;
 			}
 
@@ -122,16 +133,16 @@
 			const void* get_raw( handle_type h ) const { return get( h ); }
 
-			virtual void remove( handle_type h ) override
+			virtual void remove( handle_type h ) final
 			{
 				value_type* v = get( h );
 				if ( v == nullptr ) return;
-				destroy( v );
+				call_destroy( v );
 				index_type dead_eindex = m_index.remove_swap( h );
 				if ( dead_eindex == -1 ) return;
-				if ( dead_eindex != static_cast<index_type>( m_data.size() - 1 ) )
-				{
-					m_data[unsigned( dead_eindex )] = move( m_data.back() );
-				}
-				m_data.pop_back();
+				if ( dead_eindex != static_cast<index_type>( m_storage->size() - 1 ) )
+				{
+					( *m_storage )[unsigned( dead_eindex )] = move( m_storage->back() );
+				}
+				m_storage->pop_back();
 				if ( m_relational )
 					relational_rebuild( dead_eindex );
@@ -141,12 +152,12 @@
 			{
 				if ( i > size() ) return;
-				destroy( &m_data[i] );
+				call_destroy( &(*m_storage)[i] );
 				index_type dead_eindex = m_index.remove_swap_by_index( i );
 				if ( dead_eindex == -1 ) return;
-				if ( dead_eindex != static_cast<index_type>( m_data.size() - 1 ) )
-				{
-					m_data[unsigned( dead_eindex )] = move( m_data.back() );
-				}
-				m_data.pop_back();
+				if ( dead_eindex != static_cast<index_type>( m_storage->size() - 1 ) )
+				{
+					( *m_storage )[unsigned( dead_eindex )] = move( m_storage->back() );
+				}
+				m_storage->pop_back();
 				if ( m_relational )
 					relational_rebuild( dead_eindex );
@@ -159,5 +170,5 @@
 				while ( i < size() )
 				{
-					auto& md = m_data[i];
+					auto& md = ( *m_storage )[i];
 					if ( f( md ) )
 						remove_by_index( i );
@@ -167,29 +178,34 @@
 			}
 
-			virtual void destroy( value_type* )
-			{
-				// cleanup
+			virtual void on_attach( handle_type, handle_type child ) final
+			{
+				if ( m_relational )
+				{
+					relational_recursive_rebuild( child );
+				}
 			}
 
 			~component()
 			{
-				clear();
+				clear_();
+				delete m_storage;
+				m_storage = nullptr;
 			}
 			
-			inline const value_type& operator[] ( index_type i ) const { return m_data[i]; }
-			inline value_type& operator[] ( index_type i ) { return m_data[i]; }
-
-			inline size_t size() const { return m_data.size(); }
-
-			inline iterator        begin() { return m_data.begin(); }
-			inline const_iterator  begin()  const { return m_data.begin(); }
-
-			inline iterator        end() { return m_data.end(); }
-			inline const_iterator  end()  const { return m_data.end(); }
-
-			inline virtual component_storage* storage() { return &m_data; }
+			inline const value_type& operator[] ( index_type i ) const { return ( *m_storage )[i]; }
+			inline value_type& operator[] ( index_type i ) { return ( *m_storage )[i]; }
+
+			inline size_t size() const { return m_storage->size(); }
+
+			inline iterator        begin() { return m_storage->begin(); }
+			inline const_iterator  begin()  const { return m_storage->begin(); }
+
+			inline iterator        end() { return m_storage->end(); }
+			inline const_iterator  end()  const { return m_storage->end(); }
+
+			inline virtual component_storage* storage() { return m_storage; }
 		protected:
 			ecs_type&        m_ecs;
-			storage_type     m_data;
+			storage_type*    m_storage;
 		private:
 			void swap( handle_type a, handle_type b )
@@ -197,13 +213,14 @@
 				index_type ai = m_index.get( a );
 				index_type bi = m_index.get( b );
+				if ( ai < 0 || bi < 0 ) return;
 				m_index.swap( a, b );
-				value_type t = nv::move( m_data[ai] );
-				m_data[ai] = nv::move( m_data[bi] );
-				m_data[bi] = nv::move( t );
+				value_type t = nv::move( ( *m_storage )[ai] );
+				( *m_storage )[ai] = nv::move( ( *m_storage )[bi] );
+				( *m_storage )[bi] = nv::move( t );
 			}
 
 			handle_type extract_owner( index_type i )
 			{
-				return *(handle_type*)( &( m_data[i] ) );
+				return *(handle_type*)( &( ( *m_storage )[i] ) );
 			}
 
@@ -226,4 +243,17 @@
 				}
 			}
+
+			void relational_recursive_rebuild( handle_type h )
+			{
+				handle_type p = m_ecs.get_parent( h );
+				if ( !p ) return;
+				if ( m_index.get( h ) < m_index.get( p ) )
+				{
+					swap( h, p );
+					for ( auto c : m_ecs.children( h ) )
+						relational_recursive_rebuild( c );
+				}
+			}
+
 			bool             m_relational;
 			index_table_type m_index;
Index: trunk/nv/ecs/ecs.hh
===================================================================
--- trunk/nv/ecs/ecs.hh	(revision 549)
+++ trunk/nv/ecs/ecs.hh	(revision 550)
@@ -29,92 +29,6 @@
 {
 
-	namespace lua
-	{
-		class stack_proxy;
-	}
-
 	namespace ecs
 	{
-
-		namespace detail
-		{
-			template<typename, typename T>
-			struct has_update
-			{
-				static_assert( nv::integral_constant<T, false>::value, "Second template parameter needs to be of function type." );
-			};
-
-			template< typename C, typename Ret, typename... Args >
-			struct has_update<C, Ret( Args... )>
-			{
-			private:
-				template<typename T>
-				static constexpr auto check( T* )
-					-> typename nv::is_same< decltype( nv::declval<T>().update( nv::declval<Args>()... ) ), Ret >::type;
-
-				template<typename>
-				static constexpr nv::false_type check( ... );
-			public:
-				typedef decltype( check<C>( 0 ) ) type;
-				static constexpr bool value = type::value;
-			};
-
-			template < typename S, typename T, typename Cs >
-			struct has_ct_update_helper;
-
-			template < typename S, typename T, typename... Cs >
-			struct has_ct_update_helper< S, T, mpl::list< Cs... > >
-			{
-				using type = detail::has_update<S, void( Cs&..., T ) >;
-			};
-
-			template < typename S, typename E, typename T, typename Cs >
-			struct has_ect_update_helper;
-
-			template < typename S, typename E, typename T, typename... Cs >
-			struct has_ect_update_helper< S, E, T, mpl::list< Cs... > >
-			{
-				using type = detail::has_update<S, void( E&, Cs&..., T ) >;
-			};
-
-			template < typename S, typename E, typename M, typename Cs >
-			struct has_ec_message_helper;
-
-			template < typename S, typename E, typename M, typename... Cs >
-			struct has_ec_message_helper< S, E, M, mpl::list< Cs... > >
-			{
-				using type = detail::has_message<S, void( const M&, E&, Cs&... ) >;
-			};
-
-			template < typename S, typename M, typename Cs >
-			struct has_c_message_helper;
-
-			template < typename S, typename M, typename... Cs >
-			struct has_c_message_helper< S, M, mpl::list< Cs... > >
-			{
-				using type = detail::has_message<S, void( const M&, Cs&... ) >;
-			};
-
-		}
-
-
-
-		template < typename E, typename S, typename T >
-		using has_ecs_update = detail::has_update<S, void( E&, T ) >;
-
-		template < typename S, typename Cs, typename T >
-		using has_component_update = typename detail::has_ct_update_helper<S, T, Cs >::type;
-
-		template < typename E, typename S, typename Cs, typename T >
-		using has_ecs_component_update = typename detail::has_ect_update_helper<S, E, T, Cs >::type;
-
-		template < typename S, typename Cs, typename M >
-		using has_component_message = typename detail::has_c_message_helper<S, M, Cs >::type;
-
-		template < typename E, typename S, typename Cs, typename M >
-		using has_ecs_component_message = typename detail::has_ec_message_helper<S, E, M, Cs >::type;
-
-		template < typename E, typename S, typename M >
-		using has_ecs_message = detail::has_message<S, void( const M&, E& ) >;
 
 		template < typename Handle, typename MessageList, typename Time = f32 >
@@ -129,16 +43,30 @@
 			using base_type::message;
 
-			using update_handler = function< void( time_type ) >;
+			using update_handler  = function< void( time_type ) >;
+			using destroy_handler = function< void( void* ) >;
+			using create_handler  = function< void( handle_type, void*, const lua::stack_proxy& ) >;
 
 			class component_interface
 			{
 			public:
-				virtual void update( time_type dtime ) = 0;
-				virtual void clear() = 0;
-				virtual void initialize( handle_type, lua::stack_proxy& ) = 0;
+				virtual void clear_() = 0;
 				virtual void remove( handle_type h ) = 0;
+				virtual void on_attach( handle_type parent, handle_type child ) = 0;
 				virtual void* get_raw( handle_type h ) = 0;
+				virtual void* insert_raw( handle_type h ) = 0;
 				virtual const void* get_raw( handle_type h ) const = 0;
 				virtual component_storage* storage() = 0;
+				virtual uint32 temp_index( handle_type h ) const = 0;
+
+				void run_create( handle_type h, const lua::stack_proxy& p )
+				{
+					void* c = insert_raw( h );
+					for ( auto cf : m_create )
+						cf( h, c, p );
+				}
+
+				vector< create_handler >  m_create;
+				vector< destroy_handler > m_destroy;
+
 			};
 
@@ -291,6 +219,23 @@
 			{
 				register_handler< System >( name, (System*)( c ) );
+				register_component_helper< System >( c, has_components< System >::type{} );
 				register_ecs_update< System >( (System*)( c ),
 					has_ecs_update< this_type, System, time_type >::type{} );
+			}
+
+			template< typename System >
+			void register_component_helper( System* c, true_type&& )
+			{
+				using component_list = System::components;
+				register_component_messages< System, component_list >( c, message_list{} );
+				register_ecs_component_update< System >( c, component_list{},
+					has_ecs_component_update< this_type, System, component_list, time_type >::type{} );
+				register_component_update< System >( c, component_list{},
+					has_component_update< System, component_list, time_type >::type{} );
+			}
+
+			template< typename System >
+			void register_component_helper( System*, false_type&& )
+			{
 			}
 
@@ -309,4 +254,8 @@
 				register_ecs_update< Handler >( (Handler*)( c ), 
 					has_ecs_update< this_type, Handler, time_type >::type{} );
+				register_destroy< Handler, Component >( (Handler*)( c ),
+					has_destroy< Handler, Component >::type{} );
+				register_create< Handler, Component, handle_type >( (Handler*)( c ),
+					has_create< Handler, Component, handle_type >::type{} );
 				//				auto s = c->storage();
 				// 				m_cstorage.push_back( s );
@@ -323,6 +272,4 @@
 			{
 				update_time( dtime );
-				for ( auto c : m_components )
-					c->update( dtime );
 				for ( auto u : m_update_handlers )
 					u( dtime );
@@ -333,5 +280,5 @@
 				reset_events();
 				for ( auto c : m_components )
-					c->clear();
+					c->clear_();
 				m_handles.clear();
 			}
@@ -349,4 +296,12 @@
 				m_handles.detach( child );
 				m_handles.attach( parent, child );
+				for ( auto c : m_components )
+					c->on_attach( parent, child );
+			}
+
+			template< typename Component >
+			uint32 get_debug_index( handle_type h )
+			{
+				return get_interface<Component>()->temp_index( h );
 			}
 
@@ -364,4 +319,9 @@
 			{
 				return h ? m_handles.first( h ) : handle_type();
+			}
+
+			bool is_valid( handle_type h ) const
+			{
+				return m_handles.is_valid( h );
 			}
 
@@ -542,4 +502,28 @@
 			}
 
+			template < typename System, typename Component >
+			void register_destroy( System* s, true_type&& )
+			{
+				component_interface* ci = get_interface<Component>();
+				NV_ASSERT( ci, "Unregistered component!" );
+				ci->m_destroy.push_back( [=] ( void* data )
+				{
+					s->destroy( *((Component*)data) );
+				}
+				);
+			}
+
+			template < typename System, typename Component, typename Handle >
+			void register_create( System* s, true_type&& )
+			{
+				component_interface* ci = get_interface<Component>();
+				NV_ASSERT( ci, "Unregistered component!" );
+				ci->m_create.push_back( [=] ( Handle h, void* data, const lua::stack_proxy& p )
+				{
+					s->create( h, *( (Component*)data ), p );
+				}
+				);
+			}
+
 			template < typename System, typename C, typename... Cs >
 			void register_component_update( System* s, mpl::list< C, Cs...>&&, true_type&& )
@@ -578,4 +562,10 @@
 			void register_ecs_update( System*, false_type&& ) {}
 
+			template < typename System, typename Component >
+			void register_destroy( System*, false_type&& ) {}
+
+			template < typename System, typename Component, typename Handle >
+			void register_create( System*, false_type&& ) {}
+
 			template < typename System, typename... Cs >
 			void register_component_update( System*, mpl::list< Cs...>&&, false_type&& ) {}
Index: trunk/nv/ecs/message_queue.hh
===================================================================
--- trunk/nv/ecs/message_queue.hh	(revision 549)
+++ trunk/nv/ecs/message_queue.hh	(revision 550)
@@ -21,4 +21,5 @@
 #include <nv/stl/functional/function.hh>
 #include <nv/core/types.hh>
+#include <nv/ecs/field_detection.hh>
 
 namespace nv
@@ -27,33 +28,4 @@
 	namespace ecs
 	{
-
-		namespace detail
-		{
-			template<typename, typename T>
-			struct has_message
-			{
-				static_assert( nv::integral_constant<T, false>::value, "Second template parameter needs to be of function type." );
-			};
-
-			template< typename C, typename Ret, typename... Args >
-			struct has_message<C, Ret( Args... )>
-			{
-			private:
-				template<typename T>
-				static constexpr auto check( T* )
-					-> typename nv::is_same< decltype( nv::declval<T>().on( nv::declval<Args>()... ) ), Ret >::type;
-
-				template<typename>
-				static constexpr nv::false_type check( ... );
-
-			public:
-				typedef decltype( check<C>( 0 ) ) type;
-
-				static constexpr bool value = type::value;
-			};
-		}
-
-		template < typename S, typename M >
-		using has_message = detail::has_message<S, void( const M& ) >;
 
 		template < typename Payload, typename Message >
Index: trunk/nv/interface/context.hh
===================================================================
--- trunk/nv/interface/context.hh	(revision 549)
+++ trunk/nv/interface/context.hh	(revision 550)
@@ -64,5 +64,5 @@
 	};
 
-	class vertex_array_desc : private vertex_array_info
+	class vertex_array_desc : public vertex_array_info
 	{
 	private:
@@ -77,4 +77,13 @@
 			index_type = USHORT;
 		}
+
+		template < typename IDX >
+		void set_index_buffer( buffer b, bool owner )
+		{
+			index = b;
+			index_owner = owner;
+			index_type = type_to_enum< IDX >::type;
+		}
+
 
 		template < typename VTX, slot SLOT >
@@ -101,5 +110,5 @@
 			{
 				const datatype_info& info = get_datatype_info( cslot.etype );
-				add_vertex_buffer( cslot.vslot, buf, info.base, info.elements, cslot.offset, descriptor.element_size(), false );
+				add_vertex_buffer( cslot.vslot, buf, info.base, info.elements, cslot.offset, descriptor.element_size(), false, false );
 			}
 		}
@@ -107,15 +116,16 @@
 
 		// TODO: should be private
-		void add_vertex_buffer( slot location, buffer buf, datatype datatype, uint32 components, uint32 offset = 0, uint32 stride = 0, bool owner = true )
+		void add_vertex_buffer( slot location, buffer buf, datatype datatype, uint32 components, uint32 offset, uint32 stride, bool interpolate, bool owner  )
 		{
 			NV_ASSERT( count < uint16( MAX_ATTRIBUTES ), "MAX_ATTRIBUTES reached!" );
 			vertex_buffer_attribute& p = attr[count];
-			p.vbuffer    = buf;
-			p.dtype      = datatype;
-			p.components = components;
-			p.offset     = offset;
-			p.stride     = stride;
-			p.owner      = owner;
-			p.location   = location;
+			p.vbuffer     = buf;
+			p.dtype       = datatype;
+			p.components  = components;
+			p.offset      = offset;
+			p.stride      = stride;
+			p.owner       = owner;
+			p.interpolate = interpolate;
+			p.location    = location;
 			count++;
 		}
@@ -139,5 +149,5 @@
 			typedef slot_info< VTX, SLOT > vinfo;
 			typedef datatype_traits< typename vinfo::value_type > dt_traits;
-			add_vertex_buffer( SLOT, vb, type_to_enum< typename dt_traits::base_type >::type, dt_traits::size, vinfo::offset, sizeof( VTX ), owned );
+			add_vertex_buffer( SLOT, vb, type_to_enum< typename dt_traits::base_type >::type, dt_traits::size, vinfo::offset, sizeof( VTX ), false, owned );
 		}
 
Index: trunk/nv/interface/device.hh
===================================================================
--- trunk/nv/interface/device.hh	(revision 549)
+++ trunk/nv/interface/device.hh	(revision 550)
@@ -185,4 +185,5 @@
 		size_t   stride;
 		slot     location;
+		bool     interpolate;
 		bool     owner;
 	};
Index: trunk/nv/interface/window_manager.hh
===================================================================
--- trunk/nv/interface/window_manager.hh	(revision 549)
+++ trunk/nv/interface/window_manager.hh	(revision 550)
@@ -27,5 +27,5 @@
 	{
 	public:
-		virtual window* create_window( device* dev, uint16 width, uint16 height, bool fullscreen ) = 0;
+		virtual window* create_window( device* dev, uint16 width, uint16 height, bool fullscreen, bool msaa = false ) = 0;
 		virtual void* adopt_window( void* sys_w_handle ) = 0;
 		virtual void sleep( uint32 ms ) = 0;
Index: trunk/nv/sdl/sdl_window.hh
===================================================================
--- trunk/nv/sdl/sdl_window.hh	(revision 549)
+++ trunk/nv/sdl/sdl_window.hh	(revision 550)
@@ -26,5 +26,5 @@
 		{
 		public:
-			window( device* dev, uint16 width, uint16 height, bool fullscreen = false );
+			window( device* dev, uint16 width, uint16 height, bool fullscreen = false, bool msaa = false );
 			virtual void set_title( const string_view& title );
 			virtual void swap_buffers();
Index: trunk/nv/sdl/sdl_window_manager.hh
===================================================================
--- trunk/nv/sdl/sdl_window_manager.hh	(revision 549)
+++ trunk/nv/sdl/sdl_window_manager.hh	(revision 550)
@@ -26,5 +26,5 @@
 		public:
 			window_manager();
-			virtual nv::window* create_window( device* dev, uint16 width, uint16 height, bool fullscreen );
+			virtual nv::window* create_window( device* dev, uint16 width, uint16 height, bool fullscreen, bool msaa = false );
 			virtual void* adopt_window( void* sys_w_handle );
 			virtual void sleep( uint32 ms );
Index: trunk/nv/stl/math/basic.hh
===================================================================
--- trunk/nv/stl/math/basic.hh	(revision 549)
+++ trunk/nv/stl/math/basic.hh	(revision 550)
@@ -148,5 +148,5 @@
 		inline T floor( const T& x )
 		{
-			return detail::unary_functor< T >::call( floor, x );
+			return detail::unary_functor< T >::call( floorf, x );
 		}
 
@@ -162,5 +162,5 @@
 		inline T round( const T& x )
 		{
-			return detail::unary_functor< T >::call( round, x );
+			return detail::unary_functor< T >::call( roundf, x );
 		}
 
Index: trunk/nv/stl/math/geometric.hh
===================================================================
--- trunk/nv/stl/math/geometric.hh	(revision 549)
+++ trunk/nv/stl/math/geometric.hh	(revision 550)
@@ -66,8 +66,20 @@
 		}
 
+		template < typename T, typename enable_if< is_floating_point<T>::value >::type* = nullptr >
+		inline T inv_length( T v )
+		{
+			return T( 1 ) / abs( x );
+		}
+
 		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
 		inline value_type_t<T> length( const T& v )
 		{
 			return nv::sqrt( dot( v, v ) );
+		}
+
+		template < typename T, typename enable_if< is_fp_vec<T>::value >::type* = nullptr >
+		inline value_type_t<T> inv_length( const T& v )
+		{
+			return T( 1 ) / nv::sqrt( dot( v, v ) );
 		}
 
Index: trunk/nv/stl/type_traits/common.hh
===================================================================
--- trunk/nv/stl/type_traits/common.hh	(revision 549)
+++ trunk/nv/stl/type_traits/common.hh	(revision 550)
@@ -77,4 +77,14 @@
 	template < typename T1, typename T2 >
 	constexpr bool is_same_v = is_same<T1, T2>::value;
+
+#if NV_COMPILER == NV_MSVC
+	// preferred form
+	template< typename... > using void_t = void;
+#else
+	template< typename... > struct void_acceptor { using type = void; };
+	template< typename... T > using void_t = typename void_acceptor<T...>::type;
+#endif
+
+	template < typename T > struct identity { using type = T; };
 
 	// TODO: these seem to simple compared to MSVC/GCC - so we'll leave them in
Index: trunk/nv/stl/type_traits/experimental.hh
===================================================================
--- trunk/nv/stl/type_traits/experimental.hh	(revision 549)
+++ trunk/nv/stl/type_traits/experimental.hh	(revision 550)
@@ -21,12 +21,4 @@
 namespace nv
 {
-
-#if NV_COMPILER == NV_MSVC
-	// preferred form
-	template< typename... > using void_t = void;
-#else
-	template< typename... > struct void_acceptor { using type = void; };
-	template< typename... T > using void_t = typename void_acceptor<T...>::type;
-#endif
 
 #if NV_COMPILER == NV_MSVC
Index: trunk/nv/stl/vector.hh
===================================================================
--- trunk/nv/stl/vector.hh	(revision 549)
+++ trunk/nv/stl/vector.hh	(revision 550)
@@ -28,8 +28,8 @@
 	using growable_static_storage = growing_storage< static_storage< T, N > >;
 
-	template< typename T >
+	template< typename T, typename InitializePolicy = policy_initialize_standard >
 	using vector = 
 		random_access <
-				growable_dynamic_storage< T > >;
+			growing_storage< dynamic_storage< T >, InitializePolicy > >;
 
 }
Index: trunk/src/gfx/texture_font.cc
===================================================================
--- trunk/src/gfx/texture_font.cc	(revision 549)
+++ trunk/src/gfx/texture_font.cc	(revision 550)
@@ -111,5 +111,5 @@
 	else
 	{
-		flags |= FT_LOAD_FORCE_AUTOHINT;
+		//flags |= FT_LOAD_FORCE_AUTOHINT;
 	} 
 
@@ -122,4 +122,5 @@
 			FT_Library_SetLcdFilterWeights( reinterpret_cast<FT_Library>( m_rlibrary ), m_lcd_weights );
 		}
+
 	} 
 
Index: trunk/src/gl/gl_context.cc
===================================================================
--- trunk/src/gl/gl_context.cc	(revision 549)
+++ trunk/src/gl/gl_context.cc	(revision 550)
@@ -47,5 +47,5 @@
 			static_cast<GLint>( vba.components ),
 			nv::datatype_to_gl_enum( vba.dtype ),
-			GL_FALSE,
+			vba.interpolate ? GL_TRUE : GL_FALSE,
 			static_cast<GLsizei>( vba.stride ),
 			reinterpret_cast<void*>( vba.offset )
@@ -693,5 +693,5 @@
 	if ( m_render_state.multisample != multisample )
 	{
-		glDepthMask( multisample );
+		enable( GL_MULTISAMPLE, multisample );
 		m_render_state.multisample = multisample;
 	}
@@ -891,4 +891,5 @@
 	m_active_slot = texture_slot( -1 );
 	force_apply_render_state( m_render_state );
+	glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
 }
 
Index: trunk/src/sdl/sdl_window.cc
===================================================================
--- trunk/src/sdl/sdl_window.cc	(revision 549)
+++ trunk/src/sdl/sdl_window.cc	(revision 550)
@@ -15,5 +15,5 @@
 using namespace nv;
 
-sdl::window::window( device* dev, uint16 width, uint16 height, bool fullscreen )
+sdl::window::window( device* dev, uint16 width, uint16 height, bool fullscreen, bool msaa )
 	: m_device( dev ), m_width( width ), m_height( height ), m_title("Nova Engine"), m_handle( nullptr )
 {
@@ -27,6 +27,9 @@
 	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
 
-	//	SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 );
-	//	SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, 4 );
+	if ( msaa )
+	{
+		SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 );
+		SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, 4 );
+	}
 
  	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
Index: trunk/src/sdl/sdl_window_manager.cc
===================================================================
--- trunk/src/sdl/sdl_window_manager.cc	(revision 549)
+++ trunk/src/sdl/sdl_window_manager.cc	(revision 550)
@@ -27,8 +27,8 @@
 }
 
-window* sdl::window_manager::create_window( device* dev, uint16 width, uint16 height, bool fullscreen )
+window* sdl::window_manager::create_window( device* dev, uint16 width, uint16 height, bool fullscreen, bool msaa )
 {
 	if ( ! SDL_WasInit( SDL_INIT_VIDEO ) ) SDL_InitSubSystem( SDL_INIT_VIDEO );
-	sdl::window* result = new sdl::window( dev, width, height, fullscreen );
+	sdl::window* result = new sdl::window( dev, width, height, fullscreen, msaa );
 	primal_window = result->get_handle();
 	return result;
