init
This commit is contained in:
@@ -0,0 +1,394 @@
|
||||
using Hi.Disp;
|
||||
using Hi.Native;
|
||||
using Hi.PanelModels;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Collections.Generic;
|
||||
using Hi.Geom;
|
||||
|
||||
namespace Hi.Wpf.Disp
|
||||
{
|
||||
#region WPF Rendering Canvas
|
||||
public class RenderingCanvas : UserControl, IDisposable
|
||||
{
|
||||
#region Core_Properties
|
||||
/// <summary>
|
||||
/// The DispEngine instance that handles rendering and user interactions
|
||||
/// </summary>
|
||||
public DispEngine DispEngine { get; } = new DispEngine();
|
||||
|
||||
/// <summary>
|
||||
/// Internal container for rendering content
|
||||
/// </summary>
|
||||
private UserControl DisplayerPane { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary to store touch point information
|
||||
/// </summary>
|
||||
private Dictionary<int, Point> TouchingPointsMap { get; } = new Dictionary<int, Point>();
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary to store previous positions of touch points
|
||||
/// </summary>
|
||||
private Dictionary<int, Point> PreviousTouchingPointsMap { get; } = new Dictionary<int, Point>();
|
||||
#endregion
|
||||
|
||||
#region Initialization
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the RenderingCanvas
|
||||
/// </summary>
|
||||
public RenderingCanvas()
|
||||
{
|
||||
DispEngine.BackgroundColor = new Vec3d(0.1, 0.1, 0.5);
|
||||
DispEngine.BackgroundOpacity = 0.1;
|
||||
|
||||
// Configure the main control properties
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch;
|
||||
VerticalAlignment = VerticalAlignment.Stretch;
|
||||
Focusable = true;
|
||||
KeyboardNavigation.SetDirectionalNavigation(this, KeyboardNavigationMode.Cycle);
|
||||
DataContextChanged += CanvasDataContextChanged;
|
||||
|
||||
// Create and configure the display pane
|
||||
DisplayerPane = new UserControl();
|
||||
DisplayerPane.HorizontalAlignment = HorizontalAlignment.Stretch;
|
||||
DisplayerPane.VerticalAlignment = VerticalAlignment.Stretch;
|
||||
DisplayerPane.Focusable = true;
|
||||
DisplayerPane.IsTabStop = true;
|
||||
|
||||
// Connect event handlers for user input and window events
|
||||
DisplayerPane.SizeChanged += RenderingCanvas_SizeChanged;
|
||||
DisplayerPane.MouseMove += RenderingCanvas_MouseMove;
|
||||
DisplayerPane.MouseDown += RenderingCanvas_MouseDown;
|
||||
DisplayerPane.MouseUp += RenderingCanvas_MouseUp;
|
||||
DisplayerPane.MouseWheel += RenderingCanvas_MouseWheel;
|
||||
DisplayerPane.KeyDown += RenderingCanvas_KeyDown;
|
||||
DisplayerPane.KeyUp += RenderingCanvas_KeyUp;
|
||||
DisplayerPane.Loaded += RenderingCanvas_Loaded;
|
||||
DisplayerPane.Unloaded += RenderingCanvas_Unloaded;
|
||||
DisplayerPane.IsVisibleChanged += DisplayerPane_IsVisibleChanged;
|
||||
|
||||
// Add touch event handlers
|
||||
DisplayerPane.TouchDown += RenderingCanvas_TouchDown;
|
||||
DisplayerPane.TouchMove += RenderingCanvas_TouchMove;
|
||||
DisplayerPane.TouchUp += RenderingCanvas_TouchUp;
|
||||
|
||||
// Enable touch support
|
||||
this.IsManipulationEnabled = true;
|
||||
|
||||
// Add the display pane to this control's content
|
||||
Content = DisplayerPane;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Touch_Events
|
||||
/// <summary>
|
||||
/// Handles the touch down event
|
||||
/// </summary>
|
||||
private void RenderingCanvas_TouchDown(object sender, TouchEventArgs e)
|
||||
{
|
||||
// Add touch point to dictionary
|
||||
Point touchPoint = e.GetTouchPoint(DisplayerPane).Position;
|
||||
DispEngine.TouchDown(e.TouchDevice.Id,
|
||||
(int)touchPoint.X, (int)touchPoint.Y);
|
||||
|
||||
// Ensure control gets focus
|
||||
DisplayerPane.Focus();
|
||||
e.TouchDevice.Capture(DisplayerPane);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the touch move event
|
||||
/// </summary>
|
||||
private void RenderingCanvas_TouchMove(object sender, TouchEventArgs e)
|
||||
{
|
||||
Point touchPoint = e.GetTouchPoint(DisplayerPane).Position;
|
||||
DispEngine.TouchMove(e.TouchDevice.Id,
|
||||
(int)touchPoint.X, (int)touchPoint.Y);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the touch up event
|
||||
/// </summary>
|
||||
private void RenderingCanvas_TouchUp(object sender, TouchEventArgs e)
|
||||
{
|
||||
DispEngine.TouchUp(e.TouchDevice.Id);
|
||||
e.Handled = true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Window_Events
|
||||
/// <summary>
|
||||
/// Handles window state changes (maximize, minimize, etc.)
|
||||
/// </summary>
|
||||
private unsafe void RenderingCanvas_StateChanged(object sender, EventArgs e)
|
||||
{
|
||||
switch ((sender as Window).WindowState)
|
||||
{
|
||||
case WindowState.Maximized:
|
||||
DispEngine.IsVisible = true;
|
||||
break;
|
||||
case WindowState.Minimized:
|
||||
DispEngine.IsVisible = false;
|
||||
break;
|
||||
case WindowState.Normal:
|
||||
DispEngine.IsVisible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles data context changes
|
||||
/// </summary>
|
||||
private unsafe void CanvasDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
DispEngine pre = e.OldValue as DispEngine;
|
||||
DispEngine cur = e.NewValue as DispEngine;
|
||||
|
||||
//child's binding event is triggered after IsVisible event and Load event.
|
||||
if (pre != null) //this section will never occur if the datacontext not set twice.
|
||||
{
|
||||
pre.Terminate();
|
||||
pre.ImageRequestAfterBufferSwapped -= RenderingCanvas_BufferSwapped;
|
||||
}
|
||||
if (cur != null)
|
||||
{
|
||||
cur.ImageRequestAfterBufferSwapped += RenderingCanvas_BufferSwapped;
|
||||
cur.Start((int)DisplayerPane.RenderSize.Width, (int)DisplayerPane.RenderSize.Height);
|
||||
|
||||
cur.IsVisible = IsVisible;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the current window containing this control
|
||||
/// </summary>
|
||||
private Window currentWindow;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current window, connecting or disconnecting state change events
|
||||
/// </summary>
|
||||
Window CurrentWindow
|
||||
{
|
||||
get => currentWindow; set
|
||||
{
|
||||
if (currentWindow != null)
|
||||
currentWindow.StateChanged -= RenderingCanvas_StateChanged;
|
||||
currentWindow = value;
|
||||
if (currentWindow != null)
|
||||
currentWindow.StateChanged += RenderingCanvas_StateChanged;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the loaded event
|
||||
/// </summary>
|
||||
private unsafe void RenderingCanvas_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Get the window containing this control
|
||||
CurrentWindow = Window.GetWindow(this);
|
||||
|
||||
// Set up DispEngine rendering
|
||||
DispEngine.ImageRequestAfterBufferSwapped -= RenderingCanvas_BufferSwapped;
|
||||
DispEngine.ImageRequestAfterBufferSwapped += RenderingCanvas_BufferSwapped;
|
||||
DispEngine.Start((int)DisplayerPane.RenderSize.Width, (int)DisplayerPane.RenderSize.Height);
|
||||
DispEngine.IsVisible = IsVisible;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the unloaded event
|
||||
/// </summary>
|
||||
private unsafe void RenderingCanvas_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DispEngine.IsVisible = IsVisible;
|
||||
DispEngine.ImageRequestAfterBufferSwapped -= RenderingCanvas_BufferSwapped;
|
||||
CurrentWindow = null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region DispEngine_Rendering
|
||||
/// <summary>
|
||||
/// Handles the buffer swapped event from DispEngine
|
||||
/// </summary>
|
||||
private unsafe void RenderingCanvas_BufferSwapped(byte* data, int w, int h)
|
||||
{
|
||||
if (data == null)
|
||||
return;
|
||||
|
||||
// Copy pixel data from DispEngine
|
||||
int n = w * h * 4;
|
||||
byte[] arr = new byte[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
arr[i] = data[i];
|
||||
|
||||
// Update UI on the UI thread
|
||||
DisplayerPane.Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
BitmapSource bitmap = BitmapSource.Create(w, h, 1, 1, PixelFormats.Bgra32, null, arr, w * 4);
|
||||
DisplayerPane.Background = new ImageBrush(bitmap);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the size changed event
|
||||
/// </summary>
|
||||
private void RenderingCanvas_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
// Notify DispEngine of size changes
|
||||
DispEngine.Resize((int)DisplayerPane.RenderSize.Width, (int)DisplayerPane.RenderSize.Height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles visibility changes
|
||||
/// </summary>
|
||||
private unsafe void DisplayerPane_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
// Update visibility state in DispEngine
|
||||
DispEngine.IsVisible = IsVisible;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Keyboard_Events
|
||||
/// <summary>
|
||||
/// Handles the key up event
|
||||
/// </summary>
|
||||
private void RenderingCanvas_KeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
DispEngine.KeyUp((long)e.Key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the key down event
|
||||
/// </summary>
|
||||
private void RenderingCanvas_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
DispEngine.KeyDown((long)e.Key);
|
||||
|
||||
// Map specific keys for view transformation
|
||||
long key = (long)e.Key;
|
||||
if (key == (long)Key.RightShift)
|
||||
key = (long)Key.LeftShift;
|
||||
|
||||
DispEngine.KeyDownTransform(key, new key_table__transform_view_by_key_pressing_t()
|
||||
{
|
||||
HOME = (long)Key.Home,
|
||||
PAGE_UP = (long)Key.PageUp,
|
||||
PAGE_DOWN = (long)Key.PageDown,
|
||||
F1 = (long)Key.F1,
|
||||
F2 = (long)Key.F2,
|
||||
F3 = (long)Key.F3,
|
||||
F4 = (long)Key.F4,
|
||||
SHIFT = (long)Key.LeftShift,
|
||||
ARROW_LEFT = (long)Key.Left,
|
||||
ARROW_RIGHT = (long)Key.Right,
|
||||
ARROW_DOWN = (long)Key.Down,
|
||||
ARROW_UP = (long)Key.Up
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Mouse_Events
|
||||
/// <summary>
|
||||
/// Helper method to get mouse button mask
|
||||
/// </summary>
|
||||
internal static HiMouseButtonMask GetMouseButtonMask(MouseDevice device)
|
||||
{
|
||||
HiMouseButtonMask mouseButtonMask = 0;
|
||||
mouseButtonMask.SetLeftPressed(device.LeftButton == MouseButtonState.Pressed);
|
||||
mouseButtonMask.SetMiddlePressed(device.MiddleButton == MouseButtonState.Pressed);
|
||||
mouseButtonMask.SetRightPressed(device.RightButton == MouseButtonState.Pressed);
|
||||
mouseButtonMask.SetXButton1Pressed(device.XButton1 == MouseButtonState.Pressed);
|
||||
mouseButtonMask.SetXButton2Pressed(device.XButton2 == MouseButtonState.Pressed);
|
||||
return mouseButtonMask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the mouse wheel event
|
||||
/// </summary>
|
||||
private void RenderingCanvas_MouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
// Handle mouse wheel for zoom operations
|
||||
DispEngine.MouseWheel(0, e.Delta / 120);
|
||||
DispEngine.MouseWheelTransform(0, e.Delta / 120);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the mouse up event
|
||||
/// </summary>
|
||||
private void RenderingCanvas_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
// Handle mouse button release
|
||||
DispEngine.MouseButtonUp((long)e.ChangedButton);
|
||||
(sender as UIElement)?.ReleaseMouseCapture();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the mouse down event
|
||||
/// </summary>
|
||||
private void RenderingCanvas_MouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
// Handle mouse button press
|
||||
DispEngine.MouseButtonDown((long)e.ChangedButton);
|
||||
DisplayerPane.Focus();
|
||||
(sender as UIElement)?.CaptureMouse();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the mouse move event
|
||||
/// </summary>
|
||||
private void RenderingCanvas_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
// Update mouse position and handle drag transforms
|
||||
Point p = e.GetPosition(DisplayerPane);
|
||||
DispEngine.MouseMove((int)p.X, (int)p.Y);
|
||||
DispEngine.MouseDragTransform((int)p.X, (int)p.Y,
|
||||
new mouse_button_table__transform_view_by_mouse_drag_t()
|
||||
{
|
||||
LEFT_BUTTON = (long)MouseButton.Left,
|
||||
RIGHT_BUTTON = (long)MouseButton.Right
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Cleanup
|
||||
/// <summary>
|
||||
/// Flag to track disposed state
|
||||
/// </summary>
|
||||
private bool disposedValue;
|
||||
|
||||
/// <summary>
|
||||
/// Disposes managed resources
|
||||
/// </summary>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// Dispose the DispEngine to free resources
|
||||
DispEngine.Dispose();
|
||||
}
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public dispose method to free resources
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using Hi.Disp;
|
||||
using Hi.Licenses;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Hi.Wpf.Disp
|
||||
{
|
||||
/// <summary>
|
||||
/// Window for 3D rendering.
|
||||
/// </summary>
|
||||
public class RenderingWindow : Window, IGetDispEngine
|
||||
{
|
||||
public RenderingCanvas RenderingCanvas => Content as RenderingCanvas;
|
||||
|
||||
/// <summary>
|
||||
/// Ctor.
|
||||
/// </summary>
|
||||
public RenderingWindow()
|
||||
{
|
||||
Title = nameof(RenderingWindow);
|
||||
Height = 450;
|
||||
Width = 800;
|
||||
StateChanged += RenderingWind_StateChanged;
|
||||
Content = new RenderingCanvas()
|
||||
{
|
||||
BorderThickness = new Thickness(1),
|
||||
BorderBrush = Brushes.Black
|
||||
};
|
||||
}
|
||||
private void RenderingWind_StateChanged(object sender, EventArgs e)
|
||||
{
|
||||
RenderingCanvas.DispEngine.IsVisible = WindowState != WindowState.Minimized;
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public DispEngine GetDispEngine() => RenderingCanvas.DispEngine;
|
||||
/// <summary>
|
||||
/// Run a simple <see cref="RenderingWindow"/> application with given <paramref name="displayees"/>.
|
||||
/// </summary>
|
||||
/// <param name="title">Title</param>
|
||||
/// <param name="displayees">displayees</param>
|
||||
/// <returns>return value of <see cref="Application"/>.<see cref="Application.Run(Window)"/></returns>
|
||||
public static int RunApplication(string title, params IDisplayee[] displayees)
|
||||
{
|
||||
License.LogInAll();
|
||||
DispEngine.Init();
|
||||
|
||||
Application app = new Application
|
||||
{
|
||||
ShutdownMode = ShutdownMode.OnMainWindowClose
|
||||
};
|
||||
app.Exit += (o, e) =>
|
||||
{
|
||||
DispEngine.FinishDisp();
|
||||
License.LogOutAll();
|
||||
};
|
||||
RenderingWindow window = new RenderingWindow() { Title = title };
|
||||
window.RenderingCanvas.DispEngine.Displayee = new DispList(displayees);
|
||||
window.RenderingCanvas.DispEngine.SetViewToHomeView();
|
||||
return app.Run(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user