public void ScrubToHere( float currentTime, TargetPositionCache.Mode cacheMode, CinemachineBrain brain) { if (brain == null) { return; } TargetPositionCache.CacheMode = cacheMode; TargetPositionCache.CurrentTime = currentTime; if (cacheMode != TargetPositionCache.Mode.Playback) { return; } float stepSize = TargetPositionCache.CacheStepSize; var up = brain.DefaultWorldUp; var endTime = TargetPositionCache.CurrentTime; var startTime = Mathf.Max( TargetPositionCache.CacheTimeRange.Start, endTime - GetMaxDampTime()); var numSteps = Mathf.FloorToInt((endTime - startTime) / stepSize); for (int step = numSteps; step >= 0; --step) { var t = Mathf.Max(startTime, endTime - step * stepSize); TargetPositionCache.CurrentTime = t; var deltaTime = (step == numSteps) ? -1 : (t - startTime < stepSize ? t - startTime : stepSize); // Update all relevant vcams, leaf-most first for (int i = mAllCamerasForScrubbing.Count - 1; i >= 0; --i) { var sublist = mAllCamerasForScrubbing[i]; for (int j = sublist.Count - 1; j >= 0; --j) { var vcam = sublist[j]; vcam.InternalUpdateCameraState(up, deltaTime); if (deltaTime < 0) { vcam.ForceCameraPosition( TargetPositionCache.GetTargetPosition(vcam.transform), TargetPositionCache.GetTargetRotation(vcam.transform)); } } } } }
public override void OnInspectorGUI() { BeginInspector(); SerializedProperty vcamProperty = FindProperty(x => x.VirtualCamera); EditorGUI.indentLevel = 0; // otherwise subeditor layouts get screwed up AutoCreateShotFromSceneView = EditorGUILayout.Toggle(kAutoCreateLabel, AutoCreateShotFromSceneView); Rect rect; #if UNITY_2019_2_OR_NEWER GUI.enabled = !Application.isPlaying; rect = EditorGUILayout.GetControlRect(); var r = rect; r.width = EditorGUIUtility.labelWidth + EditorGUIUtility.singleLineHeight; if (Application.isPlaying) { EditorGUI.Toggle(r, kScrubbingCacheLabel, false); } else { UseScrubbingCache = EditorGUI.Toggle(r, kScrubbingCacheLabel, UseScrubbingCache); } r.x += r.width; r.width = rect.width - r.width; var buttonWidth = GUI.skin.button.CalcSize(m_ClearText).x; r.width -= buttonWidth; EditorGUI.LabelField(r, "(experimental)"); r.x += r.width; r.width = buttonWidth; GUI.enabled &= !TargetPositionCache.IsEmpty; if (GUI.Button(r, m_ClearText)) { TargetPositionCache.ClearCache(); } GUI.enabled = true; #endif EditorGUILayout.Space(); CinemachineVirtualCameraBase vcam = vcamProperty.exposedReferenceValue as CinemachineVirtualCameraBase; if (vcam != null) { EditorGUILayout.PropertyField(vcamProperty, kVirtualCameraLabel); } else { GUIContent createLabel = new GUIContent("Create"); Vector2 createSize = GUI.skin.button.CalcSize(createLabel); rect = EditorGUILayout.GetControlRect(true); rect.width -= createSize.x; EditorGUI.PropertyField(rect, vcamProperty, kVirtualCameraLabel); rect.x += rect.width; rect.width = createSize.x; if (GUI.Button(rect, createLabel)) { vcam = CreatePassiveVcamFromSceneView(); vcamProperty.exposedReferenceValue = vcam; } serializedObject.ApplyModifiedProperties(); } EditorGUI.BeginChangeCheck(); DrawRemainingPropertiesInInspector(); if (vcam != null) { DrawSubeditors(vcam); } // by default timeline rebuilds the entire graph when something changes, // but if a property of the virtual camera changes, we only need to re-evaluate the timeline. // this prevents flicker on post processing updates if (EditorGUI.EndChangeCheck()) { TimelineEditor.Refresh(RefreshReason.SceneNeedsUpdate); GUI.changed = false; } }
public void ScrubToHere(float currentTime, int playableIndex, bool isCut, float timeInClip, Vector3 up) { TargetPositionCache.CurrentTime = currentTime; if (TargetPositionCache.CacheMode == TargetPositionCache.Mode.Record) { // If the clip is newly activated, force the time to clip start, // in case timeline skipped some frames. This will avoid target lerps between shots. if (Time.frameCount != TargetPositionCache.CurrentFrame) { TargetPositionCache.IsCameraCut = false; } TargetPositionCache.CurrentFrame = Time.frameCount; if (isCut) { TargetPositionCache.IsCameraCut = true; } return; } if (!TargetPositionCache.HasCurrentTime) { return; } var cs = CachedObjects[playableIndex]; float stepSize = TargetPositionCache.CacheStepSize; // Impose upper limit on damping time, to avoid simulating too many frames float maxDampTime = Mathf.Max(0, timeInClip - stepSize); maxDampTime = Mathf.Min(cs.MaxDampTime, Mathf.Min(maxDampTime, 4.0f)); var endTime = TargetPositionCache.CurrentTime; var startTime = Mathf.Max( TargetPositionCache.CacheTimeRange.Start + stepSize, endTime - maxDampTime); var numSteps = Mathf.FloorToInt((endTime - startTime) / stepSize); for (int step = numSteps; step >= 0; --step) { var t = Mathf.Max(startTime, endTime - step * stepSize); TargetPositionCache.CurrentTime = t; var deltaTime = (step == numSteps) ? -1 : (t - startTime < stepSize ? t - startTime : stepSize); // Update all relevant vcams, leaf-most first for (int i = cs.Cameras.Count - 1; i >= 0; --i) { var sublist = cs.Cameras[i]; for (int j = sublist.Count - 1; j >= 0; --j) { var vcam = sublist[j]; if (deltaTime < 0) { vcam.ForceCameraPosition( TargetPositionCache.GetTargetPosition(vcam.transform), TargetPositionCache.GetTargetRotation(vcam.transform)); } vcam.InternalUpdateCameraState(up, deltaTime); } } } }