|
|
|
@ -2,6 +2,7 @@ using System.Text.Json.Nodes; |
|
|
|
|
using System.Windows; |
|
|
|
|
using System.Windows.Controls; |
|
|
|
|
using System.Windows.Input; |
|
|
|
|
using System.Windows.Media.Media3D; |
|
|
|
|
using HandyControl.Controls; |
|
|
|
|
using HelixToolkit.Wpf.SharpDX; |
|
|
|
|
using SharpDX; |
|
|
|
@ -13,210 +14,353 @@ namespace SparkClient.Views.UserControl; |
|
|
|
|
|
|
|
|
|
public partial class Viewport3D |
|
|
|
|
{ |
|
|
|
|
// 注册一个依赖属性,类型是 Viewport3DData |
|
|
|
|
public static readonly DependencyProperty ViewportDataProperty = |
|
|
|
|
DependencyProperty.Register( |
|
|
|
|
nameof(ViewportData), |
|
|
|
|
typeof(ViewportData.ViewportData), |
|
|
|
|
typeof(Viewport3D), |
|
|
|
|
new PropertyMetadata(null, OnViewportDataChanged)); |
|
|
|
|
|
|
|
|
|
// 公开的 CLR 属性包装器 |
|
|
|
|
public ViewportData.ViewportData ViewportData |
|
|
|
|
public Viewport3D() |
|
|
|
|
{ |
|
|
|
|
get => (ViewportData.ViewportData)GetValue(ViewportDataProperty); |
|
|
|
|
set => SetValue(ViewportDataProperty, value); |
|
|
|
|
InitializeComponent(); |
|
|
|
|
DataContext = this; |
|
|
|
|
this.Viewport3Dx.EffectsManager = new DefaultEffectsManager(); |
|
|
|
|
Viewport3Dx.ShowViewCube = false; |
|
|
|
|
Viewport3Dx.ShowCoordinateSystem = false; |
|
|
|
|
ViewportManager.SetViewport3D(Viewport3Dx); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 当 ViewportData 属性发生变化时触发 |
|
|
|
|
private static void OnViewportDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|
|
|
|
/// <summary> |
|
|
|
|
/// 初始化 |
|
|
|
|
/// </summary> |
|
|
|
|
/// <param name="sender"></param> |
|
|
|
|
/// <param name="e"></param> |
|
|
|
|
private void Viewport3D_OnLoaded(object sender, RoutedEventArgs e) |
|
|
|
|
{ |
|
|
|
|
if (d is Viewport3D control && e.NewValue is ViewportData.ViewportData data) |
|
|
|
|
{ |
|
|
|
|
control.Initialize(data); |
|
|
|
|
} |
|
|
|
|
ViewportManager.LoadModelByEntities(new List<Viewport3DTriangleEntity>()); |
|
|
|
|
|
|
|
|
|
//选项初始化 显示-后端-管理类 一致 |
|
|
|
|
ViewportRightMenuSelectFaceFrame.IsEnabled = ViewportRightMenuSelectFace.IsChecked ; |
|
|
|
|
ViewportRightMenuSelectFaceLengthText.IsEnabled = ViewportRightMenuSelectFace.IsChecked ; |
|
|
|
|
ViewportRightMenuSelectFaceAngleText.IsEnabled = ViewportRightMenuSelectFace.IsChecked ; |
|
|
|
|
ViewportRightMenuSelectFaceKind.IsEnabled = ViewportRightMenuSelectFace.IsChecked ; |
|
|
|
|
ViewportRightMenuShowModelFace.IsChecked = true; |
|
|
|
|
ViewportRightMenuShowModelFrame.IsChecked = true; |
|
|
|
|
ViewportRightMenuShowLighting.IsChecked = true; |
|
|
|
|
ViewportRightMenuSelectFace.IsChecked = ViewportManager.DoubleClickSelect; |
|
|
|
|
ViewportRightMenuSelectFaceFrame.IsChecked = ViewportManager.DoubleClickSelectShowBorder; |
|
|
|
|
ViewportRightMenuSelectFaceLengthText.IsChecked = ViewportManager.DoubleClickSelectShowBorderLength; |
|
|
|
|
ViewportRightMenuSelectFaceAngleText.IsChecked = ViewportManager.DoubleClickSelectShowBorderAngle; |
|
|
|
|
ViewportRightMenuSelectFaceKind.IsChecked = ViewportManager.DoubleClickSelectShowPlaneType; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void Initialize(ViewportData.ViewportData vpData) |
|
|
|
|
/// <summary> |
|
|
|
|
/// 双击选择面 |
|
|
|
|
/// </summary> |
|
|
|
|
/// <param name="sender"></param> |
|
|
|
|
/// <param name="e"></param> |
|
|
|
|
private void Viewport3Dx_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) |
|
|
|
|
{ |
|
|
|
|
// 根据 Viewport3DData 的内容初始化控件 |
|
|
|
|
// 例如:设置控件内部的某些属性,渲染 3D 模型等 |
|
|
|
|
if (!string.IsNullOrEmpty(vpData.DiamondData)) |
|
|
|
|
if (ViewportManager.DoubleClickSelect == false) return; |
|
|
|
|
|
|
|
|
|
var mousePosition = e.GetPosition(Viewport3Dx); |
|
|
|
|
var hits = Viewport3Dx.FindHits(mousePosition); |
|
|
|
|
// 如果没有命中任何 3D 对象 |
|
|
|
|
if (hits == null || hits.Count == 0) |
|
|
|
|
{ |
|
|
|
|
JsonNode? json = null; |
|
|
|
|
try |
|
|
|
|
{ |
|
|
|
|
json = JsonNode.Parse(vpData.DiamondData); |
|
|
|
|
} |
|
|
|
|
catch |
|
|
|
|
{ |
|
|
|
|
throw new Exception("DiamondData is invalid"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(json == null) throw new Exception("DiamondData is invalid"); |
|
|
|
|
ViewportManager.ClearDicModels(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
try |
|
|
|
|
// 获取第一个命中的对象 |
|
|
|
|
var hit = hits[0]; |
|
|
|
|
// 检查是否是 MeshGeometryModel3D |
|
|
|
|
if (hit.ModelHit is MeshGeometryModel3D modelHit) |
|
|
|
|
{ |
|
|
|
|
// 获取几何信息 |
|
|
|
|
var geometry = modelHit.Geometry as HelixToolkit.Wpf.SharpDX.MeshGeometry3D; |
|
|
|
|
if (geometry != null) |
|
|
|
|
{ |
|
|
|
|
List<Viewport3DTriangleEntity> facets = new List<Viewport3DTriangleEntity>(); |
|
|
|
|
if (json.AsObject()["facets"] != null) |
|
|
|
|
{ |
|
|
|
|
JsonArray jsonArray = json.AsObject()["facets"].AsArray(); |
|
|
|
|
foreach (var item in jsonArray) |
|
|
|
|
{ |
|
|
|
|
var value = CommonHelper.CreateByJsonStr(item.ToString()); |
|
|
|
|
facets.Add(value); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
throw new Exception("facets is invalid"); |
|
|
|
|
} |
|
|
|
|
// 获取命中的三角形索引 |
|
|
|
|
var triangleIndex = hit.TriangleIndices; |
|
|
|
|
|
|
|
|
|
if (json.AsObject()["positive_direction"] != null) |
|
|
|
|
{ |
|
|
|
|
JsonObject positive = json.AsObject()["positive_direction"].AsObject(); |
|
|
|
|
ViewportManager.PositiveDirection.X = float.Parse(positive["x"]?.ToString() ?? "1.0"); |
|
|
|
|
ViewportManager.PositiveDirection.Y = float.Parse(positive["z"]?.ToString() ?? "0"); |
|
|
|
|
ViewportManager.PositiveDirection.Z = float.Parse(positive["y"]?.ToString() ?? "0"); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
ViewportManager.PositiveDirection.X = 1.0f; |
|
|
|
|
ViewportManager.PositiveDirection.Y = 0f; |
|
|
|
|
ViewportManager.PositiveDirection.Z = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var midZ = facets.SelectMany(e => new[] { e.Point1.X, e.Point2.X, e.Point3.X }).OrderBy(z => Math.Abs(z)) |
|
|
|
|
.First(); |
|
|
|
|
List<Viewport3DTriangleEntity> facetsFinal = new List<Viewport3DTriangleEntity>(); |
|
|
|
|
foreach (var item in facets) |
|
|
|
|
{ |
|
|
|
|
var data = ViewportHelperPro.VectorClockwiseSort(new List<Vector3> |
|
|
|
|
{ item.Point1, item.Point2, item.Point3 }); |
|
|
|
|
|
|
|
|
|
if (item.PlaneType == PlaneType.StarFacet || item.PlaneType == PlaneType.UpperGirdleFacet || |
|
|
|
|
item.PlaneType == PlaneType.UpperMainFacet || item.PlaneType == PlaneType.TableFacet) |
|
|
|
|
{ |
|
|
|
|
item.Point1 = data[0]; |
|
|
|
|
item.Point2 = data[1]; |
|
|
|
|
item.Point3 = data[2]; |
|
|
|
|
} |
|
|
|
|
else if (item.PlaneType == PlaneType.Girdle) |
|
|
|
|
{ |
|
|
|
|
var center = ViewportHelperPro.GetCentroid(data); |
|
|
|
|
data.Sort((v1, v2) => |
|
|
|
|
{ |
|
|
|
|
double angle1 = Math.Atan2(v1.Y - center.Y, v1.X - center.X); |
|
|
|
|
double angle2 = Math.Atan2(v2.Y - center.Y, v2.X - center.X); |
|
|
|
|
return angle1.CompareTo(angle2); |
|
|
|
|
}); |
|
|
|
|
if (center.Z >= midZ) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
item.Point1 = data[0]; |
|
|
|
|
item.Point2 = data[1]; |
|
|
|
|
item.Point3 = data[2]; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
item.Point1 = data[2]; |
|
|
|
|
item.Point2 = data[1]; |
|
|
|
|
item.Point3 = data[0]; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
item.Point1 = data[2]; |
|
|
|
|
item.Point2 = data[1]; |
|
|
|
|
item.Point3 = data[0]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
item.TriangleCode = CommonHelper.GenerateTriangleCode(item.Point1, item.Point2, item.Point3); |
|
|
|
|
facetsFinal.Add(item); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ViewportManager.ViewportTriangle.AddRange(facetsFinal); |
|
|
|
|
ViewportManager.LoadModelByEntities(facetsFinal); |
|
|
|
|
} |
|
|
|
|
catch (Exception ex) |
|
|
|
|
{ |
|
|
|
|
throw new Exception(ex.Message); |
|
|
|
|
// 获取三角形顶点 |
|
|
|
|
var vertex1 = geometry.Positions[triangleIndex.Item1]; |
|
|
|
|
var vertex2 = geometry.Positions[triangleIndex.Item2]; |
|
|
|
|
var vertex3 = geometry.Positions[triangleIndex.Item3]; |
|
|
|
|
|
|
|
|
|
ViewportManager.ChooseTriangleCode = CommonHelper.GenerateTriangleCode(vertex1, vertex2, vertex3); |
|
|
|
|
ViewportManager.ResetChooseAddModels(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
ViewportManager.ClearDicModels(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public Viewport3D() |
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
/// 顶部按钮 - 视角切换 |
|
|
|
|
/// </summary> |
|
|
|
|
/// <param name="sender"></param> |
|
|
|
|
/// <param name="e"></param> |
|
|
|
|
/// <exception cref="NotImplementedException"></exception> |
|
|
|
|
private void BtnAngle_OnClick(object sender, RoutedEventArgs e) |
|
|
|
|
{ |
|
|
|
|
InitializeComponent(); |
|
|
|
|
DataContext = this; |
|
|
|
|
this.Viewport3Dx.EffectsManager = new DefaultEffectsManager(); |
|
|
|
|
ViewportManager.SetViewport3D(Viewport3Dx); |
|
|
|
|
var directionName = ((Button)sender).Name.ToString(); |
|
|
|
|
var directionValue = (int) TbCustomizeRevolve.Value; |
|
|
|
|
|
|
|
|
|
var center = ViewportManager.ModelBounds.Center; |
|
|
|
|
var maxDimension = ViewportManager.ModelBounds.Size.Length(); |
|
|
|
|
var distance = maxDimension *1.2; // 调整相机到模型的距离,保证视野范围内 |
|
|
|
|
// 获取当前相机 |
|
|
|
|
var camera = Viewport3Dx.Camera as HelixToolkit.Wpf.SharpDX.PerspectiveCamera; |
|
|
|
|
|
|
|
|
|
switch (directionName) |
|
|
|
|
{ |
|
|
|
|
case "BtnFrontView": |
|
|
|
|
//测 |
|
|
|
|
camera.Position = new Point3D(center.X, center.Y, center.Z + distance); // 从前面看,Z轴正方向 |
|
|
|
|
camera.UpDirection = new Vector3D(0, -1, 0); |
|
|
|
|
break; |
|
|
|
|
break; |
|
|
|
|
case "BtnTopView": |
|
|
|
|
//顶、 |
|
|
|
|
camera.Position = new Point3D(center.X, center.Y - distance, center.Z); // 从底部看,Y轴负方向 |
|
|
|
|
camera.UpDirection = new Vector3D(0, 0, -1); |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
case "BtnBottomView": |
|
|
|
|
//低 |
|
|
|
|
camera.Position = new Point3D(center.X, center.Y + distance, center.Z); // 从顶部看,Y轴正方向 |
|
|
|
|
camera.UpDirection = new Vector3D(0, 0, 1); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
camera.LookDirection = new Vector3D(center.X - camera.Position.X, center.Y - camera.Position.Y, center.Z - camera.Position.Z); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#region 菜单事件绑定 |
|
|
|
|
private void MenuItem_OnChecked(object sender, RoutedEventArgs e) |
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
/// 按钮调整相机方向[底部按钮] |
|
|
|
|
/// </summary> |
|
|
|
|
/// <param name="sender"></param> |
|
|
|
|
/// <param name="e"></param> |
|
|
|
|
private void BtnDirection_OnClick(object sender, RoutedEventArgs e) |
|
|
|
|
{ |
|
|
|
|
Growl.InfoGlobal("Viewport is checked" + e.OriginalSource); |
|
|
|
|
var directionName = ((Button)sender).Name.ToString(); |
|
|
|
|
var directionValue = (int) TbCustomizeRevolve.Value; |
|
|
|
|
|
|
|
|
|
switch (directionName) |
|
|
|
|
{ |
|
|
|
|
case "BtnTop": |
|
|
|
|
//上 |
|
|
|
|
break; |
|
|
|
|
case "BtnBottom": |
|
|
|
|
//下 |
|
|
|
|
break; |
|
|
|
|
case "BtnLeft": |
|
|
|
|
//左 |
|
|
|
|
break; |
|
|
|
|
case "BtnRight": |
|
|
|
|
//右 |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void MenuItem_OnUnchecked(object sender, RoutedEventArgs e) |
|
|
|
|
|
|
|
|
|
#region 右键菜单事件绑定 |
|
|
|
|
/// <summary> |
|
|
|
|
/// 右键选择 |
|
|
|
|
/// </summary> |
|
|
|
|
/// <param name="sender"></param> |
|
|
|
|
/// <param name="e"></param> |
|
|
|
|
private void MenuItem_OnCheckedChanged(object sender, RoutedEventArgs e) |
|
|
|
|
{ |
|
|
|
|
Growl.InfoGlobal("Viewport is Unchecked" + e.OriginalSource); |
|
|
|
|
ViewportRightMenuSelectFaceFrame.IsEnabled = ViewportRightMenuSelectFace.IsChecked ; |
|
|
|
|
ViewportRightMenuSelectFaceLengthText.IsEnabled = ViewportRightMenuSelectFace.IsChecked ; |
|
|
|
|
ViewportRightMenuSelectFaceAngleText.IsEnabled = ViewportRightMenuSelectFace.IsChecked ; |
|
|
|
|
ViewportRightMenuSelectFaceKind.IsEnabled = ViewportRightMenuSelectFace.IsChecked ; |
|
|
|
|
|
|
|
|
|
var controlName = ((MenuItem)sender).Name.ToString(); |
|
|
|
|
var checkResult = (bool)((MenuItem)sender).IsChecked; |
|
|
|
|
switch (controlName) |
|
|
|
|
{ |
|
|
|
|
case "ViewportRightMenuShowModelFace": |
|
|
|
|
//显示模型面 |
|
|
|
|
ViewportManager.ShowMainModel3D(checkResult); |
|
|
|
|
break; |
|
|
|
|
case "ViewportRightMenuShowModelFrame": |
|
|
|
|
//显示模型边框 |
|
|
|
|
ViewportManager.ShowMainModelLines(checkResult); |
|
|
|
|
break; |
|
|
|
|
case "ViewportRightMenuShowLighting": |
|
|
|
|
//显示光照 |
|
|
|
|
ViewportManager.ShowMainModelLighting(checkResult); |
|
|
|
|
break; |
|
|
|
|
case "ViewportRightMenuShowDefectFace": |
|
|
|
|
//显示瑕疵面 |
|
|
|
|
ViewportManager.MarkSpecificFaces(checkResult); |
|
|
|
|
break; |
|
|
|
|
case "ViewportRightMenuShowFront": |
|
|
|
|
//显示正方向箭头 |
|
|
|
|
ViewportManager.PointTowardsTheFront(checkResult); |
|
|
|
|
break; |
|
|
|
|
case "ViewportRightMenuSelectFace": |
|
|
|
|
//双击选择面 |
|
|
|
|
ViewportManager.DoubleClickSelect = checkResult; |
|
|
|
|
ViewportManager.ClearDicModels(); |
|
|
|
|
break; |
|
|
|
|
case "ViewportRightMenuSelectFaceFrame": |
|
|
|
|
//双击选择面的边框 |
|
|
|
|
ViewportManager.DoubleClickSelectShowBorder = checkResult; |
|
|
|
|
ViewportManager.ResetChooseAddModels(); |
|
|
|
|
break; |
|
|
|
|
case "ViewportRightMenuSelectFaceLengthText": |
|
|
|
|
//双击选择面的边框长度文字 |
|
|
|
|
ViewportManager.DoubleClickSelectShowBorderLength = checkResult; |
|
|
|
|
ViewportManager.ResetChooseAddModels(); |
|
|
|
|
break; |
|
|
|
|
case "ViewportRightMenuSelectFaceAngleText": |
|
|
|
|
//双击选择面的边框夹角文字 |
|
|
|
|
ViewportManager.DoubleClickSelectShowBorderAngle = checkResult; |
|
|
|
|
ViewportManager.ResetChooseAddModels(); |
|
|
|
|
break; |
|
|
|
|
case "ViewportRightMenuSelectFaceKind": |
|
|
|
|
//双击选择面的选择同类面 |
|
|
|
|
ViewportManager.DoubleClickSelectShowPlaneType = checkResult; |
|
|
|
|
ViewportManager.ResetChooseAddModels(); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
/// <summary> |
|
|
|
|
/// 右键按钮 |
|
|
|
|
/// </summary> |
|
|
|
|
/// <param name="sender"></param> |
|
|
|
|
/// <param name="e"></param> |
|
|
|
|
private void MenuItem_OnClick(object sender, RoutedEventArgs e) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
var controlName = ((MenuItem)sender).Name.ToString(); |
|
|
|
|
switch (controlName) |
|
|
|
|
{ |
|
|
|
|
case "ViewportRightMenuFront": |
|
|
|
|
//切换到正面 |
|
|
|
|
var Camear = |
|
|
|
|
ViewportHelperPro.CalculateCamera(ViewportManager.PositiveDirection, ViewportManager.ModelBounds); |
|
|
|
|
Viewport3Dx.Camera.Position = Camear.Position; |
|
|
|
|
Viewport3Dx.Camera.LookDirection = Camear.LookDirection; |
|
|
|
|
Viewport3Dx.Camera.UpDirection = new Vector3D(Camear.UpDirection.X, Camear.UpDirection.Y*-1, Camear.UpDirection.Z); |
|
|
|
|
break; |
|
|
|
|
case "ViewportRightMenuSaveViewToPNG": |
|
|
|
|
//保存图片 |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endregion |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region 页面隐式交互 |
|
|
|
|
|
|
|
|
|
public static readonly DependencyProperty ViewportDataProperty = |
|
|
|
|
DependencyProperty.Register( |
|
|
|
|
nameof(ViewportData), |
|
|
|
|
typeof(ViewportData.ViewportData), |
|
|
|
|
typeof(Viewport3D), |
|
|
|
|
new PropertyMetadata(null, OnViewportDataChanged)); |
|
|
|
|
|
|
|
|
|
public ViewportData.ViewportData ViewportData |
|
|
|
|
{ |
|
|
|
|
get => (ViewportData.ViewportData)GetValue(ViewportDataProperty); |
|
|
|
|
set => SetValue(ViewportDataProperty, value); |
|
|
|
|
} |
|
|
|
|
private static void OnViewportDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|
|
|
|
{ |
|
|
|
|
if (d is Viewport3D control && e.NewValue is ViewportData.ViewportData data) |
|
|
|
|
{ |
|
|
|
|
control.Initialize(data); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void Initialize(ViewportData.ViewportData vpData) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private System.Windows.Point _mouseDownPosition; |
|
|
|
|
private bool _isDragging = false; |
|
|
|
|
private void UIElement_OnPreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e) |
|
|
|
|
{ |
|
|
|
|
if (_isDragging) |
|
|
|
|
{ |
|
|
|
|
// 如果发生拖动,不显示菜单 |
|
|
|
|
_isDragging = false; // 重置拖动状态 |
|
|
|
|
_isDragging = false; |
|
|
|
|
MainBorder.ContextMenu.Visibility = Visibility.Hidden; |
|
|
|
|
MainBorder.ContextMenu.IsOpen = false; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
MainBorder.ContextMenu.Visibility = Visibility.Visible; |
|
|
|
|
// 未拖动时,显示右键菜单 |
|
|
|
|
MainBorder.ContextMenu.IsOpen = true; |
|
|
|
|
// e.Handled = true; // 阻止事件继续传播 |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void UIElement_OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) |
|
|
|
|
{ |
|
|
|
|
_mouseDownPosition = e.GetPosition(Viewport3Dx); |
|
|
|
|
_isDragging = false; // 重置拖动状态 |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
#endregion |
|
|
|
|
|
|
|
|
|
private void Viewport3D_OnLoaded(object sender, RoutedEventArgs e) |
|
|
|
|
{ |
|
|
|
|
//ViewportData.LoadData(); |
|
|
|
|
ViewportManager.LoadModelByEntities(new List<Viewport3DTriangleEntity>()); |
|
|
|
|
_isDragging = false; |
|
|
|
|
if (MainBorder.ContextMenu.Visibility == Visibility.Visible) |
|
|
|
|
{ |
|
|
|
|
MainBorder.ContextMenu.Visibility = Visibility.Hidden; |
|
|
|
|
MainBorder.ContextMenu.IsOpen = false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void Viewport3Dx_OnPreviewMouseMove(object sender, MouseEventArgs e) |
|
|
|
|
{ |
|
|
|
|
if (e.RightButton == MouseButtonState.Pressed) |
|
|
|
|
{ |
|
|
|
|
// 计算鼠标移动距离 |
|
|
|
|
var currentPosition = e.GetPosition(Viewport3Dx); |
|
|
|
|
var distance = (currentPosition - _mouseDownPosition).Length; |
|
|
|
|
MainBorder.ContextMenu.Visibility = Visibility.Hidden; |
|
|
|
|
MainBorder.ContextMenu.IsOpen = false; |
|
|
|
|
if (distance > 5) |
|
|
|
|
{ |
|
|
|
|
_isDragging = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
private void TbCustomizeRevolve_OnPreviewTextInput(object sender, TextCompositionEventArgs e) |
|
|
|
|
{ |
|
|
|
|
e.Handled = !CommonHelper.IsTextNumeric(e.Text); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void TbCustomizeRevolve_OnPreviewKeyDown(object sender, KeyEventArgs e) |
|
|
|
|
{ |
|
|
|
|
if (e.Key == Key.Back || e.Key == Key.Delete || e.Key == Key.Tab || e.Key == Key.Left || e.Key == Key.Right) |
|
|
|
|
{ |
|
|
|
|
e.Handled = false; // 不拦截 |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
e.Handled = !CommonHelper.IsKeyNumeric(e.Key); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void TbCustomizeRevolve_OnTextChanged(object sender, TextChangedEventArgs e) |
|
|
|
|
{ |
|
|
|
|
var textBox = sender as System.Windows.Controls.TextBox; |
|
|
|
|
|
|
|
|
|
// 判断是否达到拖动的阈值 |
|
|
|
|
if (distance > 5) // 阈值可根据需要调整 |
|
|
|
|
if (int.TryParse(textBox.Text, out int value)) |
|
|
|
|
{ |
|
|
|
|
if (value < 0) |
|
|
|
|
{ |
|
|
|
|
_isDragging = true; // 标记为拖动 |
|
|
|
|
textBox.Text = "0"; // 如果小于0,重置为0 |
|
|
|
|
} |
|
|
|
|
else if (value > 360) |
|
|
|
|
{ |
|
|
|
|
textBox.Text = "360"; // 如果大于360,重置为360 |
|
|
|
|
} |
|
|
|
|
textBox.SelectionStart = textBox.Text.Length; // 保持光标在文本末尾 |
|
|
|
|
} |
|
|
|
|
else if (!string.IsNullOrWhiteSpace(textBox.Text)) |
|
|
|
|
{ |
|
|
|
|
textBox.Text = "0"; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endregion |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |