commit 1065c86824cfcad250ebf693ffbb92f67e2c5c88 Author: iambossTC Date: Sun Apr 6 19:55:34 2025 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6d95f9c --- /dev/null +++ b/.gitignore @@ -0,0 +1,268 @@ +!*.lib + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +!hasp*.exe +!hasp*.dll +!HiLock.dll +!Aladdin*.dll diff --git a/AssemblyInfo.cs b/AssemblyInfo.cs new file mode 100644 index 0000000..b0ec827 --- /dev/null +++ b/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/Disp/RenderingCanvas.cs b/Disp/RenderingCanvas.cs new file mode 100644 index 0000000..6045689 --- /dev/null +++ b/Disp/RenderingCanvas.cs @@ -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 + /// + /// The DispEngine instance that handles rendering and user interactions + /// + public DispEngine DispEngine { get; } = new DispEngine(); + + /// + /// Internal container for rendering content + /// + private UserControl DisplayerPane { get; } + + /// + /// Dictionary to store touch point information + /// + private Dictionary TouchingPointsMap { get; } = new Dictionary(); + + /// + /// Dictionary to store previous positions of touch points + /// + private Dictionary PreviousTouchingPointsMap { get; } = new Dictionary(); + #endregion + + #region Initialization + /// + /// Initializes a new instance of the RenderingCanvas + /// + 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 + /// + /// Handles the touch down event + /// + 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; + } + + /// + /// Handles the touch move event + /// + 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; + } + + /// + /// Handles the touch up event + /// + private void RenderingCanvas_TouchUp(object sender, TouchEventArgs e) + { + DispEngine.TouchUp(e.TouchDevice.Id); + e.Handled = true; + } + #endregion + + #region Window_Events + /// + /// Handles window state changes (maximize, minimize, etc.) + /// + 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; + } + } + + /// + /// Handles data context changes + /// + 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; + } + } + + /// + /// Reference to the current window containing this control + /// + private Window currentWindow; + + /// + /// Gets or sets the current window, connecting or disconnecting state change events + /// + Window CurrentWindow + { + get => currentWindow; set + { + if (currentWindow != null) + currentWindow.StateChanged -= RenderingCanvas_StateChanged; + currentWindow = value; + if (currentWindow != null) + currentWindow.StateChanged += RenderingCanvas_StateChanged; + } + } + + /// + /// Handles the loaded event + /// + 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; + } + + /// + /// Handles the unloaded event + /// + private unsafe void RenderingCanvas_Unloaded(object sender, RoutedEventArgs e) + { + DispEngine.IsVisible = IsVisible; + DispEngine.ImageRequestAfterBufferSwapped -= RenderingCanvas_BufferSwapped; + CurrentWindow = null; + } + #endregion + + #region DispEngine_Rendering + /// + /// Handles the buffer swapped event from DispEngine + /// + 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); + }); + } + + /// + /// Handles the size changed event + /// + private void RenderingCanvas_SizeChanged(object sender, SizeChangedEventArgs e) + { + // Notify DispEngine of size changes + DispEngine.Resize((int)DisplayerPane.RenderSize.Width, (int)DisplayerPane.RenderSize.Height); + } + + /// + /// Handles visibility changes + /// + private unsafe void DisplayerPane_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) + { + // Update visibility state in DispEngine + DispEngine.IsVisible = IsVisible; + } + #endregion + + #region Keyboard_Events + /// + /// Handles the key up event + /// + private void RenderingCanvas_KeyUp(object sender, KeyEventArgs e) + { + DispEngine.KeyUp((long)e.Key); + } + + /// + /// Handles the key down event + /// + 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 + /// + /// Helper method to get mouse button mask + /// + 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; + } + + /// + /// Handles the mouse wheel event + /// + 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); + } + + /// + /// Handles the mouse up event + /// + private void RenderingCanvas_MouseUp(object sender, MouseButtonEventArgs e) + { + // Handle mouse button release + DispEngine.MouseButtonUp((long)e.ChangedButton); + (sender as UIElement)?.ReleaseMouseCapture(); + } + + /// + /// Handles the mouse down event + /// + private void RenderingCanvas_MouseDown(object sender, MouseButtonEventArgs e) + { + // Handle mouse button press + DispEngine.MouseButtonDown((long)e.ChangedButton); + DisplayerPane.Focus(); + (sender as UIElement)?.CaptureMouse(); + } + + /// + /// Handles the mouse move event + /// + 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 + /// + /// Flag to track disposed state + /// + private bool disposedValue; + + /// + /// Disposes managed resources + /// + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + // Dispose the DispEngine to free resources + DispEngine.Dispose(); + } + disposedValue = true; + } + } + + /// + /// Public dispose method to free resources + /// + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + #endregion + } + #endregion +} diff --git a/Disp/RenderingWindow.cs b/Disp/RenderingWindow.cs new file mode 100644 index 0000000..2af8d94 --- /dev/null +++ b/Disp/RenderingWindow.cs @@ -0,0 +1,63 @@ +using Hi.Disp; +using Hi.Licenses; +using System; +using System.Windows; +using System.Windows.Media; + +namespace Hi.Wpf.Disp +{ + /// + /// Window for 3D rendering. + /// + public class RenderingWindow : Window, IGetDispEngine + { + public RenderingCanvas RenderingCanvas => Content as RenderingCanvas; + + /// + /// Ctor. + /// + 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; + } + /// + public DispEngine GetDispEngine() => RenderingCanvas.DispEngine; + /// + /// Run a simple application with given . + /// + /// Title + /// displayees + /// return value of . + 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); + } + } +} diff --git a/Hi.Wpf.csproj b/Hi.Wpf.csproj new file mode 100644 index 0000000..531b216 --- /dev/null +++ b/Hi.Wpf.csproj @@ -0,0 +1,40 @@ + + + true + true + Exe + net9.0-windows + x64 + true + Hi.Wpf + $(AssemblyName) + + HiAPI samples for windows platform. + + Debug;Release + 3 + 1.4.$(VersionBuild) + $(AssemblyName) + techcoordinate.ico + Copyright 2022 Tech Coordinate Co., Ltd. + Tech Coordinate Co., Ltd. + Tech Coordinate Co., Ltd. + bin\$(Platform).$(Configuration)\ + Hi.Wpf.Program + + + + + + + + + true + true + true + true + + + DEBUG;TRACE + + \ No newline at end of file diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..1c7b276 --- /dev/null +++ b/Program.cs @@ -0,0 +1,19 @@ +using Hi.Disp; +using Hi.Disp.Flag; +using Hi.Geom; +using Hi.Wpf.Disp; +using System; + +namespace Hi.Wpf +{ + static class Program + { + [STAThread] + public static void Main(string[] args) + { + DispEngine.Init(); + RenderingWindow.RunApplication("test", + new CoordinateDrawing(), new Stl(Box3d.CenterUnitBox).ToFaceDrawing()); + } + } +} diff --git a/Properties/launchSettings.json b/Properties/launchSettings.json new file mode 100644 index 0000000..dbe55fa --- /dev/null +++ b/Properties/launchSettings.json @@ -0,0 +1,10 @@ +{ + "profiles": { + "HiAPI-Demo-WPF": { + "commandName": "Project", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/techcoordinate.ico b/techcoordinate.ico new file mode 100644 index 0000000..1aa69ce Binary files /dev/null and b/techcoordinate.ico differ