Index: /trunk/nv/gfx/particle_engine.hh
===================================================================
--- /trunk/nv/gfx/particle_engine.hh	(revision 306)
+++ /trunk/nv/gfx/particle_engine.hh	(revision 307)
@@ -63,8 +63,15 @@
 		vec3   odir;
 		vec3   cdir;
+		uint32 duration_min;
+		uint32 duration_max;
+		uint32 repeat_min;
+		uint32 repeat_max;
 		float  rate;
 	};
+
 	struct particle_emmiter_info
 	{
+		bool   active;
+		uint32 next_toggle;
 		uint32 last_create;
 	};
@@ -120,4 +127,5 @@
 		void create_particles( particle_system_info* info, uint32 ms );
 		void update_particles( particle_system_info* info, uint32 ms );
+		void update_emmiters( particle_system_info* info, uint32 ms );
 
 		device*                        m_device;
Index: /trunk/src/gfx/particle_engine.cc
===================================================================
--- /trunk/src/gfx/particle_engine.cc	(revision 306)
+++ /trunk/src/gfx/particle_engine.cc	(revision 307)
@@ -104,4 +104,11 @@
 				edata.lifetime_min = uint32( element.get<float>("lifetime_min", lifetime ) * 1000.f );
 				edata.lifetime_max = uint32( element.get<float>("lifetime_max", lifetime ) * 1000.f );
+				float duration     = element.get<float>("duration", 0.0f );
+				edata.duration_min = uint32( element.get<float>("duration_min", duration ) * 1000.f );
+				edata.duration_max = uint32( element.get<float>("duration_max", duration ) * 1000.f );
+				float repeat       = element.get<float>("repeat_delay", 0.0f );
+				edata.repeat_min   = uint32( element.get<float>("repeat_delay_min", repeat ) * 1000.f );
+				edata.repeat_max   = uint32( element.get<float>("repeat_delay_max", repeat ) * 1000.f );
+
 				edata.rate         = element.get<float>("rate", 1.0f );
 				edata.dir          = glm::normalize( element.get<vec3>("direction", vec3(0,1,0) ) );
@@ -153,5 +160,7 @@
 	for ( uint32 i = 0; i < ecount; ++i )
 	{
+		info->emmiters[i].active      = true;
 		info->emmiters[i].last_create = 0;
+		info->emmiters[i].next_toggle = random::get().urange( data->emmiters[i].duration_min, data->emmiters[i].duration_max );
 	}
 
@@ -208,4 +217,5 @@
 		m_inv_view_dir = glm::normalize(-s.get_camera().get_direction());
 
+		update_emmiters( info, ms );
 		destroy_particles( info, ms );
 		create_particles( info, ms );
@@ -348,39 +358,41 @@
 		const auto& edata = info->data->emmiters[i];
 		auto& einfo = info->emmiters[i];
-
-		uint32 period = glm::max<uint32>( uint32(1000.f / edata.rate), 1 );
-		while ( ms - einfo.last_create > period )
-		{
-			if ( info->count < info->data->quota-1 )
-			{
-				particle& pinfo = info->particles[info->count];
-				pinfo.position = source;
-				pinfo.color    = edata.color_min == edata.color_max ? 
-					edata.color_min : r.range( edata.color_min, edata.color_max );
-				pinfo.size     = edata.size_min == edata.size_max ?
-					edata.size_min : r.range( edata.size_min, edata.size_max );
-				if ( edata.square ) pinfo.size.y = pinfo.size.x;
-				pinfo.velocity  = edata.velocity_min == edata.velocity_max ?
-					edata.velocity_min : r.frange( edata.velocity_min, edata.velocity_max );
-				pinfo.death     = ms + ( edata.lifetime_min == edata.lifetime_max ?
-					edata.lifetime_min : r.urange( edata.lifetime_min, edata.lifetime_max ) );
-				//pinfo.rotation = r.frand( 360.0f );
-
-				pinfo.dir = edata.dir;
-				if ( edata.angle > 0.0f )
+		if ( einfo.active )
+		{
+			uint32 period = glm::max<uint32>( uint32(1000.f / edata.rate), 1 );
+			while ( ms - einfo.last_create > period )
+			{
+				if ( info->count < info->data->quota-1 )
 				{
-					float emission_angle = glm::radians( edata.angle );
-					float cos_theta = r.frange( cos( emission_angle ), 1.0f );
-					float sin_theta = glm::sqrt(1.0f - cos_theta * cos_theta );
-					float phi       = r.frange( 0.0f, 2*glm::pi<float>() );
-					pinfo.dir = orient * 
-						( edata.odir * ( glm::cos(phi) * sin_theta ) +
-						edata.cdir * ( glm::sin(phi)*sin_theta ) + 
-						edata.dir  * cos_theta );
+					particle& pinfo = info->particles[info->count];
+					pinfo.position = source;
+					pinfo.color    = edata.color_min == edata.color_max ? 
+						edata.color_min : r.range( edata.color_min, edata.color_max );
+					pinfo.size     = edata.size_min == edata.size_max ?
+						edata.size_min : r.range( edata.size_min, edata.size_max );
+					if ( edata.square ) pinfo.size.y = pinfo.size.x;
+					pinfo.velocity  = edata.velocity_min == edata.velocity_max ?
+						edata.velocity_min : r.frange( edata.velocity_min, edata.velocity_max );
+					pinfo.death     = ms + ( edata.lifetime_min == edata.lifetime_max ?
+						edata.lifetime_min : r.urange( edata.lifetime_min, edata.lifetime_max ) );
+					//pinfo.rotation = r.frand( 360.0f );
+
+					pinfo.dir = edata.dir;
+					if ( edata.angle > 0.0f )
+					{
+						float emission_angle = glm::radians( edata.angle );
+						float cos_theta = r.frange( cos( emission_angle ), 1.0f );
+						float sin_theta = glm::sqrt(1.0f - cos_theta * cos_theta );
+						float phi       = r.frange( 0.0f, 2*glm::pi<float>() );
+						pinfo.dir = orient * 
+							( edata.odir * ( glm::cos(phi) * sin_theta ) +
+							edata.cdir * ( glm::sin(phi)*sin_theta ) + 
+							edata.dir  * cos_theta );
+					}
+
+					info->count++;
 				}
-
-				info->count++;
-			}
-			einfo.last_create += period;
+				einfo.last_create += period;
+			}
 		}
 	}
@@ -416,2 +428,34 @@
 		system->last_update = ms;
 }
+
+void nv::particle_engine::update_emmiters( particle_system_info* info, uint32 ms )
+{
+	uint32 ecount = info->data->emmiter_count;
+	if ( ecount == 0 ) return;
+	random& r = random::get();
+
+	for ( uint32 i = 0; i < ecount; ++i )
+	{
+		const auto& edata = info->data->emmiters[i];
+		auto& einfo = info->emmiters[i];
+
+		if ( einfo.next_toggle != 0 && ms >= einfo.next_toggle )
+		{
+			if ( einfo.active )
+			{
+				einfo.active = false;
+				if ( edata.repeat_min > 0 )
+					einfo.next_toggle += r.urange( edata.repeat_min, edata.repeat_max );
+				else
+					einfo.next_toggle = 0;
+			}
+			else
+			{
+				einfo.active = true;
+				einfo.last_create = einfo.next_toggle;
+				einfo.next_toggle += r.urange( edata.duration_min, edata.duration_max );
+			}
+		}
+	}
+
+}
