public bool DrawQuickEditorGUI(PresetEffectSetting effect_setting, float gui_x_offset, ref float gui_y_offset, bool ignore_gui_changes)
		{
			VertexColour colorFrom = new VertexColour (), colorTo = new VertexColour (), colorThen = new VertexColour ();

			EditorGUI.LabelField (new Rect (gui_x_offset, gui_y_offset, 300, LINE_HEIGHT), effect_setting.m_setting_name);
			
			gui_y_offset += LINE_HEIGHT;
			gui_x_offset += 15;

			if(!m_use_colour_gradients)
			{
				colorFrom.top_left = EditorGUI.ColorField(new Rect(gui_x_offset, gui_y_offset, LINE_HEIGHT*2, LINE_HEIGHT), ValueFrom.top_left);
				gui_x_offset += 45;
			}
			else
			{
				colorFrom.top_left = EditorGUI.ColorField(new Rect(gui_x_offset, gui_y_offset, LINE_HEIGHT*2, LINE_HEIGHT), ValueFrom.top_left);
				colorFrom.bottom_left = EditorGUI.ColorField(new Rect(gui_x_offset, gui_y_offset + LINE_HEIGHT, LINE_HEIGHT*2, LINE_HEIGHT), ValueFrom.bottom_left);
				gui_x_offset += 45;
				colorFrom.top_right = EditorGUI.ColorField(new Rect(gui_x_offset, gui_y_offset, LINE_HEIGHT*2, LINE_HEIGHT), ValueFrom.top_right);
				colorFrom.bottom_right = EditorGUI.ColorField(new Rect(gui_x_offset, gui_y_offset + LINE_HEIGHT, LINE_HEIGHT*2, LINE_HEIGHT), ValueFrom.bottom_right);

				gui_x_offset += 45;
			}


			if(Progression == (int) ValueProgression.Eased || Progression == (int) ValueProgression.EasedCustom || Progression == (int) ValueProgression.Random)
			{
				EditorGUI.LabelField (new Rect (gui_x_offset + 5, gui_y_offset + (m_use_colour_gradients ? 10 : 0), 20, LINE_HEIGHT), "->", EditorStyles.boldLabel);

				gui_x_offset += 35;
				
				if(!m_use_colour_gradients)
				{
					colorTo.top_left = EditorGUI.ColorField(new Rect(gui_x_offset, gui_y_offset, LINE_HEIGHT*2, LINE_HEIGHT), ValueTo.top_left);
					gui_x_offset += 45;
				}
				else
				{
					colorTo.top_left = EditorGUI.ColorField(new Rect(gui_x_offset, gui_y_offset, LINE_HEIGHT*2, LINE_HEIGHT), ValueTo.top_left);
					colorTo.bottom_left = EditorGUI.ColorField(new Rect(gui_x_offset, gui_y_offset + LINE_HEIGHT, LINE_HEIGHT*2, LINE_HEIGHT), ValueTo.bottom_left);
					gui_x_offset += 45;
					colorTo.top_right = EditorGUI.ColorField(new Rect(gui_x_offset, gui_y_offset, LINE_HEIGHT*2, LINE_HEIGHT), ValueTo.top_right);
					colorTo.bottom_right = EditorGUI.ColorField(new Rect(gui_x_offset, gui_y_offset + LINE_HEIGHT, LINE_HEIGHT*2, LINE_HEIGHT), ValueTo.bottom_right);
					gui_x_offset += 45;
				}
				
				if(Progression == (int) ValueProgression.Eased && m_to_to_bool)
				{
					EditorGUI.LabelField (new Rect (gui_x_offset + 5, gui_y_offset + (m_use_colour_gradients ? 10 : 0), 20, LINE_HEIGHT), "->", EditorStyles.boldLabel);
					
					gui_x_offset += 35;

					if(!m_use_colour_gradients)
					{
						colorThen.top_left = EditorGUI.ColorField(new Rect(gui_x_offset, gui_y_offset, LINE_HEIGHT*2, LINE_HEIGHT), ValueThen.top_left);
						gui_x_offset += 45;
					}
					else
					{
						colorThen.top_left = EditorGUI.ColorField(new Rect(gui_x_offset, gui_y_offset, LINE_HEIGHT*2, LINE_HEIGHT), ValueThen.top_left);
						colorThen.bottom_left = EditorGUI.ColorField(new Rect(gui_x_offset, gui_y_offset + LINE_HEIGHT, LINE_HEIGHT*2, LINE_HEIGHT), ValueThen.bottom_left);
						gui_x_offset += 45;
						colorThen.top_right = EditorGUI.ColorField(new Rect(gui_x_offset, gui_y_offset, LINE_HEIGHT*2, LINE_HEIGHT), ValueThen.top_right);
						colorThen.bottom_right = EditorGUI.ColorField(new Rect(gui_x_offset, gui_y_offset + LINE_HEIGHT, LINE_HEIGHT*2, LINE_HEIGHT), ValueThen.bottom_right);
						gui_x_offset += 45;
					}
				}
			}

			if(m_use_colour_gradients)
				gui_y_offset += 2 * LINE_HEIGHT;
			else
				gui_y_offset += LINE_HEIGHT;


			if(GUI.changed && !ignore_gui_changes)
			{
				if(Progression == (int) ValueProgression.Constant)
					SetConstant(colorFrom);
				else if(Progression == (int) ValueProgression.Eased)
				{
					if(m_to_to_bool)
						SetEased(colorFrom, colorTo, colorThen);
					else
						SetEased(colorFrom, colorTo);
				}
				else if(Progression == (int) ValueProgression.Random)
					SetRandom(colorFrom, colorTo);
				else if(Progression == (int) ValueProgression.EasedCustom)
					SetEasedCustom(colorFrom, colorTo);
				
				return true;
			}
			
			return false;
		}
		public bool DrawQuickEditorGUI(PresetEffectSetting effect_setting, float gui_x_offset, ref float gui_y_offset, bool ignore_gui_changes, float inputsXOffset = 200)
		{
			Vector3 vector3_from = Vector3.zero, vector3_to = Vector3.zero, vector3_then = Vector3.zero;

			EditorGUI.LabelField (new Rect (gui_x_offset, gui_y_offset, 300, LINE_HEIGHT), effect_setting.m_setting_name);

			gui_y_offset += LINE_HEIGHT;

			vector3_from = EditorGUI.Vector3Field(new Rect(gui_x_offset + 15, gui_y_offset, 135, LINE_HEIGHT),"", ValueFrom);


			if(Progression == (int) ValueProgression.Eased || Progression == (int) ValueProgression.EasedCustom || Progression == (int) ValueProgression.Random)
			{
				EditorGUI.LabelField (new Rect (gui_x_offset + 160, gui_y_offset, 20, LINE_HEIGHT), "->", EditorStyles.boldLabel);
				
				vector3_to = EditorGUI.Vector3Field(new Rect(gui_x_offset + 190, gui_y_offset, 135, LINE_HEIGHT), "", ValueTo);

				if(Progression == (int) ValueProgression.Eased && m_to_to_bool)
				{
					EditorGUI.LabelField (new Rect (gui_x_offset + 335, gui_y_offset, 20, LINE_HEIGHT), "->", EditorStyles.boldLabel);
					vector3_then = EditorGUI.Vector3Field(new Rect(gui_x_offset + 365, gui_y_offset, 135, LINE_HEIGHT), "", ValueThen);
				}
			}

			gui_y_offset += LINE_HEIGHT;

			if(GUI.changed && !ignore_gui_changes)
			{
				if(Progression == (int) ValueProgression.Constant)
					SetConstant(vector3_from);
				else if(Progression == (int) ValueProgression.Eased)
				{
					if(m_to_to_bool)
						SetEased(vector3_from, vector3_to, vector3_then);
					else
						SetEased(vector3_from, vector3_to);
				}
				else if(Progression == (int) ValueProgression.Random)
					SetRandom(vector3_from, vector3_to);
				else if(Progression == (int) ValueProgression.EasedCustom)
					SetEasedCustom(vector3_from, vector3_to);
				
				return true;
			}
			
			return false;
		}
		public void ImportData(string data, TextFxAnimationManager.PresetAnimationSection animationSection, PRESET_ANIMATION_SECTION section, bool force_clear_old_audio_particles = false)
		{
			if(force_clear_old_audio_particles)
				ClearCachedAudioParticleInstances(true);
			
			int num_actions_added = 0;
			int num_loops_added = 0;
			int insert_action_index = 0;
			int insert_loop_index = 0;
			
			if(section == PRESET_ANIMATION_SECTION.MAIN)
			{
				insert_action_index = m_preset_intro.m_start_action + m_preset_intro.m_num_actions + (m_preset_intro.m_active ? 1 : 0);
				insert_loop_index = m_preset_intro.m_start_loop + m_preset_intro.m_num_loops;
			}
			else if(section == PRESET_ANIMATION_SECTION.OUTRO)
			{
				insert_action_index = m_preset_main.m_start_action + m_preset_main.m_num_actions + (m_preset_main.m_active ? 1 : 0);
				insert_loop_index = m_preset_main.m_start_loop + m_preset_main.m_num_loops;
			}
			
			
			Boomlagoon.JSON.JSONObject json_data = Boomlagoon.JSON.JSONObject.Parse(data, true);
			
			if(json_data != null)
			{
				if(m_master_animations == null || m_master_animations.Count == 0)
				m_master_animations = new List<LetterAnimation>(){ new LetterAnimation() };
				
				
				m_master_animations[0].ImportPresetSectionData(json_data["LETTER_ANIMATIONS_DATA"].Obj, m_letters, insert_action_index, insert_loop_index, ref num_actions_added, ref num_loops_added, m_animation_interface_reference.AssetNameSuffix);
				
				animationSection.m_preset_effect_settings = new List<PresetEffectSetting>();
				
				// Import any Quick setup settings info
				if(json_data.ContainsKey("PRESET_EFFECT_SETTINGS"))
				{
					PresetEffectSetting effectSetting;
					foreach(Boomlagoon.JSON.JSONValue effectSettingData in json_data["PRESET_EFFECT_SETTINGS"].Array)
					{
						effectSetting = new PresetEffectSetting();
						effectSetting.ImportData(effectSettingData.Obj);
						animationSection.m_preset_effect_settings.Add(effectSetting);
					}
				}
			}
			else
			{
				// Import string is not valid JSON, therefore assuming it is in the legacy data import format.
				Debug.LogError("TextFx animation import failed. Non-valid JSON data provided");
				
//				this.ImportLegacyData(data);
//				
//				m_preset_effect_settings = new List<PresetEffectSetting>();
			}
			
			
			if(!Application.isPlaying && m_animation_interface_reference.Text.Equals(""))
				m_animation_interface_reference.SetText("TextFx");
			
			PrepareAnimationData ();
			
			ResetAnimation();
			
			// Update mesh
			m_animation_interface_reference.UpdateTextFxMesh(MeshVerts, MeshColours);
			
			SceneView.RepaintAll();
			
			animationSection.m_num_actions = num_actions_added;
			animationSection.m_num_loops = num_loops_added;
		}
		public void ImportData(string data, bool force_clear_old_audio_particles = false)
		{
			if(force_clear_old_audio_particles)
				ClearCachedAudioParticleInstances(true);
			
			Boomlagoon.JSON.JSONObject json_data = Boomlagoon.JSON.JSONObject.Parse(data, true);
			
			if(json_data != null)
			{
				m_animate_per = (AnimatePerOptions) (int) json_data["m_animate_per"].Number;
				
				if(json_data.ContainsKey("m_begin_delay")) m_begin_delay = (float) json_data["m_begin_delay"].Number;
				if(json_data.ContainsKey("m_begin_on_start")) m_begin_on_start = json_data["m_begin_on_start"].Boolean;
				if(json_data.ContainsKey("m_on_finish_action")) m_on_finish_action = (ON_FINISH_ACTION) (int) json_data["m_on_finish_action"].Number;
				if(json_data.ContainsKey("m_time_type")) m_time_type = (AnimationTime) (int) json_data["m_time_type"].Number;
				
				m_master_animations = new List<LetterAnimation>();
				LetterAnimation letter_anim;
				foreach(Boomlagoon.JSON.JSONValue animation_data in json_data["LETTER_ANIMATIONS_DATA"].Array)
				{
					letter_anim = new LetterAnimation();
					letter_anim.ImportData(animation_data.Obj, m_animation_interface_reference.AssetNameSuffix);
					m_master_animations.Add(letter_anim);
				}

#if UNITY_EDITOR
				m_preset_effect_settings = new List<PresetEffectSetting>();

				// Import any Quick setup settings info
				if(json_data.ContainsKey("PRESET_EFFECT_SETTINGS"))
				{
					PresetEffectSetting effectSetting;
					foreach(Boomlagoon.JSON.JSONValue effectSettingData in json_data["PRESET_EFFECT_SETTINGS"].Array)
					{
						effectSetting = new PresetEffectSetting();
						effectSetting.ImportData(effectSettingData.Obj);
						m_preset_effect_settings.Add(effectSetting);
					}
				}
#endif
			}
			else
			{
				// Import string is not valid JSON, therefore assuming it is in the legacy data import format.
				Debug.LogError("TextFx animation import failed. Non-valid JSON data provided");

				this.ImportLegacyData(data);

#if UNITY_EDITOR
				m_preset_effect_settings = new List<PresetEffectSetting>();
#endif
			}


			if(!Application.isPlaying && m_animation_interface_reference.Text.Equals(""))
				m_animation_interface_reference.SetText("TextFx");

			PrepareAnimationData ();

			ResetAnimation();

			// Update mesh
			m_animation_interface_reference.UpdateTextFxMesh(MeshVerts, MeshColours);

#if UNITY_EDITOR
			SceneView.RepaintAll();
#endif
		}
		// Used for importing a preset animation section's data, to have its animation edited in the editor, or have its quick-edit settings edited
		public void ImportPresetAnimationSectionData(string data, bool force_clear_old_audio_particles = false)
		{
			if(force_clear_old_audio_particles)
				ClearCachedAudioParticleInstances(true);
			
			Boomlagoon.JSON.JSONObject json_data = Boomlagoon.JSON.JSONObject.Parse(data, true);
			
			if(json_data != null)
			{
				m_master_animations = new List<LetterAnimation>();
				LetterAnimation letter_anim = new LetterAnimation();
				letter_anim.ImportPresetSectionData(json_data["LETTER_ANIMATIONS_DATA"].Obj, m_letters, m_animation_interface_reference.AssetNameSuffix);

				m_master_animations.Add(letter_anim);
				
				m_preset_effect_settings = new List<PresetEffectSetting>();
				
				// Import any Quick setup settings info
				if(json_data.ContainsKey("PRESET_EFFECT_SETTINGS"))
				{
					PresetEffectSetting effectSetting;
					foreach(Boomlagoon.JSON.JSONValue effectSettingData in json_data["PRESET_EFFECT_SETTINGS"].Array)
					{
						effectSetting = new PresetEffectSetting();
						effectSetting.ImportData(effectSettingData.Obj);
						m_preset_effect_settings.Add(effectSetting);
					}
				}
			}
			else
			{
				// Import string is not valid JSON, therefore assuming it is in the legacy data import format.
				Debug.LogError("TextFx animation import failed. Non-valid JSON data provided");
			}
			
			if(!Application.isPlaying && m_animation_interface_reference.Text.Equals(""))
				m_animation_interface_reference.SetText("TextFx");
			
			PrepareAnimationData ();
			
			ResetAnimation();
			
			// Update mesh
			m_animation_interface_reference.UpdateTextFxMesh(MeshVerts, MeshColours);
			
			SceneView.RepaintAll();
		}