context: using UnityEngine;
  using System.Collections;
  
  /*
  
  	Detonator - A parametric explosion system for Unity
  	Created by Ben Throop in August 2009 for the Unity Summer of Code
  	
  	Simplest use case:
  	
  	1) Use a prefab
  	
  	OR
  	
  	1) Attach a Detonator to a GameObject, either through code or the Unity UI
  	2) Either set the Detonator's ExplodeOnStart = true or call Explode() yourself when the time is right
  	3) View explosion :)
  	
  	Medium Complexity Use Case:
  	
  	1) Attach a Detonator as above 
  	2) Change parameters, add your own materials, etc
  	3) Explode()
  	4) View Explosion
  	
  	Super Fun Use Case:
  	
  	1) Attach a Detonator as above
  	2) Drag one or more DetonatorComponents to that same GameObject
  	3) Tweak those parameters
  	4) Explode()
  	5) View Explosion
  	
  	Better documentation is included as a PDF with this package, or is available online. Check the Unity site for a link
  	or visit my site, listed below.
  	
  	Ben Throop
  	@ben_throop
  */
  
  [AddComponentMenu("Detonator/Detonator")]
  public class Detonator : MonoBehaviour {
  
  	private static float _baseSize = 30f;
  	private static Color _baseColor = new Color(1f, .423f, 0f, .5f);
  	private static float _baseDuration = 3f;
  	
  	/*
  		_baseSize reflects the size that DetonatorComponents at size 1 match. Yes, this is really big (30m)
  		size below is the default Detonator size, which is more reasonable for typical useage. 
  		It wasn't my intention for them to be different, and I may change that, but for now, that's how it is.
  	*/
  	public float size = 10f; 
  	public Color color = Detonator._baseColor;
  	public bool explodeOnStart = true;
  	public float duration = Detonator._baseDuration;
  	public float detail = 1f; 
  	public float upwardsBias = 0f;
  	
  	public float destroyTime = 7f; //sorry this is not auto calculated... yet.
  	public bool useWorldSpace = true;
  	public Vector3 direction = Vector3.zero;
  	
  	public Material fireballAMaterial;
  	public Material fireballBMaterial;
  	public Material smokeAMaterial;
  	public Material smokeBMaterial;
  	public Material shockwaveMaterial;
  	public Material sparksMaterial;
  	public Material glowMaterial;
  	public Material heatwaveMaterial;
  		
      private Component[] components;
  
  	private DetonatorFireball _fireball;
  	private DetonatorSparks _sparks;
  	private DetonatorShockwave _shockwave;
  	private DetonatorSmoke _smoke;
  	private DetonatorGlow _glow;
  	private DetonatorLight _light;
  	private DetonatorForce _force;
  	private DetonatorHeatwave _heatwave;
  	public bool autoCreateFireball = true;
  	public bool autoCreateSparks = true;
  	public bool autoCreateShockwave = true;
  	public bool autoCreateSmoke = true;
  	public bool autoCreateGlow = true;
  	public bool autoCreateLight = true;
  	public bool autoCreateForce = true;
  	public bool autoCreateHeatwave = false;
  	
  	void Awake() 
  	{
  		FillDefaultMaterials();
  		
          components = this.GetComponents(typeof(DetonatorComponent));
  		foreach (DetonatorComponent dc in components)
  		{
  			if (dc is DetonatorFireball)
  			{
  				_fireball = dc as DetonatorFireball;
  			}
  			if (dc is DetonatorSparks)
  			{
  				_sparks = dc as DetonatorSparks;
  			}
  			if (dc is DetonatorShockwave)
  			{
  				_shockwave = dc as DetonatorShockwave;
  			}
  			if (dc is DetonatorSmoke)
  			{
  				_smoke = dc as DetonatorSmoke;
  			}
  			if (dc is DetonatorGlow)
  			{
  				_glow = dc as DetonatorGlow;
  			}
  			if (dc is DetonatorLight)
  			{
  				_light = dc as DetonatorLight;
  			}
  			if (dc is DetonatorForce)
  			{
  				_force = dc as DetonatorForce;
  			}
  			if (dc is DetonatorHeatwave)
  			{
  				_heatwave = dc as DetonatorHeatwave;
  			}
  		}
  		
  		if (!_fireball && autoCreateFireball)
  		{
  			_fireball = gameObject.AddComponent<DetonatorFireball>() as DetonatorFireball;
  			_fireball.Reset();
  		}
  		
  		if (!_smoke && autoCreateSmoke)
  		{
  			_smoke = gameObject.AddComponent<DetonatorSmoke>() as DetonatorSmoke;
  			_smoke.Reset();
  		}
  		
  		if (!_sparks && autoCreateSparks)
  		{
  			_sparks = gameObject.AddComponent<DetonatorSparks>() as DetonatorSparks;
  			_sparks.Reset();
  		}
  		
  		if (!_shockwave && autoCreateShockwave)
  		{
  			_shockwave = gameObject.AddComponent<DetonatorShockwave>() as DetonatorShockwave;
  			_shockwave.Reset();
  		}
  		
  		if (!_glow && autoCreateGlow)
  		{
  			_glow = gameObject.AddComponent<DetonatorGlow>() as DetonatorGlow;
  			_glow.Reset();
  		}
  		
  		if (!_light && autoCreateLight)
  		{
  			_light = gameObject.AddComponent<DetonatorLight>() as DetonatorLight;
  			_light.Reset();
  		}
  		
  		if (!_force && autoCreateForce)
  		{
  			_force = gameObject.AddComponent<DetonatorForce>() as DetonatorForce;
  			_force.Reset();
  		}
  
          if (!_heatwave && autoCreateHeatwave && SystemInfo.supportsImageEffects)
  		{
  			_heatwave = gameObject.AddComponent<DetonatorHeatwave>() as DetonatorHeatwave;
  			_heatwave.Reset();
  		}
  		
  		components = this.GetComponents(typeof(DetonatorComponent));
  	}
  	
  	void FillDefaultMaterials()
  	{
  		if (!fireballAMaterial) fireballAMaterial = DefaultFireballAMaterial();
  		if (!fireballBMaterial) fireballBMaterial = DefaultFireballBMaterial();
  		if (!smokeAMaterial) smokeAMaterial = DefaultSmokeAMaterial();
  		if (!smokeBMaterial) smokeBMaterial = DefaultSmokeBMaterial();
  		if (!shockwaveMaterial) shockwaveMaterial = DefaultShockwaveMaterial();
  		if (!sparksMaterial) sparksMaterial = DefaultSparksMaterial();
  		if (!glowMaterial) glowMaterial = DefaultGlowMaterial();
  		if (!heatwaveMaterial) heatwaveMaterial = DefaultHeatwaveMaterial();
  	}
  	
  	void Start()
  	{
  		if (explodeOnStart)
  		{
  			UpdateComponents();
  			this.Explode();
  		}
  	}
  	
  	private float _lastExplosionTime = 1000f;
  	void Update () 
      {
  		if (destroyTime > 0f)
  		{
  			if (_lastExplosionTime + destroyTime <= Time.time)
  			{
  				Destroy(gameObject);
  			}
  		}
  	}
  	
  	private bool _firstComponentUpdate = true;
  
  	void UpdateComponents()
  	{
  		if (_firstComponentUpdate)
  		{
  			foreach (DetonatorComponent component in components)
  			{
  				component.Init();
  				component.SetStartValues();
  			}
  			_firstComponentUpdate = false;
  		}
  		
  		if (!_firstComponentUpdate)
  		{
  
gt: 			float s = size / _baseSize;