// Only called if action_idx has changed since last time void UpdateLoopList(LetterAnimation animation) { // add any new loops from the next action index to the loop list ActionLoopCycle loop; for (int idx = 0; idx < animation.NumLoops; idx++) { loop = animation.GetLoop(idx); if (loop.m_start_action_idx == m_anim_state_vars.m_action_index) { // add this new loop into the ordered active loop list int new_loop_cycle_span = loop.SpanWidth; int loop_idx = 0; foreach (ActionLoopCycle active_loop in m_anim_state_vars.m_active_loop_cycles) { if (loop.m_start_action_idx == active_loop.m_start_action_idx && loop.m_end_action_idx == active_loop.m_end_action_idx) { // This loop is already in the active loop list, don't re-add loop_idx = -1; break; } if (new_loop_cycle_span < active_loop.SpanWidth) { break; } loop_idx++; } if (loop_idx >= 0) { m_anim_state_vars.m_active_loop_cycles.Insert(loop_idx, loop.Clone()); } } } }
private void DrawLoopTree(LetterAnimation selected_animation) { if (font_manager.NumAnimations == 0) return; var main_editor_height = Instance.position.height - WINDOW_BORDER_TOP - WINDOW_BORDER_BOTTOM; var num_actions = selected_animation.NumActions; var gui_y_offset = WINDOW_BORDER_TOP; var action_idx = 0; gui_y_offset = WINDOW_BORDER_TOP; // Draw A's m_state_node_rects = new Rect[num_actions]; EditorGUI.LabelField(new Rect(state_overview_x, gui_y_offset, 100, LINE_HEIGHT * 2), "Loops [" + selected_animation.NumLoops + "]", EditorStyles.boldLabel); gui_y_offset += LINE_HEIGHT * 2; if (GUI.Button(new Rect(state_overview_x, gui_y_offset, 60, LINE_HEIGHT), new GUIContent(m_display_loops_tree ? "Hide" : "Show", (m_display_loops_tree ? "Hide" : "Show") + " the loops setup menu."))) m_display_loops_tree = !m_display_loops_tree; gui_y_offset += LINE_HEIGHT * 2; LOOP_SCROLL_POS = GUI.BeginScrollView(new Rect(state_overview_x, gui_y_offset, MainEditorX - state_overview_x - 14, main_editor_height - (gui_y_offset - WINDOW_BORDER_TOP)), LOOP_SCROLL_POS, new Rect(0, 0, MainEditorX - 35, selected_animation.NumActions * ACTION_NODE_SPACING)); gui_y_offset = 0; for (action_idx = 0; action_idx < selected_animation.NumActions; action_idx++) { GUI.Label(new Rect(20, gui_y_offset, 40, 20), "A" + action_idx, EditorStyles.boldLabel); if (m_display_loops_tree) m_state_node_rects[action_idx] = new Rect(20 - ACTION_NODE_MARGIN, gui_y_offset - ACTION_NODE_MARGIN, 20 + (2 * ACTION_NODE_MARGIN), 20 + (2 * ACTION_NODE_MARGIN)); gui_y_offset += ACTION_NODE_SPACING; } if (m_display_loops_tree) { // Draw existing loops Vector2 point1, point2; // Draw Loop assignment-in-progress line, triggered by users click and drag on action nodes if (m_mouse_down_node_idx >= 0) DrawLine(m_mouse_down_pos, new Vector2(m_mouse_down_pos.x, m_mouse_drag_pos.y), Color.gray, 3); state_overview_width = 0; var num_loops = selected_animation.NumLoops; var my_style = EditorStyles.miniButton; my_style.alignment = TextAnchor.MiddleLeft; my_style.normal.textColor = Color.black; // Loop through loop list, drawing loop line representations on loop timeline and adding loop list entries float loops_list_x; ActionLoopCycle loop_cycle; var last_span_width = -1; var indent_num = 0; float line_offset_x = 0; float loop_list_line_y = 0; GUI.SetNextControlName("LoopsTitle"); // Display loop list header EditorGUI.LabelField(new Rect(loop_tree_width + 60, loop_list_line_y, 100, LINE_HEIGHT), "Active Loops", EditorStyles.boldLabel); loop_list_line_y += LINE_HEIGHT; EditorGUI.LabelField(new Rect(loop_tree_width + 52, loop_list_line_y, 30, LINE_HEIGHT), new GUIContent("From", "The index of the action to start this loop."), EditorStyles.miniBoldLabel); EditorGUI.LabelField(new Rect(loop_tree_width + 87, loop_list_line_y, 20, LINE_HEIGHT), new GUIContent("To", "The index of the action to end this loop."), EditorStyles.miniBoldLabel); EditorGUI.LabelField(new Rect(loop_tree_width + 110, loop_list_line_y, 42, LINE_HEIGHT), new GUIContent("#Loops", "The number of times to run through this loop. Enter zero to run loop infinitely."), EditorStyles.miniBoldLabel); EditorGUI.LabelField(new Rect(loop_tree_width + 190, loop_list_line_y, 40, LINE_HEIGHT), new GUIContent("Type", "The type/behaviour of this loop."), EditorStyles.miniBoldLabel); EditorGUI.LabelField(new Rect(loop_tree_width + 262, loop_list_line_y, 70, LINE_HEIGHT), new GUIContent("DFO [?]", "'Delay First Only' - Letter action delays (non-constant) will only be applied for the first forward pass through the loop. This stops the letters getting more and more out of sequence with every loop interation."), EditorStyles.miniBoldLabel); loop_list_line_y += LINE_HEIGHT; for (var loop_idx = 0; loop_idx < num_loops; loop_idx++) { loop_cycle = selected_animation.GetLoop(loop_idx); if (last_span_width == -1) last_span_width = loop_cycle.SpanWidth; // Check for invalid loops if (loop_cycle.m_start_action_idx >= num_actions || loop_cycle.m_end_action_idx >= num_actions) { // invalid loop. Delete it. selected_animation.RemoveLoop(loop_idx); loop_idx--; num_loops--; continue; } // Represent loop as a line on the Action timeline if (last_span_width != loop_cycle.SpanWidth) { last_span_width = loop_cycle.SpanWidth; indent_num++; } line_offset_x = 20 + (indent_num * LOOP_LINE_OFFSET); if (loop_cycle.m_start_action_idx != loop_cycle.m_end_action_idx) { point1 = m_state_node_rects[loop_cycle.m_start_action_idx].center + new Vector2(line_offset_x, 0); point2 = m_state_node_rects[loop_cycle.m_end_action_idx].center + new Vector2(line_offset_x, 0); DrawLine(point1, point2, loop_cycle.m_loop_type == LOOP_TYPE.LOOP ? LOOP_COLOUR : LOOP_REVERSE_COLOUR, 2); DrawLine(point1 + new Vector2(0, -2), point1 + new Vector2(0, 2), loop_cycle.m_loop_type == LOOP_TYPE.LOOP ? LOOP_COLOUR : LOOP_REVERSE_COLOUR, 6); DrawLine(point2 + new Vector2(0, -2), point2 + new Vector2(0, 2), loop_cycle.m_loop_type == LOOP_TYPE.LOOP ? LOOP_COLOUR : LOOP_REVERSE_COLOUR, 6); } else { point1 = m_state_node_rects[loop_cycle.m_start_action_idx].center + new Vector2(line_offset_x, -2); point2 = m_state_node_rects[loop_cycle.m_end_action_idx].center + new Vector2(line_offset_x, 2); DrawLine(point1, point2, loop_cycle.m_loop_type == LOOP_TYPE.LOOP ? LOOP_COLOUR : LOOP_REVERSE_COLOUR, 6); } // Display loop number my_style.normal.textColor = loop_cycle.m_loop_type == LOOP_TYPE.LOOP ? LOOP_COLOUR : LOOP_REVERSE_COLOUR; EditorGUI.LabelField(new Rect(point1.x, (point1.y + point2.y) / 2 - 10, loop_cycle.m_number_of_loops > 9 ? 30 : 20, 20), loop_cycle.m_number_of_loops <= 0 ? "~" : "" + loop_cycle.m_number_of_loops, my_style); //EditorStyles.miniButton); // Display list view of loop cycle loops_list_x = loop_tree_width; EditorGUI.LabelField(new Rect(loops_list_x, loop_list_line_y, 100, LINE_HEIGHT), "Loop " + (loop_idx + 1)); loops_list_x += 58; EditorGUI.LabelField(new Rect(loops_list_x, loop_list_line_y, 20, LINE_HEIGHT), "" + loop_cycle.m_start_action_idx); loops_list_x += 30; EditorGUI.LabelField(new Rect(loops_list_x, loop_list_line_y, 20, LINE_HEIGHT), "" + loop_cycle.m_end_action_idx); loops_list_x += 32; loop_cycle.m_number_of_loops = EditorGUI.IntField(new Rect(loops_list_x, loop_list_line_y, 20, LINE_HEIGHT), loop_cycle.m_number_of_loops); loops_list_x += 30; loop_cycle.m_loop_type = (LOOP_TYPE)EditorGUI.EnumPopup(new Rect(loops_list_x, loop_list_line_y, 110, LINE_HEIGHT), loop_cycle.m_loop_type); loops_list_x += 130; loop_cycle.m_delay_first_only = EditorGUI.Toggle(new Rect(loops_list_x, loop_list_line_y, 20, LINE_HEIGHT), loop_cycle.m_delay_first_only); loops_list_x += 30; if (GUI.Button(new Rect(loops_list_x, loop_list_line_y, 24, LINE_HEIGHT), "x")) { selected_animation.RemoveLoop(loop_idx); num_loops--; continue; } loop_list_line_y += LINE_HEIGHT; } loop_list_line_y += 5; // "Add new loop" line loops_list_x = loop_tree_width; EditorGUI.LabelField(new Rect(loops_list_x, loop_list_line_y, 100, LINE_HEIGHT), "New", EditorStyles.boldLabel); loops_list_x += 58; new_loop_from = EditorGUI.IntField(new Rect(loops_list_x, loop_list_line_y, 20, LINE_HEIGHT), new_loop_from); loops_list_x += 30; new_loop_to = EditorGUI.IntField(new Rect(loops_list_x, loop_list_line_y, 20, LINE_HEIGHT), new_loop_to); loops_list_x += 32; if (GUI.Button(new Rect(loops_list_x, loop_list_line_y, 40, LINE_HEIGHT), "Add")) { selected_animation.AddLoop(new_loop_from, new_loop_to, false); font_manager.PrepareAnimationData(); new_loop_from = 0; new_loop_to = 0; // Force keyboard focus loss from any of the loop adding fields. GUI.FocusControl("LoopsTitle"); } // Set the width of the loop tree segment loop_tree_width = (int)line_offset_x + BASE_LOOP_LIST_POSITION_OFFSET; // Add additional width of loop list menu state_overview_width = loop_tree_width + LOOP_LIST_WIDTH; var eventType = Event.current.type; var mousePos = Event.current.mousePosition; if (eventType == EventType.MouseDown && mousePos.x < MainEditorX) { var rect_idx = 0; foreach (var node_rect in m_state_node_rects) { if (node_rect.Contains(mousePos)) { m_mouse_down_node_idx = rect_idx; m_mouse_down_pos = node_rect.center; m_mouse_drag_pos = m_mouse_down_pos; } rect_idx ++; } } else if (eventType == EventType.MouseDrag) { if (m_mouse_down_node_idx >= 0) { m_mouse_drag_pos = mousePos; Instance.Repaint(); } } else if (eventType == EventType.MouseUp) { if (m_mouse_down_node_idx >= 0 && mousePos.x < MainEditorX) { var rect_idx = 0; foreach (var node_rect in m_state_node_rects) { if (node_rect.Contains(mousePos)) { // Debug.LogError("you joined : " + m_mouse_down_node_idx + " and " + rect_idx + " with button " + Event.current.button); int start, end; if (m_mouse_down_node_idx < rect_idx) { start = m_mouse_down_node_idx; end = rect_idx; } else { start = rect_idx; end = m_mouse_down_node_idx; } selected_animation.AddLoop(start, end, Event.current.button == 1); font_manager.PrepareAnimationData(); break; } rect_idx ++; } } m_mouse_down_node_idx = -1; Instance.Repaint(); } } else state_overview_width = 0; GUI.EndScrollView(); }
// Only called if action_idx has changed since last time private void UpdateLoopList(LetterAnimation animation) { // add any new loops from the next action index to the loop list ActionLoopCycle loop; for (var idx = 0; idx < animation.NumLoops; idx++) { loop = animation.GetLoop(idx); if (loop.m_start_action_idx == m_anim_state_vars.m_action_index) { // add this new loop into the ordered active loop list var new_loop_cycle_span = loop.SpanWidth; var loop_idx = 0; foreach (var active_loop in m_anim_state_vars.m_active_loop_cycles) { if (loop.m_start_action_idx == active_loop.m_start_action_idx && loop.m_end_action_idx == active_loop.m_end_action_idx) { // This loop is already in the active loop list, don't re-add loop_idx = -1; break; } if (new_loop_cycle_span < active_loop.SpanWidth) break; loop_idx++; } if (loop_idx >= 0) m_anim_state_vars.m_active_loop_cycles.Insert(loop_idx, loop.Clone()); } } }
public static int ImportLegacyData(this LetterAnimation letter_anim, List <object> data_list, int index_offset = 0) { KeyValuePair <string, string> value_pair; string key, value; int idx; int loop_idx = 0, action_idx = 0; for (idx = index_offset; idx < data_list.Count; idx++) { value_pair = (KeyValuePair <string, string>)data_list[idx]; key = value_pair.Key; value = value_pair.Value; if (key.Equals("ANIM_DATA_END")) { // reached end of this animations import data break; } switch (key) { case "m_letters_to_animate": List <object> letter_list = value.StringToList(';'); letter_anim.m_letters_to_animate = new List <int>(); if (letter_list != null) { foreach (object obj in letter_list) { letter_anim.m_letters_to_animate.Add(int.Parse(obj.ToString())); } } break; case "m_letters_to_animate_custom_idx": letter_anim.m_letters_to_animate_custom_idx = int.Parse(value); break; case "m_letters_to_animate_option": letter_anim.m_letters_to_animate_option = (LETTERS_TO_ANIMATE)int.Parse(value); break; // LOOP DATA IMPORT case "LOOP_DATA_START": if (loop_idx == letter_anim.NumLoops) { letter_anim.AddLoop(); } break; case "LOOP_DATA_END": loop_idx++; break; case "m_delay_first_only": letter_anim.GetLoop(loop_idx).m_delay_first_only = bool.Parse(value); break; case "m_end_action_idx": letter_anim.GetLoop(loop_idx).m_end_action_idx = int.Parse(value); break; case "m_loop_type": letter_anim.GetLoop(loop_idx).m_loop_type = (LOOP_TYPE)int.Parse(value); break; case "m_number_of_loops": letter_anim.GetLoop(loop_idx).m_number_of_loops = int.Parse(value); break; case "m_start_action_idx": letter_anim.GetLoop(loop_idx).m_start_action_idx = int.Parse(value); break; // ACTION DATA IMPORT case "ACTION_DATA_START": if (action_idx == letter_anim.NumActions) { letter_anim.AddAction(); } idx = letter_anim.GetAction(action_idx).ImportLegacyData(data_list, idx + 1); action_idx++; break; } } // Remove any extra LoopData or LetterAction instances that existed prior to importing if (letter_anim.NumLoops > loop_idx) { letter_anim.RemoveLoops(loop_idx, letter_anim.NumLoops - loop_idx); } if (letter_anim.NumActions > action_idx) { letter_anim.RemoveActions(action_idx, letter_anim.NumActions - action_idx); } return(idx); }