示例#1
0
    public void Remove(GeometryKeyFrame keyFrame)
    {
        WritePreamble();

        if (_keyFrames.Contains(keyFrame))
        {
            OnFreezablePropertyChanged(keyFrame, null);
            _keyFrames.Remove(keyFrame);

            WritePostscript();
        }
    }
示例#2
0
    public void Insert(int index, GeometryKeyFrame keyFrame)
    {
        if (keyFrame == null)
        {
            throw new ArgumentNullException(nameof(keyFrame));
        }

        WritePreamble();

        OnFreezablePropertyChanged(null, keyFrame);
        _keyFrames.Insert(index, keyFrame);

        WritePostscript();
    }
示例#3
0
    public int Add(GeometryKeyFrame keyFrame)
    {
        if (keyFrame == null)
        {
            throw new ArgumentNullException(nameof(keyFrame));
        }

        WritePreamble();

        OnFreezablePropertyChanged(null, keyFrame);
        _keyFrames.Add(keyFrame);

        WritePostscript();

        return(_keyFrames.Count - 1);
    }
示例#4
0
    public int IndexOf(GeometryKeyFrame keyFrame)
    {
        ReadPreamble();

        return(_keyFrames.IndexOf(keyFrame));
    }
示例#5
0
    public bool Contains(GeometryKeyFrame keyFrame)
    {
        ReadPreamble();

        return(_keyFrames.Contains(keyFrame));
    }
示例#6
0
        // Takes a group of possibly-animated paths and returns an animatable
        // of PathGeometryGroups. Returns true if it succeeds without issues.
        // Even if false is returned a best-effort animatable is returned.
        internal static bool TryGroupPaths(
            TranslationContext context,
            IEnumerable <Path> paths,
            out Animatable <PathGeometryGroup> result)
        {
            // Store the keyframes in a dictionary, keyed by frame.
            var ps = paths.ToArray();

            var groupsByFrame = new Dictionary <double, GeometryKeyFrame[]>(context.FrameNumberComparer)
            {
                { 0, new GeometryKeyFrame[ps.Length] },
            };

            for (var i = 0; i < ps.Length; i++)
            {
                var p = ps[i];

                // Add the initial value.
                groupsByFrame[0][i] = new GeometryKeyFrame(p, p.Data.InitialValue, HoldEasing.Instance);

                // Add any keyframes.
                foreach (var kf in p.Data.KeyFrames.ToArray().Skip(1))
                {
                    // See if there's a key frame at the frame number already.
                    if (!groupsByFrame.TryGetValue(kf.Frame, out var array))
                    {
                        array = new GeometryKeyFrame[ps.Length];
                        groupsByFrame.Add(kf.Frame, array);
                    }

                    // NOTE: this could result in a key frame being overwritten and
                    // lost if the frame numbers are very close together. This seems
                    // to be extremely rare, so rather than trying to be too clever
                    // here we'll just let it happen. The assert should help us find
                    // any cases where this happens to determine if we should be trying
                    // harder.
                    Debug.Assert(array[i] is null, "Path key frames very close together");

                    array[i] = new GeometryKeyFrame(p, kf.Value, kf.Easing);
                }
            }

            // Make sure that every frame has a geometry from each path.
            // For any missing path, fill the hole with the path from the
            // previous frame.
            var frames             = groupsByFrame.OrderBy(kvp => kvp.Key).Select(kvp => (frame: kvp.Key, geometries: kvp.Value)).ToArray();
            var previousGeometries = frames[0].geometries;
            var success            = true;

            // Start from the second frame. The initial frame (0) will always have a value (.InitialValue).
            foreach (var(frame, geometries) in frames.Skip(1))
            {
                // Get the easing for this frame.
                var easings = geometries.Where(g => g != null).Select(g => g.Easing).Distinct().ToArray();
                if (easings.Length > 1)
                {
                    // There are conflicting easings. We can't currently handle that.
                    success = false;
                }

                for (var i = 0; i < geometries.Length; i++)
                {
                    if (geometries[i] == null)
                    {
                        // The frame doesn't have a correponding geometry for this path.
                        // Use the geometry from the previous frame, but with the easing
                        // from this frame.
                        geometries[i] = previousGeometries[i].CloneWithDifferentEasing(easings[0]);

                        // It's correct to use the previous frame's path if it isn't animated, but if
                        // it is animated it would need to be interpolated to be correct. We currently
                        // don't handle interpolation of paths in the translator, so indicate that we
                        // weren't able to do things correctly.
                        if (geometries[i].Path.Data.IsAnimated)
                        {
                            // This is a case that we can't handle correctly.
                            success = false;
                        }
                    }
                }

                previousGeometries = geometries;
            }

            // Every entry in frames now has path data. Return the groups.
            result =
                new Animatable <PathGeometryGroup>(
                    keyFrames:
                    (from f in frames
                     let firstGeometry = f.geometries[0]
                                         let easing = firstGeometry.Easing
                                                      let geometryGroup = new PathGeometryGroup(f.geometries.Select(g => g.Geometry).ToArray(), easing)
                                                                          select new KeyFrame <PathGeometryGroup>(f.frame, geometryGroup, easing)).ToArray(),
                    propertyIndex: null);

            return(success);
        }