public void Remove(GeometryKeyFrame keyFrame) { WritePreamble(); if (_keyFrames.Contains(keyFrame)) { OnFreezablePropertyChanged(keyFrame, null); _keyFrames.Remove(keyFrame); WritePostscript(); } }
public void Insert(int index, GeometryKeyFrame keyFrame) { if (keyFrame == null) { throw new ArgumentNullException(nameof(keyFrame)); } WritePreamble(); OnFreezablePropertyChanged(null, keyFrame); _keyFrames.Insert(index, keyFrame); WritePostscript(); }
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); }
public int IndexOf(GeometryKeyFrame keyFrame) { ReadPreamble(); return(_keyFrames.IndexOf(keyFrame)); }
public bool Contains(GeometryKeyFrame keyFrame) { ReadPreamble(); return(_keyFrames.Contains(keyFrame)); }
// 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); }