public ParticleEffectInstanceManager(TextFxAnimationManager animation_manager, LetterSetup letter_setup_ref, ParticleEffectSetup effect_setup, AnimationProgressionVariables progression_vars, AnimatePerOptions animate_per, ParticleEmitter particle_emitter = null, ParticleSystem particle_system = null)
		{
			m_particle_emitter = particle_emitter;
			m_particle_system = particle_system;
			m_letter_setup_ref = letter_setup_ref;
			m_follow_mesh = effect_setup.m_follow_mesh;
			m_duration = effect_setup.m_duration.GetValue(progression_vars, animate_per);
			m_delay = effect_setup.m_delay.GetValue(progression_vars, animate_per);
			m_position_offset = effect_setup.m_position_offset.GetValue(null, progression_vars, animate_per);
			m_rotation_offset = Quaternion.Euler(effect_setup.m_rotation_offset.GetValue(null, progression_vars, animate_per));
			m_rotate_with_letter = effect_setup.m_rotate_relative_to_letter;
			m_animation_manager = animation_manager;
			m_active = false;

			if(m_particle_emitter != null)
			{
				m_transform = m_particle_emitter.transform;

				m_particle_emitter.emit = true;
				m_particle_emitter.enabled = false;

				// Set the layer of the effect if an override is specified
				if(animation_manager.AnimationInterface.LayerOverride >= 0)
					m_particle_emitter.gameObject.layer = animation_manager.AnimationInterface.LayerOverride;
			}
			else if(m_particle_system != null)
			{
				m_transform = m_particle_system.transform;

				m_particle_system.playOnAwake = false;
				m_particle_system.Play();
	#if !UNITY_3_5 && UNITY_EDITOR
				p_system_timer = 0;
	#endif

				// Set the layer of the effect if an override is specified
				if(animation_manager.AnimationInterface.LayerOverride >= 0)
					m_particle_system.gameObject.layer = animation_manager.AnimationInterface.LayerOverride;
			}
		}
		public void PrepareData(TextFxAnimationManager anim_manager,
								ref LetterSetup[] letters,
		                        LetterAnimation animation_ref,
		                        int action_idx,
		                        ANIMATION_DATA_TYPE what_to_update,
		                        int num_letters,
		                        int num_white_space_chars_to_include,
		                        int num_words,
		                        int num_lines,
		                        LetterAction prev_action,
		                        AnimatePerOptions animate_per,
		                        ActionColorProgression defaultTextColour,
		                        bool prev_action_end_state = true)
		{
			// Set progression reference datas 
			m_start_colour.SetReferenceData(action_idx, ANIMATION_DATA_TYPE.COLOUR, true);
			m_start_euler_rotation.SetReferenceData(action_idx, ANIMATION_DATA_TYPE.LOCAL_ROTATION, true);
			m_start_pos.SetReferenceData(action_idx, ANIMATION_DATA_TYPE.POSITION, true);
			m_start_scale.SetReferenceData(action_idx, ANIMATION_DATA_TYPE.LOCAL_SCALE, true);
			m_global_start_euler_rotation.SetReferenceData(action_idx, ANIMATION_DATA_TYPE.GLOBAL_ROTATION, true);
			m_global_start_scale.SetReferenceData(action_idx, ANIMATION_DATA_TYPE.GLOBAL_SCALE, true);
			m_end_colour.SetReferenceData(action_idx, ANIMATION_DATA_TYPE.COLOUR, false);
			m_end_euler_rotation.SetReferenceData(action_idx, ANIMATION_DATA_TYPE.LOCAL_ROTATION, false);
			m_end_pos.SetReferenceData(action_idx, ANIMATION_DATA_TYPE.POSITION, false);
			m_end_scale.SetReferenceData(action_idx, ANIMATION_DATA_TYPE.LOCAL_SCALE, false);
			m_global_end_euler_rotation.SetReferenceData(action_idx, ANIMATION_DATA_TYPE.GLOBAL_ROTATION, false);
			m_global_end_scale.SetReferenceData(action_idx, ANIMATION_DATA_TYPE.GLOBAL_SCALE, false);


			// Prepare Data

			if(what_to_update == ANIMATION_DATA_TYPE.DURATION || what_to_update == ANIMATION_DATA_TYPE.ALL)
				m_duration_progression.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, m_duration_progression.AnimatePer, m_duration_progression.OverrideAnimatePerOption));


			if((what_to_update == ANIMATION_DATA_TYPE.AUDIO_EFFECTS || what_to_update == ANIMATION_DATA_TYPE.ALL) && m_audio_effects != null)
			{
				foreach(AudioEffectSetup effect_setup in m_audio_effects)
				{
					effect_setup.m_delay.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, effect_setup.m_delay.AnimatePer, effect_setup.m_delay.OverrideAnimatePerOption));
					effect_setup.m_offset_time.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, effect_setup.m_offset_time.AnimatePer, effect_setup.m_offset_time.OverrideAnimatePerOption));
					effect_setup.m_volume.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, effect_setup.m_volume.AnimatePer, effect_setup.m_volume.OverrideAnimatePerOption));
					effect_setup.m_pitch.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, effect_setup.m_pitch.AnimatePer, effect_setup.m_pitch.OverrideAnimatePerOption));
				}
			}

			if((what_to_update == ANIMATION_DATA_TYPE.PARTICLE_EFFECTS || what_to_update == ANIMATION_DATA_TYPE.ALL) && m_particle_effects != null)
			{
				foreach(ParticleEffectSetup effect_setup in m_particle_effects)
				{
					effect_setup.m_position_offset.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, effect_setup.m_position_offset.AnimatePer, effect_setup.m_position_offset.OverrideAnimatePerOption), null);
					effect_setup.m_rotation_offset.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, effect_setup.m_rotation_offset.AnimatePer, effect_setup.m_rotation_offset.OverrideAnimatePerOption), null);
					effect_setup.m_delay.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, effect_setup.m_delay.AnimatePer, effect_setup.m_delay.OverrideAnimatePerOption));
					effect_setup.m_duration.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, effect_setup.m_duration.AnimatePer, effect_setup.m_duration.OverrideAnimatePerOption));
				}
			}
			
			if(m_action_type == ACTION_TYPE.BREAK)
			{
				if(prev_action != null)
				{
					m_start_colour.SetValueReference(prev_action_end_state ? prev_action.m_end_colour : prev_action.m_start_colour);
					m_start_euler_rotation.SetValueReference( prev_action_end_state ? prev_action.m_end_euler_rotation : prev_action.m_start_euler_rotation );
					m_start_pos.SetValueReference( prev_action_end_state ? prev_action.m_end_pos : prev_action.m_start_pos );
					m_start_scale.SetValueReference( prev_action_end_state ? prev_action.m_end_scale : prev_action.m_start_scale );
					m_global_start_euler_rotation.SetValueReference( prev_action_end_state ? prev_action.m_global_end_euler_rotation : prev_action.m_global_start_euler_rotation );
					m_global_start_scale.SetValueReference( prev_action_end_state ? prev_action.m_global_end_scale : prev_action.m_global_start_scale );
				}

				m_end_colour.SetValueReference(m_start_colour);
				m_end_euler_rotation.SetValueReference(m_start_euler_rotation );
				m_end_pos.SetValueReference( prev_action.m_start_pos );
				m_end_scale.SetValueReference( prev_action.m_start_scale );
				m_global_end_euler_rotation.SetValueReference(prev_action.m_global_start_euler_rotation );
				m_global_end_scale.SetValueReference( prev_action.m_global_start_scale );

				return;
			}

			if (animation_ref.m_letters_to_animate_option != LETTERS_TO_ANIMATE.ALL_LETTERS || (((ValueProgression)m_delay_progression.Progression) != ValueProgression.Eased && ((ValueProgression)m_delay_progression.Progression) != ValueProgression.EasedCustom))
				m_delay_with_white_space_influence = false;


			if(what_to_update == ANIMATION_DATA_TYPE.DELAY || what_to_update == ANIMATION_DATA_TYPE.ALL)
				m_delay_progression.CalculateProgressions(GetProgressionTotal(num_letters + (m_delay_with_white_space_influence ? num_white_space_chars_to_include : 0), num_words, num_lines, animate_per, m_delay_progression.AnimatePer, m_delay_progression.OverrideAnimatePerOption));
			

			if(what_to_update == ANIMATION_DATA_TYPE.COLOUR || what_to_update == ANIMATION_DATA_TYPE.ALL)
			{
				if(m_offset_from_last && prev_action != null)
				{
					m_start_colour.SetValueReference(prev_action_end_state ? prev_action.m_end_colour : prev_action.m_start_colour );
				}
				else
				{
					m_start_colour.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, m_start_colour.AnimatePer, m_start_colour.OverrideAnimatePerOption), 
					                                     prev_action != null ? prev_action.m_end_colour : defaultTextColour,
					                                     prev_action == null || m_colour_transition_active);
				}

				m_end_colour.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, m_end_colour.AnimatePer, m_end_colour.OverrideAnimatePerOption),
				                                   m_start_colour,
				                                   prev_action == null || m_colour_transition_active);
			}
			
			
			if(m_offset_from_last && prev_action != null)
			{
				if(what_to_update == ANIMATION_DATA_TYPE.POSITION || what_to_update == ANIMATION_DATA_TYPE.ALL)
					m_start_pos.SetValueReference( prev_action_end_state ? prev_action.m_end_pos : prev_action.m_start_pos );

				if(what_to_update == ANIMATION_DATA_TYPE.LOCAL_ROTATION || what_to_update == ANIMATION_DATA_TYPE.ALL)
					m_start_euler_rotation.SetValueReference( prev_action_end_state ? prev_action.m_end_euler_rotation : prev_action.m_start_euler_rotation );

				if(what_to_update == ANIMATION_DATA_TYPE.LOCAL_SCALE || what_to_update == ANIMATION_DATA_TYPE.ALL)
					m_start_scale.SetValueReference( prev_action_end_state ? prev_action.m_end_scale : prev_action.m_start_scale );

				if(what_to_update == ANIMATION_DATA_TYPE.GLOBAL_ROTATION || what_to_update == ANIMATION_DATA_TYPE.ALL)
					m_global_start_euler_rotation.SetValueReference( prev_action_end_state ? prev_action.m_global_end_euler_rotation : prev_action.m_global_start_euler_rotation );

				if(what_to_update == ANIMATION_DATA_TYPE.GLOBAL_SCALE || what_to_update == ANIMATION_DATA_TYPE.ALL)
					m_global_start_scale.SetValueReference( prev_action_end_state ? prev_action.m_global_end_scale : prev_action.m_global_start_scale );
			}
			else
			{
				float[] start_pos_curve_letter_progressions = null;
				if(	(	what_to_update == ANIMATION_DATA_TYPE.POSITION ||
					    what_to_update == ANIMATION_DATA_TYPE.LOCAL_ROTATION ||
				     	what_to_update == ANIMATION_DATA_TYPE.GLOBAL_ROTATION ||
				     	what_to_update == ANIMATION_DATA_TYPE.ALL
				    )
					&& m_start_pos.Progression == ActionPositionVector3Progression.CURVE_OPTION_INDEX)
				{
					// Pre calculate letter progression values based on letter spacing
					start_pos_curve_letter_progressions = m_start_pos.BezierCurve.GetLetterProgressions(anim_manager, ref letters, m_letter_anchor_start);
				}

				if(what_to_update == ANIMATION_DATA_TYPE.POSITION || what_to_update == ANIMATION_DATA_TYPE.ALL)
					m_start_pos.CalculatePositionProgressions(	anim_manager,
					                                          	animation_ref,
					                                          	ref start_pos_curve_letter_progressions,
					                                          	letters,
					                                          	GetProgressionTotal(num_letters + num_white_space_chars_to_include, num_words, num_lines, animate_per, m_start_pos.AnimatePer, m_start_pos.OverrideAnimatePerOption),
																prev_action != null ? prev_action.m_end_pos : null,
					                                          	prev_action == null || m_position_transition_active);

				if(what_to_update == ANIMATION_DATA_TYPE.LOCAL_ROTATION || what_to_update == ANIMATION_DATA_TYPE.ALL)
					m_start_euler_rotation.CalculateRotationProgressions(ref start_pos_curve_letter_progressions, GetProgressionTotal(num_letters + num_white_space_chars_to_include, num_words, num_lines, animate_per, m_start_euler_rotation.AnimatePer, m_start_euler_rotation.OverrideAnimatePerOption),
																			prev_action != null ? prev_action.m_end_euler_rotation : null,
			                                                     			m_start_pos.Progression == ActionPositionVector3Progression.CURVE_OPTION_INDEX ? m_start_pos.BezierCurve : null,
					                                                     	prev_action == null || m_local_rotation_transition_active);

				if(what_to_update == ANIMATION_DATA_TYPE.LOCAL_SCALE || what_to_update == ANIMATION_DATA_TYPE.ALL)
					m_start_scale.CalculateProgressions(GetProgressionTotal(num_letters + num_white_space_chars_to_include, num_words, num_lines, animate_per, m_start_scale.AnimatePer, m_start_scale.OverrideAnimatePerOption),
														prev_action != null ? prev_action.m_end_scale : null,
					                                    prev_action == null || m_local_scale_transition_active);

				if(what_to_update == ANIMATION_DATA_TYPE.GLOBAL_ROTATION || what_to_update == ANIMATION_DATA_TYPE.ALL)
					m_global_start_euler_rotation.CalculateRotationProgressions(ref start_pos_curve_letter_progressions, GetProgressionTotal(num_letters + num_white_space_chars_to_include, num_words, num_lines, animate_per, m_global_start_euler_rotation.AnimatePer, m_global_start_euler_rotation.OverrideAnimatePerOption),
					                                                            prev_action != null ? prev_action.m_global_end_euler_rotation : null,
					                                                            null,
					                                                            prev_action == null || m_global_rotation_transition_active);

				if(what_to_update == ANIMATION_DATA_TYPE.GLOBAL_SCALE || what_to_update == ANIMATION_DATA_TYPE.ALL)
					m_global_start_scale.CalculateProgressions(	GetProgressionTotal(num_letters + num_white_space_chars_to_include, num_words, num_lines, animate_per, m_global_start_scale.AnimatePer, m_global_start_scale.OverrideAnimatePerOption),
				                                           		prev_action != null ? prev_action.m_global_end_scale : null,
					                                           	prev_action == null || m_global_scale_transition_active);
			}
			
			float[] end_pos_curve_letter_progressions = null;
			if(	(	what_to_update == ANIMATION_DATA_TYPE.POSITION ||
			     	what_to_update == ANIMATION_DATA_TYPE.LOCAL_ROTATION ||
			     	what_to_update == ANIMATION_DATA_TYPE.GLOBAL_ROTATION ||
			     	what_to_update == ANIMATION_DATA_TYPE.ALL
			    )
			   	&& m_end_pos.Progression == ActionPositionVector3Progression.CURVE_OPTION_INDEX)
			{
				// Pre calculate letter progression values based on letter spacing
				end_pos_curve_letter_progressions = m_end_pos.BezierCurve.GetLetterProgressions(anim_manager, ref letters, m_letter_anchor_end);
			}

			if(what_to_update == ANIMATION_DATA_TYPE.POSITION || what_to_update == ANIMATION_DATA_TYPE.ALL)
				m_end_pos.CalculatePositionProgressions(anim_manager,
				                                        animation_ref,
				                                        ref end_pos_curve_letter_progressions,
				                                        letters,
				                                        GetProgressionTotal(num_letters + num_white_space_chars_to_include, num_words, num_lines, animate_per, m_end_pos.AnimatePer, m_end_pos.OverrideAnimatePerOption),
				                                        m_start_pos,
				                                        prev_action == null || m_position_transition_active);

			if(what_to_update == ANIMATION_DATA_TYPE.LOCAL_ROTATION || what_to_update == ANIMATION_DATA_TYPE.ALL)
				m_end_euler_rotation.CalculateRotationProgressions(ref end_pos_curve_letter_progressions, GetProgressionTotal(num_letters + num_white_space_chars_to_include, num_words, num_lines, animate_per, m_end_euler_rotation.AnimatePer, m_end_euler_rotation.OverrideAnimatePerOption),
				                                                   m_start_euler_rotation,
				                                                   m_end_pos.Progression == ActionPositionVector3Progression.CURVE_OPTION_INDEX ? m_end_pos.BezierCurve : null,
				                                                   prev_action == null || m_local_rotation_transition_active);

			if(what_to_update == ANIMATION_DATA_TYPE.LOCAL_SCALE || what_to_update == ANIMATION_DATA_TYPE.ALL)
				m_end_scale.CalculateProgressions(GetProgressionTotal(num_letters + num_white_space_chars_to_include, num_words, num_lines, animate_per, m_end_scale.AnimatePer, m_end_scale.OverrideAnimatePerOption),
				                                  m_start_scale,
				                                  prev_action == null || m_local_scale_transition_active);

			if(what_to_update == ANIMATION_DATA_TYPE.GLOBAL_ROTATION || what_to_update == ANIMATION_DATA_TYPE.ALL)
				m_global_end_euler_rotation.CalculateRotationProgressions(ref end_pos_curve_letter_progressions, GetProgressionTotal(num_letters + num_white_space_chars_to_include, num_words, num_lines, animate_per, m_global_end_euler_rotation.AnimatePer, m_global_end_euler_rotation.OverrideAnimatePerOption),
				                                                          m_global_start_euler_rotation,
				                                                          null,
				                                                          prev_action == null || m_global_rotation_transition_active);

			if(what_to_update == ANIMATION_DATA_TYPE.GLOBAL_SCALE || what_to_update == ANIMATION_DATA_TYPE.ALL)
				m_global_end_scale.CalculateProgressions(GetProgressionTotal(num_letters + num_white_space_chars_to_include, num_words, num_lines, animate_per, m_global_end_scale.AnimatePer, m_global_end_scale.OverrideAnimatePerOption),
				                                         m_global_start_scale,
				                                         prev_action == null || m_global_scale_transition_active);

			if(what_to_update == ANIMATION_DATA_TYPE.POSITION
			   || what_to_update == ANIMATION_DATA_TYPE.POSITION
			   || what_to_update == ANIMATION_DATA_TYPE.LETTER_ANCHOR
			   || what_to_update == ANIMATION_DATA_TYPE.ALL)
				CalculateLetterAnchorOffset();
		}
		public void CalculatePositionProgressions(TextFxAnimationManager anim_manager,
		                                          LetterAnimation letter_animation,
		                                          ref float[] letter_progressions,
		                                          LetterSetup[] letters,
		                                          int num_progressions,
		                                          ActionPositionVector3Progression offset_prog,
		                                          bool variableActive = true)
		{

//			if (Progression == CURVE_OPTION_INDEX) {
//				if(m_is_offset_from_last)
//				{
//					m_value_state = PROGRESSION_VALUE_STATE.OFFSET_FROM_REFERENCE;
//					m_offset_progression = offset_prog.GetOffsetReference();
//				}
//				else
//					m_value_state = PROGRESSION_VALUE_STATE.UNIQUE;
//
//				m_values = new Vector3[num_progressions];
//
//				float baseYOffset = letters[0].BaseVerticesCenter.y - letters[0].BaseVerticesBL.y;
//				Vector3 firstLetterCenter = letters[0].BaseVerticesCenter;
//
//				for(int idx=0; idx < letter_progressions.Length; idx++)
//				{
//					m_values[idx] += m_bezier_curve.GetCurvePoint(letter_progressions[idx], yOffset : baseYOffset + (letters[idx].BaseVerticesCenter.y - firstLetterCenter.y));
//				}
//			}
//			else
//			{
				CalculateProgressions(num_progressions, offset_prog, variableActive);
//			}

			if(Progression == CURVE_OPTION_INDEX || (m_value_state == PROGRESSION_VALUE_STATE.REFERENCE ? GetOffsetReference().GetPositionVector3Prog(letter_animation.LetterActions).m_force_position_override : m_force_position_override))
			{
				Vector3 base_offset = Vector3.zero;

				if(m_values.Length == 1)
				{
					base_offset = m_values[0];
					m_values = new Vector3[letters.Length];
				}

				// Remove the base positioning offset for each letter
				for(int letter_idx =0; letter_idx < letters.Length; letter_idx++)
				{
					m_values[letter_idx] += base_offset;
					m_values[letter_idx] -= letters[letter_idx].BaseVerticesCenter / anim_manager.AnimationInterface.MovementScale;
				}
			}
		}
		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;
		}
		void OnEnable()
	    {	
			if (m_animation_manager == null)
				m_animation_manager = new TextFxAnimationManager ();

			m_animation_manager.SetParentObjectReferences (gameObject, transform, this);

			if(m_mesh != null)
				return;
			
			// Set component variable references
	        m_mesh_filter = gameObject.GetComponent<MeshFilter>();
			m_transform_reference = transform;
	        
	        if (m_mesh_filter.sharedMesh != null)
	        {
				// Check for two effects sharing the same SharedMesh instance (occurs when a MeshFilter component is duplicated)
				TextFxNative[] objects = GameObject.FindObjectsOfType(typeof(TextFxNative)) as TextFxNative[];

				foreach (TextFxNative effect_manager in objects)
	            {
	                MeshFilter otherMeshFilter = effect_manager.m_mesh_filter;
	                if (otherMeshFilter != null)
	                {
	                    if (otherMeshFilter.sharedMesh == m_mesh_filter.sharedMesh && otherMeshFilter != m_mesh_filter)
	                    {
							// Found shared SharedMesh instance; initialising a new one
	                        m_mesh_filter.mesh = new Mesh();
							
							m_mesh = m_mesh_filter.sharedMesh;
							
							// Reset Text with new meshes
							SetText(m_text);
	                    }
	                }
	            }
				
				m_mesh = m_mesh_filter.sharedMesh;
	        }
	        else
	        {
				m_mesh = new Mesh();
	            m_mesh_filter.mesh = m_mesh;

				if(IsFontDataAssigned)
				{
					// Reset Text with new meshes
					SetText(m_text);
				}
	        }

			if(m_font != null)
			{
#if !UNITY_4_6 && !UNITY_4_5 && !UNITY_4_3 && !UNITY_4_2 && !UNITY_4_1 && !UNITY_4_0_1 && !UNITY_4_0
				m_fontRebuildCallback = (Font rebuiltFont) => {
					FontImportDetected(rebuiltFont);
				};
				
				Font.textureRebuilt += m_fontRebuildCallback;
#else
				m_font.textureRebuildCallback += FontTextureRebuilt;
#endif
				
				// Make sure dynamic fonts add all the letters required for this animation
				m_font.RequestCharactersInTexture(m_text);

#if UNITY_EDITOR
				if(!Application.isPlaying)
				{
					// Force Texture Rebuild to avoid dynamic font texture size changes since playing. 
					SetText(m_text);


					if(m_forced_state_verts != null)
						// Render cached state of text from before play-mode
						UpdateMesh(m_forced_state_verts, m_forced_state_cols);
				}
#endif
			}
	    }
		public float[] GetLetterProgressions(TextFxAnimationManager anim_manager, ref LetterSetup[] letters, int letter_anchor)
		{
			float[] letter_progressions = new float[letters.Length];
			
			if(m_anchor_points == null || m_anchor_points.Count < 2)
			{
				for(int idx=0; idx < letters.Length; idx++)
				{
					letter_progressions[idx] = 0;
				}
				return letter_progressions;
			}
			
			float progress_inc = 1f / NUM_CURVE_SAMPLE_SUBSECTIONS;
			float progress;
			Vector3 new_point = new Vector3();
			Vector3 last_point = new Vector3();
			int letter_idx = 0, line_number=0;
			float base_letters_offset = 0, letters_offset = 0;
			LetterSetup letter;
			float last_line_length = 0, line_length = 0;
//			float curve_length = 0;
//			float length_val;

			// Grab reference to first letter setup
			letter = letters[letter_idx];
			
			// Calculate the total length of the belzier curve if the text alignment is set to center or right.
	//		if(effect_manager_ref.m_text_alignment == TextAlignment.Center || effect_manager_ref.m_text_alignment == TextAlignment.Right)
	//		{
	//			for(int curve_idx=0; curve_idx < m_anchor_points.Count - 1; curve_idx++)
	//			{
	//				length_val = GetCurveLength(curve_idx);
	//	
	//				curve_length += length_val;
	//			}
	//		}
			
			// Assign base letter offset value using first letters offset value
			base_letters_offset = letter.BaseVerticesCenter.x / anim_manager.AnimationInterface.MovementScale;
			
			// Setup letter offset value
			letters_offset = 0; //GetLetterAnchorOffset(letter, letter_anchor);
			
			// Handle alignment-specific offset values
	//		if(effect_manager_ref.m_text_alignment == TextAlignment.Center)
	//		{
	//			letters_offset += ((curve_length/2) - (letter.m_effect_manager_handle.TextDimensions[letter.m_progression_variables.m_line_value].m_text_line_width/2));
	//		}
	//		else if(effect_manager_ref.m_text_alignment == TextAlignment.Right)
	//		{
	//			letters_offset += (curve_length - letter.m_effect_manager_handle.TextDimensions[letter.m_progression_variables.m_line_value].m_text_line_width);
	//		}
			

			for(int curve_idx=0; curve_idx < m_anchor_points.Count - 1; curve_idx++)
			{
				for(int idx=0; idx <= NUM_CURVE_SAMPLE_SUBSECTIONS; idx++)
				{
					progress = idx * progress_inc;
					
					new_point = GetCurvePoint(progress, curve_idx : curve_idx); // / anim_manager.AnimationInterface.MovementScale;
					
					if(idx > 0)
					{
						line_length += (new_point - last_point).magnitude;
						
						while(letter_idx < letters.Length && line_length > letters_offset)
						{
							// calculate relative progress between the last two points which would represent the next letters offset distance
							progress = curve_idx + ((idx-1) * progress_inc) + (((letters_offset - last_line_length) / (line_length - last_line_length)) * progress_inc);
							
							letter_progressions[letter_idx] = progress;
							
							letter_idx++;
							
							if(letter_idx < letters.Length)
							{
								letter = letters[letter_idx];
								
								if(letter.m_progression_variables.m_line_value > line_number)
								{
									line_number = letter.m_progression_variables.m_line_value;
									
									// Set a new base offset value to that of the first letter of this new line
									base_letters_offset = letter.BaseVerticesCenter.x / anim_manager.AnimationInterface.MovementScale;
									
									curve_idx = 0;
									idx=-1;
									line_length = 0;
								}
								
								// Setup letter offset value
								letters_offset = 	((letter.BaseVerticesCenter.x / anim_manager.AnimationInterface.MovementScale) - base_letters_offset) ; //+ GetLetterAnchorOffset(letter, letter_anchor);

								// Handle alignment-specific offset values
	//							if(effect_manager_ref.m_text_alignment == TextAlignment.Center)
	//							{
	//								letters_offset += ((curve_length/2) - (letter.m_effect_manager_handle.TextDimensions[letter.m_progression_variables.m_line_value].m_text_line_width/2));
	//							}
	//							else if(effect_manager_ref.m_text_alignment == TextAlignment.Right)
	//							{
	//								letters_offset += (curve_length - letter.m_effect_manager_handle.TextDimensions[letter.m_progression_variables.m_line_value].m_text_line_width);
	//							}
							}
						}
						
						if(letter_idx == letters.Length)
							break;
					}
					
					last_point = new_point;
					last_line_length = line_length;
				}
			}
			
			// Handle any letters which didn't have room to fit on the line
			// Currently forces them to all position at the end of the line
			for(int idx=letter_idx; idx < letters.Length; idx++)
			{
				letter_progressions[idx] = m_anchor_points.Count - 1;
			}
			
			return letter_progressions;
		}
		public bool DrawGUISetting(TextFxAnimationManager animation_manager, float gui_x_offset, ref float gui_y_offset, bool gui_already_changed, int action_start_offset = 0, int loop_start_offset = 0)
		{
			LetterAnimation letterAnimation = animation_manager.GetAnimation(m_animation_idx);
			LetterAction letterAction = letterAnimation != null ? letterAnimation.GetAction(m_action_idx + action_start_offset) : null;
			
			if(letterAction == null)
				return false;


			if((m_data_type == ANIMATION_DATA_TYPE.POSITION && m_startState && letterAction.m_start_pos.DrawQuickEditorGUI(this, gui_x_offset, ref gui_y_offset, gui_already_changed)) ||
			   (m_data_type == ANIMATION_DATA_TYPE.POSITION && !m_startState && letterAction.m_end_pos.DrawQuickEditorGUI(this, gui_x_offset, ref gui_y_offset, gui_already_changed)) ||
			   (m_data_type == ANIMATION_DATA_TYPE.LOCAL_ROTATION && m_startState && letterAction.m_start_euler_rotation.DrawQuickEditorGUI(this, gui_x_offset, ref gui_y_offset, gui_already_changed)) ||
			   (m_data_type == ANIMATION_DATA_TYPE.LOCAL_ROTATION && !m_startState && letterAction.m_end_euler_rotation.DrawQuickEditorGUI(this, gui_x_offset, ref gui_y_offset, gui_already_changed)) ||
			   (m_data_type == ANIMATION_DATA_TYPE.GLOBAL_ROTATION && m_startState && letterAction.m_global_start_euler_rotation.DrawQuickEditorGUI(this, gui_x_offset, ref gui_y_offset, gui_already_changed)) ||
			   (m_data_type == ANIMATION_DATA_TYPE.GLOBAL_ROTATION && !m_startState && letterAction.m_global_end_euler_rotation.DrawQuickEditorGUI(this, gui_x_offset, ref gui_y_offset, gui_already_changed)) ||
			   (m_data_type == ANIMATION_DATA_TYPE.LOCAL_SCALE && m_startState && letterAction.m_start_scale.DrawQuickEditorGUI(this, gui_x_offset, ref gui_y_offset, gui_already_changed)) ||
			   (m_data_type == ANIMATION_DATA_TYPE.LOCAL_SCALE && !m_startState && letterAction.m_end_scale.DrawQuickEditorGUI(this, gui_x_offset, ref gui_y_offset, gui_already_changed)) ||
			   (m_data_type == ANIMATION_DATA_TYPE.GLOBAL_SCALE && m_startState && letterAction.m_global_start_scale.DrawQuickEditorGUI(this, gui_x_offset, ref gui_y_offset, gui_already_changed)) ||
			   (m_data_type == ANIMATION_DATA_TYPE.GLOBAL_SCALE && !m_startState && letterAction.m_global_end_scale.DrawQuickEditorGUI(this, gui_x_offset, ref gui_y_offset, gui_already_changed)) ||
			   (m_data_type == ANIMATION_DATA_TYPE.COLOUR && m_startState && letterAction.m_start_colour.DrawQuickEditorGUI(this, gui_x_offset, ref gui_y_offset, gui_already_changed)) ||
			   (m_data_type == ANIMATION_DATA_TYPE.COLOUR && !m_startState && letterAction.m_end_colour.DrawQuickEditorGUI(this, gui_x_offset, ref gui_y_offset, gui_already_changed)))
			{
				animation_manager.PrepareAnimationData(m_data_type);

				if(!animation_manager.Playing)
				{
					// Set the current state of the animation to show effect of changes
					animation_manager.SetAnimationState(m_action_idx,
					                                    m_startState ? 0 : 1,
					                                    update_mesh: true);
				}
			}
			else if(m_data_type == ANIMATION_DATA_TYPE.DURATION && letterAction.m_duration_progression.DrawQuickEditorGUI("Lerp Duration", gui_x_offset, ref gui_y_offset, gui_already_changed))
			{
				animation_manager.PrepareAnimationData(m_data_type);

				animation_manager.PrepareAnimationData(ANIMATION_DATA_TYPE.DELAY);
			}
			else if(m_data_type == ANIMATION_DATA_TYPE.DELAY && letterAction.m_delay_progression.DrawQuickEditorGUI("Delay Easing (Seconds)", gui_x_offset, ref gui_y_offset, gui_already_changed))
			{
				animation_manager.PrepareAnimationData(m_data_type);
			}
//			else if(m_data_type == ANIMATION_DATA_TYPE.COLOUR_START_END && letterAction.m_start_colour.DrawQuickEditorGUI(this, ref gui_y_offset, gui_already_changed))
//			{
//				// Set end colour to be the same at start colour
//				if(letterAction.m_start_colour.Progression == (int) ValueProgression.Constant)
//					letterAction.m_end_colour.SetConstant(letterAction.m_start_colour.ValueFrom);
//				else if(letterAction.m_start_colour.Progression == (int) ValueProgression.Eased)
//				{
//					if(letterAction.m_start_colour.UsingThirdValue)
//						letterAction.m_end_colour.SetEased(letterAction.m_start_colour.ValueFrom, letterAction.m_start_colour.ValueTo, letterAction.m_start_colour.ValueThen);
//					else
//						letterAction.m_end_colour.SetEased(letterAction.m_start_colour.ValueFrom, letterAction.m_start_colour.ValueTo);
//				}
//				else if(letterAction.m_start_colour.Progression == (int) ValueProgression.EasedCustom)
//					letterAction.m_end_colour.SetEasedCustom(letterAction.m_start_colour.ValueFrom, letterAction.m_start_colour.ValueTo);
//				else if(letterAction.m_start_colour.Progression == (int) ValueProgression.Random)
//					letterAction.m_end_colour.SetRandom(letterAction.m_start_colour.ValueFrom, letterAction.m_start_colour.ValueTo);
//
//				animation_manager.PrepareAnimationData(ANIMATION_DATA_TYPE.COLOUR_END);
//
//				animation_manager.PrepareAnimationData(ANIMATION_DATA_TYPE.COLOUR_START);
//				
//				if(!animation_manager.Playing)
//				{
//					// Set the current state of the animation to show effect of changes
//					animation_manager.SetAnimationState(m_action_idx, Mathf.Clamp(m_action_progress_state_override, 0f, 1f), update_mesh: true);
//				}
//			}
			else if(m_data_type == ANIMATION_DATA_TYPE.EASE_TYPE)
			{
				letterAction.m_ease_type = (EasingEquation) EditorGUI.EnumPopup(new Rect(gui_x_offset, gui_y_offset, 350, LINE_HEIGHT), m_setting_name, letterAction.m_ease_type);

				if(!gui_already_changed && GUI.changed)
					animation_manager.PrepareAnimationData(ANIMATION_DATA_TYPE.ALL);

				gui_y_offset += LINE_HEIGHT;
			}
			else if(m_data_type == ANIMATION_DATA_TYPE.DELAY_EASED_RANDOM_SWITCH)
			{
				bool newSelection = EditorGUI.Toggle(new Rect(gui_x_offset, gui_y_offset, 250, LINE_HEIGHT), "Randomised?", letterAction.m_delay_progression.Progression == (int) ValueProgression.Random);

				if(!gui_already_changed && GUI.changed)
				{
					if(newSelection)
						letterAction.m_delay_progression.SetRandom(letterAction.m_delay_progression.ValueFrom, letterAction.m_delay_progression.ValueTo, letterAction.m_delay_progression.UniqueRandomRaw);
					else
						letterAction.m_delay_progression.SetEased(letterAction.m_delay_progression.ValueFrom, letterAction.m_delay_progression.ValueTo);

					animation_manager.PrepareAnimationData(ANIMATION_DATA_TYPE.DELAY);
				}

				gui_y_offset += LINE_HEIGHT;
			}
			else if(m_data_type == ANIMATION_DATA_TYPE.NUM_LOOP_ITERATIONS)
			{
				ActionLoopCycle loop_cycle = letterAnimation.GetLoop(m_action_idx + loop_start_offset);

				if(loop_cycle != null)
					loop_cycle.m_number_of_loops = EditorGUI.IntField(new Rect(gui_x_offset, gui_y_offset, 250, LINE_HEIGHT), m_setting_name, loop_cycle.m_number_of_loops);


				gui_y_offset += LINE_HEIGHT;
			}
			
			return !gui_already_changed && GUI.changed;
		}
//		void InitAnimationManager(TextFxAnimationManager anim_manager)
//		{
//			anim_manager.m_selected_intro_animation_idx = EditorPrefs.GetInt("SelectedIntroTextFxAnim", 0);
//			anim_manager.m_selected_main_animation_idx = EditorPrefs.GetInt("SelectedMainTextFxAnim", 0);
//			anim_manager.m_selected_outro_animation_idx = EditorPrefs.GetInt("SelectedOutroTextFxAnim", 0);
//		}
	    
	    void OnGUI ()
		{
			// Check whether a EffectManager object is selected
			if(Selection.gameObjects.Length == 1)
			{
				TextFxAnimationInterface textfx_animation_interface = Selection.gameObjects[0].GetComponent(typeof(TextFxAnimationInterface)) as TextFxAnimationInterface;
				if(textfx_animation_interface != null)
				{
					m_textfx_animation_interface = textfx_animation_interface;
					m_animation_manager = textfx_animation_interface.AnimationManager;

					if(m_animation_manager.m_master_animations == null)
						m_animation_manager.m_master_animations = new List<LetterAnimation>();
				}
			}
			
			if(m_animation_manager == null || m_animation_manager.m_master_animations == null || m_textfx_animation_interface == null || m_textfx_animation_interface.AnimationManager == null || m_textfx_animation_interface.AnimationManager.GameObject == null)
			{
				return;
			}

			int edited_action = -1;
			bool start_of_action = true;
			ANIMATION_DATA_TYPE edited_data = ANIMATION_DATA_TYPE.ALL;

			DrawEffectEditorPanel();
			
			if(!ignore_gui_change)
			{
				start_of_action = editing_start_state;
				edited_action = edited_action_idx;
				edited_data = m_edited_data;
			}


			if (edited_action >= 0)
			{
				if(m_animation_manager.Playing && edited_data != ANIMATION_DATA_TYPE.NONE)
				{
					m_animation_manager.PrepareAnimationData(edited_data);
				}
				else
				{
					m_animation_manager.SetAnimationState(edited_action, start_of_action ? 0 : 1, update_action_values: true, edited_data: edited_data);
					
					m_textfx_animation_interface.UpdateTextFxMesh( m_animation_manager.MeshVerts, m_animation_manager.MeshColours);
				}
			}

			if(GUI.changed)
			{
				EditorUtility.SetDirty( m_textfx_animation_interface.GameObject );
			}
	    }
		int GetSectionRepeatLoopIndex(TextFxAnimationManager.PRESET_ANIMATION_SECTION section)
		{
			if(section == TextFxAnimationManager.PRESET_ANIMATION_SECTION.INTRO)
				return m_animation_manager.IntroRepeatLoopStartIndex;
			else if(section == TextFxAnimationManager.PRESET_ANIMATION_SECTION.MAIN)
				return m_animation_manager.MainRepeatLoopStartIndex;
			else if(section == TextFxAnimationManager.PRESET_ANIMATION_SECTION.OUTRO)
				return m_animation_manager.OutroRepeatLoopStartIndex;

			return 0;
		}
		void DrawGUIAnimationSettings(TextFxAnimationManager.PRESET_ANIMATION_SECTION section, string folder_name, ref float gui_y_offset, ref bool foldout, ref int selected_index, ref TextFxAnimationManager.PresetAnimationSection preset_anim_section, string[] anim_titles)
		{
			if(selected_index > 0)
				foldout = EditorGUI.Foldout (new Rect (20, gui_y_offset, 80, 20), foldout, TextFxAnimationManager.m_animation_section_names[(int) section], true, FoldOutHeaderGUIStyle);
			else
				EditorGUI.LabelField(new Rect (20, gui_y_offset, 80, 20), TextFxAnimationManager.m_animation_section_names[(int) section], HeaderGUIStyle);

			bool gui_changed = GUI.changed;

			// Draw Section loop options
			if(section == TextFxAnimationManager.PRESET_ANIMATION_SECTION.MAIN && selected_index > 0)
			{
				if(GUI.Button (new Rect (310, gui_y_offset - 7, 40, 40), preset_anim_section.m_repeat ? m_repeat_on_button_texture : m_repeat_off_button_texture, ButtonImageOnlyGUIStyle))
				{
					preset_anim_section.m_repeat = !preset_anim_section.m_repeat;
				}

				if(!gui_changed && GUI.changed)
				{
					// Update section loop settings
					if(!preset_anim_section.m_repeat)
					{
						// Remove section repeat loop
						m_animation_manager.m_master_animations[0].RemoveLoop(GetSectionRepeatLoopIndex(section));
					}
					else
					{
						// Add in a repeat loop
						ActionLoopCycle new_loop = new ActionLoopCycle();
						new_loop.m_start_action_idx = preset_anim_section.m_start_action;
						new_loop.m_end_action_idx = preset_anim_section.m_start_action + preset_anim_section.m_num_actions;
						new_loop.m_number_of_loops = preset_anim_section.m_repeat_count;

						m_animation_manager.m_master_animations[0].InsertLoop(GetSectionRepeatLoopIndex(section), new_loop);
					}
				}

				if(preset_anim_section.m_repeat)
				{
					gui_changed = GUI.changed;

					// display repeat num field
					preset_anim_section.m_repeat_count = Mathf.Max(EditorGUI.IntField(new Rect(355, gui_y_offset + 2, 30, LINE_HEIGHT), preset_anim_section.m_repeat_count), 0);
					
					if(preset_anim_section.m_repeat_count == 0)
					{
						GUI.DrawTexture(new Rect(390, gui_y_offset - 8, 40, 40), m_infinity_texture);
					}

					if(!gui_changed && GUI.changed)
					{
						// Update loop with current repeat count
						ActionLoopCycle repeat_loop = m_animation_manager.m_master_animations[0].GetLoop(GetSectionRepeatLoopIndex(section));
						repeat_loop.m_number_of_loops = preset_anim_section.m_repeat_count;
					}
				}
			}
			

			gui_changed = GUI.changed;

			selected_index = EditorGUI.Popup (new Rect (120, gui_y_offset, 180, 20), selected_index, anim_titles, PopupHeaderGUIStyle);
			
			if(!gui_changed && GUI.changed)
			{
				if(m_animation_manager.WipeFullEditorData(user_confirm: true))
				{
					// Handle removing any existing section anim
					if(preset_anim_section.m_num_actions > 0
					   && m_animation_manager.m_master_animations != null
					   && m_animation_manager.m_master_animations.Count > 0
					   && m_animation_manager.m_master_animations[0].NumActions >= preset_anim_section.m_num_actions + 1)
					{
						m_animation_manager.m_master_animations[0].RemoveActions(preset_anim_section.m_start_action, preset_anim_section.m_num_actions + 1);

						m_animation_manager.m_master_animations[0].RemoveLoops(preset_anim_section.m_start_loop, preset_anim_section.m_num_loops);
					}
					
					// Animation selection changed. Update animation to reflect this
					if(selected_index > 0)
					{
						preset_anim_section.m_repeat = false;
						preset_anim_section.m_repeat_count = 0;

						string path = "Assets/TextFx/AnimationConfigs/" + folder_name + "/" + anim_titles[selected_index] + ".txt";
						path = path.Replace("\n", "");
						path = path.Replace("\r", "");
						
						TextAsset animation_config_data = AssetDatabase.LoadAssetAtPath(path, typeof(TextAsset)) as TextAsset;
						
//						Debug.Log("Importing from : " + path + ", animation_config_data : " + (animation_config_data != null));
						
						if(animation_config_data != null)
						{
							preset_anim_section.m_active = true;

							m_animation_manager.ImportData(animation_config_data.text, preset_anim_section, section, true);

							// Add in an Exit Pause action after the end of this section
							LetterAction exit_pause_action = new LetterAction();
							exit_pause_action.m_action_type = ACTION_TYPE.BREAK;

							// Initialise delay duration based on existing settings
							exit_pause_action.m_duration_progression.SetConstant(preset_anim_section.m_exit_pause ? preset_anim_section.m_exit_pause_duration : INACTIVE_EXIT_PAUSE_DURATION);

							m_animation_manager.m_master_animations[0].InsertAction(preset_anim_section.ExitPauseIndex, exit_pause_action);

							m_animation_manager.PrepareAnimationData (ANIMATION_DATA_TYPE.DURATION);
						}
					}
					else
					{
						preset_anim_section.m_active = false;
						preset_anim_section.m_num_actions = 0;
						preset_anim_section.m_num_loops = 0;
					}
					
					UpdatePresetAnimSectionActionIndexes();

					// Update global loop settings if active
					if(m_animation_manager.m_repeat_all_sections)
					{
						ActionLoopCycle global_loop = m_animation_manager.m_master_animations[0].GetLoop(m_animation_manager.GlobalRepeatLoopStartIndex);

						if(global_loop == null)
						{
							// Global loop was removed during section rearranging. Re-add one in.
							global_loop = new ActionLoopCycle();
							global_loop.m_number_of_loops = m_animation_manager.m_repeat_all_sections_count;
							m_animation_manager.m_master_animations[0].InsertLoop(m_animation_manager.GlobalRepeatLoopStartIndex, global_loop, true);
						}

						global_loop.m_start_action_idx = 0;
						global_loop.m_end_action_idx = m_animation_manager.m_preset_outro.m_start_action + (m_animation_manager.m_preset_outro.m_active ? m_animation_manager.m_preset_outro.m_num_actions : -1);
					}
				}
				else
				{
					// Set selected anim index back to NONE
					selected_index = 0;
				}
			}
			
			gui_y_offset += 35;
			
			if(foldout && selected_index > 0)
			{
				if(preset_anim_section.m_preset_effect_settings == null || preset_anim_section.m_preset_effect_settings.Count == 0)
				{
					return;
				}

				bool setting_changed = false;

				float gui_x_offset = 60;

				GUI.Label(new Rect(gui_x_offset - 5, gui_y_offset, 120, LINE_HEIGHT), "Section Settings", EditorStyles.boldLabel);

				if(GUI.Button(new Rect(gui_x_offset + 150, gui_y_offset, 100, LINE_HEIGHT), "Play Section"))
					setting_changed = true;

				gui_y_offset += 30;

				foreach(PresetEffectSetting effect_setting in preset_anim_section.m_preset_effect_settings)
				{
					if(effect_setting.DrawGUISetting(m_animation_manager, gui_x_offset, ref gui_y_offset, GUI.changed, preset_anim_section.m_start_action, preset_anim_section.m_start_loop))
						setting_changed = true;
				}

				// Display Exit Pause setting
				gui_changed = GUI.changed;
				preset_anim_section.m_exit_pause = EditorGUI.Toggle(new Rect(gui_x_offset, gui_y_offset, 200, LINE_HEIGHT), "Exit Delay", preset_anim_section.m_exit_pause);
				gui_y_offset += LINE_HEIGHT;

				if(!gui_changed && GUI.changed)
				{
					LetterAction exitPauseAction = m_animation_manager.m_master_animations[0].GetAction(preset_anim_section.ExitPauseIndex);

					exitPauseAction.m_duration_progression.SetConstant(preset_anim_section.m_exit_pause ? preset_anim_section.m_exit_pause_duration : INACTIVE_EXIT_PAUSE_DURATION);

					m_animation_manager.PrepareAnimationData(ANIMATION_DATA_TYPE.DURATION);

					UpdatePresetAnimSectionActionIndexes();
				}

				if(preset_anim_section.m_exit_pause)
				{
					LetterAction exit_pause_action = m_animation_manager.m_master_animations[0].GetAction(preset_anim_section.ExitPauseIndex);

					// Force to be Constant progression type
					if(exit_pause_action.m_duration_progression.Progression != (int) ValueProgression.Constant)
						exit_pause_action.m_duration_progression.SetConstant(exit_pause_action.m_duration_progression.ValueFrom);

					gui_changed = GUI.changed;

					float exit_pause_duration = Mathf.Max(EditorGUI.FloatField(new Rect(120, gui_y_offset, 200, LINE_HEIGHT), "Duration", exit_pause_action.m_duration_progression.ValueFrom), 0);
					gui_y_offset += LINE_HEIGHT;

					if(!gui_changed && GUI.changed)
					{
						exit_pause_action.m_duration_progression.SetConstant(exit_pause_duration);

						m_animation_manager.PrepareAnimationData(ANIMATION_DATA_TYPE.DURATION);

						setting_changed = true;
					}
				}


				if(setting_changed)
				{
					PlayEditorAnimation(preset_anim_section.m_start_action);
				}
			}

			gui_y_offset += LINE_HEIGHT;
		}
		public void PrepareData(TextFxAnimationManager anim_manager, LetterSetup[] letters, ANIMATION_DATA_TYPE what_to_update, int num_words, int num_lines, AnimatePerOptions animate_per)
		{
			if(letters == null || letters.Length == 0)
			{
				return;
			}

			if(m_letters_to_animate == null || what_to_update == ANIMATION_DATA_TYPE.ALL || what_to_update == ANIMATION_DATA_TYPE.ANIMATE_ON)
			{
				CalculateLettersToAnimate(letters);
			}

			if(what_to_update == ANIMATION_DATA_TYPE.ALL || what_to_update == ANIMATION_DATA_TYPE.COLOUR || m_defaultTextColourProgression == null)
			{
				// Set values for default text colour progression
				VertexColour[] defaultextColours = new VertexColour[m_letters_to_animate.Count];

				for(int idx = 0; idx < m_letters_to_animate.Count; idx++)
				{
					defaultextColours[idx] = letters[m_letters_to_animate[idx]].BaseColour;
				}

				m_defaultTextColourProgression.SetValues(defaultextColours);
				
				// Mark as the default colour progression
				m_defaultTextColourProgression.SetReferenceData(-1, ANIMATION_DATA_TYPE.COLOUR, true);
			}

			
			// Prepare progression data in all actions
			LetterAction letter_action;
			LetterAction prev_action = null;
			bool prev_action_end_state = true;
			for(int action_idx = 0; action_idx < m_letter_actions.Count; action_idx ++)
			{
				letter_action = m_letter_actions[action_idx];

				letter_action.PrepareData(anim_manager, ref letters, this, action_idx, what_to_update, m_letters_to_animate.Count, m_num_white_space_chars_to_include, num_words, num_lines, prev_action, animate_per, m_defaultTextColourProgression, prev_action_end_state);
				
				if(letter_action.m_action_type == ACTION_TYPE.ANIM_SEQUENCE)
				{
					// Set default previous action settings
					prev_action_end_state = true;
					prev_action = letter_action;
				}
				
				// Check for reverse loops, and how the animation should progress from there
				foreach(ActionLoopCycle loop_cycle in m_loop_cycles)
				{
					if(loop_cycle.m_end_action_idx == action_idx && loop_cycle.m_loop_type == LOOP_TYPE.LOOP_REVERSE && !loop_cycle.m_finish_at_end)
					{
						prev_action = m_letter_actions[loop_cycle.m_start_action_idx];
						prev_action_end_state = false;
					}
				}
			}
		}
Example #12
0
		Color[] m_forced_state_cols;		// Verts stored for a one time rendering call

		protected override void OnEnable()
		{
			base.OnEnable ();

			if (m_animation_manager == null)
				m_animation_manager = new TextFxAnimationManager (new int[]{1,0,3,2});
			
			m_animation_manager.SetParentObjectReferences (gameObject, transform, this);

			if(!Application.isPlaying)
				// Call to update mesh rendering
				UpdateGeometry ();
		}