diff --git a/src/DynamoCoreWpf/ViewModels/Watch3D/HelixWatch3DViewModel.cs b/src/DynamoCoreWpf/ViewModels/Watch3D/HelixWatch3DViewModel.cs index 830c1293214..394af4a1b30 100644 --- a/src/DynamoCoreWpf/ViewModels/Watch3D/HelixWatch3DViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Watch3D/HelixWatch3DViewModel.cs @@ -122,6 +122,8 @@ public class HelixWatch3DViewModel : DefaultWatch3DViewModel internal const double DefaultFarClipDistance = 100000; internal static BoundingBox DefaultBounds = new BoundingBox(new Vector3(-25f, -25f, -25f), new Vector3(25f,25f,25f)); + private List sceneItems; + #if DEBUG private readonly Stopwatch renderTimer = new Stopwatch(); #endif @@ -132,6 +134,9 @@ public class HelixWatch3DViewModel : DefaultWatch3DViewModel public Object Model3DDictionaryMutex = new object(); private Dictionary model3DDictionary = new Dictionary(); + // Dictionary>> + private readonly Dictionary>> labelPlaces + = new Dictionary>>(); public event Action RequestViewRefresh; protected void OnRequestViewRefresh() @@ -345,18 +350,33 @@ public RoutedCommand LeftClickCommand public bool IsResizable { get; protected set; } + private void UpdateSceneItems() + { + if (Model3DDictionary == null) + { + sceneItems = new List(); + return; + } + + var values = Model3DDictionary.Values.ToList(); + if (Camera != null) + { + values.Sort(new Model3DComparer(Camera.Position)); + } + + sceneItems = values; + } + public IEnumerable SceneItems { get { - if (Model3DDictionary == null) + if (sceneItems == null) { - return new List(); + UpdateSceneItems(); } - var values = Model3DDictionary.Values.ToList(); - values.Sort(new Model3DComparer(Camera.Position)); - return values; + return sceneItems; } } @@ -524,6 +544,8 @@ protected override void OnClear() model.Detach(); Model3DDictionary.Remove(key); } + + labelPlaces.Clear(); } OnSceneItemsChanged(); @@ -690,14 +712,16 @@ private void DeleteGeometries(KeyValuePair[] geometryModels, bo // check if the geometry is frozen. if the gemoetry is frozen // then do not detach from UI. var frozenModel = AttachedProperties.GetIsFrozen(model3D); - if (!frozenModel) + if (frozenModel) continue; + + if (model3D != null) { - if (model3D != null) - { - model3D.Detach(); - } - Model3DDictionary.Remove(kvp.Key); + model3D.Detach(); } + + Model3DDictionary.Remove(kvp.Key); + var nodePath = kvp.Key.Split(':')[0]; + labelPlaces.Remove(nodePath); } } @@ -858,6 +882,7 @@ internal void ComputeFrameUpdate() private void OnSceneItemsChanged() { + UpdateSceneItems(); RaisePropertyChanged("SceneItems"); OnRequestViewRefresh(); } @@ -868,11 +893,8 @@ private KeyValuePair[] FindAllGeometryModel3DsForNode(NodeModel lock (Model3DDictionaryMutex) { - geometryModels = - Model3DDictionary - .Where(x => x.Key.Contains(node.AstIdentifierGuid)) - .Where(x => x.Value is GeometryModel3D) - .Select(x => x).ToArray(); + geometryModels = Model3DDictionary + .Where(x => x.Key.Contains(node.AstIdentifierGuid) && x.Value is GeometryModel3D).ToArray(); } return geometryModels; @@ -884,11 +906,8 @@ private KeyValuePair[] FindAllGeometryModel3DsForNode(string id lock (Model3DDictionaryMutex) { - geometryModels = - Model3DDictionary - .Where(x => x.Key.Contains(identifier)) - .Where(x => x.Value is GeometryModel3D) - .Select(x => x).ToArray(); + geometryModels = Model3DDictionary + .Where(x => x.Key.Contains(identifier) && x.Value is GeometryModel3D).ToArray(); } return geometryModels; @@ -1084,6 +1103,8 @@ private void InitializeHelix() { Model3DDictionary.Add(DefaultAxesName, axesModel3D); } + + UpdateSceneItems(); } /// @@ -1252,12 +1273,12 @@ public override void AddLabelForPath(string path) // it may be requested an array of items to put labels // for example, the first item in 2-dim array - path will look like var_guid:0 - // and it will select var_guid:0:0, var_guid:0:1, var_guid:0:2 and so on - var nodeLabelKeys = Model3DDictionary.Keys - .Where(k => k.StartsWith(path + ':') && Model3DDictionary[k] is GeometryModel3D).ToList(); - - // if there is a geometry to add label - if (nodeLabelKeys.Any()) + // and it will select var_guid:0:0, var_guid:0:1, var_guid:0:2 and so on. + // if there is a geometry to add label(s) + List> requestedLabelPlaces; + if (labelPlaces.ContainsKey(nodePath) && + (requestedLabelPlaces = labelPlaces[nodePath] + .Where(pair => pair.Item1.StartsWith(path)).ToList()).Any()) { // second, add requested labels var textGeometry = HelixRenderPackage.InitText3D(); @@ -1266,17 +1287,15 @@ public override void AddLabelForPath(string path) Geometry = textGeometry }; - foreach (var key in nodeLabelKeys) + foreach (var id_position in requestedLabelPlaces) { - var geom = (GeometryModel3D)Model3DDictionary[key]; - var id = key.Remove(key.LastIndexOf(':')); - var text = HelixRenderPackage.CleanTag(id.Remove(0, nodePath.Length)); - var textPosition = geom.Geometry.Positions[0] + defaultLabelOffset; + var text = HelixRenderPackage.CleanTag(id_position.Item1); + var textPosition = id_position.Item2 + defaultLabelOffset; var textInfo = new TextInfo(text, textPosition); textGeometry.TextInfo.Add(textInfo); } - Model3DDictionary.Add(nodePath + TextKey, bbText); + Model3DDictionary.Add(labelName, bbText); sceneItemsChanged = true; AttachAllGeometryModel3DToRenderHost(); } @@ -1336,7 +1355,7 @@ private void AggregateRenderPackages(IEnumerable packages) var p = rp.Points; if (p.Positions.Any()) { - id = rp.Description + PointsKey; + id = baseId + PointsKey; PointGeometryModel3D pointGeometry3D; @@ -1366,13 +1385,8 @@ private void AggregateRenderPackages(IEnumerable packages) : Enumerable.Repeat(defaultPointColor, points.Positions.Count)); points.Indices.AddRange(p.Indices.Select(i => i + startIdx)); } - - - if (rp.DisplayLabels) - { - CreateOrUpdateText(baseId, p.Positions[0], rp); - } + AddLabelPlace(baseId, p.Positions[0], rp); pointGeometry3D.Geometry = points; pointGeometry3D.Name = baseId; } @@ -1380,7 +1394,7 @@ private void AggregateRenderPackages(IEnumerable packages) var l = rp.Lines; if (l.Positions.Any()) { - id = rp.Description + LinesKey; + id = baseId + LinesKey; LineGeometryModel3D lineGeometry3D; @@ -1415,12 +1429,7 @@ private void AggregateRenderPackages(IEnumerable packages) ? l.Indices.Select(i => i + startIdx) : Enumerable.Range(startIdx, startIdx + l.Positions.Count)); - if (rp.DisplayLabels) - { - var pt = lineSet.Positions[startIdx]; - CreateOrUpdateText(baseId, pt, rp); - } - + AddLabelPlace(baseId, lineSet.Positions[startIdx], rp); lineGeometry3D.Geometry = lineSet; lineGeometry3D.Name = baseId; } @@ -1471,12 +1480,7 @@ private void AggregateRenderPackages(IEnumerable packages) meshGeometry3D.SetValue(AttachedProperties.HasTransparencyProperty, true); } - if (rp.DisplayLabels) - { - var pt = mesh.Positions[idxCount]; - CreateOrUpdateText(baseId, pt, rp); - } - + AddLabelPlace(baseId, mesh.Positions[idxCount], rp); meshGeometry3D.Geometry = mesh; meshGeometry3D.Name = baseId; } @@ -1485,6 +1489,20 @@ private void AggregateRenderPackages(IEnumerable packages) } } + private void AddLabelPlace(string nodeId, Vector3 pos, IRenderPackage rp) + { + if (!labelPlaces.ContainsKey(nodeId)) + { + labelPlaces[nodeId] = new List>(); + } + + labelPlaces[nodeId].Add(new Tuple(rp.Description, pos)); + if (rp.DisplayLabels) + { + CreateOrUpdateText(nodeId, pos, rp); + } + } + /// /// Updates or replaces the GeometryModel3D for special IRenderPackage. Special /// IRenderPackage has a Description field that starts with a string value defined diff --git a/src/VisualizationTests/HelixWatch3DViewModelTests.cs b/src/VisualizationTests/HelixWatch3DViewModelTests.cs index 76b62e0c223..d0801d1401d 100644 --- a/src/VisualizationTests/HelixWatch3DViewModelTests.cs +++ b/src/VisualizationTests/HelixWatch3DViewModelTests.cs @@ -149,14 +149,14 @@ public void Node_RenderingUpToDate() p1.UpdateValue(new UpdateValueParams("IsVisible", "false")); Assert.True(BackgroundPreviewGeometry.HasNumberOfPointsCurvesAndMeshes(7, 6, 0)); - Assert.AreEqual(6, BackgroundPreviewGeometry.NumberOfInvisiblePoints()); + Assert.AreEqual(1, BackgroundPreviewGeometry.NumberOfInvisiblePoints()); //flip off the lines node var l1 = model.CurrentWorkspace.Nodes.First(x => x.GUID.ToString() == "7c1cecee-43ed-43b5-a4bb-5f71c50341b2"); l1.UpdateValue(new UpdateValueParams("IsVisible", "false")); Assert.True(BackgroundPreviewGeometry.HasNumberOfPointsCurvesAndMeshes(7, 6, 0)); - Assert.AreEqual(6, BackgroundPreviewGeometry.NumberOfInvisibleCurves()); + Assert.AreEqual(1, BackgroundPreviewGeometry.NumberOfInvisibleCurves()); //flip those back on and ensure the visualization returns p1.UpdateValue(new UpdateValueParams("IsVisible", "true")); @@ -322,7 +322,7 @@ public void Node_VisibilityOff_CachedValueUpdated_VisibilityOn_RenderDataCorrect p1.UpdateValue(new UpdateValueParams("IsVisible", "false")); Assert.True(BackgroundPreviewGeometry.HasNumberOfPointsCurvesAndMeshes(7, 6, 0)); - Assert.AreEqual(6, BackgroundPreviewGeometry.NumberOfInvisiblePoints()); + Assert.AreEqual(1, BackgroundPreviewGeometry.NumberOfInvisiblePoints()); // Now change the number of points var cbn =