public void SoftResetStarts(LetterAction prev_action, AnimationProgressionVariables progression_variables, AnimatePerOptions animate_per)
        {
            if (m_use_gradient_start)
            {
                if (!m_offset_from_last && m_start_vertex_colour.UniqueRandom)
                {
                    m_start_vertex_colour.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_vertex_colour.Values : null);
                }
            }
            else
            {
                if (!m_offset_from_last && m_start_colour.UniqueRandom)
                {
                    m_start_colour.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_colour.Values : null);
                }
            }

            if (!m_offset_from_last)
            {
                if (m_start_pos.UniqueRandom)
                {
                    m_start_pos.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_pos.Values : null);
                }
                if (m_start_euler_rotation.UniqueRandom)
                {
                    m_start_euler_rotation.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_euler_rotation.Values : null);
                }
                if (m_start_scale.UniqueRandom)
                {
                    m_start_scale.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_scale.Values : null);
                }
            }
        }
		public ParticleEffectInstanceManager(EffectManager effect_manager, Mesh character_mesh, bool letter_flipped, 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_mesh = character_mesh;
			m_letter_flipped = letter_flipped;
			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(progression_vars, animate_per);
			m_rotation_offset = Quaternion.Euler(effect_setup.m_rotation_offset.GetValue(progression_vars, animate_per));
			m_rotate_with_letter = effect_setup.m_rotate_relative_to_letter;
			m_effect_manager_handle = effect_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;
			}
			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
			}
		}
Beispiel #3
0
        public void Recycle(string character, int letter_idx, Mesh mesh, Vector3 base_offset, ref CustomCharacterInfo char_info, int line_num, int word_idx, EffectManager effect_manager)
        {
            m_character             = character;
            m_mesh                  = mesh;
            m_base_offset           = base_offset;
            m_effect_manager_handle = effect_manager;

            m_progression_variables = new AnimationProgressionVariables(letter_idx, word_idx, line_num);

            SetupLetterMesh(ref char_info);

            if (m_flipped)
            {
                // flip UV coords in x axis.
                m_mesh.uv = new Vector2[] { mesh.uv[3], mesh.uv[2], mesh.uv[1], mesh.uv[0] };
            }

            m_current_letter_action = null;
        }
Beispiel #4
0
        public LetterSetup(string character, int letter_idx, Mesh mesh, Vector3 base_offset, ref CustomCharacterInfo char_info, int line_num, int word_idx, EffectManager effect_manager)
        {
            m_character             = character;
            m_mesh                  = mesh;
            m_base_offset           = base_offset;
            m_effect_manager_handle = effect_manager;

            m_progression_variables = new AnimationProgressionVariables(letter_idx, word_idx, line_num);

            m_anim_state_vars = new AnimationStateVariables();
            m_anim_state_vars.m_active_loop_cycles = new List <ActionLoopCycle>();

            SetupLetterMesh(ref char_info);

            if (m_flipped)
            {
                // flip UV coords in x axis.
                m_mesh.uv = new Vector2[] { mesh.uv[3], mesh.uv[2], mesh.uv[1], mesh.uv[0] };
            }
        }
		public void CalculateUniqueRandom(AnimationProgressionVariables progression_variables, AnimatePerOptions animate_per, Vector3[] offset_vec)
		{
			int progression_idx = GetProgressionIndex(progression_variables, animate_per);
			bool constant_offset = offset_vec != null && offset_vec.Length == 1;
				
			m_values[progression_idx] = m_is_offset_from_last ? offset_vec[constant_offset ? 0 : progression_idx] : Vector3.zero;
			m_values[progression_idx] += new Vector3(m_from.x + (m_to.x - m_from.x) * UnityEngine.Random.value, m_from.y + (m_to.y - m_from.y) * UnityEngine.Random.value, m_from.z + (m_to.z - m_from.z) * UnityEngine.Random.value);
		}
		public Vector3 GetValue(AnimationProgressionVariables progression_variables, AnimatePerOptions animate_per_default)
		{
			return GetValue(GetProgressionIndex(progression_variables,animate_per_default));
		}
		public int GetProgressionIndex(AnimationProgressionVariables progression_variables, AnimatePerOptions animate_per_default)
		{
			return progression_variables.GetValue(m_override_animate_per_option ? m_animate_per : animate_per_default);
		}
		public void CalculateUniqueRandom(AnimationProgressionVariables progression_variables, AnimatePerOptions animate_per)
		{
			m_values[GetProgressionIndex(progression_variables, animate_per)] = m_from + (m_to - m_from) * UnityEngine.Random.value;
		}
		public void CalculateUniqueRandom(AnimationProgressionVariables progression_variables, AnimatePerOptions animate_per, VertexColour[] offset_colours)
		{
			int progression_idx = GetProgressionIndex(progression_variables, animate_per);
			bool constant_offset = offset_colours != null && offset_colours.Length == 1;
				
			m_values[progression_idx] = m_is_offset_from_last ? offset_colours[constant_offset ? 0 : progression_idx].Clone() : new VertexColour(new Color(0,0,0,0));
			m_values[progression_idx] = m_values[progression_idx].Add(m_from.Add(m_to.Sub(m_from).Multiply(UnityEngine.Random.value)));
		}
		public void PlayParticleEffect(Mesh character_mesh, bool m_letter_flipped, ParticleEffectSetup effect_setup, AnimationProgressionVariables progression_vars, AnimatePerOptions animate_per)
		{
			bool effect_played = false;

			if(effect_setup.m_legacy_particle_effect != null)
			{
				if(m_particle_emitters == null)
				{
					m_particle_emitters = new List<ParticleEmitter>();
				}

				foreach(ParticleEmitter p_emitter in m_particle_emitters)
				{
					if(!p_emitter.emit && p_emitter.particleCount == 0 && p_emitter.name.Equals(effect_setup.m_legacy_particle_effect.name + "(Clone)"))
					{
						m_effect_managers.Add(new ParticleEffectInstanceManager(this, character_mesh, m_letter_flipped, effect_setup, progression_vars, animate_per, particle_emitter : p_emitter));
						
						effect_played = true;
						break;
					}
				}

				if(!effect_played)
				{
					ParticleEmitter p_emitter = GameObject.Instantiate(effect_setup.m_legacy_particle_effect) as ParticleEmitter;
					m_particle_emitters.Add(p_emitter);
					p_emitter.gameObject.SetActive(true);
					p_emitter.emit = false;
					p_emitter.transform.parent = this.transform;
					
					m_effect_managers.Add(new ParticleEffectInstanceManager(this, character_mesh, m_letter_flipped, effect_setup, progression_vars, animate_per, particle_emitter : p_emitter));
				}
			}
			else if(effect_setup.m_shuriken_particle_effect != null)
			{
				if(m_particle_systems == null)
					m_particle_systems = new List<ParticleSystem>();
				
				foreach(ParticleSystem p_system in m_particle_systems)
				{
					// check if particle system instance is currently not being used, and if it's the same type of effect that we're looking for.
					if(!p_system.isPlaying && p_system.particleCount == 0 && p_system.name.Equals(effect_setup.m_shuriken_particle_effect.name + "(Clone)"))
					{
						m_effect_managers.Add(new ParticleEffectInstanceManager(this, character_mesh, m_letter_flipped, effect_setup, progression_vars, animate_per, particle_system : p_system));
						
						effect_played = true;
						break;
					}
				}

				if(!effect_played)
				{
					// Make a new instance of the particleSystem effect and add to pool
					ParticleSystem p_system = GameObject.Instantiate(effect_setup.m_shuriken_particle_effect) as ParticleSystem;
					m_particle_systems.Add(p_system);
					p_system.gameObject.SetActive(true);
					p_system.playOnAwake = false;
					p_system.Stop();
					p_system.transform.parent = this.transform;
					
					m_effect_managers.Add(new ParticleEffectInstanceManager(this, character_mesh, m_letter_flipped, effect_setup, progression_vars, animate_per, particle_system : p_system));
				}
			}
		}
        public void SoftReset(LetterAction prev_action, AnimationProgressionVariables progression_variables, AnimatePerOptions animate_per, bool first_action = false)
        {
            if (m_use_gradient_start)
            {
                if (!m_offset_from_last && m_start_vertex_colour.UniqueRandom && !first_action)
                {
                    m_start_vertex_colour.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_vertex_colour.Values : null);
                }
            }
            else
            {
                if (!m_offset_from_last && m_start_colour.UniqueRandom && !first_action)
                {
                    m_start_colour.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_colour.Values : null);
                }
            }

            if (!m_offset_from_last && !first_action)
            {
                if (m_start_pos.UniqueRandom)
                {
                    m_start_pos.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_pos.Values : null);
                }
                if (m_start_euler_rotation.UniqueRandom)
                {
                    m_start_euler_rotation.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_euler_rotation.Values : null);
                }
                if (m_start_scale.UniqueRandom)
                {
                    m_start_scale.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_scale.Values : null);
                }
            }

            // End State Unique Randoms
            if (m_use_gradient_end)
            {
                if (m_end_vertex_colour.UniqueRandom)
                {
                    m_end_vertex_colour.CalculateUniqueRandom(progression_variables, animate_per, m_start_vertex_colour.Values);
                }
            }
            else
            {
                if (m_end_colour.UniqueRandom)
                {
                    m_end_colour.CalculateUniqueRandom(progression_variables, animate_per, m_start_colour.Values);
                }
            }
            if (m_end_pos.UniqueRandom)
            {
                m_end_pos.CalculateUniqueRandom(progression_variables, animate_per, m_start_pos.Values);
            }
            if (m_end_euler_rotation.UniqueRandom)
            {
                m_end_euler_rotation.CalculateUniqueRandom(progression_variables, animate_per, m_start_euler_rotation.Values);
            }
            if (m_end_scale.UniqueRandom)
            {
                m_end_scale.CalculateUniqueRandom(progression_variables, animate_per, m_start_scale.Values);
            }


            // Timing unique randoms
            if (m_delay_progression.UniqueRandom)
            {
                m_delay_progression.CalculateUniqueRandom(progression_variables, animate_per);
            }
            if (m_duration_progression.UniqueRandom)
            {
                m_duration_progression.CalculateUniqueRandom(progression_variables, animate_per);
            }

            if (m_audio_effects != null)
            {
                foreach (AudioEffectSetup effect_setup in m_audio_effects)
                {
                    if (effect_setup.m_delay.UniqueRandom)
                    {
                        effect_setup.m_delay.CalculateUniqueRandom(progression_variables, animate_per);
                    }
                    if (effect_setup.m_offset_time.UniqueRandom)
                    {
                        effect_setup.m_offset_time.CalculateUniqueRandom(progression_variables, animate_per);
                    }
                    if (effect_setup.m_volume.UniqueRandom)
                    {
                        effect_setup.m_volume.CalculateUniqueRandom(progression_variables, animate_per);
                    }
                    if (effect_setup.m_pitch.UniqueRandom)
                    {
                        effect_setup.m_pitch.CalculateUniqueRandom(progression_variables, animate_per);
                    }
                }
            }

            if (m_particle_effects != null)
            {
                foreach (ParticleEffectSetup effect_setup in m_particle_effects)
                {
                    if (effect_setup.m_position_offset.UniqueRandom)
                    {
                        effect_setup.m_position_offset.CalculateUniqueRandom(progression_variables, animate_per, null);
                    }
                    if (effect_setup.m_rotation_offset.UniqueRandom)
                    {
                        effect_setup.m_rotation_offset.CalculateUniqueRandom(progression_variables, animate_per, null);
                    }
                    if (effect_setup.m_delay.UniqueRandom)
                    {
                        effect_setup.m_delay.CalculateUniqueRandom(progression_variables, animate_per);
                    }
                    if (effect_setup.m_duration.UniqueRandom)
                    {
                        effect_setup.m_duration.CalculateUniqueRandom(progression_variables, animate_per);
                    }
                }
            }
        }
		void SetupMesh(LetterAction letter_action, LetterAction prev_action, float action_progress, AnimationProgressionVariables progression_variables, AnimatePerOptions animate_per, float linear_progress, EffectManager effect_manager)
		{	
			// construct current anchor offset vector
			m_anchor_offset = letter_action.AnchorOffsetStart;
			m_anchor_offset = new Vector3(	m_anchor_offset.x * m_width, 
											letter_action.m_letter_anchor_start == (int) TextfxTextAnchor.BaselineLeft || letter_action.m_letter_anchor_start == (int) TextfxTextAnchor.BaselineCenter || letter_action.m_letter_anchor_start == (int) TextfxTextAnchor.BaselineRight 
												? 0		// zero because letters are based around the baseline already.
												: (effect_manager.IsFontBaseLineSet 
														? (effect_manager.FontBaseLine + m_y_offset) - (m_anchor_offset.y * -m_height)
														: (m_anchor_offset.y * m_height)),	// Legacy effect support when baseline isn't already set.
											0);
			
			if(letter_action.m_letter_anchor_2_way)
			{
				m_anchor_offset = letter_action.AnchorOffsetEnd;
				m_anchor_offset = Vector3.Lerp(	m_anchor_offset,
												new Vector3(
													m_anchor_offset.x * m_width,
													letter_action.m_letter_anchor_end == (int) TextfxTextAnchor.BaselineLeft || letter_action.m_letter_anchor_end == (int) TextfxTextAnchor.BaselineCenter || letter_action.m_letter_anchor_end == (int) TextfxTextAnchor.BaselineRight
														? 0		// zero because letters are based around the baseline already.
														: (effect_manager.IsFontBaseLineSet
																? (effect_manager.FontBaseLine + m_y_offset) - (m_anchor_offset.y * -m_height)
																: (m_anchor_offset.y * m_height)),	// Legacy effect support when baseline isn't already set.
													0),
												action_progress);
			}
			
			
			// Calculate Scale Vector
			from_vec = letter_action.m_start_scale.GetValue(progression_variables, animate_per);
			to_vec = letter_action.m_end_scale.GetValue(progression_variables, animate_per);
			
			if(letter_action.m_scale_axis_ease_data.m_override_default)
			{
				m_letter_scale = new Vector3(	EffectManager.FloatLerp(from_vec.x, to_vec.x, EasingManager.GetEaseProgress(letter_action.m_scale_axis_ease_data.m_x_ease, linear_progress)),
												EffectManager.FloatLerp(from_vec.y, to_vec.y, EasingManager.GetEaseProgress(letter_action.m_scale_axis_ease_data.m_y_ease, linear_progress)),
												EffectManager.FloatLerp(from_vec.z, to_vec.z, EasingManager.GetEaseProgress(letter_action.m_scale_axis_ease_data.m_z_ease, linear_progress)));
			}
			else
			{
				m_letter_scale = EffectManager.Vector3Lerp(
												from_vec,
												to_vec,
												action_progress);
			}
			
			// Calculate Rotation
			from_vec = letter_action.m_start_euler_rotation.GetValue(progression_variables, animate_per);
			to_vec = letter_action.m_end_euler_rotation.GetValue(progression_variables, animate_per);
			
			if(letter_action.m_rotation_axis_ease_data.m_override_default)
			{
				m_letter_rotation =	Quaternion.Euler
									(
										EffectManager.FloatLerp(from_vec.x, to_vec.x, EasingManager.GetEaseProgress(letter_action.m_rotation_axis_ease_data.m_x_ease, linear_progress)),
										EffectManager.FloatLerp(from_vec.y, to_vec.y, EasingManager.GetEaseProgress(letter_action.m_rotation_axis_ease_data.m_y_ease, linear_progress)),
										EffectManager.FloatLerp(from_vec.z, to_vec.z, EasingManager.GetEaseProgress(letter_action.m_rotation_axis_ease_data.m_z_ease, linear_progress))
									);
			}
			else
			{
				m_letter_rotation = Quaternion.Euler(
											EffectManager.Vector3Lerp(
												from_vec,
												to_vec,
												action_progress)
											);
			}
			
			
			// Calculate Position
			if(letter_action.m_start_pos.Progression == ActionPositionVector3Progression.CURVE_OPTION_INDEX || (letter_action.m_offset_from_last && prev_action != null && prev_action.m_end_pos.Progression == ActionPositionVector3Progression.CURVE_OPTION_INDEX))
				from_vec = new Vector3(-m_anchor_offset.x,m_base_offset.y,0);
			else if(letter_action.m_start_pos.ForcePositionOverride)
				from_vec = new Vector3(-m_anchor_offset.x,0,0);
			else
				from_vec = BaseOffset;
			
			from_vec += letter_action.m_start_pos.GetValue(progression_variables, animate_per);
			
			if(letter_action.m_end_pos.Progression == ActionPositionVector3Progression.CURVE_OPTION_INDEX || (letter_action.m_end_pos.IsOffsetFromLast && letter_action.m_start_pos.Progression == ActionPositionVector3Progression.CURVE_OPTION_INDEX))
				to_vec = new Vector3(-m_anchor_offset.x,m_base_offset.y,0);
			else if(letter_action.m_end_pos.ForcePositionOverride)
				to_vec = new Vector3(-m_anchor_offset.x,0,0);
			else
				to_vec = BaseOffset;
			
			to_vec += letter_action.m_end_pos.GetValue(progression_variables, animate_per);
			
			if(letter_action.m_position_axis_ease_data.m_override_default)
			{
				m_letter_position = new Vector3(	EffectManager.FloatLerp(from_vec.x, to_vec.x, EasingManager.GetEaseProgress(letter_action.m_position_axis_ease_data.m_x_ease, linear_progress)),
													EffectManager.FloatLerp(from_vec.y, to_vec.y, EasingManager.GetEaseProgress(letter_action.m_position_axis_ease_data.m_y_ease, linear_progress)),
													EffectManager.FloatLerp(from_vec.z, to_vec.z, EasingManager.GetEaseProgress(letter_action.m_position_axis_ease_data.m_z_ease, linear_progress)));
			}
			else
			{
				m_letter_position = EffectManager.Vector3Lerp(
					from_vec, 
					to_vec,
					action_progress);
			}
			
			// Calculate letter center position
			m_letter_center = new Vector3(m_width / 2, m_height/2, 0);
			m_letter_center -= m_anchor_offset;
			m_letter_center = Vector3.Scale(m_letter_center, m_letter_scale);
			m_letter_center = m_letter_rotation	* m_letter_center;
			m_letter_center += m_anchor_offset + m_letter_position;
			
			
			if(mesh_verts == null || mesh_verts.Length == 0)
				mesh_verts = new Vector3[4];
			for(int idx=0; idx < 4; idx++)
			{
				mesh_verts[idx] = m_base_vertices[idx];
				
				// normalise vert position to the anchor point before scaling and rotating.
				mesh_verts[idx] -= m_anchor_offset;
				
				// Scale verts
				mesh_verts[idx] = Vector3.Scale(mesh_verts[idx], m_letter_scale);
				
				// Rotate vert
				mesh_verts[idx] = m_letter_rotation	* mesh_verts[idx];
				
				mesh_verts[idx] += m_anchor_offset;
				
				// translate vert
				mesh_verts[idx] += m_letter_position;
			}
			m_mesh.vertices = mesh_verts;
			
			
			
			// Sort out letters colour
			if(letter_action.m_use_gradient_start)
			{
				start_colour = letter_action.m_start_vertex_colour.GetValue(progression_variables, animate_per);
			}
			else
			{
				start_colour = new VertexColour(letter_action.m_start_colour.GetValue(progression_variables, animate_per));
			}
			
			if(letter_action.m_use_gradient_end)
			{
				end_colour = letter_action.m_end_vertex_colour.GetValue(progression_variables, animate_per);
			}
			else
			{
				end_colour = new VertexColour(letter_action.m_end_colour.GetValue(progression_variables, animate_per));
			}
			
			if(!m_flipped)
			{
				m_mesh.colors = new Color[]{ 
					Color.Lerp(start_colour.top_right, end_colour.top_right, action_progress), 
					Color.Lerp(start_colour.top_left, end_colour.top_left, action_progress), 
					Color.Lerp(start_colour.bottom_left, end_colour.bottom_left, action_progress), 
					Color.Lerp(start_colour.bottom_right, end_colour.bottom_right, action_progress)};
			}
			else
			{
				m_mesh.colors = new Color[]{
					Color.Lerp(start_colour.top_left, end_colour.top_left, action_progress),
					Color.Lerp(start_colour.bottom_left, end_colour.bottom_left, action_progress),
					Color.Lerp(start_colour.bottom_right, end_colour.bottom_right, action_progress),
					Color.Lerp(start_colour.top_right, end_colour.top_right, action_progress)
				};
			}
		}
		public void Recycle(string character, int letter_idx, Mesh mesh, Vector3 base_offset, ref CustomCharacterInfo char_info, int line_num, int word_idx, EffectManager effect_manager)
		{
			m_character = character;
			m_mesh = mesh;
			m_base_offset = base_offset;
			m_effect_manager_handle = effect_manager;
			
			m_progression_variables = new AnimationProgressionVariables(letter_idx, word_idx, line_num);
			
			SetupLetterMesh(ref char_info);
			
			if(m_flipped)
			{
				// flip UV coords in x axis.
				m_mesh.uv = new Vector2[] {mesh.uv[3], mesh.uv[2], mesh.uv[1], mesh.uv[0]};
			}
			
			m_current_letter_action = null;
		}
		public LetterSetup(string character, int letter_idx, Mesh mesh, Vector3 base_offset, ref CustomCharacterInfo char_info, int line_num, int word_idx, EffectManager effect_manager)
		{
			m_character = character;
			m_mesh = mesh;
			m_base_offset = base_offset;
			m_effect_manager_handle = effect_manager;
			
			m_progression_variables = new AnimationProgressionVariables(letter_idx, word_idx, line_num);
			
			m_anim_state_vars = new AnimationStateVariables();
			m_anim_state_vars.m_active_loop_cycles = new List<ActionLoopCycle>();
			
			SetupLetterMesh(ref char_info);
			
			if(m_flipped)
			{
				// flip UV coords in x axis.
				m_mesh.uv = new Vector2[] {mesh.uv[3], mesh.uv[2], mesh.uv[1], mesh.uv[0]};
			}
		}
Beispiel #15
0
        void SetupMesh(LetterAction letter_action, LetterAction prev_action, float action_progress, AnimationProgressionVariables progression_variables, AnimatePerOptions animate_per, float linear_progress, EffectManager effect_manager)
        {
            // construct current anchor offset vector
            m_anchor_offset = letter_action.AnchorOffsetStart;
            m_anchor_offset = new Vector3(m_anchor_offset.x * m_width,
                                          letter_action.m_letter_anchor_start == (int)TextfxTextAnchor.BaselineLeft || letter_action.m_letter_anchor_start == (int)TextfxTextAnchor.BaselineCenter || letter_action.m_letter_anchor_start == (int)TextfxTextAnchor.BaselineRight
                                                                                                ? 0             // zero because letters are based around the baseline already.
                                                                                                : (effect_manager.IsFontBaseLineSet
                                                                                                                ? (effect_manager.FontBaseLine + m_y_offset) - (m_anchor_offset.y * -m_height)
                                                                                                                : (m_anchor_offset.y * m_height)),      // Legacy effect support when baseline isn't already set.
                                          0);

            if (letter_action.m_letter_anchor_2_way)
            {
                m_anchor_offset = letter_action.AnchorOffsetEnd;
                m_anchor_offset = Vector3.Lerp(m_anchor_offset,
                                               new Vector3(
                                                   m_anchor_offset.x * m_width,
                                                   letter_action.m_letter_anchor_end == (int)TextfxTextAnchor.BaselineLeft || letter_action.m_letter_anchor_end == (int)TextfxTextAnchor.BaselineCenter || letter_action.m_letter_anchor_end == (int)TextfxTextAnchor.BaselineRight
                                                                                                                ? 0             // zero because letters are based around the baseline already.
                                                                                                                : (effect_manager.IsFontBaseLineSet
                                                                                                                                ? (effect_manager.FontBaseLine + m_y_offset) - (m_anchor_offset.y * -m_height)
                                                                                                                                : (m_anchor_offset.y * m_height)),      // Legacy effect support when baseline isn't already set.
                                                   0),
                                               action_progress);
            }


            // Calculate Scale Vector
            from_vec = letter_action.m_start_scale.GetValue(progression_variables, animate_per);
            to_vec   = letter_action.m_end_scale.GetValue(progression_variables, animate_per);

            if (letter_action.m_scale_axis_ease_data.m_override_default)
            {
                m_letter_scale = new Vector3(EffectManager.FloatLerp(from_vec.x, to_vec.x, EasingManager.GetEaseProgress(letter_action.m_scale_axis_ease_data.m_x_ease, linear_progress)),
                                             EffectManager.FloatLerp(from_vec.y, to_vec.y, EasingManager.GetEaseProgress(letter_action.m_scale_axis_ease_data.m_y_ease, linear_progress)),
                                             EffectManager.FloatLerp(from_vec.z, to_vec.z, EasingManager.GetEaseProgress(letter_action.m_scale_axis_ease_data.m_z_ease, linear_progress)));
            }
            else
            {
                m_letter_scale = EffectManager.Vector3Lerp(
                    from_vec,
                    to_vec,
                    action_progress);
            }

            // Calculate Rotation
            from_vec = letter_action.m_start_euler_rotation.GetValue(progression_variables, animate_per);
            to_vec   = letter_action.m_end_euler_rotation.GetValue(progression_variables, animate_per);

            if (letter_action.m_rotation_axis_ease_data.m_override_default)
            {
                m_letter_rotation = Quaternion.Euler
                                    (
                    EffectManager.FloatLerp(from_vec.x, to_vec.x, EasingManager.GetEaseProgress(letter_action.m_rotation_axis_ease_data.m_x_ease, linear_progress)),
                    EffectManager.FloatLerp(from_vec.y, to_vec.y, EasingManager.GetEaseProgress(letter_action.m_rotation_axis_ease_data.m_y_ease, linear_progress)),
                    EffectManager.FloatLerp(from_vec.z, to_vec.z, EasingManager.GetEaseProgress(letter_action.m_rotation_axis_ease_data.m_z_ease, linear_progress))
                                    );
            }
            else
            {
                m_letter_rotation = Quaternion.Euler(
                    EffectManager.Vector3Lerp(
                        from_vec,
                        to_vec,
                        action_progress)
                    );
            }


            // Calculate Position
            if (letter_action.m_start_pos.Progression == ActionPositionVector3Progression.CURVE_OPTION_INDEX || (letter_action.m_offset_from_last && prev_action != null && prev_action.m_end_pos.Progression == ActionPositionVector3Progression.CURVE_OPTION_INDEX))
            {
                from_vec = new Vector3(-m_anchor_offset.x, m_base_offset.y, 0);
            }
            else if (letter_action.m_start_pos.ForcePositionOverride)
            {
                from_vec = new Vector3(-m_anchor_offset.x, 0, 0);
            }
            else
            {
                from_vec = BaseOffset;
            }

            from_vec += letter_action.m_start_pos.GetValue(progression_variables, animate_per);

            if (letter_action.m_end_pos.Progression == ActionPositionVector3Progression.CURVE_OPTION_INDEX || (letter_action.m_end_pos.IsOffsetFromLast && letter_action.m_start_pos.Progression == ActionPositionVector3Progression.CURVE_OPTION_INDEX))
            {
                to_vec = new Vector3(-m_anchor_offset.x, m_base_offset.y, 0);
            }
            else if (letter_action.m_end_pos.ForcePositionOverride)
            {
                to_vec = new Vector3(-m_anchor_offset.x, 0, 0);
            }
            else
            {
                to_vec = BaseOffset;
            }

            to_vec += letter_action.m_end_pos.GetValue(progression_variables, animate_per);

            if (letter_action.m_position_axis_ease_data.m_override_default)
            {
                m_letter_position = new Vector3(EffectManager.FloatLerp(from_vec.x, to_vec.x, EasingManager.GetEaseProgress(letter_action.m_position_axis_ease_data.m_x_ease, linear_progress)),
                                                EffectManager.FloatLerp(from_vec.y, to_vec.y, EasingManager.GetEaseProgress(letter_action.m_position_axis_ease_data.m_y_ease, linear_progress)),
                                                EffectManager.FloatLerp(from_vec.z, to_vec.z, EasingManager.GetEaseProgress(letter_action.m_position_axis_ease_data.m_z_ease, linear_progress)));
            }
            else
            {
                m_letter_position = EffectManager.Vector3Lerp(
                    from_vec,
                    to_vec,
                    action_progress);
            }

            // Calculate letter center position
            m_letter_center  = new Vector3(m_width / 2, m_height / 2, 0);
            m_letter_center -= m_anchor_offset;
            m_letter_center  = Vector3.Scale(m_letter_center, m_letter_scale);
            m_letter_center  = m_letter_rotation * m_letter_center;
            m_letter_center += m_anchor_offset + m_letter_position;


            if (mesh_verts == null || mesh_verts.Length == 0)
            {
                mesh_verts = new Vector3[4];
            }
            for (int idx = 0; idx < 4; idx++)
            {
                mesh_verts[idx] = m_base_vertices[idx];

                // normalise vert position to the anchor point before scaling and rotating.
                mesh_verts[idx] -= m_anchor_offset;

                // Scale verts
                mesh_verts[idx] = Vector3.Scale(mesh_verts[idx], m_letter_scale);

                // Rotate vert
                mesh_verts[idx] = m_letter_rotation * mesh_verts[idx];

                mesh_verts[idx] += m_anchor_offset;

                // translate vert
                mesh_verts[idx] += m_letter_position;
            }
            m_mesh.vertices = mesh_verts;



            // Sort out letters colour
            if (letter_action.m_use_gradient_start)
            {
                start_colour = letter_action.m_start_vertex_colour.GetValue(progression_variables, animate_per);
            }
            else
            {
                start_colour = new VertexColour(letter_action.m_start_colour.GetValue(progression_variables, animate_per));
            }

            if (letter_action.m_use_gradient_end)
            {
                end_colour = letter_action.m_end_vertex_colour.GetValue(progression_variables, animate_per);
            }
            else
            {
                end_colour = new VertexColour(letter_action.m_end_colour.GetValue(progression_variables, animate_per));
            }

            if (!m_flipped)
            {
                m_mesh.colors = new Color[] {
                    Color.Lerp(start_colour.top_right, end_colour.top_right, action_progress),
                    Color.Lerp(start_colour.top_left, end_colour.top_left, action_progress),
                    Color.Lerp(start_colour.bottom_left, end_colour.bottom_left, action_progress),
                    Color.Lerp(start_colour.bottom_right, end_colour.bottom_right, action_progress)
                };
            }
            else
            {
                m_mesh.colors = new Color[] {
                    Color.Lerp(start_colour.top_left, end_colour.top_left, action_progress),
                    Color.Lerp(start_colour.bottom_left, end_colour.bottom_left, action_progress),
                    Color.Lerp(start_colour.bottom_right, end_colour.bottom_right, action_progress),
                    Color.Lerp(start_colour.top_right, end_colour.top_right, action_progress)
                };
            }
        }
		public void SoftReset(LetterAction prev_action, AnimationProgressionVariables progression_variables, AnimatePerOptions animate_per, bool first_action = false)
		{
			if(m_use_gradient_start)
			{
				if(!m_offset_from_last && m_start_vertex_colour.UniqueRandom && !first_action)
				{
					m_start_vertex_colour.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_vertex_colour.Values : null);
				}
			}
			else
			{
				if(!m_offset_from_last && m_start_colour.UniqueRandom && !first_action)
				{
					m_start_colour.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_colour.Values : null);
				}
			}
			
			if(!m_offset_from_last && !first_action)
			{
				if(m_start_pos.UniqueRandom)
				{
					m_start_pos.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_pos.Values : null);
				}
				if(m_start_euler_rotation.UniqueRandom)
				{
					m_start_euler_rotation.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_euler_rotation.Values : null);
				}
				if(m_start_scale.UniqueRandom)
				{
					m_start_scale.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_scale.Values : null);
				}
			}
			
			// End State Unique Randoms
			if(m_use_gradient_end)
			{
				if(m_end_vertex_colour.UniqueRandom)
				{
					m_end_vertex_colour.CalculateUniqueRandom(progression_variables, animate_per, m_start_vertex_colour.Values);
				}
			}
			else
			{
				if(m_end_colour.UniqueRandom)
				{
					m_end_colour.CalculateUniqueRandom(progression_variables, animate_per, m_start_colour.Values);
				}
			}
			if(m_end_pos.UniqueRandom)
			{
				m_end_pos.CalculateUniqueRandom(progression_variables, animate_per, m_start_pos.Values);
			}
			if(m_end_euler_rotation.UniqueRandom)
			{
				m_end_euler_rotation.CalculateUniqueRandom(progression_variables, animate_per, m_start_euler_rotation.Values);
			}
			if(m_end_scale.UniqueRandom)
			{
				m_end_scale.CalculateUniqueRandom(progression_variables, animate_per, m_start_scale.Values);
			}
			
			
			// Timing unique randoms
			if(m_delay_progression.UniqueRandom)
			{
				m_delay_progression.CalculateUniqueRandom(progression_variables, animate_per);
			}
			if(m_duration_progression.UniqueRandom)
			{
				m_duration_progression.CalculateUniqueRandom(progression_variables, animate_per);
			}
			
			if(m_audio_effects != null)
			{
				foreach(AudioEffectSetup effect_setup in m_audio_effects)
				{
					if(effect_setup.m_delay.UniqueRandom)
						effect_setup.m_delay.CalculateUniqueRandom(progression_variables, animate_per);
					if(effect_setup.m_offset_time.UniqueRandom)
						effect_setup.m_offset_time.CalculateUniqueRandom(progression_variables, animate_per);
					if(effect_setup.m_volume.UniqueRandom)
						effect_setup.m_volume.CalculateUniqueRandom(progression_variables, animate_per);
					if(effect_setup.m_pitch.UniqueRandom)
						effect_setup.m_pitch.CalculateUniqueRandom(progression_variables, animate_per);
				}
			}
			
			if(m_particle_effects != null)
			{
				foreach(ParticleEffectSetup effect_setup in m_particle_effects)
				{
					if(effect_setup.m_position_offset.UniqueRandom)
						effect_setup.m_position_offset.CalculateUniqueRandom(progression_variables, animate_per, null);
					if(effect_setup.m_rotation_offset.UniqueRandom)
						effect_setup.m_rotation_offset.CalculateUniqueRandom(progression_variables, animate_per, null);
					if(effect_setup.m_delay.UniqueRandom)
						effect_setup.m_delay.CalculateUniqueRandom(progression_variables, animate_per);
					if(effect_setup.m_duration.UniqueRandom)
						effect_setup.m_duration.CalculateUniqueRandom(progression_variables, animate_per);
				}
			}
		}
		public void SoftResetStarts(LetterAction prev_action, AnimationProgressionVariables progression_variables, AnimatePerOptions animate_per)
		{
			if(m_use_gradient_start)
			{
				if(!m_offset_from_last && m_start_vertex_colour.UniqueRandom)
				{
					m_start_vertex_colour.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_vertex_colour.Values : null);
				}
			}
			else
			{
				if(!m_offset_from_last && m_start_colour.UniqueRandom)
				{
					m_start_colour.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_colour.Values : null);
				}
			}
			
			if(!m_offset_from_last)
			{
				if(m_start_pos.UniqueRandom)
				{
					m_start_pos.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_pos.Values : null);
				}
				if(m_start_euler_rotation.UniqueRandom)
				{
					m_start_euler_rotation.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_euler_rotation.Values : null);
				}
				if(m_start_scale.UniqueRandom)
				{
					m_start_scale.CalculateUniqueRandom(progression_variables, animate_per, prev_action != null ? prev_action.m_end_scale.Values : null);
				}
			}
		}
        public ParticleEffectInstanceManager(EffectManager effect_manager, Mesh character_mesh, bool letter_flipped, 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_mesh           = character_mesh;
            m_letter_flipped        = letter_flipped;
            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(progression_vars, animate_per);
            m_rotation_offset       = Quaternion.Euler(effect_setup.m_rotation_offset.GetValue(progression_vars, animate_per));
            m_rotate_with_letter    = effect_setup.m_rotate_relative_to_letter;
            m_effect_manager_handle = effect_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;
            }
            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
            }
        }
		public void CalculateUniqueRandom(AnimationProgressionVariables progression_variables, AnimatePerOptions animate_per, Color[] offset_cols)
		{
			int progression_idx = GetProgressionIndex(progression_variables, animate_per);
			bool constant_offset = offset_cols != null && offset_cols.Length == 1;
				
			m_values[progression_idx] = m_is_offset_from_last ? offset_cols[constant_offset ? 0 : progression_idx] : new Color(0,0,0,0);
			m_values[progression_idx] += m_from + (m_to - m_from) * UnityEngine.Random.value;
		}
		public void PlayAudioClip(AudioEffectSetup effect_setup, AnimationProgressionVariables progression_vars, AnimatePerOptions animate_per)
		{
			bool sound_played = false;
			AudioSource source = null;
			
			if(m_audio_sources != null)
			{
				foreach(AudioSource a_source in m_audio_sources)
				{
					if(!a_source.isPlaying)
					{
						// audio source free to play a sound
						source= a_source;
						
						sound_played = true;
						break;
					}
				}
				
				if(!sound_played)
				{
					source = AddNewAudioChild();
				}
			}
			else
			{
				source = AddNewAudioChild();
			}
			
			PlayClip(
				source,
				effect_setup.m_audio_clip,
				effect_setup.m_delay.GetValue(progression_vars, animate_per),
				effect_setup.m_offset_time.GetValue(progression_vars, animate_per),
				effect_setup.m_volume.GetValue(progression_vars, animate_per),
				effect_setup.m_pitch.GetValue(progression_vars, animate_per));
		}