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(); }
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())); }
private void FilesDropOnNodeCreated(Node node) { if (node is Widget) { SetProperty.Perform(node, nameof(Widget.Position), mousePositionOnFilesDrop); } }
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(); } }
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())); }
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(); } }
private static void FilesDropNodePostProcessor(Node node) { if (node is Widget) { SetProperty.Perform(node, nameof(Widget.Position), Instance.mousePositionOnFilesDrop); } }
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(); } }
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); } } }
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); }
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); } } } }
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); } } } }
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); } } } }
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); } }
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); }
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(); } }
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; }
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); } } }
/// <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(); } }
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); }
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(); } }
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(); } }
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); }