public IEnumerator <object> Task() { var g = Timeline.Instance.Globals; while (true) { var rq = g.Get <DragKeyframesRequest>(); if (rq != null) { Document.Current.History.DoTransaction(() => { Operations.DragKeyframes.Perform(rq.Offset, rq.RemoveOriginals); Operations.ShiftGridSelection.Perform(rq.Offset); if (rq.Offset.Y != 0) { var selected = Document.Current.SelectedRows().Where(r => r.Selected).Select(r => r.Index).ToDictionary(x => x); ClearRowSelection.Perform(); foreach (var row in Document.Current.Rows) { if (selected.ContainsKey(row.Index - rq.Offset.Y)) { SelectRow.Perform(row, select: true); } } } g.Remove <DragKeyframesRequest>(); }); } yield return(null); } }
public override void ExecuteTransaction() { var groups = Document.Current?.SelectedNodes().OfType <Frame>().ToList(); if (groups?.Count == 0) { return; } var container = (Widget)Document.Current.Container; var p = container.RootFolder().Find(groups[0]); ClearRowSelection.Perform(); UntieWidgetsFromBones.Perform(Document.Current.Container.Nodes.OfType <Bone>(), groups); foreach (var group in groups) { UnlinkFolderItem.Perform(container, group); } foreach (var group in groups) { var flipXFactor = group.Scale.X < 0 ? -1 : 1; var flipYFactor = group.Scale.Y < 0 ? -1 : 1; var flipVector = Vector2.Right + Vector2.Down * flipXFactor * flipYFactor; var groupRootBones = new List <Bone>(); var groupNodes = group.Nodes.ToList().Where(GroupNodes.IsValidNode).ToList(); var localToParentTransform = group.CalcLocalToParentTransform(); foreach (var node in groupNodes) { UnlinkFolderItem.Perform(group, node); InsertFolderItem.Perform(container, p, node); SelectNode.Perform(node); p.Index++; if (node is Widget) { GroupNodes.TransformPropertyAndKeyframes <Vector2>(node, nameof(Widget.Position), v => localToParentTransform * v); GroupNodes.TransformPropertyAndKeyframes <Vector2>(node, nameof(Widget.Scale), v => v * group.Scale); GroupNodes.TransformPropertyAndKeyframes <float>(node, nameof(Widget.Rotation), v => v * Mathf.Sign(group.Scale.X * group.Scale.Y) + group.Rotation); GroupNodes.TransformPropertyAndKeyframes <Color4>(node, nameof(Widget.Color), v => group.Color * v); } else if (node is Bone) { var root = BoneUtils.FindBoneRoot((Bone)node, groupNodes); if (!groupRootBones.Contains(root)) { GroupNodes.TransformPropertyAndKeyframes <Vector2>(node, nameof(Bone.Position), v => localToParentTransform * v); GroupNodes.TransformPropertyAndKeyframes <float>(node, nameof(Bone.Rotation), v => (Matrix32.Rotation(v * Mathf.DegToRad) * localToParentTransform).ToTransform2().Rotation); groupRootBones.Add(root); } else if (flipVector != Vector2.One) { GroupNodes.TransformPropertyAndKeyframes <Vector2>(node, nameof(Bone.Position), v => v * flipVector); GroupNodes.TransformPropertyAndKeyframes <float>(node, nameof(Bone.Rotation), v => - v); } GroupNodes.TransformPropertyAndKeyframes <Vector2>(node, nameof(Bone.RefPosition), v => localToParentTransform * v); GroupNodes.TransformPropertyAndKeyframes <float>(node, nameof(Bone.RefRotation), v => (Matrix32.Rotation(v * Mathf.DegToRad) * localToParentTransform).ToTransform2().Rotation); } } } }
public override void ExecuteTransaction() { var selectedNodes = Document.Current.SelectedNodes().Where(IsValidNode).ToList(); if (!Utils.CalcHullAndPivot(selectedNodes, out var hull, out _)) { return; } hull = hull.Transform(Document.Current.Container.AsWidget.LocalToWorldTransform.CalcInversed()); var aabb = hull.ToAABB(); var container = Document.Current.Container; foreach (var row in Document.Current.SelectedRows()) { if (row.Components.Contains <BoneRow>()) { var boneRow = row.Components.Get <BoneRow>(); if (!boneRow.ChildrenExpanded) { selectedNodes.AddRange(BoneUtils.FindBoneDescendats(boneRow.Bone, container.Nodes.OfType <Bone>())); } } } var selectedBones = selectedNodes.OfType <Bone>().ToList(); var loc = container.RootFolder().Find(selectedNodes[0]); Frame group; try { group = (Frame)Core.Operations.CreateNode.Perform(container, loc, typeof(Frame)); } catch (InvalidOperationException e) { AlertDialog.Show(e.Message); return; } group.Id = selectedNodes[0].Id + "Group"; group.Pivot = Vector2.Half; group.Position = aabb.Center; group.Size = aabb.Size; var bonesExceptSelected = container.Nodes.Except(selectedNodes).OfType <Bone>().ToList(); UntieWidgetsFromBones.Perform(bonesExceptSelected, selectedNodes.OfType <Widget>()); UntieWidgetsFromBones.Perform(selectedBones, container.Nodes.Except(selectedNodes).OfType <Widget>()); var nodeKeyframesDict = new Dictionary <Node, BoneAnimationData>(); var localRoots = new List <Bone>(); foreach (var bone in BoneUtils.SortBones(container.Nodes.OfType <Bone>())) { Bone localRoot; var delta = Vector2.Zero; var isSelectedBone = selectedBones.Contains(bone); if (isSelectedBone) { localRoot = BoneUtils.FindBoneRoot(bone, selectedNodes); delta = -aabb.A; } else { localRoot = BoneUtils.FindBoneRoot(bone, bonesExceptSelected); } if (!localRoots.Contains(localRoot)) { if (!isSelectedBone && localRoot.BaseIndex == 0) { localRoots.Add(localRoot); continue; } nodeKeyframesDict.Add(localRoot, EvaluateBoneAnimationUsingParent(localRoot, v => v + delta)); localRoots.Add(localRoot); } } SetKeyframes(nodeKeyframesDict); foreach (var n in selectedNodes) { UnlinkFolderItem.Perform(container, n); } int i = 0; foreach (var node in selectedNodes) { InsertFolderItem.Perform(group, new FolderItemLocation(group.RootFolder(), i++), node); if (node is Widget) { TransformPropertyAndKeyframes <Vector2>(node, nameof(Widget.Position), v => v - aabb.A); } if (node is Bone) { TransformPropertyAndKeyframes <Vector2>(node, nameof(Bone.RefPosition), v => v - aabb.A); } } group.DefaultAnimation.Frame = container.DefaultAnimation.Frame; ClearRowSelection.Perform(); SelectNode.Perform(group); }
public IEnumerator <object> Task() { Probers.Add(new BoneRowProber()); Probers.Add(new FolderRowProber()); Probers.Add(new NodeRowProber()); Probers.Add(new AnimationTrackRowProber()); var roll = Timeline.Instance.Roll; var input = roll.RootWidget.Input; var cg = new ClickGesture(0, () => { var row = RowUnderMouse(input.MousePosition); if (row == null) { return; } if (input.IsKeyPressed(Key.Shift)) { if (Document.Current.SelectedRows().Any()) { var firstRow = Document.Current.SelectedRows().FirstOrDefault(); Document.Current.History.DoTransaction(() => { ClearRowSelection.Perform(); SelectRowRange.Perform(firstRow, row); }); } else { Document.Current.History.DoTransaction(() => { ClearRowSelection.Perform(); SelectRow.Perform(row); }); } } else if (input.IsKeyPressed(Key.Control)) { Document.Current.History.DoTransaction(() => { SelectRow.Perform(row, !row.Selected); }); } else { Document.Current.History.DoTransaction(() => { ClearRowSelection.Perform(); SelectRow.Perform(row); }); input.ConsumeKey(Key.Mouse0); } }); var dg = new DragGesture(0); dg.Recognized += () => { var row = RowUnderMouse(dg.MousePressPosition); // Have to turn off PreviewAnimation manually in order // to provide the same behaviour whether widget is selected or not // (PreviewAnimation is turned off when performing operation) if (Document.Current.PreviewAnimation) { Document.Current.TogglePreviewAnimation(); } if (!row?.Selected ?? false) { Document.Current.History.DoTransaction(() => { ClearRowSelection.Perform(); SelectRow.Perform(row); }); } roll.OnRenderOverlay += OnRollRenderOverlay; dragLocation = new RowLocation(Document.Current.RowTree, 0); }; dg.Changed += () => { dragLocation = MouseToRowLocation(input.MousePosition); CommonWindow.Current.Invalidate(); }; dg.Ended += () => { if (!dg.IsRecognizing()) { roll.OnRenderOverlay -= OnRollRenderOverlay; CommonWindow.Current.Invalidate(); if (dragLocation != null) { DragRows(dragLocation.Value); } } }; roll.RootWidget.Gestures.Add(dg); roll.RootWidget.Gestures.Add(cg); yield break; }
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 IEnumerator <object> Task() { var roll = Timeline.Instance.Roll; var input = roll.RootWidget.Input; input.AcceptMouseThroughDescendants = true; while (true) { yield return(null); if (!input.WasMousePressed() || input.WasKeyPressed(Key.Mouse0DoubleClick)) { continue; } var initialMousePosition = input.MousePosition; var row = RowUnderMouse(initialMousePosition); if (row == null) { continue; } if (input.IsKeyPressed(Key.Shift)) { if (Document.Current.SelectedRows().Any()) { var firstRow = Document.Current.SelectedRows().FirstOrDefault(); Document.Current.History.DoTransaction(() => { ClearRowSelection.Perform(); SelectRowRange.Perform(firstRow, row); }); } else { Document.Current.History.DoTransaction(() => { ClearRowSelection.Perform(); SelectRow.Perform(row); }); } } else if (input.IsKeyPressed(Key.Control)) { Document.Current.History.DoTransaction(() => { SelectRow.Perform(row, !row.Selected); }); } else { if (!row.Selected) { Document.Current.History.DoTransaction(() => { ClearRowSelection.Perform(); SelectRow.Perform(row); }); } while ( input.IsMousePressed() && Math.Abs(initialMousePosition.Y - input.MousePosition.Y) < TimelineMetrics.DefaultRowHeight / 4 ) { yield return(null); } if (input.IsMousePressed()) { yield return(DragTask()); } else { Document.Current.History.DoTransaction(() => { ClearRowSelection.Perform(); SelectRow.Perform(row); }); } } } }