context: using UnityEngine;
  #if UNITY_EDITOR
  	using UnityEditor;
  #endif
  using System.Collections;
  using System.Reflection;
  
  // Cartoon FX Easy Editor - (c) 2013, Jean Moreno
  
  #if UNITY_EDITOR
  public class CFXEasyEditor : EditorWindow
  {
  	static private CFXEasyEditor SingleWindow;
  	
  	[MenuItem("Window/CartoonFX Easy Editor")]
  	static void ShowWindow()
  	{
  		CFXEasyEditor window = EditorWindow.GetWindow<CFXEasyEditor>(EditorPrefs.GetBool("CFX_ShowAsToolbox", true), "CartoonFX Easy Editor", true);
  		window.minSize = new Vector2(300, 8);
  		window.maxSize = new Vector2(300, 8);
  		window.foldoutChanged = true;
  	}
  	
  	//Change Start Color
  	private bool AffectAlpha = true;
  	private Color ColorValue = Color.white;
  	private Color ColorValue2 = Color.white;
  	
  	//Scale
  	private float ScalingValue = 2.0f;
  	private float LTScalingValue = 100.0f;
  	
  	//Delay
  	private float DelayValue = 1.0f;
  	
  	//Duration
  	private float DurationValue = 5.0f;
  	
  	//Tint
  	private bool TintStartColor = true;
  	private bool TintColorModule = true;
  	private bool TintColorSpeedModule = true;
  	private Color TintColorValue = Color.white;
  	
  	//Change Lightness
  	private int LightnessStep = 10;
  	
  	//Module copying
  	private ParticleSystem sourceObject;
  	private Color ColorSelected = new Color(0.8f,0.95f,1.0f,1.0f);
  	private bool[] b_modules = new bool[16];
  	
  	//Foldouts
  	bool basicFoldout = false;
  	bool colorFoldout = false;
  	bool copyFoldout = false;
  	bool foldoutChanged;
  	
  	//Editor Prefs
  	private bool pref_ShowAsToolbox;
  	private bool pref_IncludeChildren;
  	
  	void OnEnable()
  	{
  		//Load Settings
  		pref_ShowAsToolbox = EditorPrefs.GetBool("CFX_ShowAsToolbox", true);
  		pref_IncludeChildren = EditorPrefs.GetBool("CFX_IncludeChildren", true);
  		basicFoldout = EditorPrefs.GetBool("CFX_BasicFoldout", false);
  		colorFoldout = EditorPrefs.GetBool("CFX_ColorFoldout", false);
  		copyFoldout = EditorPrefs.GetBool("CFX_CopyFoldout", false);
  	}
  	
  	void OnDisable()
  	{
  		//Save Settings
  		EditorPrefs.SetBool("CFX_BasicFoldout", basicFoldout);
  		EditorPrefs.SetBool("CFX_ColorFoldout", colorFoldout);
  		EditorPrefs.SetBool("CFX_CopyFoldout", copyFoldout);
  	}
  	
  	void OnGUI()
  	{
  		GUILayout.BeginArea(new Rect(0,0,this.position.width - 8,this.position.height));
  		GUILayout.Space(4);
  		
  		GUILayout.BeginHorizontal();
  		GUILayout.Label("CARTOON FX Easy Editor", EditorStyles.boldLabel);
  		pref_ShowAsToolbox = GUILayout.Toggle(pref_ShowAsToolbox, new GUIContent("Toolbox", "If enabled, the window will be displayed as an external toolbox.\nIf false, it will act as a dockable Unity window."), GUILayout.Width(60));
  		if(GUI.changed)
  		{
  			EditorPrefs.SetBool("CFX_ShowAsToolbox", pref_ShowAsToolbox);
  			this.Close();
  			CFXEasyEditor.ShowWindow();
  		}
  		GUILayout.EndHorizontal();
  		GUILayout.Label("Easily change properties of any Particle System!", EditorStyles.miniLabel);
  		
  	//----------------------------------------------------------------
  		
  		pref_IncludeChildren = GUILayout.Toggle(pref_IncludeChildren, new GUIContent("Include Children", "If checked, changes will affect every Particle Systems from each child of the selected GameObject(s)"));
  		if(GUI.changed)
  		{
  			EditorPrefs.SetBool("CFX_IncludeChildren", pref_IncludeChildren);
  		}
  		
  		EditorGUILayout.BeginHorizontal();
  		
  		GUILayout.Label("Test effect(s):");
  		
  		if(GUILayout.Button("Play", EditorStyles.miniButtonLeft, GUILayout.Width(50f)))
  		{
  			foreach(GameObject go in Selection.gameObjects)
  			{
  				ParticleSystem[] systems = go.GetComponents<ParticleSystem>();
  				if(systems.Length == 0) continue;
  				foreach(ParticleSystem system in systems)
  					system.Play(pref_IncludeChildren);
  			}
  		}
  		if(GUILayout.Button("Pause", EditorStyles.miniButtonMid, GUILayout.Width(50f)))
  		{
  			foreach(GameObject go in Selection.gameObjects)
  			{
  				ParticleSystem[] systems = go.GetComponents<ParticleSystem>();
  				if(systems.Length == 0) continue;
  				foreach(ParticleSystem system in systems)
  					system.Pause(pref_IncludeChildren);
  			}
  		}
  		if(GUILayout.Button("Stop", EditorStyles.miniButtonMid, GUILayout.Width(50f)))
  		{
  			foreach(GameObject go in Selection.gameObjects)
  			{
  				ParticleSystem[] systems = go.GetComponents<ParticleSystem>();
  				if(systems.Length == 0) continue;
  				foreach(ParticleSystem system in systems)
  					system.Stop(pref_IncludeChildren);
  			}
  		}
  		if(GUILayout.Button("Clear", EditorStyles.miniButtonRight, GUILayout.Width(50f)))
  		{
  			foreach(GameObject go in Selection.gameObjects)
  			{
  				ParticleSystem[] systems = go.GetComponents<ParticleSystem>();
  				if(systems.Length == 0) continue;
  				foreach(ParticleSystem system in systems)
  				{
  					system.Stop(pref_IncludeChildren);
  					system.Clear(pref_IncludeChildren);
  				}
  			}
  		}
  		
  		GUILayout.FlexibleSpace();
  		EditorGUILayout.EndHorizontal();
  		
  	//----------------------------------------------------------------
  		
  		//Separator
  		GUILayout.Box("",GUILayout.Width(this.position.width - 12), GUILayout.Height(3));
  		
  		EditorGUI.BeginChangeCheck();
  		basicFoldout = EditorGUILayout.Foldout(basicFoldout, "QUICK EDIT");
  		if(EditorGUI.EndChangeCheck())
  		{
  			foldoutChanged = true;
  		}
  		if(basicFoldout)
  		{
  		
  		//----------------------------------------------------------------
  			
  			GUILayout.BeginHorizontal();
  			if(GUILayout.Button(new GUIContent("Scale Size", "Changes the size of the Particle System(s) and other values accordingly (speed, gravity, etc.)"), GUILayout.Width(120)))
  			{
  				applyScale();
  			}
  			GUILayout.Label("Multiplier:",GUILayout.Width(110));
  			ScalingValue = EditorGUILayout.FloatField(ScalingValue,GUILayout.Width(50));
  			if(ScalingValue <= 0) ScalingValue = 0.1f;
  			GUILayout.EndHorizontal();
  			
  		//----------------------------------------------------------------
  			
  			GUILayout.BeginHorizontal();
  			if(GUILayout.Button(new GUIContent("Set Speed", "Changes the speed of the Particle System(s) (if you want quicker or longer effects, 100% = default speed)"), GUILayout.Width(120)))
  			{
  				applySpeed();
  			}
  			GUILayout.Label("Speed (%):",GUILayout.Width(110));
  			LTScalingValue = EditorGUILayout.FloatField(LTScalingValue,GUILayout.Width(50));
  			if(LTScalingValue < 0.1f) LTScalingValue = 0.1f;
  			else if(LTScalingValue > 9999) LTScalingValue = 9999;
  			GUILayout.EndHorizontal();
  			
  		//----------------------------------------------------------------
  			
  			GUILayout.BeginHorizontal();
  			if(GUILayout.Button(new GUIContent("Set Duration", "Changes the duration of the Particle System(s)"), GUILayout.Width(120)))
  			{
  				applyDuration();
  			}
  			GUILayout.Label("Duration (sec):",GUILayout.Width(110));
  			DurationValue = EditorGUILayout.FloatField(DurationValue,GUILayout.Width(50));
  			if(DurationValue < 0.1f) DurationValue = 0.1f;
  			else if(DurationValue > 9999) DurationValue = 9999;
  			GUILayout.EndHorizontal();
  			
  		//----------------------------------------------------------------
  			
  			GUILayout.BeginHorizontal();
  			if(GUILayout.Button(new GUIContent("Set Delay", "Changes the delay of the Particle System(s)"), GUILayout.Width(120)))
  			{
  				applyDelay();
  			}
  			GUILayout.Label("Delay :",GUILayout.Width(110));
  			DelayValue = EditorGUILayout.FloatField(DelayValue,GUILayout.Width(50));
  			if(DelayValue < 0.0f) DelayValue = 0.0f;
  			else if(DelayValue > 9999f) DelayValue = 9999f;
  			GUILayout.EndHorizontal();
  			
  		//----------------------------------------------------------------
  			
  			GUILayout.Space(2);
  			
  			GUILayout.BeginHorizontal();
  			if(GUILayout.Button(new GUIContent("Loop", "Loop the effect (might not work properly on some effects such as explosions)"), EditorStyles.miniButtonLeft))
  			{
  				loopEffect(true);
  			}
  			if(GUILayout.Button(new GUIContent("Unloop", "Remove looping from the effect"), EditorStyles.miniButtonRight))
  			{
  				loopEffect(false);
  			}
  			if(GUILayout.Button(new GUIContent("Prewarm On", "Prewarm the effect (if looped)"), EditorStyles.miniButtonLeft))
  			{
  				prewarmEffect(true);
  			}
  			if(GUILayout.Button(new GUIContent("Prewarm Off", "Don't prewarm the effect (if looped)"), EditorStyles.miniButtonRight))
  			{
  				prewarmEffect(false);
  			}
  			GUILayout.EndHorizontal();
  			
  			GUILayout.Space(2);
  		
  	//----------------------------------------------------------------
  		
  		}
  		
  		//Separator
  		GUILayout.Box("",GUILayout.Width(this.position.width - 12), GUILayout.Height(3));
  		
  		EditorGUI.BeginChangeCheck();
  		colorFoldout = EditorGUILayout.Foldout(colorFoldout, "COLOR EDIT");
  		if(EditorGUI.EndChangeCheck())
  		{
  			foldoutChanged = true;
  		}
  		if(colorFoldout)
  		{
  		
  		//----------------------------------------------------------------
  			
  			GUILayout.BeginHorizontal();
  			if(GUILayout.Button(new GUIContent("Set Start Color(s)", "Changes the color(s) of the Particle System(s)\nSecond Color is used when Start Color is 'Random Between Two Colors'."),GUILayout.Width(120)))
  			{
  				applyColor();
  			}
  			ColorValue = EditorGUILayout.ColorField(ColorValue);
  			ColorValue2 = EditorGUILayout.ColorField(ColorValue2);
  			AffectAlpha = GUILayout.Toggle(AffectAlpha, new GUIContent("Alpha", "If checked, the alpha value will also be changed"));
  			GUILayout.EndHorizontal();
  			
  		//----------------------------------------------------------------
  			
  			GUILayout.BeginHorizontal();
  			if(GUILayout.Button(new GUIContent("Tint Colors", "Tints the colors of the Particle System(s), including gradients!\n(preserving their saturation and lightness)"),GUILayout.Width(120)))
  			{
  				tintColor();
  			}
  			TintColorValue = EditorGUILayout.ColorField(TintColorValue);
  			TintColorValue = HSLColor.FromRGBA(TintColorValue).VividColor();
  			GUILayout.EndHorizontal();
  			
  		//----------------------------------------------------------------
  			
  			/*
  			GUILayout.BeginHorizontal();
  			GUILayout.Label("Add/Substract Lightness:");
  			
  			LightnessStep = EditorGUILayout.IntField(LightnessStep, GUILayout.Width(30));
  			if(LightnessStep > 99) LightnessStep = 99;
  			else if(LightnessStep < 1) LightnessStep = 1;
  			GUILayout.Label("%");
  			
  			if(GUILayout.Button("-", EditorStyles.miniButtonLeft, GUILayout.Width(22)))
  			{
  				addLightness(true);
  			}
  			if(GUILayout.Button("+", EditorStyles.miniButtonRight, GUILayout.Width(22)))
  			{
  				addLightness(false);
  			}
  			GUILayout.FlexibleSpace();
  			GUILayout.EndHorizontal();
  			*/
  			
  		//----------------------------------------------------------------
  			
  			GUILayout.Label("Color Modules to affect:");
  			
  			GUILayout.BeginHorizontal();
  			GUILayout.FlexibleSpace();
  			
  			GUI.color = TintStartColor ? ColorSelected : Color.white; if(GUILayout.Button(new GUIContent("Start Color", "If checked, the \"Start Color\" value(s) will be affected."), EditorStyles.toolbarButton, GUILayout.Width(70))) TintStartColor = !TintStartColor;
  			GUI.color = TintColorModule ? ColorSelected : Color.white; if(GUILayout.Button(new GUIContent("Color over Lifetime", "If checked, the \"Color over Lifetime\" value(s) will be affected."), EditorStyles.toolbarButton, GUILayout.Width(110))) TintColorModule = !TintColorModule;
  			GUI.color = TintColorSpeedModule ? ColorSelected : Color.white; if(GUILayout.Button(new GUIContent("Color by Speed", "If checked, the \"Color by Speed\" value(s) will be affected."), EditorStyles.toolbarButton, GUILayout.Width(100))) TintColorSpeedModule = !TintColorSpeedModule;
  			GUI.color = Color.white;
  			
  			GUILayout.FlexibleSpace();
  			GUILayout.EndHorizontal();
  			
  			GUILayout.Space(4);
  			
  		//----------------------------------------------------------------
  			
  		}
  		
  		//Separator
  		GUILayout.Box("",GUILayout.Width(this.position.width - 12), GUILayout.Height(3));
  //		GUILayout.Space(6);
  		
  	//----------------------------------------------------------------
  		
  		EditorGUI.BeginChangeCheck();
  		copyFoldout = EditorGUILayout.Foldout(copyFoldout, "COPY MODULES");
  		if(EditorGUI.EndChangeCheck())
  		{
  			foldoutChanged = true;
  		}
  		if(copyFoldout)
  		{
  		
  			GUILayout.Label("Copy properties from a Particle System to others!", EditorStyles.miniLabel);
  			
  			GUILayout.BeginHorizontal();
  			GUILayout.Label("Source Object:", GUILayout.Width(110));
  			sourceObject = (ParticleSystem)EditorGUILayout.ObjectField(sourceObject, typeof(ParticleSystem), true);
  			GUILayout.EndHorizontal();
  			
  			EditorGUILayout.LabelField("Modules to Copy:");
  			
  			GUILayout.BeginHorizontal();
  			GUILayout.FlexibleSpace();
  			if(GUILayout.Button("ALL", EditorStyles.miniButtonLeft, GUILayout.Width(120)))
  			{
  				for(int i = 0; i < b_modules.Length; i++) b_modules[i] = true;
  			}
  			if(GUILayout.Button("NONE", EditorStyles.miniButtonRight, GUILayout.Width(120)))
  			{
  				for(int i = 0; i < b_modules.Length; i++) b_modules[i] = false;
  			}
  			GUILayout.FlexibleSpace();
  			GUILayout.EndHorizontal();
  			
  			GUILayout.Space(4);
  			
  			GUILayout.BeginHorizontal();
  			GUILayout.FlexibleSpace();
  			GUI.color = b_modules[0] ? ColorSelected : Color.white;	if(GUILayout.Button("Initial", EditorStyles.toolbarButton, GUILayout.Width(70))) b_modules[0] = !b_modules[0];
  			GUI.color = b_modules[1] ? ColorSelected : Color.white;	if(GUILayout.Button("Emission", EditorStyles.toolbarButton, GUILayout.Width(70))) b_modules[1] = !b_modules[1];
  			GUI.color = b_modules[2] ? ColorSelected : Color.white;	if(GUILayout.Button("Shape", EditorStyles.toolbarButton, GUILayout.Width(70))) b_modules[2] = !b_modules[2];
  			GUILayout.FlexibleSpace();
  			GUILayout.EndHorizontal();
  			GUILayout.BeginHorizontal();
  			GUILayout.FlexibleSpace();
  			GUI.color = b_modules[3] ? ColorSelected : Color.white;	if(GUILayout.Button("Velocity", EditorStyles.toolbarButton, GUILayout.Width(70))) b_modules[3] = !b_modules[3];
  			GUI.color = b_modules[4] ? ColorSelected : Color.white;	if(GUILayout.Button("Limit Velocity", EditorStyles.toolbarButton, GUILayout.Width(100))) b_modules[4] = !b_modules[4];
  			GUI.color = b_modules[5] ? ColorSelected : Color.white;	if(GUILayout.Button("Force", EditorStyles.toolbarButton, GUILayout.Width(70))) b_modules[5] = !b_modules[5];
  			GUILayout.FlexibleSpace();
  			GUILayout.EndHorizontal();
  			GUILayout.BeginHorizontal();
  			GUILayout.FlexibleSpace();
  			GUI.color = b_modules[6] ? ColorSelected : Color.white;	if(GUILayout.Button("Color over Lifetime", EditorStyles.toolbarButton, GUILayout.Width(120))) b_modules[6] = !b_modules[6];
  			GUI.color = b_modules[7] ? ColorSelected : Color.white;	if(GUILayout.Button("Color by Speed", EditorStyles.toolbarButton, GUILayout.Width(120))) b_modules[7] = !b_modules[7];
  			GUILayout.FlexibleSpace();
  			GUILayout.EndHorizontal();
  			GUILayout.BeginHorizontal();
  			GUILayout.FlexibleSpace();
  			GUI.color = b_modules[8] ? ColorSelected : Color.white;	if(GUILayout.Button("Size over Lifetime", EditorStyles.toolbarButton, GUILayout.Width(120))) b_modules[8] = !b_modules[8];
  			GUI.color = b_modules[9] ? ColorSelected : Color.white;	if(GUILayout.Button("Size by Speed", EditorStyles.toolbarButton, GUILayout.Width(120))) b_modules[9] = !b_modules[9];
  			GUILayout.FlexibleSpace();
  			GUILayout.EndHorizontal();
  			GUILayout.BeginHorizontal();
  			GUILayout.FlexibleSpace();
  			GUI.color = b_modules[10] ? ColorSelected : Color.white;	if(GUILayout.Button("Rotation over Lifetime", EditorStyles.toolbarButton, GUILayout.Width(120))) b_modules[10] = !b_modules[10];
  			GUI.color = b_modules[11] ? ColorSelected : Color.white;	if(GUILayout.Button("Rotation by Speed", EditorStyles.toolbarButton, GUILayout.Width(120))) b_modules[11] = !b_modules[11];
  			GUILayout.FlexibleSpace();
  			GUILayout.EndHorizontal();
  			GUILayout.BeginHorizontal();
  			GUILayout.FlexibleSpace();
  			GUI.color = b_modules[12] ? ColorSelected : Color.white;	if(GUILayout.Button("Collision", EditorStyles.toolbarButton, GUILayout.Width(100))) b_modules[12] = !b_modules[12];
  			GUI.color = b_modules[13] ? ColorSelected : Color.white;	if(GUILayout.Button("Sub Emitters", EditorStyles.toolbarButton, GUILayout.Width(100))) b_modules[13] = !b_modules[13];
  			GUILayout.FlexibleSpace();
  			GUILayout.EndHorizontal();
  			GUILayout.BeginHorizontal();
  			GUILayout.FlexibleSpace();
  			GUI.color = b_modules[14] ? ColorSelected : Color.white;	if(GUILayout.Button("Texture Animation", EditorStyles.toolbarButton, GUILayout.Width(110))) b_modules[14] = !b_modules[14];
  			GUI.color = b_modules[15] ? ColorSelected : Color.white;	if(GUILayout.Button("Renderer", EditorStyles.toolbarButton, GUILayout.Width(90))) b_modules[15] = !b_modules[15];
  			GUILayout.FlexibleSpace();
  			GUILayout.EndHorizontal();
  			
  			GUI.color = Color.white;
  			
  			GUILayout.Space(4);
  			if(GUILayout.Button("Copy properties to selected Object(s)"))
  			{
  				bool foundPs = false;
  				foreach(GameObject go in Selection.gameObjects)
  				{
  					ParticleSystem[] systems;
  					if(pref_IncludeChildren)		systems = go.GetComponentsInChildren<ParticleSystem>(true);
  					else 					systems = go.GetComponents<ParticleSystem>();
  					
  					if(systems.Length == 0) continue;
  					
  					foundPs = true;
  					foreach(ParticleSystem system in systems)	CopyModules(sourceObject, system);
  				}
  				
  				if(!foundPs)
  				{
  					Debug.LogWarning("CartoonFX Easy Editor: No Particle System found in the selected GameObject(s)!");
  				}
  			}
  		}
  			
  		//----------------------------------------------------------------
  		
  		GUILayout.Space(8);
  		
  		//Resize window
  		if(foldoutChanged && Event.current.type == EventType.repaint)
  		{
  			foldoutChanged = false;
  			
  			Rect r = GUILayoutUtility.GetLastRect();
  			this.minSize = new Vector2(300,r.y + 8);
  			this.maxSize = new Vector2(300,r.y + 8);
  		}
  		
  		GUILayout.EndArea();
  	}
  	
  	//Loop effects
  	private void loopEffect(bool setLoop)
  	{
  		foreach(GameObject go in Selection.gameObjects)
  		{
  			//Scale Shuriken Particles Values
  			ParticleSystem[] systems;
  			if(pref_IncludeChildren)		systems = go.GetComponentsInChildren<ParticleSystem>(true);
  			else 					systems = go.GetComponents<ParticleSystem>();
  			
  			foreach(ParticleSystem ps in systems)
  			{
  				SerializedObject so = new SerializedObject(ps);
  				so.FindProperty("looping").boolValue = setLoop;
  				so.ApplyModifiedProperties();
  			}
  		}
  	}
  	
  	//Prewarm effects
  	private void prewarmEffect(bool setPrewarm)
  	{
  		foreach(GameObject go in Selection.gameObjects)
  		{
  			//Scale Shuriken Particles Values
  			ParticleSystem[] systems;
  			if(pref_IncludeChildren)		systems = go.GetComponentsInChildren<ParticleSystem>(true);
  			else 					systems = go.GetComponents<ParticleSystem>();
  			
  			foreach(ParticleSystem ps in systems)
  			{
  				SerializedObject so = new SerializedObject(ps);
  				so.FindProperty("prewarm").boolValue = setPrewarm;
  				so.ApplyModifiedProperties();
  			}
  		}
  	}
  	
  	//Scale Size
  	private void applyScale()
  	{
  		foreach(GameObject go in Selection.gameObjects)
  		{
  			//Scale Shuriken Particles Values
  			ParticleSystem[] systems;
  			if(pref_IncludeChildren)		systems = go.GetComponentsInChildren<ParticleSystem>(true);
  
gt: 			else 					systems = go.GetComponents<ParticleSystem>();