public void SetAnimationVars(LetterSetup master_letter) { m_anim_state_vars = master_letter.AnimStateVars.Clone(); m_current_letter_action = null; // clone the list of active loop cycles, so that the list reference is not shared between two letters m_anim_state_vars.m_active_loop_cycles = new List <ActionLoopCycle>(); foreach (ActionLoopCycle loop_cycle in master_letter.AnimStateVars.m_active_loop_cycles) { m_anim_state_vars.m_active_loop_cycles.Add(loop_cycle.Clone()); } }
public void PrepareData(ref LetterSetup[] letters, int num_letters, int num_words, int num_lines, LetterAction prev_action, AnimatePerOptions animate_per, bool prev_action_end_state = true) { m_duration_progression.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, m_duration_progression.AnimatePer, m_duration_progression.OverrideAnimatePerOption)); if(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(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) { return; } m_delay_progression.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, m_delay_progression.AnimatePer, m_delay_progression.OverrideAnimatePerOption)); if(m_offset_from_last && prev_action != null) { m_use_gradient_start = prev_action.m_use_gradient_end; if(prev_action_end_state) { if(m_use_gradient_start) { m_start_vertex_colour.Values = prev_action.m_end_vertex_colour.Values; } else { m_start_colour.Values = prev_action.m_end_colour.Values; } } else { if(m_use_gradient_start) { m_start_vertex_colour.Values = prev_action.m_start_vertex_colour.Values; } else { m_start_colour.Values = prev_action.m_start_colour.Values; } } } else { if(m_use_gradient_start || (prev_action != null && (prev_action.m_use_gradient_end))) { if(!m_use_gradient_start) { // Need to convert flat colour into a vertex colour m_use_gradient_start = true; m_start_vertex_colour.ConvertFromFlatColourProg(m_start_colour); } // add this colour to previous state m_start_vertex_colour.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, m_start_vertex_colour.AnimatePer, m_start_vertex_colour.OverrideAnimatePerOption), prev_action != null && (prev_action.m_use_gradient_end) ? prev_action.m_end_vertex_colour.Values : null, prev_action != null && (!prev_action.m_use_gradient_end) ? prev_action.m_end_colour.Values : null); } 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.Values : null); } } if(m_use_gradient_end || m_use_gradient_start) { if(!m_use_gradient_end) { // Need to convert flat colour into a vertex colour m_use_gradient_end = true; m_end_vertex_colour.ConvertFromFlatColourProg(m_end_colour); } m_end_vertex_colour.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, m_end_vertex_colour.AnimatePer, m_end_vertex_colour.OverrideAnimatePerOption), (m_use_gradient_start) ? m_start_vertex_colour.Values : null, (!m_use_gradient_start) ? m_start_colour.Values : null); } else { m_end_colour.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, m_end_colour.AnimatePer, m_end_colour.OverrideAnimatePerOption), m_start_colour.Values); } if(m_offset_from_last && prev_action != null) { m_start_pos.Values = prev_action_end_state ? prev_action.m_end_pos.Values : prev_action.m_start_pos.Values; m_start_euler_rotation.Values = prev_action_end_state ? prev_action.m_end_euler_rotation.Values : prev_action.m_start_euler_rotation.Values; m_start_scale.Values = prev_action_end_state ? prev_action.m_end_scale.Values : prev_action.m_start_scale.Values; } else { float[] start_pos_curve_letter_progressions = null; if(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(ref letters, m_letter_anchor_start); } m_start_pos.CalculatePositionProgressions(ref start_pos_curve_letter_progressions, GetProgressionTotal(num_letters, num_words, num_lines, animate_per, m_start_pos.AnimatePer, m_start_pos.OverrideAnimatePerOption), prev_action != null ? prev_action.m_end_pos.Values : new Vector3[]{Vector3.zero}); m_start_euler_rotation.CalculateRotationProgressions(ref start_pos_curve_letter_progressions, GetProgressionTotal(num_letters, 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.Values : new Vector3[]{Vector3.zero}, m_start_pos.Progression == ActionPositionVector3Progression.CURVE_OPTION_INDEX ? m_start_pos.BezierCurve : null); m_start_scale.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, m_start_scale.AnimatePer, m_start_scale.OverrideAnimatePerOption), prev_action != null ? prev_action.m_end_scale.Values : new Vector3[]{Vector3.zero}); } float[] end_pos_curve_letter_progressions = null; if(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(ref letters, m_letter_anchor_end); } m_end_pos.CalculatePositionProgressions(ref end_pos_curve_letter_progressions, GetProgressionTotal(num_letters, num_words, num_lines, animate_per, m_end_pos.AnimatePer, m_end_pos.OverrideAnimatePerOption), m_start_pos.Values); m_end_euler_rotation.CalculateRotationProgressions(ref end_pos_curve_letter_progressions, GetProgressionTotal(num_letters, num_words, num_lines, animate_per, m_end_euler_rotation.AnimatePer, m_end_euler_rotation.OverrideAnimatePerOption), m_start_euler_rotation.Values, m_end_pos.Progression == ActionPositionVector3Progression.CURVE_OPTION_INDEX ? m_end_pos.BezierCurve : null); m_end_scale.CalculateProgressions(GetProgressionTotal(num_letters, num_words, num_lines, animate_per, m_end_scale.AnimatePer, m_end_scale.OverrideAnimatePerOption), m_start_scale.Values); CalculateLetterAnchorOffset(); }
float GetLetterAnchorOffset(LetterSetup letter, int letter_anchor) { return(letter_anchor == (int)TextfxTextAnchor.LowerCenter || letter_anchor == (int)TextfxTextAnchor.MiddleCenter || letter_anchor == (int)TextfxTextAnchor.UpperCenter || letter_anchor == (int)TextfxTextAnchor.BaselineCenter ? (letter.m_offset_width + (letter.m_width - letter.m_offset_width)) / 2 : ((letter_anchor == (int)TextfxTextAnchor.LowerRight || letter_anchor == (int)TextfxTextAnchor.MiddleRight || letter_anchor == (int)TextfxTextAnchor.UpperRight || letter_anchor == (int)TextfxTextAnchor.BaselineRight) ? (letter.m_offset_width + (letter.m_width - letter.m_offset_width)) : 0)); }
float GetLetterAnchorOffset(LetterSetup letter, int letter_anchor) { return (letter_anchor == (int) TextfxTextAnchor.LowerCenter || letter_anchor == (int) TextfxTextAnchor.MiddleCenter || letter_anchor == (int) TextfxTextAnchor.UpperCenter || letter_anchor == (int) TextfxTextAnchor.BaselineCenter ? (letter.m_offset_width + (letter.m_width - letter.m_offset_width))/2 : ((letter_anchor == (int) TextfxTextAnchor.LowerRight || letter_anchor == (int) TextfxTextAnchor.MiddleRight || letter_anchor == (int) TextfxTextAnchor.UpperRight || letter_anchor == (int) TextfxTextAnchor.BaselineRight) ? (letter.m_offset_width + (letter.m_width - letter.m_offset_width)) : 0)); }
public float[] GetLetterProgressions(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; EffectManager effect_manager_ref; 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]; // grab a reference to the EffectManager instance effect_manager_ref = letter.m_effect_manager_handle; // 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.m_base_offset.x; // Setup letter offset value letters_offset = (letter.m_base_offset.x - 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); } 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); 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.m_base_offset.x; curve_idx = 0; idx=-1; line_length = 0; } // Setup letter offset value letters_offset = (letter.m_base_offset.x - 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 void PrepareData(LetterSetup[] letters, int num_words, int num_lines, AnimatePerOptions animate_per) { if(letters == null || letters.Length == 0) { return; } int num_letters = letters.Length; // Populate list of letters to animate by index, and set Letter indexes accordingly if(m_letters_to_animate_option == LETTERS_TO_ANIMATE.ALL_LETTERS) { m_letters_to_animate = new List<int>(); for(int letter_idx=0; letter_idx < num_letters; letter_idx++) { m_letters_to_animate.Add(letter_idx); letters[letter_idx].m_progression_variables.m_letter_value = letter_idx; } } else if(m_letters_to_animate_option == LETTERS_TO_ANIMATE.FIRST_LETTER || m_letters_to_animate_option == LETTERS_TO_ANIMATE.LAST_LETTER) { m_letters_to_animate = new List<int>(); m_letters_to_animate.Add(m_letters_to_animate_option == LETTERS_TO_ANIMATE.FIRST_LETTER ? 0 : letters.Length -1); letters[m_letters_to_animate_option == LETTERS_TO_ANIMATE.FIRST_LETTER ? 0 : letters.Length - 1].m_progression_variables.m_letter_value = 0; } else if(m_letters_to_animate_option != LETTERS_TO_ANIMATE.CUSTOM) { m_letters_to_animate = new List<int>(); int line_idx = m_letters_to_animate_option == LETTERS_TO_ANIMATE.LAST_LETTER_LINES ? 0 : -1; int word_idx = m_letters_to_animate_option == LETTERS_TO_ANIMATE.LAST_LETTER_WORDS ? 0 : -1; int target_idx = 0; if(m_letters_to_animate_option == LETTERS_TO_ANIMATE.LAST_WORD) target_idx = letters[letters.Length-1].m_progression_variables.m_word_value; else if(m_letters_to_animate_option == LETTERS_TO_ANIMATE.LAST_LINE) target_idx = letters[letters.Length-1].m_progression_variables.m_line_value; else if(m_letters_to_animate_option == LETTERS_TO_ANIMATE.NTH_WORD || m_letters_to_animate_option == LETTERS_TO_ANIMATE.NTH_LINE) target_idx = m_letters_to_animate_custom_idx - 1; int letter_idx = 0; int progression_idx = 0; foreach(LetterSetup letter in letters) { if(m_letters_to_animate_option == LETTERS_TO_ANIMATE.FIRST_LINE || m_letters_to_animate_option == LETTERS_TO_ANIMATE.LAST_LINE || m_letters_to_animate_option == LETTERS_TO_ANIMATE.NTH_LINE) { if(letter.m_progression_variables.m_line_value == target_idx) { letter.m_progression_variables.m_letter_value = progression_idx; m_letters_to_animate.Add(letter_idx); progression_idx ++; } } else if(letter.m_progression_variables.m_line_value > line_idx) { if(m_letters_to_animate_option == LETTERS_TO_ANIMATE.FIRST_LETTER_LINES) { letter.m_progression_variables.m_letter_value = progression_idx; m_letters_to_animate.Add(letter_idx); progression_idx ++; } else if(m_letters_to_animate_option == LETTERS_TO_ANIMATE.LAST_LETTER_LINES) { letter.m_progression_variables.m_letter_value = progression_idx - 1; m_letters_to_animate.Add(letter_idx - 1); progression_idx ++; } line_idx = letter.m_progression_variables.m_line_value; } if(m_letters_to_animate_option == LETTERS_TO_ANIMATE.FIRST_WORD || m_letters_to_animate_option == LETTERS_TO_ANIMATE.LAST_WORD || m_letters_to_animate_option == LETTERS_TO_ANIMATE.NTH_WORD) { if(letter.m_progression_variables.m_word_value == target_idx) { letter.m_progression_variables.m_letter_value = progression_idx; m_letters_to_animate.Add(letter_idx); progression_idx ++; } } else if(letter.m_progression_variables.m_word_value > word_idx) { if(m_letters_to_animate_option == LETTERS_TO_ANIMATE.FIRST_LETTER_WORDS) { letter.m_progression_variables.m_letter_value = progression_idx; m_letters_to_animate.Add(letter_idx); progression_idx ++; } else if(m_letters_to_animate_option == LETTERS_TO_ANIMATE.LAST_LETTER_WORDS) { letter.m_progression_variables.m_letter_value = progression_idx; m_letters_to_animate.Add(letter_idx - 1); progression_idx ++; } word_idx = letter.m_progression_variables.m_word_value; } letter_idx++; } if(m_letters_to_animate_option == LETTERS_TO_ANIMATE.LAST_LETTER_WORDS || m_letters_to_animate_option == LETTERS_TO_ANIMATE.LAST_LETTER_LINES) { letters[num_letters - 1].m_progression_variables.m_letter_value = letter_idx - 1; m_letters_to_animate.Add(letter_idx - 1); } } else { int progression_idx = 0; for(int letter_idx=0; letter_idx < num_letters; letter_idx++) { if(m_letters_to_animate.Contains(letter_idx)) { letters[letter_idx].m_progression_variables.m_letter_value = progression_idx; progression_idx ++; } } } // Prepare data 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(ref letters, m_letters_to_animate.Count, num_words, num_lines, prev_action, animate_per, 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) { prev_action = m_letter_actions[loop_cycle.m_start_action_idx]; prev_action_end_state = false; } } } }
public void SetAnimationVars(LetterSetup master_letter) { m_anim_state_vars = master_letter.AnimStateVars.Clone(); m_current_letter_action = null; // clone the list of active loop cycles, so that the list reference is not shared between two letters m_anim_state_vars.m_active_loop_cycles = new List<ActionLoopCycle>(); foreach(ActionLoopCycle loop_cycle in master_letter.AnimStateVars.m_active_loop_cycles) { m_anim_state_vars.m_active_loop_cycles.Add(loop_cycle.Clone()); } }
public void SetText(string new_text, bool force_all_new = false) { if(m_renderer == null) { m_renderer = this.GetComponent<Renderer>(); } bool setup_correctly = false; // Automatically assign the font material to the renderer if its not already set if((m_renderer.sharedMaterial == null || m_renderer.sharedMaterial != m_font_material) && m_font_material != null) { m_renderer.sharedMaterial = m_font_material; } else if(m_font != null) { if(m_renderer.sharedMaterial == null || m_renderer.sharedMaterial != m_font_material) { m_font_material = m_font.material; m_renderer.sharedMaterial = m_font_material; } if(m_renderer.sharedMaterial != null) { setup_correctly = true; } } if(!setup_correctly && (m_renderer.sharedMaterial == null || m_font_data_file == null)) { // Incorrectly setup font information m_font = Resources.GetBuiltinResource(typeof(Font), "Arial.ttf") as Font; m_font_material = m_font.material; m_renderer.sharedMaterial = m_font_material; m_font_data_file = null; } m_text = new_text; // Remove all carriage return char's from new_text new_text = new_text.Replace("\r", ""); string raw_chars = m_text.Replace(" ", ""); raw_chars = raw_chars.Replace("\n", ""); raw_chars = raw_chars.Replace("\r", ""); raw_chars = raw_chars.Replace("\t", ""); int text_length = new_text.Length; LetterSetup[] prev_letters = m_letters; m_letters= new LetterSetup[raw_chars.Length]; CustomCharacterInfo char_info = new CustomCharacterInfo(); CustomCharacterInfo last_char_info = null; m_text_datas = new List<TextSizeData>(); if(m_font != null) { // Make sure font contains all characters required m_font.RequestCharactersInTexture(m_text); if(m_font_material.mainTexture.width != m_font_texture_width || m_font_material.mainTexture.height != m_font_texture_height) { // Font texture size has changed m_font_texture_width = m_font_material.mainTexture.width; m_font_texture_height = m_font_material.mainTexture.height; SetText(m_text, true); return; } } // Calculate bounds of text mesh char character; float y_max=0, y_min=0, x_max=0, x_min=0; float text_width = 0, text_height = 0; int line_letter_idx = 0; float line_height_offset = 0; float total_text_width = 0, total_text_height = 0; float line_width_at_last_space = 0; float space_char_offset = 0; int last_letter_setup_idx = -1; float last_space_y_max = 0; float last_space_y_min = 0; Rect uv_data; LetterSetup last_letter = null; float letter_offset = 0; int letter_count = 0; int line_idx = 0; int word_idx = 0; m_line_height = 0; Action AddNewLineData = new Action( () => { if(m_display_axis == TextDisplayAxis.HORIZONTAL) { float height = Mathf.Abs(y_max - y_min ) * LineHeightFactor; // Check if line is the tallest so far if(height > m_line_height) m_line_height = height; if(last_char_info != null) { // Re-adjust width of last letter since its the end of the text line text_width += - last_char_info.width + last_char_info.vert.width + last_char_info.vert.x; } m_text_datas.Add( new TextSizeData(text_width, height, line_height_offset, y_max)); line_height_offset += height; if(text_width > total_text_width) { total_text_width = text_width; } total_text_height += height; } else { float width = Mathf.Abs( x_max - x_min ) * LineHeightFactor; // Check if line is the tallest so far if(width > m_line_height) m_line_height = width; m_text_datas.Add( new TextSizeData( width, text_height * -1, line_height_offset, 0)); line_height_offset += width; total_text_width += width; if(text_height < total_text_height) { total_text_height = text_height; } } line_letter_idx = 0; text_width = 0; line_width_at_last_space = 0; space_char_offset = 0; last_space_y_max = 0; last_space_y_min = 0; last_letter_setup_idx = -1; text_height = 0; last_char_info = null; }); for(int letter_idx=0; letter_idx < text_length; letter_idx++) { character = new_text[letter_idx]; if(GetCharacterInfo(character, ref char_info)) { if(character.Equals('\t')) { continue; } else if(character.Equals(' ')) { if(m_display_axis == TextDisplayAxis.HORIZONTAL) { // Record the state of the line dims at this point incase the next word is forced onto next line by bound box line_width_at_last_space = text_width; space_char_offset = char_info.width; last_space_y_max = y_max; last_space_y_min = y_min; last_letter_setup_idx = letter_count; text_width += char_info.width; } else { char_info.vert.height = -char_info.width; } // Add space width to offset value letter_offset += m_display_axis == TextDisplayAxis.HORIZONTAL ? char_info.width : -char_info.width; //Increment word count word_idx++; } else if(character.Equals('\n')) { AddNewLineData.Invoke(); letter_offset = 0; line_idx++; //Increment word count word_idx++; } else { if(m_display_axis == TextDisplayAxis.HORIZONTAL) { if(line_letter_idx == 0 || char_info.vert.y > y_max) { y_max = char_info.vert.y; } if(line_letter_idx == 0 || char_info.vert.y + char_info.vert.height < y_min) { y_min = char_info.vert.y + char_info.vert.height; } // increment the text width by the letter progress width, and then full mesh width for last letter or end of line. text_width += (letter_idx == text_length - 1) ? char_info.vert.width + char_info.vert.x : char_info.width; // Handle bounding box if setup if(m_max_width > 0 && last_letter_setup_idx >= 0) { float actual_line_width = (letter_idx == text_length - 1) ? text_width : text_width - char_info.width + char_info.vert.width + char_info.vert.x; if(actual_line_width > m_max_width) { // Line exceeds bounding box width float new_line_text_width = text_width - line_width_at_last_space - space_char_offset; float new_line_y_min = last_space_y_min; float new_line_y_max = last_space_y_max; // Set line width to what it was at the last space (which is now the end of this line) text_width = line_width_at_last_space; y_max = last_space_y_max; y_min = last_space_y_min; letter_offset = 0; line_idx++; // Need to change the associated line number and positional offset of the letters now on a new line for(int past_letter_idx=last_letter_setup_idx; past_letter_idx < letter_count; past_letter_idx++) { m_letters[past_letter_idx].m_progression_variables.m_line_value = line_idx; m_letters[past_letter_idx].m_base_offset = m_display_axis == TextDisplayAxis.HORIZONTAL ? new Vector3(letter_offset, 0, 0) : new Vector3(0, letter_offset, 0); letter_offset += m_display_axis == TextDisplayAxis.HORIZONTAL ? m_letters[past_letter_idx].m_offset_width + (m_px_offset.x / FontScale) : m_letters[past_letter_idx].m_height + (-m_px_offset.y / FontScale); } AddNewLineData.Invoke(); // Setup current values text_width = new_line_text_width; y_min = new_line_y_min; y_max = new_line_y_max; } } } else { if(line_letter_idx == 0 || char_info.vert.x + char_info.vert.width > x_max) { x_max = char_info.vert.x + char_info.vert.width; } if(line_letter_idx == 0 || char_info.vert.x < x_min) { x_min = char_info.vert.x; } text_height += char_info.vert.height; } // Get letterSetup reference if(letter_count < prev_letters.Length && !force_all_new) { last_letter = prev_letters[letter_count]; } // Either reuse the same previous instance of LetterSetup or create a new one for this character. if( !force_all_new && prev_letters != null && letter_count < prev_letters.Length && last_letter.m_character.Equals(new_text[letter_idx].ToString()) && last_letter.m_progression_variables.m_letter_value == letter_idx && last_letter.m_mesh != null) { // Use same LetterSetup from previous configuration m_letters[letter_count] = last_letter; // Remove instance from previous letters list prev_letters[letter_count] = null; // position the letter offset again, incase it has changed from previous letters changing. last_letter.m_base_offset = m_display_axis == TextDisplayAxis.HORIZONTAL ? new Vector3(letter_offset, 0, 0) : new Vector3(0, letter_offset, 0); last_letter.SetupLetterMesh(ref char_info); last_letter.m_progression_variables.m_line_value = line_idx; last_letter.m_progression_variables.m_word_value = word_idx; last_letter.m_base_offsets_setup = false; } else { uv_data = char_info.uv; if(letter_count < prev_letters.Length && !force_all_new) { // Recycle last letter instance. m_letters[letter_count] = last_letter; // Setup Mesh UV co-ords and triangles (and fill in placeholder vertices) last_letter.m_mesh.vertices = new Vector3[]{Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero}; last_letter.m_mesh.uv = new Vector2[]{ new Vector2(uv_data.x + uv_data.width, uv_data.y + uv_data.height), new Vector2(uv_data.x, uv_data.y + uv_data.height), new Vector2(uv_data.x, uv_data.y), new Vector2(uv_data.x + uv_data.width, uv_data.y)}; last_letter.m_mesh.triangles = new int[]{2,1,0, 3,2,0}; last_letter.m_mesh.normals = new Vector3[]{ Vector3.back, Vector3.back, Vector3.back, Vector3.back}; last_letter.Recycle( "" + character, letter_count, last_letter.m_mesh, m_display_axis == TextDisplayAxis.HORIZONTAL ? new Vector3(letter_offset, 0, 0) : new Vector3(0, letter_offset, 0), // base_offset ref char_info, line_idx, word_idx, this); last_letter.m_base_offsets_setup = false; // Remove instance from previous letters list prev_letters[letter_count] = null; } else { Mesh mesh = new Mesh(); // Setup Mesh UV co-ords and triangles (and fill in placeholder vertices) mesh.vertices = new Vector3[]{Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero}; mesh.uv = new Vector2[]{ new Vector2(uv_data.x + uv_data.width, uv_data.y + uv_data.height), new Vector2(uv_data.x, uv_data.y + uv_data.height), new Vector2(uv_data.x, uv_data.y), new Vector2(uv_data.x + uv_data.width, uv_data.y)}; mesh.triangles = new int[]{2,1,0, 3,2,0}; mesh.normals = new Vector3[]{ Vector3.back, Vector3.back, Vector3.back, Vector3.back}; m_letters[letter_count] = new LetterSetup( "" + character, letter_count, mesh, m_display_axis == TextDisplayAxis.HORIZONTAL ? new Vector3(letter_offset, 0, 0) : new Vector3(0, letter_offset, 0), // base_offset ref char_info, line_idx, word_idx, this); if(last_letter != null) { m_letters[letter_count].SetAnimationVars(last_letter); } } } letter_count ++; letter_offset += m_display_axis == TextDisplayAxis.HORIZONTAL ? char_info.width + (m_px_offset.x / FontScale) : char_info.vert.height + (-m_px_offset.y / FontScale); last_char_info = char_info; } } line_letter_idx++; } // Save line and word info for later m_number_of_words = word_idx + 1; m_number_of_lines = line_idx + 1; if(m_display_axis == TextDisplayAxis.HORIZONTAL) { float height = Mathf.Abs(y_max - y_min ); m_text_datas.Add( new TextSizeData(text_width, height, line_height_offset, y_max)); if(text_width > total_text_width) { total_text_width = text_width; } total_text_height += height; } else { float width = Mathf.Abs( x_max - x_min ); m_text_datas.Add( new TextSizeData( width, text_height * -1, line_height_offset, 0)); total_text_width += width; if(text_height < total_text_height) { total_text_height = text_height; } } #if UNITY_EDITOR m_total_text_width = total_text_width; m_total_text_height = total_text_height; #endif for(int idx=0; idx < m_text_datas.Count; idx++) { m_text_datas[idx].m_total_text_height = total_text_height * (m_display_axis == TextDisplayAxis.HORIZONTAL ? 1 : -1); if(m_max_width > 0) { m_text_datas[idx].m_total_text_width = m_max_width; } else { m_text_datas[idx].m_total_text_width = total_text_width; } } // Destroy any left over unused meshes if(prev_letters != null) { foreach(LetterSetup old_letter in prev_letters) { if(old_letter != null) { // Letter wasn't used in new text setup; delete it's mesh instance. if(Application.isPlaying) { Destroy(old_letter.m_mesh); } else { DestroyImmediate(old_letter.m_mesh); } } } } // Set letter base offsets where needed bool all_offsets_set = true; do { all_offsets_set = true; foreach(LetterSetup letter in m_letters) { if(!letter.m_base_offsets_setup) { if(m_text_datas.Count == 0) { all_offsets_set = false; break; } letter.SetBaseOffset(m_text_anchor, m_display_axis, m_text_alignment, m_text_datas); } } if(!all_offsets_set) { // If text_datas has been lost or if legacy effect and hasn't been created, re-set text to recalculate it. Debug.LogError("If text_datas has been lost or if legacy effect and hasn't been created, reset text."); SetText(m_text); } } while(!all_offsets_set); // Calculate action progression values PrepareAnimationData(); // Render state of newly set text UpdateMesh(true, true, 0, 0); }