From 792f430f2f41fbbaf22027486485a9e5af8afa75 Mon Sep 17 00:00:00 2001 From: Nice3point Date: Sat, 25 May 2024 00:54:57 +0300 Subject: [PATCH] XYZ visualization --- .../Core/ComponentModel/DescriptorMap.cs | 1 + .../Descriptors/FaceDescriptor.cs | 2 +- .../Descriptors/MeshDescriptor.cs | 4 +- .../Descriptors/XyzDescriptor.cs | 65 +++++ .../FaceVisualizationServer.cs | 7 +- .../MeshVisualizationServer.cs | 12 +- .../Render3dUtils.cs | 78 +++++- .../Visualization/XyzVisualizationServer.cs | 260 ++++++++++++++++++ .../FaceVisualizationViewModel.cs | 4 +- .../MeshVisualizationViewModel.cs | 4 +- .../XyzVisualizationViewModel.cs | 84 ++++++ .../FaceVisualizationDialog.xaml | 6 +- .../FaceVisualizationDialog.xaml.cs | 6 +- .../MeshVisualizationDialog.xaml | 6 +- .../MeshVisualizationDialog.xaml.cs | 6 +- .../Visualization/XyzVisualizationDialog.xaml | 86 ++++++ .../XyzVisualizationDialog.xaml.cs | 65 +++++ 17 files changed, 659 insertions(+), 37 deletions(-) create mode 100644 source/RevitLookup/Core/ComponentModel/Descriptors/XyzDescriptor.cs rename source/RevitLookup/Core/{Render => Visualization}/FaceVisualizationServer.cs (98%) rename source/RevitLookup/Core/{Render => Visualization}/MeshVisualizationServer.cs (97%) rename source/RevitLookup/Core/{Render => Visualization}/Render3dUtils.cs (77%) create mode 100644 source/RevitLookup/Core/Visualization/XyzVisualizationServer.cs rename source/RevitLookup/ViewModels/Dialogs/{Render => Visualization}/FaceVisualizationViewModel.cs (97%) rename source/RevitLookup/ViewModels/Dialogs/{Render => Visualization}/MeshVisualizationViewModel.cs (97%) create mode 100644 source/RevitLookup/ViewModels/Dialogs/Visualization/XyzVisualizationViewModel.cs rename source/RevitLookup/Views/Dialogs/{Render => Visualization}/FaceVisualizationDialog.xaml (94%) rename source/RevitLookup/Views/Dialogs/{Render => Visualization}/FaceVisualizationDialog.xaml.cs (94%) rename source/RevitLookup/Views/Dialogs/{Render => Visualization}/MeshVisualizationDialog.xaml (94%) rename source/RevitLookup/Views/Dialogs/{Render => Visualization}/MeshVisualizationDialog.xaml.cs (91%) create mode 100644 source/RevitLookup/Views/Dialogs/Visualization/XyzVisualizationDialog.xaml create mode 100644 source/RevitLookup/Views/Dialogs/Visualization/XyzVisualizationDialog.xaml.cs diff --git a/source/RevitLookup/Core/ComponentModel/DescriptorMap.cs b/source/RevitLookup/Core/ComponentModel/DescriptorMap.cs index dc778edf..fabe663c 100644 --- a/source/RevitLookup/Core/ComponentModel/DescriptorMap.cs +++ b/source/RevitLookup/Core/ComponentModel/DescriptorMap.cs @@ -65,6 +65,7 @@ public static Descriptor FindDescriptor(object obj, Type type) ElementId value when type is null || type == typeof(ElementId) => new ElementIdDescriptor(value), GuidEnum value when type is null || type == typeof(GuidEnum) => new GuidEnumDescriptor(value), Definition value when type is null || type == typeof(Definition) => new DefinitionDescriptor(value), + XYZ value when type is null || type == typeof(XYZ) => new XyzDescriptor(value), //Enumerator DefinitionBindingMapIterator value => new DefinitionBindingMapIteratorDescriptor(value), diff --git a/source/RevitLookup/Core/ComponentModel/Descriptors/FaceDescriptor.cs b/source/RevitLookup/Core/ComponentModel/Descriptors/FaceDescriptor.cs index 8213e0fd..303ffde8 100644 --- a/source/RevitLookup/Core/ComponentModel/Descriptors/FaceDescriptor.cs +++ b/source/RevitLookup/Core/ComponentModel/Descriptors/FaceDescriptor.cs @@ -26,7 +26,7 @@ using RevitLookup.Core.Contracts; using RevitLookup.Core.Objects; using RevitLookup.ViewModels.Contracts; -using RevitLookup.Views.Dialogs.Render; +using RevitLookup.Views.Dialogs.Visualization; namespace RevitLookup.Core.ComponentModel.Descriptors; diff --git a/source/RevitLookup/Core/ComponentModel/Descriptors/MeshDescriptor.cs b/source/RevitLookup/Core/ComponentModel/Descriptors/MeshDescriptor.cs index 77543ef9..990bcd9b 100644 --- a/source/RevitLookup/Core/ComponentModel/Descriptors/MeshDescriptor.cs +++ b/source/RevitLookup/Core/ComponentModel/Descriptors/MeshDescriptor.cs @@ -24,7 +24,7 @@ using RevitLookup.Core.Contracts; using RevitLookup.Core.Objects; using RevitLookup.ViewModels.Contracts; -using RevitLookup.Views.Dialogs.Render; +using RevitLookup.Views.Dialogs.Visualization; using RevitLookup.Views.Extensions; namespace RevitLookup.Core.ComponentModel.Descriptors; @@ -48,7 +48,7 @@ public void RegisterMenu(ContextMenu contextMenu) } catch (Exception exception) { - var logger = context.ServiceProvider.GetService>(); + var logger = context.ServiceProvider.GetService>(); logger.LogError(exception, "VisualizationDialog error"); } }) diff --git a/source/RevitLookup/Core/ComponentModel/Descriptors/XyzDescriptor.cs b/source/RevitLookup/Core/ComponentModel/Descriptors/XyzDescriptor.cs new file mode 100644 index 00000000..d61a12d8 --- /dev/null +++ b/source/RevitLookup/Core/ComponentModel/Descriptors/XyzDescriptor.cs @@ -0,0 +1,65 @@ +// Copyright 2003-2024 by Autodesk, Inc. +// +// Permission to use, copy, modify, and distribute this software in +// object code form for any purpose and without fee is hereby granted, +// provided that the above copyright notice appears in all copies and +// that both that copyright notice and the limited warranty and +// restricted rights notice below appear in all supporting +// documentation. +// +// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. +// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF +// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. +// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE +// UNINTERRUPTED OR ERROR FREE. +// +// Use, duplication, or disclosure by the U.S. Government is subject to +// restrictions set forth in FAR 52.227-19 (Commercial Computer +// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) +// (Rights in Technical Data and Computer Software), as applicable. + +using System.Windows.Controls; +using System.Windows.Input; +using Microsoft.Extensions.Logging; +using RevitLookup.Core.Contracts; +using RevitLookup.Core.Objects; +using RevitLookup.ViewModels.Contracts; +using RevitLookup.Views.Dialogs.Visualization; +using RevitLookup.Views.Extensions; + +namespace RevitLookup.Core.ComponentModel.Descriptors; + +public class XyzDescriptor : Descriptor, IDescriptorConnector +{ + private readonly XYZ _point; + + public XyzDescriptor(XYZ point) + { + _point = point; + Name = point.ToString(); + } + + public void RegisterMenu(ContextMenu contextMenu) + { + contextMenu.AddMenuItem("VisualizeMenuItem") + .SetAvailability(!_point.IsUnitLength()) + .SetCommand(_point, async point => + { + if (Context.UiDocument is null) return; + + var context = (ISnoopViewModel) contextMenu.DataContext; + + try + { + var dialog = new XyzVisualizationDialog(context.ServiceProvider, point); + await dialog.ShowAsync(); + } + catch (Exception exception) + { + var logger = context.ServiceProvider.GetService>(); + logger.LogError(exception, "VisualizationDialog error"); + } + }) + .SetShortcut(Key.F8); + } +} \ No newline at end of file diff --git a/source/RevitLookup/Core/Render/FaceVisualizationServer.cs b/source/RevitLookup/Core/Visualization/FaceVisualizationServer.cs similarity index 98% rename from source/RevitLookup/Core/Render/FaceVisualizationServer.cs rename to source/RevitLookup/Core/Visualization/FaceVisualizationServer.cs index b1714b73..d094de44 100644 --- a/source/RevitLookup/Core/Render/FaceVisualizationServer.cs +++ b/source/RevitLookup/Core/Visualization/FaceVisualizationServer.cs @@ -23,10 +23,12 @@ using Microsoft.Extensions.Logging; using RevitLookup.Models.Render; -namespace RevitLookup.Core.Render; +namespace RevitLookup.Core.Visualization; public sealed class FaceVisualizationServer(Face face, ILogger logger) : IDirectContext3DServer { + private const double NormalLength = 1d; + private bool _hasGeometryUpdates = true; private bool _hasEffectsUpdates = true; @@ -133,7 +135,7 @@ private void MapGeometryBuffer() Render3dUtils.MapSurfaceBuffer(_surfaceBuffer, mesh, _thickness); Render3dUtils.MapMeshGridBuffer(_meshGridBuffer, mesh, _thickness); - Render3dUtils.MapNormalVectorBuffer(_normalBuffer, face.Evaluate(center), normal, _thickness); + Render3dUtils.MapNormalVectorBuffer(_normalBuffer, face.Evaluate(center), normal, _thickness + 0.2, NormalLength); } private void UpdateEffects() @@ -203,7 +205,6 @@ public void UpdateTransparency(double value) uiDocument.UpdateAllOpenViews(); } - public void UpdateSurfaceVisibility(bool visible) { var uiDocument = Context.UiDocument; diff --git a/source/RevitLookup/Core/Render/MeshVisualizationServer.cs b/source/RevitLookup/Core/Visualization/MeshVisualizationServer.cs similarity index 97% rename from source/RevitLookup/Core/Render/MeshVisualizationServer.cs rename to source/RevitLookup/Core/Visualization/MeshVisualizationServer.cs index ca64e05c..5dd976ec 100644 --- a/source/RevitLookup/Core/Render/MeshVisualizationServer.cs +++ b/source/RevitLookup/Core/Visualization/MeshVisualizationServer.cs @@ -23,10 +23,12 @@ using Microsoft.Extensions.Logging; using RevitLookup.Models.Render; -namespace RevitLookup.Core.Render; +namespace RevitLookup.Core.Visualization; public sealed class MeshVisualizationServer(Mesh mesh, ILogger logger) : IDirectContext3DServer { + private const double NormalLength = 1d; + private bool _hasGeometryUpdates = true; private bool _hasEffectsUpdates = true; @@ -65,9 +67,9 @@ public void RenderScene(View view, DisplayStyle displayStyle) { try { - if (_hasGeometryUpdates || !_surfaceBuffer.IsValid() || !_meshGridBuffer.IsValid()) + if (_hasGeometryUpdates || !_surfaceBuffer.IsValid() || !_meshGridBuffer.IsValid() || _normalBuffers.Any(storage => !storage.IsValid())) { - UpdateGeometryBuffer(); + MapGeometryBuffer(); _hasGeometryUpdates = false; } @@ -125,7 +127,7 @@ public void RenderScene(View view, DisplayStyle displayStyle) } } - private void UpdateGeometryBuffer() + private void MapGeometryBuffer() { Render3dUtils.MapSurfaceBuffer(_surfaceBuffer, mesh, _thickness); Render3dUtils.MapMeshGridBuffer(_meshGridBuffer, mesh, _thickness); @@ -150,7 +152,7 @@ private void MapNormalsBuffer() } var normal = Render3dUtils.GetNormal(mesh, i, mesh.DistributionOfNormals); - Render3dUtils.MapNormalVectorBuffer(buffer, vertex, normal, _thickness); + Render3dUtils.MapNormalVectorBuffer(buffer, vertex, normal, _thickness + 0.2, NormalLength); } } diff --git a/source/RevitLookup/Core/Render/Render3dUtils.cs b/source/RevitLookup/Core/Visualization/Render3dUtils.cs similarity index 77% rename from source/RevitLookup/Core/Render/Render3dUtils.cs rename to source/RevitLookup/Core/Visualization/Render3dUtils.cs index d6921251..60ea3c18 100644 --- a/source/RevitLookup/Core/Render/Render3dUtils.cs +++ b/source/RevitLookup/Core/Visualization/Render3dUtils.cs @@ -21,7 +21,7 @@ using Autodesk.Revit.DB.DirectContext3D; using RevitLookup.Models.Render; -namespace RevitLookup.Core.Render; +namespace RevitLookup.Core.Visualization; public static class Render3dUtils { @@ -178,16 +178,74 @@ public static void MapMeshGridBuffer(RenderingBufferStorage buffer, Mesh mesh, d buffer.VertexFormat = new VertexFormat(buffer.FormatBits); } - public static void MapNormalVectorBuffer(RenderingBufferStorage buffer, XYZ origin, XYZ normal, double thickness) + public static void MapSideBuffer(RenderingBufferStorage buffer, XYZ min, XYZ max) { - const double arrowLength = 1d; - const double arrowHeadSize = 0.2; - - var arrowStart = origin + 0.2 * normal + normal * thickness; - var arrowEnd = arrowStart + normal * arrowLength; - var arrowHeadBase = arrowEnd - normal.Multiply(arrowHeadSize); - var basisVector = Math.Abs(normal.Z).IsAlmostEqual(1) ? XYZ.BasisX : XYZ.BasisZ; - var perpendicular1 = normal.CrossProduct(basisVector).Normalize().Multiply(arrowHeadSize * 0.5); + var vertexCount = 4; + var normal = (max - min).Normalize(); + var length = (max - min).GetLength() / 2; + + XYZ point1; + XYZ point2; + XYZ point3; + XYZ point4; + if (normal.IsAlmostEqualTo(XYZ.BasisX)) + { + point1 = new XYZ(min.X, min.Y - length, min.Z); + point2 = new XYZ(min.X, min.Y + length, min.Z); + point3 = new XYZ(max.X, max.Y - length, max.Z); + point4 = new XYZ(max.X, max.Y + length, max.Z); + } + else if (normal.IsAlmostEqualTo(XYZ.BasisY)) + { + point1 = new XYZ(min.X, min.Y, min.Z - length); + point2 = new XYZ(min.X, min.Y, min.Z + length); + point3 = new XYZ(max.X, max.Y, max.Z - length); + point4 = new XYZ(max.X, max.Y, max.Z + length); + } + else + { + point1 = new XYZ(min.X - length, min.Y, min.Z); + point2 = new XYZ(min.X + length, min.Y, min.Z); + point3 = new XYZ(max.X - length, max.Y, max.Z); + point4 = new XYZ(max.X + length, max.Y, max.Z); + } + + buffer.VertexBufferCount = vertexCount; + buffer.PrimitiveCount = 2; + + var vertexBufferSizeInFloats = VertexPosition.GetSizeInFloats() * buffer.VertexBufferCount; + buffer.FormatBits = VertexFormatBits.Position; + buffer.VertexBuffer = new VertexBuffer(vertexBufferSizeInFloats); + buffer.VertexBuffer.Map(vertexBufferSizeInFloats); + + var vertexStream = buffer.VertexBuffer.GetVertexStreamPosition(); + vertexStream.AddVertex(new VertexPosition(point1)); + vertexStream.AddVertex(new VertexPosition(point2)); + vertexStream.AddVertex(new VertexPosition(point3)); + vertexStream.AddVertex(new VertexPosition(point4)); + + buffer.VertexBuffer.Unmap(); + buffer.IndexBufferCount = 2 * IndexTriangle.GetSizeInShortInts(); + buffer.IndexBuffer = new IndexBuffer(buffer.IndexBufferCount); + buffer.IndexBuffer.Map(buffer.IndexBufferCount); + + var indexStream = buffer.IndexBuffer.GetIndexStreamTriangle(); + indexStream.AddTriangle(new IndexTriangle(0, 1, 2)); + indexStream.AddTriangle(new IndexTriangle(1, 2, 3)); + + buffer.IndexBuffer.Unmap(); + buffer.VertexFormat = new VertexFormat(buffer.FormatBits); + } + + public static void MapNormalVectorBuffer(RenderingBufferStorage buffer, XYZ origin, XYZ vector, double offset, double length) + { + const double headSize = 0.2; + + var arrowStart = origin + vector * offset; + var arrowEnd = arrowStart + vector * length; + var arrowHeadBase = arrowEnd - vector * headSize; + var basisVector = Math.Abs(vector.Z).IsAlmostEqual(1) ? XYZ.BasisX : XYZ.BasisZ; + var perpendicular1 = vector.CrossProduct(basisVector).Normalize().Multiply(headSize * 0.5); buffer.VertexBufferCount = 4; buffer.PrimitiveCount = 3; diff --git a/source/RevitLookup/Core/Visualization/XyzVisualizationServer.cs b/source/RevitLookup/Core/Visualization/XyzVisualizationServer.cs new file mode 100644 index 00000000..df9e7e0b --- /dev/null +++ b/source/RevitLookup/Core/Visualization/XyzVisualizationServer.cs @@ -0,0 +1,260 @@ +// Copyright 2003-2024 by Autodesk, Inc. +// +// Permission to use, copy, modify, and distribute this software in +// object code form for any purpose and without fee is hereby granted, +// provided that the above copyright notice appears in all copies and +// that both that copyright notice and the limited warranty and +// restricted rights notice below appear in all supporting +// documentation. +// +// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. +// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF +// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. +// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE +// UNINTERRUPTED OR ERROR FREE. +// +// Use, duplication, or disclosure by the U.S. Government is subject to +// restrictions set forth in FAR 52.227-19 (Commercial Computer +// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) +// (Rights in Technical Data and Computer Software), as applicable. + +using Autodesk.Revit.DB.DirectContext3D; +using Autodesk.Revit.DB.ExternalService; +using Microsoft.Extensions.Logging; +using RevitLookup.Models.Render; + +namespace RevitLookup.Core.Visualization; + +public sealed class XyzVisualizationServer(XYZ point, ILogger logger) : IDirectContext3DServer +{ + private bool _hasGeometryUpdates = true; + private bool _hasEffectsUpdates = true; + + private readonly Guid _guid = Guid.NewGuid(); + private readonly List _surfaceBuffers = new(); + private readonly List _axisBuffers = new(); + + private readonly XYZ[] _normals = + [ + XYZ.BasisX, + XYZ.BasisY, + XYZ.BasisZ + ]; + + private double _axisLength; + private bool _drawSurface; + private Color _surfaceColor; + private Color _axisColor; + private double _transparency; + + public Guid GetServerId() => _guid; + public string GetVendorId() => "RevitLookup"; + public string GetName() => "XYZ visualization server"; + public string GetDescription() => "XYZ geometry visualization"; + public ExternalServiceId GetServiceId() => ExternalServices.BuiltInExternalServices.DirectContext3DService; + public string GetApplicationId() => string.Empty; + public string GetSourceId() => string.Empty; + public bool UsesHandles() => false; + public bool CanExecute(View view) => true; + public bool UseInTransparentPass(View view) => true; + + public Outline GetBoundingBox(View view) + { + return null; + } + + public void RenderScene(View view, DisplayStyle displayStyle) + { + try + { + if (_hasGeometryUpdates || _surfaceBuffers.Any(storage => !storage.IsValid()) || _axisBuffers.Any(storage => !storage.IsValid())) + { + UpdateGeometryBuffer(); + _hasGeometryUpdates = false; + } + + if (_hasEffectsUpdates) + { + UpdateEffects(); + _hasEffectsUpdates = false; + } + + foreach (var buffer in _axisBuffers) + { + DrawContext.FlushBuffer(buffer.VertexBuffer, + buffer.VertexBufferCount, + buffer.IndexBuffer, + buffer.IndexBufferCount, + buffer.VertexFormat, + buffer.EffectInstance, PrimitiveType.LineList, 0, + buffer.PrimitiveCount); + } + + if (_drawSurface) + { + var isTransparentPass = DrawContext.IsTransparentPass(); + if (isTransparentPass && _transparency > 0 || !isTransparentPass && _transparency == 0) + { + foreach (var buffer in _surfaceBuffers) + { + DrawContext.FlushBuffer(buffer.VertexBuffer, + buffer.VertexBufferCount, + buffer.IndexBuffer, + buffer.IndexBufferCount, + buffer.VertexFormat, + buffer.EffectInstance, PrimitiveType.TriangleList, 0, + buffer.PrimitiveCount); + } + } + } + } + catch (Exception exception) + { + logger.LogError(exception, "Rendering error"); + } + } + + private void UpdateGeometryBuffer() + { + MapNormalBuffer(); + MapSurfaceBuffer(); + } + + private void MapNormalBuffer() + { + for (var i = 0; i < _normals.Length; i++) + { + var normal = _normals[i]; + RenderingBufferStorage buffer; + if (_axisBuffers.Count > i) + { + buffer = _axisBuffers[i]; + } + else + { + buffer = new RenderingBufferStorage(); + _axisBuffers.Add(buffer); + } + + Render3dUtils.MapNormalVectorBuffer(buffer, point - normal * _axisLength, normal, 0, _axisLength * 2); + } + } + + private void MapSurfaceBuffer() + { + for (var i = 0; i < _normals.Length; i++) + { + var normal = _normals[i]; + RenderingBufferStorage buffer; + if (_surfaceBuffers.Count > i) + { + buffer = _surfaceBuffers[i]; + } + else + { + buffer = new RenderingBufferStorage(); + _surfaceBuffers.Add(buffer); + } + + Render3dUtils.MapSideBuffer(buffer, point - normal * _axisLength, point + normal * _axisLength); + } + } + + private void UpdateEffects() + { + foreach (var buffer in _surfaceBuffers) + { + buffer.EffectInstance ??= new EffectInstance(buffer.FormatBits); + buffer.EffectInstance.SetColor(_surfaceColor); + buffer.EffectInstance.SetTransparency(_transparency); + } + + foreach (var buffer in _axisBuffers) + { + buffer.EffectInstance ??= new EffectInstance(buffer.FormatBits); + buffer.EffectInstance.SetColor(_axisColor); + } + } + + public void UpdateSurfaceColor(Color value) + { + var uiDocument = Context.UiDocument; + if (uiDocument is null) return; + + _surfaceColor = value; + _hasEffectsUpdates = true; + + uiDocument.UpdateAllOpenViews(); + } + + public void UpdateAxisColor(Color value) + { + var uiDocument = Context.UiDocument; + if (uiDocument is null) return; + + _axisColor = value; + _hasEffectsUpdates = true; + + uiDocument.UpdateAllOpenViews(); + } + + public void UpdateAxisLength(double value) + { + var uiDocument = Context.UiDocument; + if (uiDocument is null) return; + + _axisLength = value; + _hasGeometryUpdates = true; + + uiDocument.UpdateAllOpenViews(); + } + + public void UpdateTransparency(double value) + { + var uiDocument = Context.UiDocument; + if (uiDocument is null) return; + + _transparency = value; + _hasEffectsUpdates = true; + + uiDocument.UpdateAllOpenViews(); + } + + public void UpdateSurfaceVisibility(bool visible) + { + var uiDocument = Context.UiDocument; + if (uiDocument is null) return; + + _drawSurface = visible; + + uiDocument.UpdateAllOpenViews(); + } + + public void Register() + { + Application.ActionEventHandler.Raise(application => + { + if (application.ActiveUIDocument is null) return; + + var directContextService = (MultiServerService) ExternalServiceRegistry.GetService(ExternalServices.BuiltInExternalServices.DirectContext3DService); + var serverIds = directContextService.GetActiveServerIds(); + + directContextService.AddServer(this); + serverIds.Add(GetServerId()); + directContextService.SetActiveServers(serverIds); + + application.ActiveUIDocument.UpdateAllOpenViews(); + }); + } + + public void Unregister() + { + Application.ActionEventHandler.Raise(application => + { + var directContextService = (MultiServerService) ExternalServiceRegistry.GetService(ExternalServices.BuiltInExternalServices.DirectContext3DService); + directContextService.RemoveServer(GetServerId()); + + application.ActiveUIDocument?.UpdateAllOpenViews(); + }); + } +} \ No newline at end of file diff --git a/source/RevitLookup/ViewModels/Dialogs/Render/FaceVisualizationViewModel.cs b/source/RevitLookup/ViewModels/Dialogs/Visualization/FaceVisualizationViewModel.cs similarity index 97% rename from source/RevitLookup/ViewModels/Dialogs/Render/FaceVisualizationViewModel.cs rename to source/RevitLookup/ViewModels/Dialogs/Visualization/FaceVisualizationViewModel.cs index 9fb9ea27..732b2f1b 100644 --- a/source/RevitLookup/ViewModels/Dialogs/Render/FaceVisualizationViewModel.cs +++ b/source/RevitLookup/ViewModels/Dialogs/Visualization/FaceVisualizationViewModel.cs @@ -20,10 +20,10 @@ using System.Windows.Media; using Microsoft.Extensions.Logging; -using RevitLookup.Core.Render; +using RevitLookup.Core.Visualization; using Color = Autodesk.Revit.DB.Color; -namespace RevitLookup.ViewModels.Dialogs.Render; +namespace RevitLookup.ViewModels.Dialogs.Visualization; public sealed partial class FaceVisualizationViewModel(Face face, ILogger logger) : ObservableObject { diff --git a/source/RevitLookup/ViewModels/Dialogs/Render/MeshVisualizationViewModel.cs b/source/RevitLookup/ViewModels/Dialogs/Visualization/MeshVisualizationViewModel.cs similarity index 97% rename from source/RevitLookup/ViewModels/Dialogs/Render/MeshVisualizationViewModel.cs rename to source/RevitLookup/ViewModels/Dialogs/Visualization/MeshVisualizationViewModel.cs index 1ca6c064..ae03afe5 100644 --- a/source/RevitLookup/ViewModels/Dialogs/Render/MeshVisualizationViewModel.cs +++ b/source/RevitLookup/ViewModels/Dialogs/Visualization/MeshVisualizationViewModel.cs @@ -20,10 +20,10 @@ using System.Windows.Media; using Microsoft.Extensions.Logging; -using RevitLookup.Core.Render; +using RevitLookup.Core.Visualization; using Color = Autodesk.Revit.DB.Color; -namespace RevitLookup.ViewModels.Dialogs.Render; +namespace RevitLookup.ViewModels.Dialogs.Visualization; public sealed partial class MeshVisualizationViewModel(Mesh face, ILogger logger) : ObservableObject { diff --git a/source/RevitLookup/ViewModels/Dialogs/Visualization/XyzVisualizationViewModel.cs b/source/RevitLookup/ViewModels/Dialogs/Visualization/XyzVisualizationViewModel.cs new file mode 100644 index 00000000..4adb4b31 --- /dev/null +++ b/source/RevitLookup/ViewModels/Dialogs/Visualization/XyzVisualizationViewModel.cs @@ -0,0 +1,84 @@ +// Copyright 2003-2024 by Autodesk, Inc. +// +// Permission to use, copy, modify, and distribute this software in +// object code form for any purpose and without fee is hereby granted, +// provided that the above copyright notice appears in all copies and +// that both that copyright notice and the limited warranty and +// restricted rights notice below appear in all supporting +// documentation. +// +// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. +// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF +// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. +// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE +// UNINTERRUPTED OR ERROR FREE. +// +// Use, duplication, or disclosure by the U.S. Government is subject to +// restrictions set forth in FAR 52.227-19 (Commercial Computer +// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) +// (Rights in Technical Data and Computer Software), as applicable. + +using System.Windows.Media; +using Microsoft.Extensions.Logging; +using RevitLookup.Core.Visualization; +using Color = Autodesk.Revit.DB.Color; + +namespace RevitLookup.ViewModels.Dialogs.Visualization; + +public sealed partial class XyzVisualizationViewModel(XYZ point, ILogger logger) : ObservableObject +{ + private readonly XyzVisualizationServer _server = new(point, logger); + + [ObservableProperty] private double _axisLength = 12; + [ObservableProperty] private double _transparency = 40; + + [ObservableProperty] private System.Windows.Media.Color _surfaceColor = Colors.DodgerBlue; + [ObservableProperty] private System.Windows.Media.Color _axisColor = System.Windows.Media.Color.FromArgb(0, 255, 89, 30); + + [ObservableProperty] private bool _showSurface = true; + + public double MinAxisLength { get; } = 4; + + public void RegisterServer() + { + OnShowSurfaceChanged(ShowSurface); + + OnSurfaceColorChanged(SurfaceColor); + OnAxisColorChanged(AxisColor); + + OnAxisLengthChanged(AxisLength); + OnTransparencyChanged(Transparency); + + _server.Register(); + } + + public void UnregisterServer() + { + _server.Unregister(); + } + + partial void OnSurfaceColorChanged(System.Windows.Media.Color value) + { + _server.UpdateSurfaceColor(new Color(value.R, value.G, value.B)); + } + + partial void OnAxisColorChanged(System.Windows.Media.Color value) + { + _server.UpdateAxisColor(new Color(value.R, value.G, value.B)); + } + + partial void OnAxisLengthChanged(double value) + { + _server.UpdateAxisLength(value / 12); + } + + partial void OnTransparencyChanged(double value) + { + _server.UpdateTransparency(value / 100); + } + + partial void OnShowSurfaceChanged(bool value) + { + _server.UpdateSurfaceVisibility(value); + } +} \ No newline at end of file diff --git a/source/RevitLookup/Views/Dialogs/Render/FaceVisualizationDialog.xaml b/source/RevitLookup/Views/Dialogs/Visualization/FaceVisualizationDialog.xaml similarity index 94% rename from source/RevitLookup/Views/Dialogs/Render/FaceVisualizationDialog.xaml rename to source/RevitLookup/Views/Dialogs/Visualization/FaceVisualizationDialog.xaml index 85f6e5e2..65e6ae29 100644 --- a/source/RevitLookup/Views/Dialogs/Render/FaceVisualizationDialog.xaml +++ b/source/RevitLookup/Views/Dialogs/Visualization/FaceVisualizationDialog.xaml @@ -1,14 +1,14 @@  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/RevitLookup/Views/Dialogs/Visualization/XyzVisualizationDialog.xaml.cs b/source/RevitLookup/Views/Dialogs/Visualization/XyzVisualizationDialog.xaml.cs new file mode 100644 index 00000000..0e2988d7 --- /dev/null +++ b/source/RevitLookup/Views/Dialogs/Visualization/XyzVisualizationDialog.xaml.cs @@ -0,0 +1,65 @@ +// Copyright 2003-2024 by Autodesk, Inc. +// +// Permission to use, copy, modify, and distribute this software in +// object code form for any purpose and without fee is hereby granted, +// provided that the above copyright notice appears in all copies and +// that both that copyright notice and the limited warranty and +// restricted rights notice below appear in all supporting +// documentation. +// +// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. +// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF +// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. +// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE +// UNINTERRUPTED OR ERROR FREE. +// +// Use, duplication, or disclosure by the U.S. Government is subject to +// restrictions set forth in FAR 52.227-19 (Commercial Computer +// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) +// (Rights in Technical Data and Computer Software), as applicable. + +using Microsoft.Extensions.Logging; +using RevitLookup.Core.Visualization; +using RevitLookup.ViewModels.Dialogs.Visualization; +using Wpf.Ui; +using MeshVisualizationViewModel = RevitLookup.ViewModels.Dialogs.Visualization.MeshVisualizationViewModel; + +namespace RevitLookup.Views.Dialogs.Visualization; + +public sealed partial class XyzVisualizationDialog +{ + private readonly IServiceProvider _serviceProvider; + private readonly XyzVisualizationViewModel _viewModel; + + public XyzVisualizationDialog(IServiceProvider serviceProvider, XYZ point) + { + var logger = serviceProvider.GetService>(); + + _serviceProvider = serviceProvider; + _viewModel = new XyzVisualizationViewModel(point, logger); + + DataContext = _viewModel; + InitializeComponent(); + MonitorServerConnection(); + } + + public async Task ShowAsync() + { + var dialogOptions = new SimpleContentDialogCreateOptions + { + Title = "Visualization settings", + Content = this, + CloseButtonText = "Close", + DialogMaxWidth = 500, + DialogMaxHeight = 450 + }; + + await _serviceProvider.GetService().ShowSimpleDialogAsync(dialogOptions); + } + + private void MonitorServerConnection() + { + _viewModel.RegisterServer(); + Unloaded += (_, _) => _viewModel.UnregisterServer(); + } +} \ No newline at end of file