Index: trunk/nv/ecs/ecs.hh
===================================================================
--- trunk/nv/ecs/ecs.hh	(revision 497)
+++ trunk/nv/ecs/ecs.hh	(revision 498)
@@ -104,4 +104,6 @@
 		};
 	
+
+
 		template < typename HANDLE = handle<> >
 		class ecs
@@ -110,17 +112,66 @@
 			typedef HANDLE handle_type;
 
-			template < typename COMPONENT, typename MANAGER >
-			void register_component( string_view /*name*/, MANAGER* /*manager*/ )
-			{
-
-			}
-
-			handle_type create_handle()
+			typedef uint32 message_type;
+
+			struct message
+			{
+				message_type type;
+				handle_type  entity;
+				uint8        payload[128 - sizeof( uint32 ) - sizeof( handle_type )];
+			};
+
+			class component_interface
+			{
+			public:
+				virtual bool handle_message( const message& ) = 0;
+				virtual void clear() = 0;
+				virtual void remove( handle_type h ) = 0;
+			};
+
+			template < typename Payload >
+			static const Payload& message_cast( const message& m )
+			{
+				static_assert( sizeof( Payload ) < sizeof( message::payload ), "Payload size over limit!" );
+				NV_ASSERT( Payload::message_id == m.type, "Payload cast fail!" );
+				return *reinterpret_cast<const Payload*>( &( m.payload ) );
+			}
+
+			template < typename COMPONENT >
+			void register_component( string_view /*name*/, component_interface* c )
+			{
+				m_components.push_back( c );
+			}
+
+			bool dispatch( const message& m )
+			{
+				for ( auto c : m_components )
+					c->handle_message( m );
+				return true;
+			}
+
+			template < typename Payload, typename ...Args >
+			bool dispatch( handle_type h, Args&&... args )
+			{
+				message m{ Payload::message_id, h };
+				new( &m.payload ) Payload{ nv::forward<Args>( args )... };
+				return dispatch( m );
+			}
+
+			handle_type create()
 			{
 				return m_handles.create_handle();
 			}
 
-			void free_handle( handle_type h )
-			{
+			void clear()
+			{
+				for ( auto c : m_components )
+					c->clear();
+				m_handles.clear();
+			}
+
+			void remove( handle_type h )
+			{
+				for ( auto c : m_components )
+					c->remove( h );
 				m_handles.free_handle( h );
 			}
@@ -133,11 +184,13 @@
 		protected:
 			handle_manager< handle_type > m_handles;
+			vector< component_interface* > m_components;
 		};
 
 		template < typename ECS, typename COMPONENT >
-		class component
+		class component : public ECS::component_interface
 		{
 		public:
 			typedef ECS                                    ecs_type;
+			typedef typename ecs_type::message             message_type;
 			typedef typename ecs_type::handle_type         handle_type;
 			typedef index_table< handle_type >             index_table_type;
@@ -169,4 +222,13 @@
 			}
 
+			template < typename ...Args >
+			value_type& insert( handle_type h, Args&&... args )
+			{
+				/*index_type i = */m_index.insert( h );
+				//NV_ASSERT( i == m_data.size(), "Fail!" );
+				m_data.emplace_back( nv::forward<Args>( args )... );
+				return m_data.back();
+			}
+
 			bool exists( handle_type h )
 			{
@@ -174,5 +236,5 @@
 			}
 
-			void clear()
+			virtual void clear()
 			{
 				m_index.clear();
@@ -192,5 +254,5 @@
 			}
 
-			void remove( handle_type h )
+			virtual void remove( handle_type h )
 			{
 				index_type dead_eindex = m_index.remove_swap( h );
@@ -202,4 +264,10 @@
 				m_data.pop_back();
 			}
+
+			virtual bool handle_message( const message_type& )
+			{
+				return true;
+			}
+
 
 			handle_type get_handle( index_type i ) const { return m_index.get_handle( i ); }
Index: trunk/nv/stl/handle.hh
===================================================================
--- trunk/nv/stl/handle.hh	(revision 497)
+++ trunk/nv/stl/handle.hh	(revision 498)
@@ -115,4 +115,11 @@
 			const index_entry& entry = m_entries[h.index()];
 			return entry.next_free == USED && entry.counter == hop::get_counter( h );
+		}
+
+		void clear()
+		{
+			m_first_free = NONE;
+			m_last_free  = NONE;
+			m_entries.clear();
 		}
 
@@ -385,5 +392,5 @@
 		void resize_to( index_type i )
 		{
-			index_type size = index_type( m_indexes.size() );
+			index_type size = index_type( m_handles.size() );
 			if ( i >= size )
 			{
Index: trunk/nv/stl/memory.hh
===================================================================
--- trunk/nv/stl/memory.hh	(revision 497)
+++ trunk/nv/stl/memory.hh	(revision 498)
@@ -191,5 +191,5 @@
 	inline void construct_object( T* object, Args&&... params )
 	{
-		new ( object )T( ::nv::forward<Args>( params )... );
+		new ( object )T{ ::nv::forward<Args>( params )... };
 	}
 
Index: trunk/src/engine/material_manager.cc
===================================================================
--- trunk/src/engine/material_manager.cc	(revision 497)
+++ trunk/src/engine/material_manager.cc	(revision 498)
@@ -28,5 +28,5 @@
 	{
 		gpu_material* result = new gpu_material;
-		sampler smp( sampler::LINEAR, sampler::REPEAT );
+		sampler smp( sampler::LINEAR_MIPMAP_LINEAR, sampler::REPEAT );
 		for ( uint32 i = 0; i < size( mat->paths ); ++i )
 			if ( !mat->paths[i].empty() )
Index: trunk/src/gl/gl_device.cc
===================================================================
--- trunk/src/gl/gl_device.cc	(revision 497)
+++ trunk/src/gl/gl_device.cc	(revision 498)
@@ -109,9 +109,9 @@
 
 	// Detect if mipmapping was requested
-	if ( gl_type == GL_TEXTURE_2D && gl_enum != GL_RED_INTEGER && asampler.filter_min != sampler::LINEAR && asampler.filter_min != sampler::NEAREST )
-	{
-		// TODO: This should not be done if we use framebuffers!
-		glTexParameteri( gl_type, GL_GENERATE_MIPMAP, GL_TRUE);
-	}
+// 	if ( gl_type == GL_TEXTURE_2D && gl_enum != GL_RED_INTEGER && asampler.filter_min != sampler::LINEAR && asampler.filter_min != sampler::NEAREST )
+// 	{
+// 		// TODO: This should not be done if we use framebuffers!
+// 		glTexParameteri( gl_type, GL_GENERATE_MIPMAP, GL_TRUE);
+// 	}
 
 	if ( asampler.filter_max != sampler::NEAREST )
@@ -154,4 +154,11 @@
 	else
 		glTexImage2DMultisample( gl_type, 4, gl_internal, size.x, size.y, 1 );
+
+	if ( gl_type == GL_TEXTURE_2D && gl_enum != GL_RED_INTEGER && asampler.filter_min != sampler::LINEAR && asampler.filter_min != sampler::NEAREST )
+	{
+		// TODO: This should not be done if we use framebuffers!
+		glGenerateMipmap( gl_type );
+	}
+
 
 	glBindTexture( gl_type, 0 );
