diff --git a/src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs index 209a89ea37b..a44d5554975 100644 --- a/src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Core/WorkspaceViewModel.cs @@ -482,8 +482,8 @@ public double Zoom /// /// When enabled, some child wpf framework elements will not animate opacity changes. /// Useful for improving performance during zoom. - /// TODO DYN-8193 a future optimiztion if found to be neccesary is to modify the styles this flag controls - /// to set visibility instead of opacity, this will likely lead to many fewers elements in the visual tree to + /// TODO DYN-8193 a future optimization if found to be necessary is to modify the styles this flag controls + /// to set visibility instead of opacity, this will likely lead to many fewer elements in the visual tree to /// layout and render. /// [JsonIgnore] diff --git a/src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml.cs b/src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml.cs index a64660908c0..37b6464498a 100644 --- a/src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml.cs +++ b/src/DynamoCoreWpf/Views/Core/WorkspaceView.xaml.cs @@ -11,6 +11,7 @@ using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; +using System.Windows.Threading; using Dynamo.Controls; using Dynamo.Graph; using Dynamo.Graph.Annotations; @@ -149,6 +150,8 @@ private void RemoveViewModelsubscriptions(WorkspaceViewModel ViewModel) ViewModel.Model.CurrentOffsetChanged -= vm_CurrentOffsetChanged; DynamoSelection.Instance.Selection.CollectionChanged -= OnSelectionCollectionChanged; infiniteGridView.DetachFromZoomBorder(zoomBorder); + + currentRenderScale = -1; } /// @@ -640,9 +643,82 @@ void vm_CurrentOffsetChanged(object sender, EventArgs e) void vm_ZoomChanged(object sender, EventArgs e) { - zoomBorder.SetZoom((e as ZoomEventArgs).Zoom); - if (PortContextMenu.IsOpen) DestroyPortContextMenu(); + var newZoomScale = (e as ZoomEventArgs).Zoom; + zoomBorder.SetZoom(newZoomScale); + if (PortContextMenu.IsOpen) + { + DestroyPortContextMenu(); + } + + CheckZoomScaleAndApplyNodeViewCache(newZoomScale); + } + + #region NodeView_BitmapCache + private double currentRenderScale = -1; + const double maxZoomScaleForCache = .8; + + private void CheckZoomScaleAndApplyNodeViewCache(double newZoomScale) + { + if (!ViewModel.StopNodeViewOpacityAnimations) + { + if (currentRenderScale > 0) // number of nodes reduced below max threshold + { + Dispatcher.BeginInvoke(ClearNodeViewCache, DispatcherPriority.Normal); + } + + return; + } + + if (newZoomScale > maxZoomScaleForCache) + { + if (currentRenderScale > 0) + { + Dispatcher.BeginInvoke(ClearNodeViewCache, DispatcherPriority.Normal); + } + + return; + } + + var newRenderScale = newZoomScale <= .2 ? .2 : newZoomScale <= .5 ? .5 : 1; + + if (Math.Abs(newRenderScale - currentRenderScale) <= 0.01) + { + return; + } + + currentRenderScale = newRenderScale; + Dispatcher.BeginInvoke(UpdateNodeViewCacheScale, DispatcherPriority.Normal); + } + + private void ClearNodeViewCache() + { + var nodes = this.ChildrenOfType(); + foreach (var node in nodes) + { + node.CacheMode = null; + } + + currentRenderScale = -1; + } + + private void UpdateNodeViewCacheScale() + { + var nodes = this.ChildrenOfType(); + foreach (var node in nodes) + { + var cache = node.CacheMode as BitmapCache; + if (cache == null) + { + cache = new BitmapCache(currentRenderScale); + node.CacheMode = cache; + } + else + { + cache.RenderAtScale = currentRenderScale; + } + } } + #endregion void vm_ZoomAtViewportCenter(object sender, EventArgs e) {