示例#1
0
        private void ScaleKeyframes()
        {
            var boundaries = GridSelection.GetSelectionBoundaries();

            if (boundaries.HasValue || Scale < Mathf.ZeroTolerance)
            {
                var saved = new List <IKeyframe>();
                for (int i = boundaries.Value.Top; i <= boundaries.Value.Bottom; ++i)
                {
                    if (!(Document.Current.Rows[i].Components.Get <NodeRow>()?.Node is IAnimationHost animable))
                    {
                        continue;
                    }
                    foreach (var animator in animable.Animators.ToList())
                    {
                        saved.Clear();
                        IEnumerable <IKeyframe> keys = animator.ReadonlyKeys.Where(k =>
                                                                                   k.Frame >= boundaries.Value.Left && k.Frame < boundaries.Value.Right
                                                                                   ).ToList();
                        if (Scale < 1)
                        {
                            keys = keys.Reverse().ToList();
                        }
                        foreach (var key in keys)
                        {
                            saved.Add(key);
                            RemoveKeyframe.Perform(animator, key.Frame);
                        }
                        foreach (var key in saved)
                        {
                            // The formula should behave similiar to stretching animation with mouse
                            int newFrame = (int)(
                                boundaries.Value.Left +
                                (key.Frame - boundaries.Value.Left) *
                                (1 + (boundaries.Value.Left - boundaries.Value.Right) * Scale) /
                                (1 + boundaries.Value.Left - boundaries.Value.Right)
                                );
                            var newKey = key.Clone();
                            newKey.Frame = newFrame;
                            SetAnimableProperty.Perform(
                                animable, animator.TargetPropertyPath, newKey.Value,
                                createAnimatorIfNeeded: true,
                                createInitialKeyframeForNewAnimator: false,
                                newKey.Frame
                                );
                            SetKeyframe.Perform(animable, animator.TargetPropertyPath, Document.Current.AnimationId, newKey);
                        }
                    }
                }
                ClearGridSelection.Perform();
                for (int i = boundaries.Value.Top; i <= boundaries.Value.Bottom; ++i)
                {
                    SelectGridSpan.Perform(i, boundaries.Value.Left, (int)(boundaries.Value.Left + (boundaries.Value.Right - boundaries.Value.Left) * Scale));
                }
            }
            else
            {
                Document.Current.History.RollbackTransaction();
            }
        }
示例#2
0
        public static void Perform()
        {
            var Boundaries = GetSelectionBoundaries();

            if (Boundaries == null)
            {
                AlertDialog.Show("Can't invert animation in a non-rectangular selection. The selection must be a single rectangle.");
                return;
            }
            using (Document.Current.History.BeginTransaction()) {
                for (int i = Boundaries.Value.Top; i <= Boundaries.Value.Bottom; ++i)
                {
                    if (!(Document.Current.Rows[i].Components.Get <NodeRow>()?.Node is IAnimationHost animable))
                    {
                        continue;
                    }
                    foreach (var animator in animable.Animators.ToList())
                    {
                        var saved = animator.Keys.Where(k =>
                                                        Boundaries.Value.Left <= k.Frame &&
                                                        k.Frame < Boundaries.Value.Right).ToList();
                        foreach (var key in saved)
                        {
                            RemoveKeyframe.Perform(animator, key.Frame);
                        }
                        foreach (var key in saved)
                        {
                            SetProperty.Perform(key, nameof(IKeyframe.Frame), Boundaries.Value.Left + Boundaries.Value.Right - key.Frame - 1);
                            SetKeyframe.Perform(animable, animator.TargetPropertyPath, animator.AnimationId, key);
                        }
                    }
                }
                Document.Current.History.CommitTransaction();
            }
        }
示例#3
0
 private void CreateSpriteAnimatedImage(List <string> files)
 {
     onBeforeDrop?.Invoke();
     using (Document.Current.History.BeginTransaction()) {
         var node = CreateNode.Perform(typeof(Image));
         SetProperty.Perform(node, nameof(Widget.Pivot), Vector2.Half);
         SetProperty.Perform(node, nameof(Widget.Id), "Temp");
         postProcessNode?.Invoke(node);
         var      i     = 0;
         ITexture first = null;
         foreach (var file in files)
         {
             if (!Utils.ExtractAssetPathOrShowAlert(file, out var assetPath, out var assetType))
             {
                 continue;
             }
             var text = new SerializableTexture(assetPath);
             first = first ?? text;
             SetKeyframe.Perform(node, nameof(Widget.Texture), Document.Current.AnimationId,
                                 new Keyframe <ITexture> {
                 Value    = text,
                 Frame    = i++,
                 Function = KeyFunction.Steep,
             });
         }
         SetProperty.Perform(node, nameof(Widget.Size), (Vector2)first.ImageSize);
         Document.Current.History.CommitTransaction();
     }
 }
示例#4
0
        public static void Perform(IntVector2 offset, bool removeOriginals)
        {
            var rows = Document.Current.Rows.ToList();

            if (offset.Y > 0)
            {
                rows.Reverse();
            }
            foreach (var row in rows)
            {
                var track = row.Components.Get <AnimationTrackRow>()?.Track;
                if (track?.EditorState().Locked != false)
                {
                    continue;
                }
                var clips = track.Clips.Where(i => i.IsSelected).ToList();
                var keys  = new List <IKeyframe>();
                if (track.Animators.TryFind(nameof(AnimationTrack.Weight), out var weightAnimator, Document.Current.AnimationId))
                {
                    keys = weightAnimator.ReadonlyKeys.Where(k => clips.Any(c => c.BeginFrame <= k.Frame && k.Frame <= c.EndFrame)).ToList();
                }
                if (removeOriginals)
                {
                    foreach (var key in keys)
                    {
                        RemoveKeyframe.Perform(weightAnimator, key.Frame);
                    }
                }
                foreach (var clip in clips)
                {
                    if (removeOriginals)
                    {
                        AnimationClipToolbox.RemoveClip(track, clip);
                    }
                    else
                    {
                        SetProperty.Perform(clip, nameof(AnimationClip.IsSelected), false);
                    }
                }
                int numRows   = Document.Current.Rows.Count;
                var destRow   = Document.Current.Rows[(row.Index + offset.Y).Clamp(0, numRows - 1)];
                var destTrack = destRow.Components.Get <AnimationTrackRow>()?.Track;
                foreach (var clip in clips)
                {
                    var newClip = clip.Clone();
                    newClip.BeginFrame += offset.X;
                    newClip.EndFrame   += offset.X;
                    newClip.IsSelected  = true;
                    AnimationClipToolbox.InsertClip(destTrack, newClip);
                }
                foreach (var k in keys)
                {
                    var key = k.Clone();
                    key.Frame += offset.X;
                    SetKeyframe.Perform(destTrack, nameof(AnimationTrack.Weight), Document.Current.AnimationId, key);
                }
            }
        }
示例#5
0
 private void ScaleKeyframes()
 {
     if (GridSelection.GetSelectionBoundaries(out var boundaries) && Scale > Mathf.ZeroTolerance)
     {
         var processed = new HashSet <IAnimator>();
         var saved     = new List <IKeyframe>();
         foreach (var animable in GridSelection.EnumerateAnimators(boundaries))
         {
             foreach (var animator in animable.Animators)
             {
                 if (animator.AnimationId != Document.Current.AnimationId || processed.Contains(animator))
                 {
                     continue;
                 }
                 processed.Add(animator);
                 saved.Clear();
                 IEnumerable <IKeyframe> keys = animator.ReadonlyKeys.Where(k =>
                                                                            k.Frame >= boundaries.Left && k.Frame < boundaries.Right
                                                                            ).ToList();
                 if (Scale < 1)
                 {
                     keys = keys.Reverse().ToList();
                 }
                 foreach (var key in keys)
                 {
                     saved.Add(key);
                     RemoveKeyframe.Perform(animator, key.Frame);
                 }
                 foreach (var key in saved)
                 {
                     // The formula should behave similiar to stretching animation with mouse
                     int newFrame = (int)(
                         boundaries.Left +
                         (key.Frame - boundaries.Left) *
                         (1 + (boundaries.Left - boundaries.Right) * Scale) /
                         (1 + boundaries.Left - boundaries.Right)
                         );
                     var newKey = key.Clone();
                     newKey.Frame = newFrame;
                     SetAnimableProperty.Perform(
                         animable.Host, animator.TargetPropertyPath, newKey.Value,
                         createAnimatorIfNeeded: true,
                         createInitialKeyframeForNewAnimator: false,
                         newKey.Frame
                         );
                     SetKeyframe.Perform(animable.Host, animator.TargetPropertyPath, Document.Current.AnimationId, newKey);
                 }
             }
         }
         ClearGridSelection.Perform();
         for (int i = boundaries.Top; i <= boundaries.Bottom; ++i)
         {
             SelectGridSpan.Perform(i, boundaries.Left, (int)(boundaries.Left + (boundaries.Right - boundaries.Left) * Scale));
         }
     }
 private static void RestoreChildrenPositions(Widget widget, Matrix32 transform)
 {
     foreach (var child in widget.Nodes.OfType <Widget>())
     {
         var newPosition = transform.TransformVector(child.Position);
         SetProperty.Perform(child, nameof(Widget.Position), newPosition);
         if (child.Animators.TryFind(nameof(Widget.Position), out var animator))
         {
             foreach (var key in animator.ReadonlyKeys.ToList())
             {
                 var newKey = key.Clone();
                 newKey.Value = transform.TransformVector((Vector2)key.Value);
                 SetKeyframe.Perform(animator, newKey);
             }
         }
     }
 }
示例#7
0
        public static void TransformPropertyAndKeyframes <T>(Node node, string propertyId, Func <T, T> transformer)
        {
            var value = new Property <T>(node, propertyId).Value;

            SetProperty.Perform(node, propertyId, transformer(value));
            foreach (var animation in node.Animators)
            {
                if (animation.TargetPropertyPath == propertyId)
                {
                    foreach (var keyframe in animation.Keys.ToList())
                    {
                        var newKeyframe = keyframe.Clone();
                        newKeyframe.Value = transformer((T)newKeyframe.Value);
                        SetKeyframe.Perform(node, animation.TargetPropertyPath, animation.AnimationId, newKeyframe);
                    }
                }
            }
        }
示例#8
0
        public static void Perform()
        {
            var keys = KeyframeClipboard.Keys;

            if (keys == null || !Document.Current.TopLevelSelectedRows().Any())
            {
                return;
            }
            int startRow = Document.Current.TopLevelSelectedRows().First().Index;
            var spans    = Document.Current.Rows[startRow].Components.Get <GridSpanListComponent>()?.Spans;

            if (spans == null || !spans.Any())
            {
                return;
            }
            int startCol = spans.First().A;

            Document.Current.History.DoTransaction(() => {
                foreach (var key in keys)
                {
                    int rowIndex = startRow + key.Row;
                    int colIndex = startCol + key.Frame;
                    if (rowIndex >= Document.Current.Rows.Count || colIndex < 0)
                    {
                        continue;
                    }
                    var animable = Document.Current.Rows[rowIndex].Components.Get <NodeRow>()?.Node as IAnimationHost;
                    if (animable == null)
                    {
                        continue;
                    }
                    var property = animable.GetType().GetProperty(key.Property);
                    if (property == null)
                    {
                        continue;
                    }
                    var keyframe   = key.Keyframe.Clone();
                    keyframe.Frame = colIndex;
                    SetKeyframe.Perform(animable, key.Property, key.AnimationId, keyframe);
                }
            });
        }
示例#9
0
 private static void SetKeyframes(Dictionary <Node, BoneAnimationData> keyframeDictionary)
 {
     foreach (var pair in keyframeDictionary)
     {
         if (pair.Value.NoParentKeyframes)
         {
             TransformPropertyAndKeyframes(pair.Key, nameof(Bone.Position), pair.Value.PositionTransformer);
         }
         else
         {
             SetProperty.Perform(pair.Key, nameof(Bone.Position), pair.Value.CurrentPosition);
             SetProperty.Perform(pair.Key, nameof(Bone.Rotation), pair.Value.CurrentRotation);
             foreach (var keyframe in pair.Value.PositionKeyframes)
             {
                 SetKeyframe.Perform(pair.Key, nameof(Bone.Position), Document.Current.AnimationId, keyframe.Value);
             }
             foreach (var keyframe in pair.Value.RotationKeyframes)
             {
                 SetKeyframe.Perform(pair.Key, nameof(Bone.Rotation), Document.Current.AnimationId, keyframe.Value);
             }
             SetAnimableProperty.Perform(pair.Key, nameof(Bone.BaseIndex), 0);
         }
     }
 }
示例#10
0
 /// <summary>
 /// Handles files drop.
 /// </summary>
 /// <param name="files">Dropped files.</param>
 public void Handle(List <string> files)
 {
     using (Document.Current.History.BeginTransaction()) {
         foreach (var file in files.Where(f => Path.GetExtension(f) == ".ogg").ToList())
         {
             files.Remove(file);
             if (!Utils.ExtractAssetPathOrShowAlert(file, out var assetPath, out var assetType))
             {
                 continue;
             }
             var node   = CreateNode.Perform(typeof(Audio));
             var sample = new SerializableSample(assetPath);
             SetProperty.Perform(node, nameof(Audio.Sample), sample);
             SetProperty.Perform(node, nameof(Node.Id), Path.GetFileNameWithoutExtension(assetPath));
             SetProperty.Perform(node, nameof(Audio.Volume), 1);
             var key = new Keyframe <AudioAction> {
                 Frame = Document.Current.AnimationFrame,
                 Value = AudioAction.Play
             };
             SetKeyframe.Perform(node, nameof(Audio.Action), Document.Current.AnimationId, key);
         }
         Document.Current.History.CommitTransaction();
     }
 }
        public void Handle(List <string> files)
        {
            var grid = Timeline.Instance.Grid;
            var rowLocationUnderMouseOnFilesDrop =
                SelectAndDragRowsProcessor.MouseToRowLocation(grid.RootWidget.Input.MousePosition);
            var handled = new List <string>();
            var cellUnderMouseOnFilesDrop = grid.CellUnderMouse();
            var animateTextureCellOffset  = 0;

            using (Document.Current.History.BeginTransaction()) {
                foreach (var file in files.ToList())
                {
                    if (Document.Current.Animation.IsCompound)
                    {
                        try {
                            // Dirty hack: using a file drag&drop mechanics for dropping animation clips on the grid.
                            var decodedAnimationId = Encoding.UTF8.GetString(Convert.FromBase64String(file));
                            AddAnimationClip.Perform(
                                new IntVector2(
                                    cellUnderMouseOnFilesDrop.X + animateTextureCellOffset,
                                    cellUnderMouseOnFilesDrop.Y),
                                decodedAnimationId);
                            return;
                        } catch { }
                    }
                    if (!Utils.ExtractAssetPathOrShowAlert(file, out var assetPath, out var assetType))
                    {
                        continue;
                    }
                    switch (assetType)
                    {
                    case ".png": {
                        if (Document.Current.Rows.Count == 0)
                        {
                            continue;
                        }
                        var widget = Document.Current.Rows[cellUnderMouseOnFilesDrop.Y].Components.Get <NodeRow>()?.Node as Widget;
                        if (widget == null)
                        {
                            continue;
                        }
                        var key = new Keyframe <ITexture> {
                            Frame    = cellUnderMouseOnFilesDrop.X + animateTextureCellOffset,
                            Value    = new SerializableTexture(assetPath),
                            Function = KeyFunction.Steep,
                        };
                        SetKeyframe.Perform(widget, nameof(Widget.Texture), Document.Current.AnimationId, key);
                        animateTextureCellOffset++;
                        break;
                    }

                    case ".ogg": {
                        var node = CreateNode.Perform(typeof(Audio));
                        if (rowLocationUnderMouseOnFilesDrop.HasValue)
                        {
                            var location = rowLocationUnderMouseOnFilesDrop.Value;
                            var row      = Document.Current.Rows.FirstOrDefault(r => r.Components.Get <Core.Components.NodeRow>()?.Node == node);
                            if (row != null)
                            {
                                if (location.Index >= row.Index)
                                {
                                    location.Index++;
                                }
                                SelectAndDragRowsProcessor.Probers.Any(p => p.Probe(row, location));
                            }
                        }
                        var sample = new SerializableSample(assetPath);
                        SetProperty.Perform(node, nameof(Audio.Sample), sample);
                        SetProperty.Perform(node, nameof(Node.Id), assetPath);
                        SetProperty.Perform(node, nameof(Audio.Volume), 1);
                        var key = new Keyframe <AudioAction> {
                            Frame = cellUnderMouseOnFilesDrop.X,
                            Value = AudioAction.Play
                        };
                        SetKeyframe.Perform(node, nameof(Audio.Action), Document.Current.AnimationId, key);
                        break;
                    }
                    }
                    files.Remove(file);
                }
                Document.Current.History.CommitTransaction();
            }
        }
示例#12
0
        private void ShowContextMenu()
        {
            SelectAnimationBasedOnMousePosition();
            var menu     = new Menu();
            var rootNode = Document.Current.RootNode;

            menu.Add(new Command("Add", () => AddAnimation(rootNode, false)));
            menu.Add(new Command("Add Compound", () => AddAnimation(rootNode, true)));
            menu.Add(new Command("Add ZeroPose", () => AddZeroPoseAnimation(rootNode))
            {
                Enabled = !rootNode.Animations.TryFind(Animation.ZeroPoseId, out _)
            });
            var path = GetNodePath(Document.Current.Container);

            if (!string.IsNullOrEmpty(path))
            {
                var container = Document.Current.Container;
                menu.Add(new Command($"Add To '{path}'", () => AddAnimation(container, false)));
                menu.Add(new Command($"Add Compound To '{path}'", () => AddAnimation(container, true)));
                menu.Add(new Command($"Add ZeroPose To '{path}'", () => AddZeroPoseAnimation(container))
                {
                    Enabled = !container.Animations.TryFind(Animation.ZeroPoseId, out _)
                });
            }
            menu.Add(Command.MenuSeparator);
            menu.Add(new Command("Rename", RenameAnimation));
            menu.Add(new Command("Duplicate", DuplicateAnimation));
            menu.Add(Command.Delete);
            menu.Popup();

            void AddAnimation(Node node, bool compound)
            {
                Document.Current.History.DoTransaction(() => {
                    var animation = new Animation {
                        Id = GenerateAnimationId("NewAnimation"), IsCompound = compound
                    };
                    Core.Operations.InsertIntoList.Perform(node.Animations, node.Animations.Count, animation);
                    SelectAnimation(GetAnimations().IndexOf(animation));
                    if (compound)
                    {
                        var track = new AnimationTrack {
                            Id = "Track1"
                        };
                        Core.Operations.InsertIntoList <AnimationTrackList, AnimationTrack> .Perform(animation.Tracks, 0, track);
                    }
                });
                // Schedule animation rename on the next update, since the widgets are not built yet
                panelWidget.Tasks.Add(DelayedRenameAnimation());
            }

            void AddZeroPoseAnimation(Node node)
            {
                Document.Current.History.DoTransaction(() => {
                    var animation = new Animation {
                        Id = Animation.ZeroPoseId
                    };
                    InsertIntoList.Perform(node.Animations, node.Animations.Count, animation);
                    foreach (var a in node.Descendants.SelectMany(n => n.Animators).ToList())
                    {
                        var(propertyData, animable, index) =
                            AnimationUtils.GetPropertyByPath(a.Owner, a.TargetPropertyPath);
                        var zeroPoseKey   = Keyframe.CreateForType(propertyData.Info.PropertyType);
                        zeroPoseKey.Value = index == -1
                                                        ? propertyData.Info.GetValue(animable)
                                                        : propertyData.Info.GetValue(animable, new object[] { index });
                        zeroPoseKey.Function = KeyFunction.Steep;
                        SetKeyframe.Perform(a.Owner, a.TargetPropertyPath, Animation.ZeroPoseId, zeroPoseKey);
                    }
                    SelectAnimation(GetAnimations().IndexOf(animation));
                });
            }

            IEnumerator <object> DelayedRenameAnimation()
            {
                yield return(null);

                RenameAnimation();
            }
        }
        private void Stretch(IntRectangle boundaries, DragSide side, int newPos, bool stretchMarkers)
        {
            int length;

            if (side == DragSide.Left)
            {
                length = boundaries.Right - newPos - 1;
            }
            else
            {
                length = newPos - boundaries.Left - 1;
            }
            int oldLength = boundaries.Right - boundaries.Left - 1;
            var processed = new HashSet <IAnimator>();

            foreach (var animable in GridSelection.EnumerateAnimators(boundaries))
            {
                foreach (var animator in animable.Animators)
                {
                    if (animator.AnimationId != Document.Current.AnimationId || processed.Contains(animator) || !savedKeyframes.ContainsKey(animator))
                    {
                        continue;
                    }
                    processed.Add(animator);
                    IEnumerable <IKeyframe> saved = savedKeyframes[animator];
                    if (
                        side == DragSide.Left && length < oldLength ||
                        side == DragSide.Right && length > oldLength
                        )
                    {
                        saved = saved.Reverse();
                    }
                    foreach (var key in saved)
                    {
                        RemoveKeyframe.Perform(animator, key.Frame);
                    }
                    foreach (var key in saved)
                    {
                        double relpos = savedPositions[key];
                        int    newFrame;
                        if (side == DragSide.Left)
                        {
                            newFrame = (int)Math.Round(newPos + relpos * length);
                        }
                        else
                        {
                            newFrame = (int)Math.Round(boundaries.Left + relpos * length);
                        }
                        var newKey = key.Clone();
                        newKey.Frame = newFrame;
                        SetAnimableProperty.Perform(
                            animable.Host, animator.TargetPropertyPath, newKey.Value,
                            createAnimatorIfNeeded: true,
                            createInitialKeyframeForNewAnimator: false,
                            newKey.Frame
                            );
                        SetKeyframe.Perform(animable.Host, animator.TargetPropertyPath, Document.Current.AnimationId, newKey);
                    }
                }
            }
            if (stretchMarkers)
            {
                foreach (var marker in savedMarkers)
                {
                    DeleteMarker.Perform(marker, removeDependencies: false);
                }
                foreach (var marker in savedMarkers)
                {
                    double relpos = savedMarkerPositions[marker];
                    int    newFrame;
                    if (side == DragSide.Left)
                    {
                        newFrame = (int)Math.Round(newPos + relpos * length);
                    }
                    else
                    {
                        newFrame = (int)Math.Round(boundaries.Left + relpos * length);
                    }
                    var newMarker = marker.Clone();
                    newMarker.Frame = newFrame;
                    SetMarker.Perform(newMarker, removeDependencies: false);
                }
            }
        }
示例#14
0
        public static void Perform(IntVector2 offset, bool removeOriginals)
        {
            var processedKeys = new HashSet <IKeyframe>();
            var operations    = new List <Action>();

            foreach (var row in Document.Current.Rows)
            {
                var spans = row.Components.GetOrAdd <GridSpanListComponent>().Spans.GetNonOverlappedSpans(offset.X > 0);
                foreach (var span in spans)
                {
                    var node = row.Components.Get <NodeRow>()?.Node ?? row.Components.Get <PropertyRow>()?.Node;
                    if (node == null)
                    {
                        continue;
                    }
                    var property = row.Components.Get <PropertyRow>()?.Animator.TargetPropertyPath;
                    foreach (var a in node.Animators.ToList())
                    {
                        if (property != null && a.TargetPropertyPath != property)
                        {
                            continue;
                        }
                        IEnumerable <IKeyframe> keysEnumerable = a.Keys.Where(k => k.Frame >= span.A && k.Frame < span.B);
                        if (offset.X > 0)
                        {
                            keysEnumerable = keysEnumerable.Reverse();
                        }
                        foreach (var k in keysEnumerable)
                        {
                            if (processedKeys.Contains(k))
                            {
                                continue;
                            }
                            processedKeys.Add(k);
                            var destRow = row.Index + offset.Y;
                            if (!CheckRowRange(destRow))
                            {
                                continue;
                            }
                            var destRowComponents = Document.Current.Rows[destRow].Components;
                            var destNode          = destRowComponents.Get <NodeRow>()?.Node ?? destRowComponents.Get <PropertyRow>()?.Node;
                            if (destNode == null || !ArePropertiesCompatible(node, destNode, a.TargetPropertyPath))
                            {
                                continue;
                            }
                            if (k.Frame + offset.X >= 0)
                            {
                                var k1 = k.Clone();
                                k1.Frame += offset.X;
                                // The same logic is used to create keyframes as everywhere, but extended by setting
                                // all parameters from a particular keyframe. Yes, this creates some overhead.
                                operations.Add(() => SetAnimableProperty.Perform(destNode, a.TargetPropertyPath, k1.Value, true, false, k1.Frame));
                                operations.Add(() => SetKeyframe.Perform(destNode, a.TargetPropertyPath, Document.Current.AnimationId, k1));
                            }
                            // Order is importent. RemoveKeyframe must be after SetKeyframe,
                            // to prevent animator clean up if all keys were removed.
                            if (removeOriginals)
                            {
                                operations.Add(() => RemoveKeyframe.Perform(a, k.Frame));
                            }
                        }
                    }
                }
            }
            foreach (var o in operations)
            {
                o();
            }
        }
示例#15
0
        private void Handle(IEnumerable <string> files)
        {
            Handling?.Invoke();
            using (Document.Current.History.BeginTransaction()) {
                pendingImages = new List <string>();
                foreach (var file in files)
                {
                    try {
                        string assetPath, assetType;
                        if (!Utils.ExtractAssetPathOrShowAlert(file, out assetPath, out assetType) ||
                            !Utils.AssertCurrentDocument(assetPath, assetType))
                        {
                            continue;
                        }

                        var nodeCreatingEventArgs = new NodeCreatingEventArgs(assetPath, assetType);
                        NodeCreating?.Invoke(nodeCreatingEventArgs);
                        if (nodeCreatingEventArgs.Cancel)
                        {
                            continue;
                        }

                        var fileName = Path.GetFileNameWithoutExtension(assetPath);
                        switch (assetType)
                        {
                        case ".png":
                            pendingImages.Add(assetPath);
                            break;

                        case ".ogg": {
                            var node   = CreateNode.Perform(typeof(Audio));
                            var sample = new SerializableSample(assetPath);
                            SetProperty.Perform(node, nameof(Audio.Sample), sample);
                            SetProperty.Perform(node, nameof(Node.Id), fileName);
                            SetProperty.Perform(node, nameof(Audio.Volume), 1);
                            var key = new Keyframe <AudioAction> {
                                Frame = Document.Current.AnimationFrame,
                                Value = AudioAction.Play
                            };
                            SetKeyframe.Perform(node, nameof(Audio.Action), Document.Current.AnimationId, key);
                            OnNodeCreated(node);
                            break;
                        }

                        case ".tan":
                        case ".model":
                        case ".scene":
                            DropSceneContextMenu.Create(assetPath, assetType, NodeCreated);
                            break;
                        }
                    } catch (System.Exception e) {
                        AlertDialog.Show(e.Message);
                    }
                }

                if (pendingImages.Count > 0)
                {
                    var menu = new Menu();
                    foreach (var kv in imageDropCommands.Commands)
                    {
                        if (NodeCompositionValidator.Validate(Document.Current.Container.GetType(), kv.Value))
                        {
                            menu.Add(kv.Key);
                        }
                    }
                    menu.Popup();
                }
                Document.Current.History.CommitTransaction();
            }
        }
示例#16
0
        public static void Perform()
        {
            var keys = KeyframeClipboard.Keys;

            if (keys == null || !Document.Current.TopLevelSelectedRows().Any())
            {
                return;
            }
            int startRow = Document.Current.TopLevelSelectedRows().First().Index;
            var spans    = Document.Current.Rows[startRow].Components.Get <GridSpanListComponent>()?.Spans;

            if (spans == null || !spans.Any())
            {
                return;
            }
            int startCol = spans.First().A;

            Document.Current.History.DoTransaction(() => {
                var rows                     = Document.Current.Rows;
                int rowIndex                 = startRow;
                int animationHostIndex       = 0;
                IAnimationHost animationHost = null;
                Node node                    = null;

                foreach (var key in keys)
                {
                    int colIndex = startCol + key.Frame;
                    if (rowIndex >= Document.Current.Rows.Count || colIndex < 0)
                    {
                        continue;
                    }
                    while (rowIndex < rows.Count)
                    {
                        node          = rows[rowIndex].Components.Get <NodeRow>()?.Node;
                        animationHost = node;
                        if (animationHost != null)
                        {
                            if (animationHostIndex == key.AnimationHostOrderIndex)
                            {
                                break;
                            }
                            animationHostIndex++;
                        }
                        ++rowIndex;
                    }
                    if (rowIndex >= rows.Count)
                    {
                        break;
                    }
                    if (node.EditorState().Locked)
                    {
                        continue;
                    }
                    var(pd, _, _) = AnimationUtils.GetPropertyByPath(animationHost, key.Property);
                    if (pd.Info == null)
                    {
                        continue;
                    }
                    var keyframe   = key.Keyframe.Clone();
                    keyframe.Frame = colIndex;
                    SetKeyframe.Perform(animationHost, key.Property, Document.Current.AnimationId, keyframe);
                }
            });
        }
示例#17
0
        private void Stretch(Boundaries boundaries, DragSide side, int newPos, bool stretchMarkers)
        {
            int length;

            if (side == DragSide.Left)
            {
                length = boundaries.Right - newPos - 1;
            }
            else
            {
                length = newPos - boundaries.Left - 1;
            }
            int oldLength = boundaries.Right - boundaries.Left - 1;

            for (int i = boundaries.Top; i <= boundaries.Bottom; ++i)
            {
                if (!(Document.Current.Rows[i].Components.Get <NodeRow>()?.Node is IAnimationHost animable))
                {
                    continue;
                }
                foreach (var animator in animable.Animators.ToList())
                {
                    IEnumerable <IKeyframe> saved = savedKeyframes[animator];
                    if (
                        side == DragSide.Left && length < oldLength ||
                        side == DragSide.Right && length > oldLength
                        )
                    {
                        saved = saved.Reverse();
                    }
                    foreach (var key in saved)
                    {
                        RemoveKeyframe.Perform(animator, key.Frame);
                    }
                    foreach (var key in saved)
                    {
                        double relpos = savedPositions[key];
                        int    newFrame;
                        if (side == DragSide.Left)
                        {
                            newFrame = (int)Math.Round(newPos + relpos * length);
                        }
                        else
                        {
                            newFrame = (int)Math.Round(boundaries.Left + relpos * length);
                        }
                        var newKey = key.Clone();
                        newKey.Frame = newFrame;
                        SetAnimableProperty.Perform(
                            animable, animator.TargetPropertyPath, newKey.Value,
                            createAnimatorIfNeeded: true,
                            createInitialKeyframeForNewAnimator: false,
                            newKey.Frame
                            );
                        SetKeyframe.Perform(animable, animator.TargetPropertyPath, Document.Current.AnimationId, newKey);
                    }
                }
            }
            if (stretchMarkers)
            {
                foreach (var marker in savedMarkers)
                {
                    DeleteMarker.Perform(Document.Current.Container, marker, removeDependencies: false);
                }
                foreach (var marker in savedMarkers)
                {
                    double relpos = savedMarkerPositions[marker];
                    int    newFrame;
                    if (side == DragSide.Left)
                    {
                        newFrame = (int)Math.Round(newPos + relpos * length);
                    }
                    else
                    {
                        newFrame = (int)Math.Round(boundaries.Left + relpos * length);
                    }
                    var newMarker = marker.Clone();
                    newMarker.Frame = newFrame;
                    SetMarker.Perform(Document.Current.Container, newMarker, removeDependencies: false);
                }
            }
        }