/************************************************************************************************************************/ private void RepaintEventsGUI(EventSequenceDrawer.Context context) { var color = GUI.color; for (int i = 0; i < EventTimes.Count; i++) { var currentColor = color; // Read Only: currentColor *= new Color(0.9f, 0.9f, 0.9f, 0.5f * alpha); if (context.SelectedEvent == i) { currentColor *= SelectedEventColor; } else { currentColor *= UnselectedEventColor; } if (i == EventTimes.Count - 1 && !_HasEndTime) { currentColor.a *= 0.65f; } GUI.color = currentColor; var area = GetEventIconArea(i); GUI.DrawTexture(area, EventIcon); } GUI.color = color; }
/************************************************************************************************************************/ #region Events /************************************************************************************************************************/ private void GatherEventTimes(EventSequenceDrawer.Context context) { EventTimes.Clear(); if (context.Times.Count > 0) { var depth = context.Times.Property.depth; var time = context.Times.GetElement(0); while (time.depth > depth) { EventTimes.Add(time.floatValue * _Duration); time.Next(false); } _EndTime = EventTimes[EventTimes.Count - 1]; if (!float.IsNaN(_EndTime)) { _HasEndTime = true; return; } } _EndTime = AnimancerEvent.Sequence.GetDefaultNormalizedEndTime(_Speed) * _Duration; _HasEndTime = false; if (EventTimes.Count == 0) { EventTimes.Add(_EndTime); } else { EventTimes[EventTimes.Count - 1] = _EndTime; } }
/************************************************************************************************************************/ private void RoundEventTime(EventSequenceDrawer.Context context) { var time = context.Times.GetElement(context.SelectedEvent); var value = time.floatValue; var format = System.Globalization.NumberFormatInfo.InvariantInfo; var text = value.ToString(format); var dot = text.IndexOf('.'); if (dot < 0) { return; } Round: var newValue = (float)System.Math.Round(value, text.Length - dot - 2, System.MidpointRounding.AwayFromZero); if (newValue == value) { dot--; goto Round; } time.floatValue = newValue; }
/************************************************************************************************************************/ private void RoundEventTime(EventSequenceDrawer.Context context) { var time = context.Times.GetElement(context.SelectedEvent); var value = time.floatValue; if (TryRoundValue(ref value)) { time.floatValue = value; } }
/************************************************************************************************************************/ private static void AddContextFunction( GenericMenu menu, EventSequenceDrawer.Context context, string label, bool enabled, Action function) { menu.AddFunction(label, enabled, () => { using (context.SetAsCurrent()) { function(); GUI.changed = true; } }); }
/// <summary> /// Draws the details of the <see cref="EventSequenceDrawer.Context.Callbacks"/>. /// </summary> public void DoEventsGUI(EventSequenceDrawer.Context context, out float addEventNormalizedTime) { addEventNormalizedTime = float.NaN; var currentGUIEvent = Event.current; EventControlIDs.Clear(); var selectedEventControlID = -1; var baseControlID = GUIUtility.GetControlID(EventHash - 1, FocusType.Passive); for (int i = 0; i < EventTimes.Count; i++) { var controlID = GUIUtility.GetControlID(EventHash + i, FocusType.Keyboard); EventControlIDs.Add(controlID); if (context.SelectedEvent == i) { selectedEventControlID = controlID; } } EventControlIDs.Add(baseControlID); switch (currentGUIEvent.type) { case EventType.Repaint: RepaintEventsGUI(context); break; case EventType.MouseDown: if (_Area.Contains(currentGUIEvent.mousePosition)) { OnMouseDown(currentGUIEvent, context, out addEventNormalizedTime); } break; case EventType.MouseDrag: if (GUIUtility.hotControl == baseControlID) { SetPreviewTime(currentGUIEvent); GUIUtility.ExitGUI(); } break; case EventType.KeyUp: if (GUIUtility.keyboardControl == selectedEventControlID && (currentGUIEvent.keyCode == KeyCode.Delete || currentGUIEvent.keyCode == KeyCode.Backspace)) { EventSequenceDrawer.RemoveEvent(context, context.SelectedEvent); GUIUtility.ExitGUI(); } break; } }
/************************************************************************************************************************/ private void NudgeEventTime(EventSequenceDrawer.Context context, float offsetPixels) { var time = context.Times.GetElement(context.SelectedEvent); var value = time.floatValue; value = NormalizedToSeconds(value); value = SecondsToPixels(value); value += offsetPixels; value = PixelsToSeconds(value); value = SecondsToNormalized(value); time.floatValue = value; }
/************************************************************************************************************************/ private void NudgeEventTime(EventSequenceDrawer.Context context, bool right) { var time = context.Times.GetElement(context.SelectedEvent); var value = time.floatValue; value = NormalizedToSeconds(value); value = SecondsToPixels(value); var nudge = right ? 1f : -1f; if (Event.current.shift) { nudge *= 10; } value += nudge; value = PixelsToSeconds(value); value = SecondsToNormalized(value); time.floatValue = value; }
/************************************************************************************************************************/ private void OnMouseDown(Event currentGUIEvent, EventSequenceDrawer.Context context, out float addEventNormalizedTime) { var selectedEventControlID = 0; var selectedEvent = -1; for (int i = 0; i < EventControlIDs.Count; i++) { var area = i < EventTimes.Count ? GetEventIconArea(i) : _Area; if (area.Contains(currentGUIEvent.mousePosition)) { selectedEventControlID = EventControlIDs[i]; selectedEvent = i; break; } } GUIUtility.hotControl = GUIUtility.keyboardControl = selectedEventControlID; if (selectedEvent < 0 || selectedEvent >= EventTimes.Count) { SetPreviewTime(currentGUIEvent); selectedEvent = -1; } if (currentGUIEvent.type == EventType.MouseDown && currentGUIEvent.clickCount == 2) { addEventNormalizedTime = PixelsToSeconds(currentGUIEvent.mousePosition.x); addEventNormalizedTime = SecondsToNormalized(addEventNormalizedTime); } else { addEventNormalizedTime = float.NaN; } context.SelectedEvent = selectedEvent; currentGUIEvent.Use(); }
/************************************************************************************************************************/ private void ShowContextMenu(Event currentGUIEvent, EventSequenceDrawer.Context context) { context = context.Copy(); var time = SecondsToNormalized(PixelsToSeconds(currentGUIEvent.mousePosition.x)); var hasSelectedEvent = context.SelectedEvent >= 0; var menu = new GenericMenu(); AddContextFunction(menu, context, "Add Event (Double Click)", true, () => EventSequenceDrawer.AddEvent(context, time)); AddContextFunction(menu, context, "Remove Event (Delete)", hasSelectedEvent, () => EventSequenceDrawer.RemoveEvent(context, context.SelectedEvent)); const string NudgePrefix = "Nudge Event Time/"; AddContextFunction(menu, context, NudgePrefix + "Left 1 Pixel (Left Arrow)", hasSelectedEvent, () => NudgeEventTime(context, -1)); AddContextFunction(menu, context, NudgePrefix + "Left 10 Pixels (Shift + Left Arrow)", hasSelectedEvent, () => NudgeEventTime(context, -10)); AddContextFunction(menu, context, NudgePrefix + "Right 1 Pixel (Right Arrow)", hasSelectedEvent, () => NudgeEventTime(context, 1)); AddContextFunction(menu, context, NudgePrefix + "Right 10 Pixels (Shift + Right Arrow)", hasSelectedEvent, () => NudgeEventTime(context, 10)); var canRoundTime = hasSelectedEvent; if (canRoundTime) { time = context.Times.GetElement(context.SelectedEvent).floatValue; canRoundTime = TryRoundValue(ref time); } AddContextFunction(menu, context, $"Round Event Time to {time}x (Space)", canRoundTime, () => RoundEventTime(context)); menu.ShowAsContext(); }
/// <summary> /// Draws the details of the <see cref="EventSequenceDrawer.Context.Callbacks"/>. /// </summary> public void DoEventsGUI(EventSequenceDrawer.Context context, out float addEventNormalizedTime) { addEventNormalizedTime = float.NaN; var currentGUIEvent = Event.current; EventControlIDs.Clear(); var selectedEventControlID = -1; var baseControlID = GUIUtility.GetControlID(EventHash - 1, FocusType.Passive); for (int i = 0; i < EventTimes.Count; i++) { var controlID = GUIUtility.GetControlID(EventHash + i, FocusType.Keyboard); EventControlIDs.Add(controlID); if (context.SelectedEvent == i) { selectedEventControlID = controlID; } } EventControlIDs.Add(baseControlID); switch (currentGUIEvent.type) { case EventType.Repaint: RepaintEventsGUI(context); break; case EventType.MouseDown: if (_Area.Contains(currentGUIEvent.mousePosition)) { OnMouseDown(currentGUIEvent, context, out addEventNormalizedTime); } break; case EventType.MouseUp: if (currentGUIEvent.button == 1 && _Area.Contains(currentGUIEvent.mousePosition)) { ShowContextMenu(currentGUIEvent, context); currentGUIEvent.Use(); } break; case EventType.MouseDrag: if (_Duration <= 0) { break; } var hotControl = GUIUtility.hotControl; if (hotControl == baseControlID) { SetPreviewTime(currentGUIEvent); GUIUtility.ExitGUI(); } else { for (int i = 0; i < EventTimes.Count; i++) { if (hotControl == EventControlIDs[i]) { if (context.Times.Count < 1) { context.Times.Count = 1; } var timeProperty = context.Times.GetElement(i); var seconds = PixelsToSeconds(currentGUIEvent.mousePosition.x); timeProperty.floatValue = seconds / _Duration; timeProperty.serializedObject.ApplyModifiedProperties(); GUIUtility.hotControl = EventControlIDs[context.SelectedEvent]; GUI.changed = true; SetPreviewTime(currentGUIEvent); GUIUtility.ExitGUI(); } } } break; case EventType.KeyUp: if (GUIUtility.keyboardControl != selectedEventControlID) { break; } var exitGUI = false; switch (currentGUIEvent.keyCode) { case KeyCode.Delete: case KeyCode.Backspace: EventSequenceDrawer.RemoveEvent(context, context.SelectedEvent); exitGUI = true; break; case KeyCode.LeftArrow: NudgeEventTime(context, Event.current.shift ? -10 : -1); break; case KeyCode.RightArrow: NudgeEventTime(context, Event.current.shift ? 10 : 1); break; case KeyCode.Space: RoundEventTime(context); break; default: return; // Don't call Use. } currentGUIEvent.Use(); GUI.changed = true; if (exitGUI) { GUIUtility.ExitGUI(); } break; } }
/************************************************************************************************************************/ /// <summary> /// Draws the ruler GUI and handles input events for the specified `context`. /// </summary> public void DoGUI(Rect area, EventSequenceDrawer.Context context, out float addEventNormalizedTime) { BeginGUI(area); if (context.Property.hasMultipleDifferentValues) { GUI.Label(_Area, "Multi-editing is not supported"); addEventNormalizedTime = float.NaN; } else { var transition = context.TransitionContext.Transition; _Speed = transition.Speed; var playDirection = _Speed < 0 ? -1 : 1; _Duration = context.TransitionContext.MaximumDuration; if (_Duration <= 0) { _Duration = 1; } GatherEventTimes(context); _StartTime = transition.NormalizedStartTime; if (float.IsNaN(_StartTime)) { _StartTime = _Speed < 0 ? _Duration : 0; } else { _StartTime *= _Duration; } _FadeInEnd = _StartTime + transition.FadeDuration * playDirection; _FadeOutEnd = GetFadeOutEnd(_Speed, _EndTime, _Duration); _MinTime = Mathf.Min(0, _StartTime); _MinTime = Mathf.Min(_MinTime, _FadeOutEnd); _MinTime = Mathf.Min(_MinTime, EventTimes[0]); _MaxTime = Mathf.Max(_StartTime, _FadeOutEnd); if (EventTimes.Count >= 2) { _MaxTime = Mathf.Max(_MaxTime, EventTimes[EventTimes.Count - 2]); } if (_MaxTime < _Duration) { _MaxTime = _Duration; } _SecondsToPixels = _Area.width / (_MaxTime - _MinTime); DoFadeHighlightGUI(); DoEventsGUI(context, out addEventNormalizedTime); DoRulerGUI(); if (_Speed > 0) { if (_StartTime > _EndTime) { GUI.Label(_Area, "Start Time is after End Time"); } } else if (_Speed < 0) { if (_StartTime < _EndTime) { GUI.Label(_Area, "Start Time is before End Time"); } } } EndGUI(); }
/// <summary> /// Draws the details of the <see cref="EventSequenceDrawer.Context.Callbacks"/>. /// </summary> public void DoEventsGUI(EventSequenceDrawer.Context context, out float addEventNormalizedTime) { addEventNormalizedTime = float.NaN; var currentGUIEvent = Event.current; EventControlIDs.Clear(); var selectedEventControlID = -1; var baseControlID = GUIUtility.GetControlID(EventHash - 1, FocusType.Passive); for (int i = 0; i < EventTimes.Count; i++) { var controlID = GUIUtility.GetControlID(EventHash + i, FocusType.Keyboard); EventControlIDs.Add(controlID); if (context.SelectedEvent == i) { selectedEventControlID = controlID; } } EventControlIDs.Add(baseControlID); switch (currentGUIEvent.type) { case EventType.Repaint: RepaintEventsGUI(context); break; case EventType.MouseDown: if (_Area.Contains(currentGUIEvent.mousePosition)) { OnMouseDown(currentGUIEvent, context, out addEventNormalizedTime); } break; case EventType.MouseDrag: if (GUIUtility.hotControl == baseControlID) { SetPreviewTime(currentGUIEvent); GUIUtility.ExitGUI(); } break; case EventType.KeyUp: if (GUIUtility.keyboardControl != selectedEventControlID) { break; } var exitGUI = false; switch (currentGUIEvent.keyCode) { case KeyCode.Delete: case KeyCode.Backspace: EventSequenceDrawer.RemoveEvent(context, context.SelectedEvent); exitGUI = true; break; case KeyCode.LeftArrow: NudgeEventTime(context, false); break; case KeyCode.RightArrow: NudgeEventTime(context, true); break; case KeyCode.Space: RoundEventTime(context); break; default: return; // Don't call Use. } currentGUIEvent.Use(); GUI.changed = true; if (exitGUI) { GUIUtility.ExitGUI(); } break; } }