diff --git a/NamedPipes/IVisualizerKontract.cs b/NamedPipes/IVisualizerKontract.cs
index ecc8fa6..51ff48a 100644
--- a/NamedPipes/IVisualizerKontract.cs
+++ b/NamedPipes/IVisualizerKontract.cs
@@ -1,6 +1,4 @@
-using System;
-using System.Numerics;
-using System.Threading.Tasks;
+using System.Threading.Tasks;
namespace NamedPipes;
public interface IDebugVisualizer
diff --git a/NamedPipes/PipeSerializer.cs b/NamedPipes/PipeSerializer.cs
index 45b136d..c42eab6 100644
--- a/NamedPipes/PipeSerializer.cs
+++ b/NamedPipes/PipeSerializer.cs
@@ -10,18 +10,25 @@ namespace NamedPipes;
///
public class PipeSerializer : IPipeSerializer
{
+ private JsonSerializerOptions options = new()
+ {
+ IncludeFields = true
+ };
+
public object Deserialize(byte[] data, Type type)
{
- return JsonSerializer.Deserialize(data, type) ?? throw new InvalidDataException($"Can not deserialize to type: {type} ");
+
+ var obj = JsonSerializer.Deserialize(data, type, options) ?? throw new InvalidDataException($"Can not deserialize to type: {type} ");
+ return obj;
}
public byte[] Serialize(object o)
{
- using (var memoryStream = new MemoryStream())
- using (var utf8JsonWriter = new Utf8JsonWriter(memoryStream))
- {
- JsonSerializer.Serialize(utf8JsonWriter, o);
- return memoryStream.ToArray();
- }
+
+ using var memoryStream = new MemoryStream();
+ using var utf8JsonWriter = new Utf8JsonWriter(memoryStream);
+ JsonSerializer.Serialize(utf8JsonWriter, o, options);
+ var data = memoryStream.ToArray();
+ return data;
}
}
diff --git a/NrxDebugVisualizer/App.axaml b/NrxDebugVisualizer/App.axaml
index cd9bb79..9036f7c 100644
--- a/NrxDebugVisualizer/App.axaml
+++ b/NrxDebugVisualizer/App.axaml
@@ -3,8 +3,9 @@
x:Class="NrxDebugVisualizer.App"
RequestedThemeVariant="Default">
-
+
-
+
+
\ No newline at end of file
diff --git a/NrxDebugVisualizer/App.axaml.cs b/NrxDebugVisualizer/App.axaml.cs
index 96c58a4..6f7ca60 100644
--- a/NrxDebugVisualizer/App.axaml.cs
+++ b/NrxDebugVisualizer/App.axaml.cs
@@ -1,19 +1,21 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
-using Avalonia.Data.Core;
-using Avalonia.Data.Core.Plugins;
using Avalonia.Markup.Xaml;
+using Controls.Utilities;
using NrxDebugVisualizer.ViewModels;
using NrxDebugVisualizer.Views;
-using System.Linq;
namespace NrxDebugVisualizer;
public partial class App : Application
{
+ public static Settings? Settings { get; set; }
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
+#if DEBUG
+ this.AttachDeveloperTools();
+#endif
}
public override void OnFrameworkInitializationCompleted()
@@ -24,10 +26,9 @@ public partial class App : Application
{
DataContext = new MainWindowViewModel(),
};
- }
+ Settings = Settings.Load(desktop.MainWindow);
+ }
base.OnFrameworkInitializationCompleted();
}
-
-
-}
\ No newline at end of file
+}
diff --git a/NrxDebugVisualizer/Models/PipeServer.cs b/NrxDebugVisualizer/Models/PipeServer.cs
index 710e5a0..6b1be11 100644
--- a/NrxDebugVisualizer/Models/PipeServer.cs
+++ b/NrxDebugVisualizer/Models/PipeServer.cs
@@ -1,22 +1,25 @@
using NamedPipes;
using NrxDebugVisualizer.Scenes;
using Num.Roto.Visualization.Math.Geometry;
+using Num.Roto.Visualization.Math.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Threading;
-using KontractFrame = System.ValueTuple;
+
namespace NrxDebugVisualizer.Models;
internal sealed class PipeServer
{
+
private string PipeName { get; }
private NamedPipesServer? NamedPipesServer { get; set; }
- public PipeServer(string pipeName, DebugVisualizerScene debuggerScene,CancellationToken cancellationToken)
+ private Action UpdateAction { get; init; }
+ public PipeServer(string pipeName, Action updateAction,CancellationToken cancellationToken)
{
PipeName = pipeName;
- DebugVisualizerScene = debuggerScene;
+ UpdateAction = updateAction;
StartPipeServer(cancellationToken);
}
private void NamedPipesServer_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
@@ -24,56 +27,17 @@ internal sealed class PipeServer
if (e.PropertyName != nameof(NamedPipesServer.VisualizerModel)) return;
var visualizerObject = NamedPipesServer?.VisualizerModel;
if (visualizerObject is null) return;
-
- SetPoint(visualizerObject.Point);
- SetPointList(visualizerObject.PointArray);
- SetFrame(visualizerObject.Frame);
- SetFrameList(visualizerObject.FrameArray);
+ UpdateAction(visualizerObject);
}
#region NamedPipesServer
private async void StartPipeServer(CancellationToken cancellationToken)
{
- NamedPipesServer = new NamedPipesServer(PipeName, logger: Console.WriteLine);
+ NamedPipesServer = new NamedPipesServer(PipeName, logger: (s) => Log.Info(s,0));
NamedPipesServer.PropertyChanged += NamedPipesServer_PropertyChanged;
- await NamedPipesServer.RunAsync(cancellationToken);
+ await NamedPipesServer.RunAsync(cancellationToken).ConfigureAwait(false);
}
#endregion
- #region DebugVisualizerScene
- private DebugVisualizerScene DebugVisualizerScene { get; }
- private static Frame ToFrame(KontractFrame kontractFrame)
- {
- var (translation, orientation, scale) = kontractFrame;
- return new Frame(translation, scale, orientation);
- }
- private static Frame[] ToFrameArray(IEnumerable frameList)
- {
- return [.. frameList.Select(ToFrame)];
- }
-
- private void SetPoint(Vector3? point)
- {
- if (point is null) return;
- DebugVisualizerScene.AddPointGeometry(point.Value, 20f);
- }
-
- private void SetPointList(Vector3[]? pointList)
- {
- if (pointList == null || pointList.Length < 1) return;
- DebugVisualizerScene.AddPointListGeometry(pointList, 5);
- }
-
- private void SetFrame(KontractFrame? kontractFrame)
- {
- if (kontractFrame is null) return;
- DebugVisualizerScene.AddFrameGeometry(ToFrame(kontractFrame.Value), 1);
- }
-
- private void SetFrameList(KontractFrame[]? frameArray)
- {
- if (frameArray == null || frameArray.Length < 1) return;
- DebugVisualizerScene.AddFrameListGeometry(ToFrameArray(frameArray), 1);
- }
- #endregion
+
}
diff --git a/NrxDebugVisualizer/NrxDebugVisualizer.csproj b/NrxDebugVisualizer/NrxDebugVisualizer.csproj
index 132e447..a8f3cff 100644
--- a/NrxDebugVisualizer/NrxDebugVisualizer.csproj
+++ b/NrxDebugVisualizer/NrxDebugVisualizer.csproj
@@ -24,6 +24,7 @@
+
diff --git a/NrxDebugVisualizer/ViewModels/MainWindowViewModel.cs b/NrxDebugVisualizer/ViewModels/MainWindowViewModel.cs
index 7535766..db8fa0b 100644
--- a/NrxDebugVisualizer/ViewModels/MainWindowViewModel.cs
+++ b/NrxDebugVisualizer/ViewModels/MainWindowViewModel.cs
@@ -1,8 +1,127 @@
-using CommunityToolkit.Mvvm.ComponentModel;
-
+using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
+using CommunityToolkit.Mvvm.Input;
+using Controls.ViewModels;
+using NamedPipes;
+using NrxDebugVisualizer.Models;
+using NrxDebugVisualizer.Scenes;
+using Num.Roto.Visualization.Math.Geometry;
+using Num.Roto.Visualization.Math.Utilities;
+using Num.Roto.Visualization.Types;
+using Num.Roto.Visualization.VulkanLib.SceneInteraction;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using System.Threading;
+using KontractFrame = System.ValueTuple;
namespace NrxDebugVisualizer.ViewModels;
-public partial class MainWindowViewModel : ObservableObject
+internal sealed partial class MainWindowViewModel : ViewModelBase
{
- public string Greeting { get; } = "Welcome to Avalonia!";
+ public ProportionalDockControlViewModel ProportionalDockControlViewModel { get; } = new();
+ public VulkanSceneControlViewModel VulkanSceneControlViewModel => ProportionalDockControlViewModel.VulkanSceneControlViewModel;
+ public SceneTreeViewViewModel SceneTreeViewViewModel => ProportionalDockControlViewModel.SceneTreeViewViewModel?? throw new InvalidOperationException("SceneTreeViewViewModel is not available");
+ public SceneInteraction SceneInteraction => ProportionalDockControlViewModel.SceneInteraction;
+
+ public DebugVisualizerScene DebugVisualizerScene => ProportionalDockControlViewModel.Scene as DebugVisualizerScene ?? throw new InvalidOperationException("Scene is not a DebugVisualizerScene");
+
+ private PipeServer PipeServer {get;init;}
+ public MainWindowViewModel()
+ {
+ ProportionalDockControlViewModel.Scene = new DebugVisualizerScene();
+ ProportionalDockControlViewModel.Scene.SelectedCamera.DefaultFrame = CameraView.Frame(ViewPosition);
+ PipeServer = new PipeServer(nameof(NrxDebugVisualizer), UpdateScene, cancellationToken: CancellationToken.None);
+ }
+
+ #region Commands
+ [RelayCommand]
+ public static void ShowLogViewer()
+ {
+ Log.LogViewerEnabled = true;
+ }
+ [RelayCommand]
+ private static void Exit(object? parameter)
+ {
+ if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopApp)
+ {
+ desktopApp.Shutdown();
+ }
+ }
+ [RelayCommand]
+ internal void ResetCamera()
+ {
+ ProportionalDockControlViewModel.VulkanSceneControlViewModel.ResetCamera(CameraView.Frame(ViewPosition));
+ }
+
+ [RelayCommand]
+ internal void FitToWindow()
+ {
+ ProportionalDockControlViewModel.Scene?.FitToWindow(0.95f);
+ ProportionalDockControlViewModel.VulkanSceneControlViewModel.SceneInteraction.Update();
+ }
+ #endregion
+
+ #region Camera View
+ public static IEnumerable ViewPositions => Enum.GetValues();
+ private CameraView.Position _viewPosition = CameraView.Position.Custom1;
+ public CameraView.Position ViewPosition
+ {
+ get => _viewPosition;
+ set
+ {
+ if (_viewPosition == value) return;
+ _viewPosition = value;
+ OnPropertyChanged();
+ if (_viewPosition == CameraView.Position.User) return;
+ ProportionalDockControlViewModel.Scene?.SelectedCamera.DefaultFrame = CameraView.Frame(_viewPosition);
+ FitToWindow();
+ }
+ }
+ #endregion
+
+ #region Pipe Server
+ private void UpdateScene(VisualizerModel visualizerModel)
+ {
+ SetPoint(visualizerModel.Point);
+ SetPointList(visualizerModel.PointArray);
+ SetFrame(visualizerModel.Frame);
+ SetFrameList(visualizerModel.FrameArray);
+ SceneInteraction.Update();
+ }
+ private static Frame ToFrame(KontractFrame kontractFrame)
+ {
+ var (translation, orientation, scale) = kontractFrame;
+ return new Frame(translation, scale, orientation);
+ }
+ private static Frame[] ToFrameArray(IEnumerable frameList)
+ {
+ return [.. frameList.Select(ToFrame)];
+ }
+
+ private void SetPoint(Vector3? point)
+ {
+ if (point is null) return;
+ DebugVisualizerScene.AddPointGeometry(point.Value, 5f);
+ }
+
+ private void SetPointList(Vector3[]? pointList)
+ {
+ if (pointList == null || pointList.Length < 1) return;
+ DebugVisualizerScene.AddPointListGeometry(pointList, 5);
+ }
+
+ private void SetFrame(KontractFrame? kontractFrame)
+ {
+ if (kontractFrame is null) return;
+ DebugVisualizerScene.AddFrameGeometry(ToFrame(kontractFrame.Value), 1);
+ }
+
+ private void SetFrameList(KontractFrame[]? frameArray)
+ {
+ if (frameArray == null || frameArray.Length < 1) return;
+ DebugVisualizerScene.AddFrameListGeometry(ToFrameArray(frameArray), 1);
+ }
+ #endregion
}
+
diff --git a/NrxDebugVisualizer/Views/MainWindow.axaml b/NrxDebugVisualizer/Views/MainWindow.axaml
index 64030e1..c077543 100644
--- a/NrxDebugVisualizer/Views/MainWindow.axaml
+++ b/NrxDebugVisualizer/Views/MainWindow.axaml
@@ -6,14 +6,45 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="NrxDebugVisualizer.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
+ xmlns:viewModels="clr-namespace:NrxDebugVisualizer.ViewModels"
+ xmlns:controls="clr-namespace:Controls.Views;assembly=Controls"
Icon="/Assets/avalonia-logo.ico"
- Title="NrxDebugVisualizer">
+ Title="NrxDebugVisualizer"
+ Width="1200"
+ Height="800"
+ MinWidth="800"
+ MinHeight="600">
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NrxDebugVisualizer/Views/MainWindow.axaml.cs b/NrxDebugVisualizer/Views/MainWindow.axaml.cs
index 2f0f3a3..543fc6a 100644
--- a/NrxDebugVisualizer/Views/MainWindow.axaml.cs
+++ b/NrxDebugVisualizer/Views/MainWindow.axaml.cs
@@ -1,4 +1,10 @@
using Avalonia.Controls;
+using Avalonia.Interactivity;
+using NrxDebugVisualizer.ViewModels;
+using Num.Roto.Visualization.Types;
+using System.Data;
+using System.Globalization;
+using System.Threading;
namespace NrxDebugVisualizer.Views;
@@ -6,6 +12,29 @@ public partial class MainWindow : Window
{
public MainWindow()
{
+ Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
InitializeComponent();
+
+ Closing += OnClosing;
+
+ }
+ protected override void OnLoaded(RoutedEventArgs e)
+ {
+ base.OnLoaded(e);
+ if (DataContext is not MainWindowViewModel viewModel) throw new DataException("wrong viewModel type!");
+ if (App.Settings?.CameraFrame is not { } cameraFrame) return;
+ var scene = viewModel.ProportionalDockControlViewModel.Scene;
+ var camera = scene?.SelectedCamera;
+ camera?.Frame = cameraFrame;
+ viewModel.ViewPosition = CameraView.Position.User;
+ }
+ private async void OnClosing(object? sender, System.ComponentModel.CancelEventArgs e)
+ {
+ if (DataContext is not MainWindowViewModel viewModel) throw new DataException("wrong viewModel type!");
+ var scene = viewModel.ProportionalDockControlViewModel.Scene;
+ var camera = scene?.SelectedCamera;
+ App.Settings?.MainWindow = this;
+ App.Settings?.CameraFrame = camera?.Frame;
+ App.Settings?.Save();
}
}
\ No newline at end of file
diff --git a/TestClient/Program.cs b/TestClient/Program.cs
index 183d309..9ff0b6b 100644
--- a/TestClient/Program.cs
+++ b/TestClient/Program.cs
@@ -13,10 +13,12 @@ VisualizerModel visualizerModel = new()
};
while (true)
{
- var pipeClient = new NamedPipeClient("TestPipe", @".\","TestServer",logger:Console.WriteLine);
+ var serverName = "NrxDebugVisualizer";
+ var pipeClient = new NamedPipeClient(serverName, @".\", serverName, logger:Console.WriteLine);
Thread.Sleep(1000);
+ visualizerModel.Point = new System.Numerics.Vector3(count, count * 2, count * 3);
+ count++;
await pipeClient.SetVisualizerModelAsync(visualizerModel);
- pipeClient.SetMessageAsync($"Hello from TestClient " + count++).GetAwaiter().GetResult();
- //pipeClient.SetDebugObjectAsync(new DebugObject{Type = typeof(string).FullName,Data = Encoding.GetEncoding("UTF-8").GetBytes(message)}).GetAwaiter().GetResult();
+ //await pipeClient.SetMessageAsync($"Hello from TestClient " + count++);
pipeClient.Dispose();
}
diff --git a/TestServer/Program.cs b/TestServer/Program.cs
index c115b97..ab288f3 100644
--- a/TestServer/Program.cs
+++ b/TestServer/Program.cs
@@ -1,6 +1,6 @@
using System;
using System.Threading;
-var pipeServer = new NamedPipes.NamedPipesServer("TestPipe", logger:Console.WriteLine);
+var pipeServer = new NamedPipes.NamedPipesServer("NrxDebugVisualizer", logger:Console.WriteLine);
await pipeServer.RunAsync(CancellationToken.None).ConfigureAwait(true);
diff --git a/TestServer/Properties/launchSettings.json b/TestServer/Properties/launchSettings.json
index b0f0d47..5490bce 100644
--- a/TestServer/Properties/launchSettings.json
+++ b/TestServer/Properties/launchSettings.json
@@ -2,7 +2,7 @@
"profiles": {
"TestServer": {
"commandName": "Project",
- "workingDirectory": "C:\\Users\\heilm\\Documents\\Visual Studio 2026\\Visualizers"
+ "workingDirectory": "C:\\Users\\matth\\Documents\\Visual Studio 2026\\Visualizers"
}
}
}
\ No newline at end of file