public static void RepositionKeyframesForConstantSpeed(SpherePointKeyframeGroup group) { if (group.GetKeyFrameCount() < 2) { return; } // Because time is always 1, no need to divide by it. float totalDistance = GetTotalDistanceBetweenKeyframes(group); float targetSpeed = totalDistance; int keyFrameCount = group.GetKeyFrameCount(); for (int j = 0; j < keyFrameCount; j++) { for (int i = keyFrameCount - 2; i >= 0; i--) { int nextIndex = i + 1; SpherePointKeyframe keyframe = group.keyframes[i]; SpherePointKeyframe nextKeyframe = group.keyframes[nextIndex]; MoveKeyframeTimeToMatchSpeed(keyframe, nextKeyframe, targetSpeed); } // This is a hack, we resort and re-calculated edges since durations were changed. group.SortKeyframes(); } }
public SpherePointKeyframe(SpherePointKeyframe keyframe) : base(keyframe.time) { spherePoint = new SpherePoint( keyframe.spherePoint.horizontalRotation, keyframe.spherePoint.verticalRotation); interpolationCurve = keyframe.interpolationCurve; interpolationDirection = keyframe.interpolationDirection; }
private void InsertKeyframeInSpherePointGroup(float time, SpherePointKeyframeGroup group) { SpherePointKeyframe previousKeyFrame = group.GetPreviousKeyFrame(time); SpherePointKeyframe newKeyFrame = new SpherePointKeyframe(previousKeyFrame); newKeyFrame.time = time; group.AddKeyFrame(newKeyFrame); KeyframeInspectorWindow.SetKeyframeData( newKeyFrame, group, KeyframeInspectorWindow.KeyType.SpherePoint, m_ActiveSkyProfile); }
public static float GetSpeedBetweenKeyframes(SpherePointKeyframe from, SpherePointKeyframe to) { float distance = Vector3.Angle(from.spherePoint.GetWorldDirection(), to.spherePoint.GetWorldDirection()); float duration = GetDurationBetweenKeyframes(from, to); // Just in case duration is zero... if (duration == 0.0f) { duration = .00001f; } return(distance / duration); }
public static float GetTotalDistanceBetweenKeyframes(SpherePointKeyframeGroup group) { float total = 0; for (int i = 0; i < group.GetKeyFrameCount(); i++) { int nextIndex = (i + 1) % group.GetKeyFrameCount(); SpherePointKeyframe currentKeyframe = group.keyframes[i]; SpherePointKeyframe nextKeyframe = group.keyframes[nextIndex]; total += GetDistanceBetweenKeyframes(currentKeyframe, nextKeyframe); } return(total); }
public static void MoveKeyframeTimeToMatchSpeed(SpherePointKeyframe keyframe, SpherePointKeyframe nextKeyframe, float speed) { // Solve for duration required to match a speed. float duration = GetDistanceBetweenKeyframes(keyframe, nextKeyframe) / speed; float durationDelta = GetDurationBetweenKeyframes(keyframe, nextKeyframe) - duration; if (keyframe.time + durationDelta < 0) { keyframe.time = 1.0f - (keyframe.time + durationDelta); } else { keyframe.time += durationDelta; } keyframe.time = Mathf.Clamp01(keyframe.time); }
private void ShowSpherePointKeyframesInSkybox(SpherePointKeyframeGroup group) { int debugPoints = 0; for (int i = 0; i < group.keyframes.Count; i++) { SpherePointKeyframe keyframe = group.keyframes[i]; Vector3 direction = keyframe.spherePoint.GetWorldDirection(); float isActiveKeyframe = SkyEditorUtility.IsKeyframeActiveInInspector(keyframe) ? 1.0f : 0.0f; Vector4 pointData = new Vector4(direction.x, direction.y, direction.z, isActiveKeyframe); if (i < MAX_DEBUG_POINTS) { m_DebugPoints[i] = pointData; debugPoints += 1; } } ShowDebugPoints(m_DebugPoints, debugPoints); }
public static void RenderSpherePointRow(Rect rect, SkyProfile profile, SpherePointKeyframeGroup group) { bool sortGroup = false; RenderColorGradients(rect, group); for (int i = 0; i < group.keyframes.Count; i++) { SpherePointKeyframe currentKey = group.GetKeyframe(i); // Track key marker mouse events and render. bool didSingleClick = false; bool isDragging = false; bool keyframeUpdated = false; SkyEditorUtility.DrawHorizontalKeyMarker(rect, currentKey, profile, out didSingleClick, out isDragging, out keyframeUpdated); if (keyframeUpdated) { sortGroup = true; } // Show the color keyframe property window. if (didSingleClick || isDragging) { // Load info about this keyframe and show the editor window. KeyframeInspectorWindow.SetKeyframeData( currentKey, group, KeyframeInspectorWindow.KeyType.SpherePoint, profile); if (didSingleClick) { KeyframeInspectorWindow.ShowWindow(); } } } if (sortGroup) { group.SortKeyframes(); } }
private bool RenderSpherePointPropertyGroup(ProfileGroupDefinition def) { EditorGUILayout.BeginHorizontal(); bool valueChanged = false; SpherePointKeyframeGroup group = m_Profile.GetGroup <SpherePointKeyframeGroup>(def.propertyKey); if (m_Profile.IsManagedByTimeline(def.propertyKey)) { EditorGUILayout.PrefixLabel(new GUIContent(def.groupName, def.tooltip)); RenderManagedOnTimlineMessage(); } else { SpherePointKeyframe frame = group.GetKeyframe(0); EditorGUILayout.BeginVertical(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(new GUIContent(group.name, def.tooltip)); GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); EditorGUI.BeginChangeCheck(); EditorGUI.indentLevel += 1; SpherePoint selectedPoint = SpherePointGUI.SpherePointField( frame.spherePoint, true, frame.id); EditorGUI.indentLevel -= 1; if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(m_Profile, "Changed sphere point"); frame.spherePoint = selectedPoint; } EditorGUILayout.EndVertical(); } EditorGUILayout.EndHorizontal(); return(valueChanged); }
private bool RenderSpherePointGUI() { bool didModify = false; SpherePointKeyframe spherePointKeyframe = keyframe as SpherePointKeyframe; if (spherePointKeyframe == null) { return(false); } EditorGUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); SpherePoint selectedSpherePoint = SpherePointGUI.SpherePointField(spherePointKeyframe.spherePoint, true, keyframe.id); if (EditorGUI.EndChangeCheck()) { spherePointKeyframe.spherePoint = selectedSpherePoint; didModify = true; } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); GUIStyle style = GUI.skin.button; EditorGUILayout.PrefixLabel( new GUIContent("Normalize Speed", "Adjust all keyframes so that there is a constant speed of animation between them.")); GUILayout.Button(new GUIContent("Reposition All Keyframes..."), style); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(profile, "Normalize keyframe speeds"); didModify = true; SpherePointTimelineRow.RepositionKeyframesForConstantSpeed(group as SpherePointKeyframeGroup); } EditorGUILayout.EndHorizontal(); return(didModify); }
// Color based on last edge speed. public static List <Vector4> GenerateColorSpeedPoints(SpherePointKeyframeGroup group) { List <Vector4> colorPoints = new List <Vector4>(); if (group.GetKeyFrameCount() <= 1) { colorPoints.Add(new Vector4(0.0f, m_AvgColor.r, m_AvgColor.g, m_AvgColor.b)); colorPoints.Add(new Vector4(1.0f, m_AvgColor.r, m_AvgColor.g, m_AvgColor.b)); return(colorPoints); } float gradientOffset = .02f; const float maxSpeed = 1200.0f; for (int i = 0; i < group.keyframes.Count; i++) { int nextIndex = (i + 1) % group.GetKeyFrameCount(); SpherePointKeyframe currentKeyframe = group.keyframes[i]; SpherePointKeyframe nextKeyframe = group.keyframes[nextIndex]; // Last keyframe has special rules if (i == group.keyframes.Count - 1) { float speed = GetSpeedBetweenKeyframes(currentKeyframe, nextKeyframe); Color speedColor = Color.Lerp(m_AvgColor, m_MaxColor, speed / maxSpeed); float gradientBeginTime = currentKeyframe.time + gradientOffset; float gradientEndTime = 1.0f; if (gradientBeginTime >= 1.0f) { gradientBeginTime = currentKeyframe.time; } colorPoints.Add( new Vector4(gradientBeginTime, speedColor.r, speedColor.g, speedColor.b)); colorPoints.Add( new Vector4(gradientEndTime, speedColor.r, speedColor.g, speedColor.b)); // Now bridge gap if any to first keyframe. if (!SkyEditorUtility.IsKeyFrameAtStart(nextKeyframe)) { gradientBeginTime = 0.0f; gradientEndTime = nextKeyframe.time - gradientOffset; if (gradientEndTime < 0) { gradientEndTime = nextKeyframe.time; } colorPoints.Insert(0, new Vector4(gradientEndTime, speedColor.r, speedColor.g, speedColor.b)); colorPoints.Insert(0, new Vector4(gradientBeginTime, speedColor.r, speedColor.g, speedColor.b)); } else { colorPoints.Insert( 0, new Vector4(0, speedColor.r, speedColor.g, speedColor.b)); } } else { float gradientBeginTime = currentKeyframe.time + gradientOffset; float gradientEndTime = nextKeyframe.time - gradientOffset; // Need to play with these to see how they look. Maybe use a percentage between them instead? if (gradientBeginTime >= nextKeyframe.time) { gradientBeginTime = currentKeyframe.time; } if (gradientEndTime <= currentKeyframe.time) { gradientEndTime = nextKeyframe.time; } float speed = GetSpeedBetweenKeyframes(currentKeyframe, nextKeyframe); Color speedColor = Color.Lerp(m_AvgColor, m_MaxColor, speed / maxSpeed); colorPoints.Add( new Vector4(gradientBeginTime, speedColor.r, speedColor.g, speedColor.b)); colorPoints.Add( new Vector4(gradientEndTime, speedColor.r, speedColor.g, speedColor.b)); } } return(colorPoints); }
public static float GetDistanceBetweenKeyframes(SpherePointKeyframe from, SpherePointKeyframe to) { return(Vector3.Angle(from.spherePoint.GetWorldDirection(), to.spherePoint.GetWorldDirection())); }