Index: trunk/src/engine/mesh_manager.cc
===================================================================
--- trunk/src/engine/mesh_manager.cc	(revision 520)
+++ trunk/src/engine/mesh_manager.cc	(revision 522)
@@ -85,10 +85,10 @@
 
 		NV_LOG_ERROR( "Resource path fail! - ", path );
-		NV_ASSERT( false, "Resource path fail!" );
+		//NV_ASSERT( false, "Resource path fail!" );
 	}
 	else
 	{
 		NV_LOG_ERROR( "Resource lock fail! - ", path );
-		NV_ASSERT( false, "Resource lock fail!" );
+		//NV_ASSERT( false, "Resource lock fail!" );
 	}
 	return nv::resource< nv::data_channel_set >();
Index: trunk/src/engine/particle_engine.cc
===================================================================
--- trunk/src/engine/particle_engine.cc	(revision 520)
+++ trunk/src/engine/particle_engine.cc	(revision 522)
@@ -306,5 +306,4 @@
 		else
 			info->emitters[i].pause = m_rng->frange( data->emitters[i].duration_min, data->emitters[i].duration_max );
-
 	}
 
@@ -313,4 +312,11 @@
 
 	return result;
+}
+
+void nv::particle_engine::set_on_collide( particle_system system, const particle_on_collide_func& f )
+{
+	particle_system_info* info = m_systems.get( system );
+	if ( info )
+		info->on_collide = f;
 }
 
@@ -364,4 +370,22 @@
 		m_systems.destroy( system );
 	}
+}
+
+bool nv::particle_engine::is_finished( particle_system system )
+{
+	particle_system_info* info = m_systems.get( system );
+	if ( info )
+	{
+		if ( info->count > 0 ) return false;
+		for ( uint32 i = 0; i < info->data->emitter_count; ++i )
+		{
+			const auto& edata = info->emitters[i];
+			if ( edata.active || edata.pause > 0.0f )
+			{
+				return false;
+			}
+		}
+	}
+	return true;
 }
 
@@ -403,5 +427,4 @@
 void nv::particle_engine::set_texcoords( particle_system system, vec2 a, vec2 b )
 {
-
 	particle_system_info* info = m_systems.get( system );
 	if ( info )
@@ -513,4 +536,18 @@
 		pdata.position += pdata.velocity * factor;
 	}
+
+	if ( info->on_collide )
+	{
+		for ( uint32 i = 0; i < info->count; ++i )
+		{
+			particle& pdata = info->particles[i];
+			if ( pdata.position.y <= 0.0f )
+			{
+				info->on_collide( pdata.position, pdata.velocity );
+				pdata.death = pdata.lifetime;
+			}
+		}
+	}
+
 }
 
Index: trunk/src/engine/renderer.cc
===================================================================
--- trunk/src/engine/renderer.cc	(revision 520)
+++ trunk/src/engine/renderer.cc	(revision 522)
@@ -117,4 +117,5 @@
 
 	scene_state ss( s );
+	render_state rs( pass.rstate );
 	m_context->bind( pass.fbuffer, FRAMEBUFFER );
 	m_context->set_draw_buffers( pass.output_count, pass.output );
@@ -157,9 +158,11 @@
 					m_context->get_device()->set_opt_uniform( *program, "nv_index", unsigned( index ) );
 					m_context->apply_engine_uniforms( *program, ss );
+					if ( rs.blending != element.blending )
+						rs.blending = element.blending;
 
 					if ( element.instances > 0 )
-						m_context->draw_instanced( TRIANGLES, pass.rstate, *program, element.instances, element.va, element.count, element.first );
+						m_context->draw_instanced( TRIANGLES, rs, *program, element.instances, element.va, element.count, element.first );
 					else
-						m_context->draw( TRIANGLES, pass.rstate, *program, element.va, element.count, element.first );
+						m_context->draw( TRIANGLES, rs, *program, element.va, element.count, element.first );
 
 					m_statistics[TRIANGLE_COUNT] += ( element.count / 3 ) * max< uint32 >( element.instances, 1 );
