Beispiel #1
0
        public static void Create(string assetPath, string assetType, Action <Node> onNodeCreated)
        {
            var fileName = Path.GetFileNameWithoutExtension(assetPath);
            var menu     = new Menu()
            {
                new Command("Open in New Tab", () => Project.Current.OpenDocument(assetPath)),
                new Command("Add As External Scene", () => Document.Current.History.DoTransaction(
                                () => {
                    var scene = Node.CreateFromAssetBundle(assetPath, yuzu: TangerineYuzu.Instance.Value);
                    var node  = CreateNode.Perform(scene.GetType());
                    SetProperty.Perform(node, nameof(Widget.ContentsPath), assetPath);
                    SetProperty.Perform(node, nameof(Node.Id), fileName);
                    if (scene is Widget)
                    {
                        SetProperty.Perform(node, nameof(Widget.Pivot), Vector2.Half);
                        SetProperty.Perform(node, nameof(Widget.Size), ((Widget)scene).Size);
                    }
                    onNodeCreated?.Invoke(node);
                    node.LoadExternalScenes();
                })),
                new Command("Cancel")
            };

            menu[0].Enabled = assetType != ".model";
            menu.Popup();
        }
Beispiel #2
0
        public static void Generate(CompressionFormat compressionFormat)
        {
            var   size      = Document.Current.RootNode.AsWidget.Size;
            float newWidth  = previewWidth;
            float newHeight = previewHeight;

            if (size.X > size.Y)
            {
                newHeight *= size.Y / size.X;
            }
            else
            {
                newWidth *= size.X / size.Y;
            }
            // Andrey Tyshchenko: Enable animation preview to disable presenters while rendering document preview
            var savedPreviewAnimation = Document.Current.PreviewAnimation;

            Document.Current.PreviewAnimation = true;
            var bitmap = Document.Current.RootNode.AsWidget.ToBitmap().Rescale(newWidth.Round(), newHeight.Round());

            Document.Current.PreviewAnimation = savedPreviewAnimation;
            var stream = new MemoryStream();

            bitmap.SaveTo(stream, compressionFormat);
            SetProperty.Perform(Document.Current, nameof(Document.Preview), Convert.ToBase64String(stream.ToArray()));
        }
Beispiel #3
0
 private void FilesDropOnNodeCreated(Node node)
 {
     if (node is Widget)
     {
         SetProperty.Perform(node, nameof(Widget.Position), mousePositionOnFilesDrop);
     }
 }
Beispiel #4
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();
     }
 }
Beispiel #5
0
        public static void Generate(CompressionFormat compressionFormat)
        {
            var   size      = Document.Current.RootNode.AsWidget.Size;
            float newWidth  = previewWidth;
            float newHeight = previewHeight;

            if (size.X > size.Y)
            {
                newHeight *= size.Y / size.X;
            }
            else
            {
                newWidth *= size.X / size.Y;
            }
            var savedPreviewScene = Document.Current.PreviewScene;

            Document.Current.PreviewScene = true;
            var bitmap = Document.Current.RootNode.AsWidget.ToBitmap().Rescale(newWidth.Round(), newHeight.Round());

            Document.Current.PreviewScene = savedPreviewScene;
            var stream = new MemoryStream();

            bitmap.SaveTo(stream, compressionFormat);
            SetProperty.Perform(Document.Current, nameof(Document.Preview), Convert.ToBase64String(stream.ToArray()));
        }
Beispiel #6
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();
            }
        }
Beispiel #7
0
 private static void FilesDropNodePostProcessor(Node node)
 {
     if (node is Widget)
     {
         SetProperty.Perform(node, nameof(Widget.Position), Instance.mousePositionOnFilesDrop);
     }
 }
Beispiel #8
0
 public static void SetResolution(ResolutionInfo resolution)
 {
     using (Document.Current.History.BeginTransaction()) {
         SetProperty.Perform(Document.Current.RootNode, nameof(Widget.Size), resolution.Size);
         SetMarker(Document.Current.RootNode, resolution.MarkerId);
         Document.Current.History.CommitTransaction();
     }
 }
Beispiel #9
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);
                }
            }
        }
Beispiel #10
0
        void DragMarker(Marker marker, int destColumn)
        {
            var markerToRemove = Document.Current.Animation.Markers.FirstOrDefault(m => m.Frame == destColumn);

            if (marker.Frame != destColumn && markerToRemove != null)
            {
                DeleteMarker.Perform(markerToRemove, false);
            }
            // Delete and add marker again, because we want to maintain the markers order.
            DeleteMarker.Perform(marker, false);
            SetProperty.Perform(marker, "Frame", destColumn);
            SetMarker.Perform(marker, true);
        }
Beispiel #11
0
 private static void Expand()
 {
     foreach (var row in Document.Current.SelectedRows().ToList())
     {
         if (row.Components.Get <NodeRow>() is NodeRow nodeRow)
         {
             SetProperty.Perform(nodeRow, nameof(NodeRow.Expanded), !nodeRow.Expanded, isChangingDocument: false);
             if (nodeRow.Expanded && row.Rows.Count > 0)
             {
                 Timeline.Instance.EnsureRowChildsVisible(row);
             }
         }
     }
 }
Beispiel #12
0
        private void SelectAnimation(int index)
        {
            var a = GetAnimations();

            index = index.Clamp(0, a.Count - 1);
            EnsureRowVisible(index);
            Window.Current.Invalidate();
            var document = Document.Current;

            document.History.DoTransaction(() => {
                SetProperty.Perform(document, nameof(Document.SelectedAnimation), a[index], isChangingDocument: false);
            });
            // Invalidate dependent documents for which this is an external scene.
            Project.Current.SceneCache.InvalidateEntryFromOpenedDocumentChanged(document.Path, () => document.RootNodeUnwrapped);
        }
 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);
             }
         }
     }
 }
Beispiel #14
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);
                    }
                }
            }
        }
Beispiel #15
0
 protected void UpsampleNodeAnimation(Node node)
 {
     foreach (var a in node.Animations)
     {
         foreach (var m in a.Markers)
         {
             SetProperty.Perform(m, "Frame", m.Frame * 2);
         }
     }
     foreach (var a in node.Animators)
     {
         foreach (var k in a.Keys)
         {
             SetProperty.Perform(k, "Frame", k.Frame * 2);
         }
     }
     foreach (var n in node.Nodes)
     {
         UpsampleNodeAnimation(n);
     }
 }
Beispiel #16
0
 public void HandleDropImage()
 {
     foreach (var kv in imageDropCommands.Commands)
     {
         if (pendingImages != null && kv.Key.WasIssued())
         {
             kv.Key.Consume();
             using (Document.Current.History.BeginTransaction()) {
                 foreach (var assetPath in pendingImages)
                 {
                     var node     = CreateNode.Perform(kv.Value);
                     var texture  = new SerializableTexture(assetPath);
                     var nodeSize = (Vector2)texture.ImageSize;
                     var nodeId   = Path.GetFileNameWithoutExtension(assetPath);
                     if (node is Widget)
                     {
                         SetProperty.Perform(node, nameof(Widget.Texture), texture);
                         SetProperty.Perform(node, nameof(Widget.Pivot), Vector2.Half);
                         SetProperty.Perform(node, nameof(Widget.Size), nodeSize);
                         SetProperty.Perform(node, nameof(Widget.Id), nodeId);
                     }
                     else if (node is ParticleModifier)
                     {
                         SetProperty.Perform(node, nameof(ParticleModifier.Texture), texture);
                         SetProperty.Perform(node, nameof(ParticleModifier.Size), nodeSize);
                         SetProperty.Perform(node, nameof(ParticleModifier.Id), nodeId);
                     }
                     OnNodeCreated(node);
                 }
                 Document.Current.History.CommitTransaction();
                 pendingImages = null;
             }
         }
         else
         {
             kv.Key.Consume();
         }
     }
 }
            protected override bool ProbeInternal(BoneRow node, Row row, RowLocation location)
            {
                if (!(location.ParentRow.Components.Contains <BoneRow>() || location.ParentRow.Components.Contains <FolderRow>()))
                {
                    return(false);
                }
                var targetParent = location.ParentRow.Components.Get <BoneRow>()?.Bone;

                try {
                    var bone = row.Components.Get <BoneRow>().Bone;
                    // Check if bone target parent is bone descendant
                    if (IsDescendant(bone, targetParent))
                    {
                        return(false);
                    }
                    if (bone.BaseIndex == 0 && !location.ParentRow.Components.Contains <BoneRow>())
                    {
                        MoveFolderItemTo(bone, location);
                    }
                    else
                    {
                        SetProperty.Perform(bone, nameof(Bone.Position), Vector2.Zero);
                    }

                    SetProperty.Perform(bone, nameof(Bone.BaseIndex), targetParent?.Index ?? 0);
                    SortBonesInChain.Perform(bone);
                    var nodes      = Document.Current.Container.Nodes;
                    var parentBone = nodes.GetBone(bone.BaseIndex);
                    while (parentBone != null && !parentBone.EditorState().ChildrenExpanded)
                    {
                        SetProperty.Perform(parentBone.EditorState(), nameof(NodeEditorState.ChildrenExpanded), true);
                        bone = nodes.GetBone(bone.BaseIndex);
                    }
                } catch (InvalidOperationException e) {
                    AlertDialog.Show(e.Message);
                    return(false);
                }
                return(true);
            }
Beispiel #18
0
 private void CreateImageTypeInstance(Type type, List <string> files)
 {
     onBeforeDrop?.Invoke();
     using (Document.Current.History.BeginTransaction()) {
         var nodes = new List <Node>(files.Count);
         foreach (var file in files)
         {
             if (!Utils.ExtractAssetPathOrShowAlert(file, out var assetPath, out var assetType))
             {
                 continue;
             }
             var node = CreateNode.Perform(type);
             nodes.Add(node);
             var texture  = new SerializableTexture(assetPath);
             var nodeSize = (Vector2)texture.ImageSize;
             var nodeId   = Path.GetFileNameWithoutExtension(assetPath);
             if (node is Widget)
             {
                 SetProperty.Perform(node, nameof(Widget.Texture), texture);
                 SetProperty.Perform(node, nameof(Widget.Pivot), Vector2.Half);
                 SetProperty.Perform(node, nameof(Widget.Size), nodeSize);
                 SetProperty.Perform(node, nameof(Widget.Id), nodeId);
             }
             else if (node is ParticleModifier)
             {
                 SetProperty.Perform(node, nameof(ParticleModifier.Texture), texture);
                 SetProperty.Perform(node, nameof(ParticleModifier.Size), nodeSize);
                 SetProperty.Perform(node, nameof(ParticleModifier.Id), nodeId);
             }
             postProcessNode?.Invoke(node);
         }
         foreach (var node in nodes)
         {
             SelectNode.Perform(node);
         }
         Document.Current.History.CommitTransaction();
     }
 }
Beispiel #19
0
        public static void SetAnimatorAndInitialKeyframeIfNeed(IAnimable animable, params string[] properties)
        {
            var frame = Document.Current.AnimationFrame;

            Document.Current.AnimationFrame = 0;
            IAnimator animator;

            foreach (var propName in properties)
            {
                if (!animable.Animators.TryFind(propName, out animator, Document.Current.AnimationId))
                {
                    var propValue = animable.GetType().GetProperty(propName).GetValue(animable);
                    SetProperty.Perform(animable, propName, propValue);
                    var type = animable.GetType().GetProperty(propName).PropertyType;
                    animator = AnimatorRegistry.Instance.CreateAnimator(type);
                    animator.TargetProperty = propName;
                    animator.AnimationId    = Document.Current.AnimationId;
                    SetAnimator.Perform(animable, animator);
                    SetAnimableProperty.Perform(animable, propName, propValue);
                }
            }
            Document.Current.AnimationFrame = frame;
        }
Beispiel #20
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);
         }
     }
 }
Beispiel #21
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();
     }
 }
Beispiel #22
0
            protected override bool ProbeInternal(BoneRow node, Row row, RowLocation location)
            {
                if (!(location.ParentRow.Components.Contains <BoneRow>() || location.ParentRow.Components.Contains <FolderRow>()))
                {
                    return(false);
                }
                var targetParent = location.ParentRow.Components.Get <BoneRow>()?.Bone;

                try {
                    var bone = row.Components.Get <BoneRow>().Bone;
                    // Check if bone target parent is bone descendant
                    if (IsDescendant(bone, targetParent))
                    {
                        return(false);
                    }
                    if (bone.BaseIndex == 0 && !location.ParentRow.Components.Contains <BoneRow>())
                    {
                        MoveFolderItemTo(bone, location);
                    }
                    else if (!location.ParentRow.Components.Contains <BoneRow>())
                    {
                        SetAnimableProperty.Perform(
                            bone, nameof(Bone.Position),
                            bone.Position * bone.CalcLocalToParentWidgetTransform(),
                            CoreUserPreferences.Instance.AutoKeyframes);
                        var   boneEntry = bone.Parent.AsWidget.BoneArray[bone.Index];
                        float angle     = (boneEntry.Tip - boneEntry.Joint).Atan2Deg;
                        SetAnimableProperty.Perform(
                            bone, nameof(Bone.Rotation),
                            angle, CoreUserPreferences.Instance.AutoKeyframes);
                    }
                    else
                    {
                        SetAnimableProperty.Perform(
                            bone, nameof(Bone.Position),
                            Vector2.Zero, CoreUserPreferences.Instance.AutoKeyframes);
                        var   newParent   = location.ParentRow.Components.Get <BoneRow>().Bone;
                        var   parentEntry = newParent.Parent.AsWidget.BoneArray[newParent.Index];
                        float parentAngle = (parentEntry.Tip - parentEntry.Joint).Atan2Deg;
                        var   boneEntry   = bone.Parent.AsWidget.BoneArray[bone.Index];
                        float angle       = (boneEntry.Tip - boneEntry.Joint).Atan2Deg;
                        SetAnimableProperty.Perform(
                            bone, nameof(Bone.Rotation),
                            angle - parentAngle, CoreUserPreferences.Instance.AutoKeyframes);
                    }

                    SetProperty.Perform(bone, nameof(Bone.BaseIndex), targetParent?.Index ?? 0);
                    SortBonesInChain.Perform(bone);
                    var nodes      = Document.Current.Container.Nodes;
                    var parentBone = nodes.GetBone(bone.BaseIndex);
                    while (parentBone != null && !parentBone.EditorState().ChildrenExpanded)
                    {
                        SetProperty.Perform(parentBone.EditorState(), nameof(NodeEditorState.ChildrenExpanded), true);
                        bone = nodes.GetBone(bone.BaseIndex);
                    }
                } catch (InvalidOperationException e) {
                    AlertDialog.Show(e.Message);
                    return(false);
                }
                return(true);
            }
Beispiel #23
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();
            }
        }
Beispiel #24
0
        private static void InternalExpand(bool recursive = false)
        {
            void ExpandOrCollapseRow(Row row, object component, string property, bool expanded, int level)
            {
                if (!recursive)
                {
                    SetProperty.Perform(component, property, expanded, isChangingDocument: false);
                }
                else if (expanded)
                {
                    SetProperty.Perform(component, property, expanded, isChangingDocument: false);
                    foreach (var child in row.Rows.ToList())
                    {
                        SetExpanded(child, expanded, level);
                    }
                }
                else
                {
                    foreach (var child in row.Rows.ToList())
                    {
                        SetExpanded(child, expanded, level);
                    }
                    SetProperty.Perform(component, property, expanded, isChangingDocument: false);
                }
            }

            var processedRows = new HashSet <Row>();

            void SetExpanded(Row row, bool expanded = false, int level = 0)
            {
                if (processedRows.Contains(row))
                {
                    return;
                }

                processedRows.Add(row);
                foreach (var component in row.Components)
                {
                    switch (component)
                    {
                    case NodeRow nodeRow:
                        ExpandOrCollapseRow(row, nodeRow, nameof(NodeRow.Expanded), expanded, level + 1);
                        if (nodeRow.Expanded && row.Rows.Count > 0)
                        {
                            Timeline.Instance.EnsureRowChildsVisible(row);
                        }
                        break;

                    case BoneRow boneRow:
                        if (boneRow.HaveChildren)
                        {
                            ExpandOrCollapseRow(row, boneRow, nameof(BoneRow.ChildrenExpanded), expanded, level + 1);
                            if (boneRow.ChildrenExpanded)
                            {
                                Timeline.Instance.EnsureRowChildsVisible(row);
                            }
                        }
                        else if (row.Parent.Parent != null)
                        {
                            SetExpanded(row.Parent, expanded, level);
                            if (level == 0)
                            {
                                Core.Operations.SelectRow.Perform(row, select: false);
                                Core.Operations.SelectRow.Perform(row.Parent, select: true);
                            }
                        }
                        return;

                    case FolderRow folderRow:
                        var folder = folderRow.Folder;
                        if (folder.Items.Count > 0)
                        {
                            ExpandOrCollapseRow(row, folder, nameof(Folder.Expanded), expanded, level + 1);
                            if (folder.Expanded)
                            {
                                Timeline.Instance.EnsureRowChildsVisible(row);
                            }
                        }
                        return;

                    case PropertyRow propertyRow:
                        SetExpanded(row.Parent, expanded, level);
                        if (level == 0)
                        {
                            Core.Operations.SelectRow.Perform(row, select: false);
                            Core.Operations.SelectRow.Perform(row.Parent, select: true);
                        }
                        return;
                    }
                }
            }

            var topMostRows = new HashSet <Row>(Document.Current.SelectedRows());

            foreach (var row in Document.Current.SelectedRows())
            {
                for (var p = row.Parent; p != null; p = p.Parent)
                {
                    if (topMostRows.Contains(p))
                    {
                        topMostRows.Remove(row);
                        break;
                    }
                }
            }

            ClearRowSelection.Perform();
            foreach (var row in topMostRows)
            {
                Core.Operations.SelectRow.Perform(row);
                SetExpanded(row, expanded: !IsRowExpanded(row));
            }
        }
        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();
            }
        }
Beispiel #26
0
        IEnumerator <object> CreateSplinePoint3DTask()
        {
            command.Checked = true;
            while (true)
            {
                if (sv.InputArea.IsMouseOver())
                {
                    Utils.ChangeCursorIfDefault(MouseCursor.Hand);
                }
                CreateNodeRequestComponent.Consume <Node>(sv.Components);
                if (input.ConsumeKeyPress(Key.Mouse0))
                {
                    using (history.BeginTransaction()) {
                        SplinePoint3D point;
                        try {
                            point = (SplinePoint3D)CreateNode.Perform(typeof(SplinePoint3D), aboveSelected: false);
                        }
                        catch (InvalidOperationException e) {
                            AlertDialog.Show(e.Message);
                            yield break;
                        }
                        var spline  = (Spline3D)Document.Current.Container;
                        var vp      = spline.Viewport;
                        var ray     = vp.ScreenPointToRay(input.MousePosition);
                        var xyPlane = new Plane(new Vector3(0, 0, 1), 0).Transform(spline.GlobalTransform);
                        var d       = ray.Intersects(xyPlane);
                        if (d.HasValue)
                        {
                            var pos = (ray.Position + ray.Direction * d.Value) * spline.GlobalTransform.CalcInverted();
                            SetProperty.Perform(point, nameof(SplinePoint3D.Position), pos);
                            using (history.BeginTransaction()) {
                                while (input.IsMousePressed())
                                {
                                    history.RollbackTransaction();
                                    ray = vp.ScreenPointToRay(input.MousePosition);
                                    d   = ray.Intersects(xyPlane);
                                    if (d.HasValue)
                                    {
                                        var tangent = (ray.Position + ray.Direction * d.Value) *
                                                      spline.GlobalTransform.CalcInverted() - point.Position;
                                        SetProperty.Perform(point, nameof(SplinePoint3D.TangentA), tangent);
                                        SetProperty.Perform(point, nameof(SplinePoint3D.TangentB), -tangent);
                                    }
                                    history.CommitTransaction();
                                    yield return(null);
                                }

                                if (point.TangentA.Length < 0.01f)
                                {
                                    SetProperty.Perform(point, nameof(SplinePoint3D.TangentA), new Vector3(1, 0, 0));
                                    SetProperty.Perform(point, nameof(SplinePoint3D.TangentB), new Vector3(-1, 0, 0));
                                }
                            }
                        }
                        history.CommitTransaction();
                    }
                    history.CommitTransaction();
                }
                if (input.WasMousePressed(1) || input.WasKeyPressed(Key.Escape))
                {
                    break;
                }
                yield return(null);
            }

            command.Checked = false;
            Utils.ChangeCursorIfDefault(MouseCursor.Default);
        }