/// <summary> /// Gets a collection of items containing data for performing linear interpolation of managed key frames /// when setting the content of the unmanaged Direct2D renderer's preview items cache. /// </summary> /// <param name="previewFrameNumber">The target frame number for creating interpolated unmanaged preview items.</param> /// <param name="segmentModelsFilteredByFrameNumber">The source collection of frame number filtered segment models.</param> /// <returns>A collection of data items for performing key frame linear interpolation.</returns> protected IEnumerable <SegmentKeyFrameLerpDataItem> GetSegmentKeyFrameLerpDataForPreviewFrame(int previewFrameNumber, IEnumerable <SegmentModelBase> segmentModelsFilteredByFrameNumber) { foreach (SegmentModelBase segmentModel in segmentModelsFilteredByFrameNumber) { KeyFrameModelBase keyFrameAtOrBefore, keyFrameAfter = null; double lerpAmount = 0d; int keyFrameIndex = segmentModel.KeyFrames.BinarySearch(previewFrameNumber); if (keyFrameIndex >= 0) { // Exact match for frame number found keyFrameAtOrBefore = segmentModel.KeyFrames[keyFrameIndex]; } else { // The index of the first key frame that has a frame number greater than or equal to previewFrameNumber // or the value of segmentModel.KeyFrames.Count if no such key frame was found. keyFrameIndex = ~keyFrameIndex; keyFrameAtOrBefore = (keyFrameIndex > 0) ? segmentModel.KeyFrames[keyFrameIndex - 1] : segmentModel.KeyFrames[keyFrameIndex]; keyFrameAfter = (keyFrameIndex < segmentModel.KeyFrames.Count) ? segmentModel.KeyFrames[keyFrameIndex] : keyFrameAtOrBefore; int frameRange = keyFrameAfter.FrameNumber - keyFrameAtOrBefore.FrameNumber; if (frameRange > 0) // prevent double.NaN value as a result of division by zero { lerpAmount = (double)(previewFrameNumber - keyFrameAtOrBefore.FrameNumber) / frameRange; } } yield return(new SegmentKeyFrameLerpDataItem(segmentModel.TrackNumber, keyFrameAtOrBefore, keyFrameAfter, lerpAmount)); } }
/// <inheritdoc/> public virtual SegmentViewModelBase CreateSplitSegmentModelViewModel(SegmentViewModelBase segmentViewModelToSplit, int frameNumberToSplitAt) { KeyFrameViewModelCollection splitKeyFrameViewModels = new KeyFrameViewModelCollection(); if (segmentViewModelToSplit.ActiveKeyFrame?.FrameNumber >= frameNumberToSplitAt) { segmentViewModelToSplit.ActiveKeyFrame = null; } int keyFrameIndex = segmentViewModelToSplit.KeyFrameViewModels.LowerBoundIndex(frameNumberToSplitAt); if (keyFrameIndex < segmentViewModelToSplit.KeyFrameViewModels.Count) { KeyFrameViewModelBase keyFrameViewModel = segmentViewModelToSplit.KeyFrameViewModels[keyFrameIndex]; if (keyFrameViewModel.FrameNumber > frameNumberToSplitAt) { // Lerp new KeyFrameViewModel and add to splitKeyFrameViewModels Debug.Assert(keyFrameIndex > 0); keyFrameViewModel = segmentViewModelToSplit.KeyFrameViewModels[keyFrameIndex - 1].Lerp(frameNumberToSplitAt, keyFrameViewModel); splitKeyFrameViewModels.Add(keyFrameViewModel); } // Loop from keyFrameIndex and move (via remove & add) KeyFrameViewModel(s) to splitKeyFrameViewModels do { keyFrameViewModel = segmentViewModelToSplit.KeyFrameViewModels[keyFrameIndex]; segmentViewModelToSplit.KeyFrameViewModels.RemoveAt(keyFrameIndex); segmentViewModelToSplit.Model.KeyFrames.RemoveAt(keyFrameIndex); splitKeyFrameViewModels.Add(keyFrameViewModel); } while (keyFrameIndex < segmentViewModelToSplit.KeyFrameViewModels.Count); } else { // Lerp new KeyFrameViewModel and add to splitKeyFrameViewModels KeyFrameModelBase keyFrameModel = segmentViewModelToSplit.Model.KeyFrames.Last(kfm => kfm.FrameNumber < frameNumberToSplitAt).DeepCopy(); keyFrameModel.FrameNumber = frameNumberToSplitAt; splitKeyFrameViewModels.Add(segmentViewModelToSplit.CreateKeyFrameViewModel(keyFrameModel)); } int splitViewModelEndFrame = segmentViewModelToSplit.EndFrame; segmentViewModelToSplit.EndFrame = frameNumberToSplitAt - 1; return(CreateSegmentModelViewModel(segmentViewModelToSplit, segmentViewModelToSplit.TrackNumber, frameNumberToSplitAt, splitViewModelEndFrame, segmentViewModelToSplit.Name, splitKeyFrameViewModels)); }
/// <summary> /// Gets a <see cref="KeyFrameModelCollection"/> containing the data models of key frame view models in a <see cref="KeyFrameViewModelCollection"/>, /// optionally creating deep copies of the data models and offsetting the key frame numbers. /// </summary> /// <param name="keyFrameViewModels">The source <see cref="KeyFrameViewModelCollection"/>.</param> /// <param name="createCopies">Whether to create deep copies of the data models. Defaults to false.</param> /// <param name="frameOffset">The number of frames to offset the frame numbers of the data models by. Defaults to zero.</param> /// <returns> /// A <see cref="KeyFrameModelCollection"/> containing the data models of key frame view models in the <see cref="KeyFrameViewModelCollection"/> /// which have been deep copied and/or frame offset if so specified. /// </returns> protected KeyFrameModelCollection GetKeyFrameModels(KeyFrameViewModelCollection keyFrameViewModels, bool createCopies = false, int frameOffset = 0) { KeyFrameModelCollection keyFrameModels = new KeyFrameModelCollection(); for (int i = 0; i < keyFrameViewModels.Count; i++) { KeyFrameModelBase keyFrameModel = createCopies ? keyFrameViewModels[i].Model.DeepCopy() : keyFrameViewModels[i].Model; if (frameOffset != 0) { keyFrameModel.FrameNumber += frameOffset; } keyFrameModels.Add(keyFrameModel); } return(keyFrameModels); }