예제 #1
0
        /// <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);
        }