3020 lines
120 KiB
C#
3020 lines
120 KiB
C#
using Autodesk.Navisworks.Api;
|
||
using Autodesk.Navisworks.Api.Plugins;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.ComponentModel;
|
||
using System.Drawing;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Windows.Forms;
|
||
using NavisApplication = Autodesk.Navisworks.Api.Application;
|
||
|
||
namespace NavisworksTransport
|
||
{
|
||
/// <summary>
|
||
/// 全局异常处理工具类
|
||
/// </summary>
|
||
public static class GlobalExceptionHandler
|
||
{
|
||
private static bool _isInitialized = false;
|
||
|
||
/// <summary>
|
||
/// 初始化全局异常处理器
|
||
/// </summary>
|
||
public static void Initialize()
|
||
{
|
||
if (_isInitialized) return;
|
||
|
||
try
|
||
{
|
||
// 捕获未处理的异常
|
||
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
|
||
System.Windows.Forms.Application.ThreadException += OnThreadException;
|
||
_isInitialized = true;
|
||
|
||
LogManager.Info("[全局异常] 全局异常处理器已初始化");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"[全局异常] 初始化异常处理器失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理未捕获的异常
|
||
/// </summary>
|
||
private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||
{
|
||
try
|
||
{
|
||
Exception ex = e.ExceptionObject as Exception;
|
||
string message = ex?.Message ?? "未知异常";
|
||
string stackTrace = ex?.StackTrace ?? "无堆栈信息";
|
||
|
||
LogManager.Error($"[全局异常] 未处理异常: {message}");
|
||
LogManager.Error($"[全局异常] 堆栈信息: {stackTrace}");
|
||
LogManager.Error($"[全局异常] 异常类型: {ex?.GetType().Name ?? "Unknown"}");
|
||
LogManager.Error($"[全局异常] 是否终止: {e.IsTerminating}");
|
||
|
||
// 显示用户友好的错误信息
|
||
ShowErrorDialog("程序发生未预期的错误", message, ex);
|
||
|
||
// 尝试恢复关键组件
|
||
TryRecoverComponents();
|
||
}
|
||
catch
|
||
{
|
||
// 异常处理中的异常,保持静默
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理线程异常
|
||
/// </summary>
|
||
private static void OnThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
|
||
{
|
||
try
|
||
{
|
||
Exception ex = e.Exception;
|
||
LogManager.Error($"[全局异常] 线程异常: {ex.Message}");
|
||
LogManager.Error($"[全局异常] 堆栈信息: {ex.StackTrace}");
|
||
LogManager.Error($"[全局异常] 异常类型: {ex.GetType().Name}");
|
||
|
||
// 显示用户友好的错误信息
|
||
ShowErrorDialog("程序发生线程错误", ex.Message, ex);
|
||
|
||
// 尝试恢复关键组件
|
||
TryRecoverComponents();
|
||
}
|
||
catch
|
||
{
|
||
// 异常处理中的异常,保持静默
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 安全执行方法,捕获所有异常
|
||
/// </summary>
|
||
public static T SafeExecute<T>(Func<T> action, T defaultValue = default(T), string operationName = "操作")
|
||
{
|
||
try
|
||
{
|
||
return action();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"[安全执行] {operationName}失败: {ex.Message}");
|
||
LogManager.Error($"[安全执行] 堆栈信息: {ex.StackTrace}");
|
||
LogManager.Error($"[安全执行] 异常类型: {ex.GetType().Name}");
|
||
|
||
// 对于用户操作,显示简短的错误提示
|
||
if (!string.IsNullOrEmpty(operationName) && operationName != "操作")
|
||
{
|
||
ShowErrorToast($"{operationName}失败: {ex.Message}");
|
||
}
|
||
|
||
return defaultValue;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 安全执行方法(无返回值)
|
||
/// </summary>
|
||
public static void SafeExecute(Action action, string operationName = "操作")
|
||
{
|
||
SafeExecute(() => { action(); return true; }, false, operationName);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示错误对话框
|
||
/// </summary>
|
||
private static void ShowErrorDialog(string title, string message, Exception ex = null)
|
||
{
|
||
try
|
||
{
|
||
string detailMessage = message;
|
||
if (ex != null)
|
||
{
|
||
detailMessage += $"\n\n技术详情: {ex.GetType().Name}";
|
||
if (!string.IsNullOrEmpty(ex.Message))
|
||
{
|
||
detailMessage += $"\n错误信息: {ex.Message}";
|
||
}
|
||
}
|
||
|
||
MessageBox.Show(detailMessage, title, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
catch
|
||
{
|
||
// 如果连错误对话框都显示不了,就保持静默
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示简短的错误提示
|
||
/// </summary>
|
||
private static void ShowErrorToast(string message)
|
||
{
|
||
try
|
||
{
|
||
MessageBox.Show(message, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||
}
|
||
catch
|
||
{
|
||
// 保持静默
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 尝试恢复关键组件
|
||
/// </summary>
|
||
private static void TryRecoverComponents()
|
||
{
|
||
try
|
||
{
|
||
LogManager.Info("[全局异常] 尝试恢复关键组件...");
|
||
|
||
// 尝试重置路径编辑状态
|
||
var activeManager = PathPlanningManager.GetActivePathManager();
|
||
if (activeManager != null)
|
||
{
|
||
activeManager.ResetPathEditState();
|
||
LogManager.Info("[全局异常] 已重置路径编辑状态");
|
||
}
|
||
|
||
// 尝试清除临时高亮
|
||
if (NavisApplication.ActiveDocument?.Models != null)
|
||
{
|
||
NavisApplication.ActiveDocument.Models.ResetAllTemporaryMaterials();
|
||
LogManager.Info("[全局异常] 已清除临时材质");
|
||
}
|
||
|
||
LogManager.Info("[全局异常] 组件恢复完成");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"[全局异常] 组件恢复失败: {ex.Message}");
|
||
}
|
||
}
|
||
}
|
||
|
||
[PluginAttribute("Basic", "Tian", ToolTip = "Transport Plugin", DisplayName = "Transport Plugin")]
|
||
[AddInPlugin(AddInLocation.AddIn)] // 将插件显示在Navisworks的"附加模块"选项卡中
|
||
public class Main : AddInPlugin
|
||
{
|
||
/// <summary>
|
||
/// 会话初始化标志,用于确保在同一Navisworks会话中只清空一次日志
|
||
/// </summary>
|
||
private static bool _isSessionInitialized = false;
|
||
|
||
// 静态变量保存控制面板实例,避免重复创建
|
||
private static Form _controlPanelForm = null;
|
||
|
||
// 保存关键UI控件引用,用于实时更新
|
||
private static Label _instructionLabel = null;
|
||
private static Label _selectedModelsLabel = null;
|
||
private static ListView _logisticsListView = null;
|
||
private static Label _statsLabel = null;
|
||
|
||
// 动画管理器实例(类级别变量)
|
||
private static PathAnimationManager _animationManager;
|
||
|
||
// 路径规划管理器实例
|
||
private static PathPlanningManager _pathPlanningManager;
|
||
|
||
// 路径编辑UI控件引用
|
||
private static ListView _pathListView = null;
|
||
private static Label _currentPathStatusLabel = null;
|
||
private static ListView _currentPathPointsListView = null; // 使用ListView替代ListBox
|
||
|
||
public override int Execute(params string[] parameters)
|
||
{
|
||
return GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
// 初始化会话(只执行一次)
|
||
if (!_isSessionInitialized)
|
||
{
|
||
InitializeSession();
|
||
_isSessionInitialized = true;
|
||
}
|
||
|
||
// 显示控制面板
|
||
ShowDockPane();
|
||
return 0;
|
||
|
||
}, -1, "插件初始化");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示左侧控制面板(无模态对话框)
|
||
/// </summary>
|
||
private void ShowDockPane()
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
// 如果面板已存在,直接显示并置前
|
||
if (_controlPanelForm != null && !_controlPanelForm.IsDisposed)
|
||
{
|
||
_controlPanelForm.Show();
|
||
_controlPanelForm.BringToFront();
|
||
_controlPanelForm.Focus();
|
||
LogManager.Info("控制面板已显示并置前");
|
||
return;
|
||
}
|
||
|
||
// 创建新的控制面板
|
||
ShowCategorySelectionDialog();
|
||
|
||
}, "显示控制面板");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化插件会话
|
||
/// </summary>
|
||
private void InitializeSession()
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
LogManager.Info("=== 物流路径规划插件初始化开始 ===");
|
||
|
||
// 初始化全局异常处理
|
||
GlobalExceptionHandler.Initialize();
|
||
|
||
// 初始化路径规划管理器
|
||
InitializePathPlanningManager();
|
||
|
||
LogManager.Info("插件会话初始化完成");
|
||
|
||
}, "初始化会话");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化路径规划管理器并设置事件订阅
|
||
/// </summary>
|
||
private void InitializePathPlanningManager()
|
||
{
|
||
try
|
||
{
|
||
LogManager.Info("开始初始化PathPlanningManager");
|
||
|
||
// 创建或获取PathPlanningManager实例
|
||
_pathPlanningManager = PathPlanningManager.GetActivePathManager() ?? new PathPlanningManager();
|
||
|
||
// 订阅路径编辑状态变更事件
|
||
_pathPlanningManager.PathEditStateChanged += OnPathEditStateChanged;
|
||
|
||
// 订阅路径点相关事件
|
||
_pathPlanningManager.PathPointAddedIn3D += OnPathPointAddedIn3D;
|
||
_pathPlanningManager.PathPointRemovedFrom3D += OnPathPointRemovedFrom3D;
|
||
_pathPlanningManager.PathPointsListUpdated += OnPathPointsListUpdated;
|
||
|
||
// 订阅路径变更事件
|
||
_pathPlanningManager.CurrentRouteChanged += OnCurrentRouteChanged;
|
||
|
||
// 订阅状态和错误事件
|
||
_pathPlanningManager.StatusChanged += OnPathManagerStatusChanged;
|
||
_pathPlanningManager.ErrorOccurred += OnPathManagerErrorOccurred;
|
||
|
||
LogManager.Info("PathPlanningManager初始化完成,事件订阅成功");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"初始化PathPlanningManager失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示类别选择和主控制面板(无模态对话框)
|
||
/// </summary>
|
||
private void ShowCategorySelectionDialog()
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
// 创建主窗体
|
||
_controlPanelForm = new Form
|
||
{
|
||
Text = "物流路径规划控制面板",
|
||
Size = new Size(380, 700),
|
||
StartPosition = FormStartPosition.Manual,
|
||
Location = new Point(20, 140), // 避免遮挡菜单
|
||
TopMost = true,
|
||
ShowInTaskbar = false,
|
||
MaximizeBox = false,
|
||
MinimizeBox = false,
|
||
FormBorderStyle = FormBorderStyle.FixedSingle
|
||
};
|
||
|
||
// 添加选择变化事件监听
|
||
NavisApplication.ActiveDocument.CurrentSelection.Changed += OnSelectionChanged;
|
||
|
||
// 创建主面板
|
||
Panel mainPanel = new Panel
|
||
{
|
||
Dock = DockStyle.Fill,
|
||
Padding = new Padding(5)
|
||
};
|
||
_controlPanelForm.Controls.Add(mainPanel);
|
||
|
||
// 创建Tab控件
|
||
TabControl tabControl = new TabControl
|
||
{
|
||
Dock = DockStyle.Fill,
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
mainPanel.Controls.Add(tabControl);
|
||
|
||
// 创建四个Tab页
|
||
CreateModelSettingsTab(tabControl);
|
||
CreatePathEditingTab(tabControl);
|
||
CreateAnimationControlTab(tabControl);
|
||
CreateSystemManagementTab(tabControl);
|
||
|
||
// 创建底部操作栏
|
||
Panel bottomPanel = new Panel
|
||
{
|
||
Height = 50,
|
||
Dock = DockStyle.Bottom
|
||
};
|
||
mainPanel.Controls.Add(bottomPanel);
|
||
|
||
// 帮助按钮
|
||
Button helpButton = new Button
|
||
{
|
||
Text = "帮助",
|
||
Size = new Size(60, 30),
|
||
Location = new Point(10, 10),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
bottomPanel.Controls.Add(helpButton);
|
||
|
||
// 关于按钮
|
||
Button aboutButton = new Button
|
||
{
|
||
Text = "关于",
|
||
Size = new Size(60, 30),
|
||
Location = new Point(80, 10),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
bottomPanel.Controls.Add(aboutButton);
|
||
|
||
// 关闭按钮
|
||
Button closeButton = new Button
|
||
{
|
||
Text = "关闭",
|
||
Size = new Size(60, 30),
|
||
Location = new Point(290, 10),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
bottomPanel.Controls.Add(closeButton);
|
||
|
||
// 关闭按钮事件处理
|
||
closeButton.Click += (sender, e) =>
|
||
{
|
||
_controlPanelForm.Close();
|
||
};
|
||
|
||
// 事件处理
|
||
helpButton.Click += (sender, e) =>
|
||
{
|
||
MessageBox.Show("物流路径规划插件使用说明:\n\n1. 类别设置:设置对象类别和可见性\n2. 路径编辑:创建和管理3D路径\n3. 动画控制:创建路径动画\n4. 系统管理:插件设置和日志",
|
||
"帮助", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
};
|
||
|
||
aboutButton.Click += (sender, e) =>
|
||
{
|
||
MessageBox.Show("物流路径规划插件 v1.0\n\n适用于 Navisworks 2017\n开发:AI助手\n\n功能:3D路径规划、动画创建、碰撞检测",
|
||
"关于插件", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
};
|
||
|
||
// 添加窗口关闭事件处理
|
||
_controlPanelForm.FormClosed += (sender, e) =>
|
||
{
|
||
// 清理选择事件监听
|
||
try
|
||
{
|
||
NavisApplication.ActiveDocument.CurrentSelection.Changed -= OnSelectionChanged;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"清理选择事件监听失败: {ex.Message}");
|
||
}
|
||
|
||
_controlPanelForm = null; // 清空引用
|
||
_instructionLabel = null;
|
||
_selectedModelsLabel = null;
|
||
_logisticsListView = null;
|
||
_statsLabel = null;
|
||
LogManager.Info("控制面板已关闭,已清理所有引用和事件监听");
|
||
};
|
||
|
||
// 显示无模态对话框
|
||
_controlPanelForm.Show();
|
||
LogManager.Info("控制面板已显示在屏幕左侧");
|
||
}, "显示主控制面板");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建类别设置Tab页
|
||
/// </summary>
|
||
private void CreateModelSettingsTab(TabControl tabControl)
|
||
{
|
||
TabPage modelTab = new TabPage("类别设置");
|
||
modelTab.Padding = new Padding(10);
|
||
|
||
Panel scrollPanel = new Panel
|
||
{
|
||
Dock = DockStyle.Fill,
|
||
AutoScroll = true
|
||
};
|
||
modelTab.Controls.Add(scrollPanel);
|
||
|
||
int currentY = 10;
|
||
|
||
// 选择提示和状态信息(保存引用)
|
||
_instructionLabel = new Label
|
||
{
|
||
Text = "请在主界面中点击选择模型",
|
||
Font = new Font("微软雅黑", 8, FontStyle.Bold),
|
||
ForeColor = System.Drawing.Color.Orange,
|
||
AutoSize = true,
|
||
Location = new Point(10, currentY)
|
||
};
|
||
scrollPanel.Controls.Add(_instructionLabel);
|
||
currentY += 25;
|
||
|
||
// 显示选中模型名称(保存引用)
|
||
_selectedModelsLabel = new Label
|
||
{
|
||
Text = "选中模型: ",
|
||
Font = new Font("微软雅黑", 8),
|
||
ForeColor = System.Drawing.Color.DarkBlue,
|
||
AutoSize = true,
|
||
Location = new Point(10, currentY),
|
||
MaximumSize = new Size(320, 0),
|
||
Visible = false // 初始隐藏
|
||
};
|
||
scrollPanel.Controls.Add(_selectedModelsLabel);
|
||
currentY += 30;
|
||
|
||
// 类别属性设置
|
||
GroupBox categoryGroupBox = new GroupBox
|
||
{
|
||
Text = "类别属性设置",
|
||
Location = new Point(10, currentY),
|
||
Size = new Size(340, 80),
|
||
Font = new Font("微软雅黑", 8, FontStyle.Bold)
|
||
};
|
||
scrollPanel.Controls.Add(categoryGroupBox);
|
||
CreateCategoryDropdown(categoryGroupBox);
|
||
currentY += 100;
|
||
|
||
// 物流模型列表
|
||
GroupBox logisticsListGroupBox = new GroupBox
|
||
{
|
||
Text = "物流模型列表",
|
||
Location = new Point(10, currentY),
|
||
Size = new Size(340, 180),
|
||
Font = new Font("微软雅黑", 8, FontStyle.Bold)
|
||
};
|
||
scrollPanel.Controls.Add(logisticsListGroupBox);
|
||
CreateLogisticsModelList(logisticsListGroupBox);
|
||
currentY += 190;
|
||
|
||
// 统计信息(简化为一行,保存引用)
|
||
_statsLabel = new Label
|
||
{
|
||
Text = "统计: 正在计算物流模型信息...",
|
||
Font = new Font("微软雅黑", 8),
|
||
ForeColor = System.Drawing.Color.DarkGreen,
|
||
AutoSize = true,
|
||
Location = new Point(10, currentY)
|
||
};
|
||
scrollPanel.Controls.Add(_statsLabel);
|
||
UpdateLogisticsStatsStatic(_statsLabel);
|
||
currentY += 25;
|
||
|
||
// 可见性控制
|
||
GroupBox visibilityGroupBox = new GroupBox
|
||
{
|
||
Text = "可见性控制",
|
||
Location = new Point(10, currentY),
|
||
Size = new Size(340, 100),
|
||
Font = new Font("微软雅黑", 8, FontStyle.Bold)
|
||
};
|
||
scrollPanel.Controls.Add(visibilityGroupBox);
|
||
CreateVisibilityControls(visibilityGroupBox);
|
||
|
||
tabControl.TabPages.Add(modelTab);
|
||
|
||
// 初始更新选择显示
|
||
UpdateSelectionDisplay();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建路径编辑Tab页
|
||
/// </summary>
|
||
private void CreatePathEditingTab(TabControl tabControl)
|
||
{
|
||
TabPage pathTab = new TabPage("路径编辑");
|
||
pathTab.Padding = new Padding(10);
|
||
|
||
Panel scrollPanel = new Panel
|
||
{
|
||
Dock = DockStyle.Fill,
|
||
AutoScroll = true
|
||
};
|
||
pathTab.Controls.Add(scrollPanel);
|
||
|
||
int currentY = 10;
|
||
|
||
// 第一层:路径列表管理
|
||
GroupBox pathListGroupBox = new GroupBox
|
||
{
|
||
Text = "路径列表管理",
|
||
Location = new Point(10, currentY),
|
||
Size = new Size(320, 160),
|
||
Font = new Font("微软雅黑", 8, FontStyle.Bold)
|
||
};
|
||
scrollPanel.Controls.Add(pathListGroupBox);
|
||
CreatePathListManagement(pathListGroupBox);
|
||
currentY += 180;
|
||
|
||
// 第二层:当前路径编辑
|
||
GroupBox currentPathGroupBox = new GroupBox
|
||
{
|
||
Text = "当前路径编辑",
|
||
Location = new Point(10, currentY),
|
||
Size = new Size(320, 250),
|
||
Font = new Font("微软雅黑", 8, FontStyle.Bold)
|
||
};
|
||
scrollPanel.Controls.Add(currentPathGroupBox);
|
||
CreateCurrentPathEditor(currentPathGroupBox);
|
||
currentY += 270;
|
||
|
||
// 第三层:文件管理
|
||
GroupBox fileManagementGroupBox = new GroupBox
|
||
{
|
||
Text = "路径文件管理",
|
||
Location = new Point(10, currentY),
|
||
Size = new Size(320, 80),
|
||
Font = new Font("微软雅黑", 8, FontStyle.Bold)
|
||
};
|
||
scrollPanel.Controls.Add(fileManagementGroupBox);
|
||
CreatePathFileManagement(fileManagementGroupBox);
|
||
|
||
tabControl.TabPages.Add(pathTab);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建动画控制Tab页
|
||
/// </summary>
|
||
private void CreateAnimationControlTab(TabControl tabControl)
|
||
{
|
||
TabPage animationTab = new TabPage("动画控制");
|
||
animationTab.Padding = new Padding(10);
|
||
|
||
Panel scrollPanel = new Panel
|
||
{
|
||
Dock = DockStyle.Fill,
|
||
AutoScroll = true
|
||
};
|
||
animationTab.Controls.Add(scrollPanel);
|
||
|
||
int currentY = 10;
|
||
|
||
// 动画参数设置
|
||
GroupBox animationGroupBox = new GroupBox
|
||
{
|
||
Text = "动画参数设置",
|
||
Location = new Point(10, currentY),
|
||
Size = new Size(320, 120),
|
||
Font = new Font("微软雅黑", 8, FontStyle.Bold)
|
||
};
|
||
scrollPanel.Controls.Add(animationGroupBox);
|
||
CreateAnimationControls(animationGroupBox);
|
||
currentY += 140;
|
||
|
||
// 播放控制
|
||
GroupBox playbackGroupBox = new GroupBox
|
||
{
|
||
Text = "播放控制",
|
||
Location = new Point(10, currentY),
|
||
Size = new Size(320, 100),
|
||
Font = new Font("微软雅黑", 8, FontStyle.Bold)
|
||
};
|
||
scrollPanel.Controls.Add(playbackGroupBox);
|
||
CreatePlaybackControls(playbackGroupBox);
|
||
currentY += 120;
|
||
|
||
// 碰撞检测
|
||
GroupBox collisionGroupBox = new GroupBox
|
||
{
|
||
Text = "碰撞检测",
|
||
Location = new Point(10, currentY),
|
||
Size = new Size(320, 100),
|
||
Font = new Font("微软雅黑", 8, FontStyle.Bold)
|
||
};
|
||
scrollPanel.Controls.Add(collisionGroupBox);
|
||
CreateCollisionControls(collisionGroupBox);
|
||
|
||
tabControl.TabPages.Add(animationTab);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建系统管理Tab页
|
||
/// </summary>
|
||
private void CreateSystemManagementTab(TabControl tabControl)
|
||
{
|
||
TabPage systemTab = new TabPage("系统管理");
|
||
systemTab.Padding = new Padding(10);
|
||
|
||
Panel scrollPanel = new Panel
|
||
{
|
||
Dock = DockStyle.Fill,
|
||
AutoScroll = true
|
||
};
|
||
systemTab.Controls.Add(scrollPanel);
|
||
|
||
int currentY = 10;
|
||
|
||
// 日志管理
|
||
GroupBox logGroupBox = new GroupBox
|
||
{
|
||
Text = "日志管理",
|
||
Location = new Point(10, currentY),
|
||
Size = new Size(320, 120),
|
||
Font = new Font("微软雅黑", 8, FontStyle.Bold)
|
||
};
|
||
scrollPanel.Controls.Add(logGroupBox);
|
||
CreateLogManagementControls(logGroupBox);
|
||
currentY += 140;
|
||
|
||
// 插件设置
|
||
GroupBox settingsGroupBox = new GroupBox
|
||
{
|
||
Text = "插件设置",
|
||
Location = new Point(10, currentY),
|
||
Size = new Size(320, 100),
|
||
Font = new Font("微软雅黑", 8, FontStyle.Bold)
|
||
};
|
||
scrollPanel.Controls.Add(settingsGroupBox);
|
||
CreatePluginSettingsControls(settingsGroupBox);
|
||
currentY += 120;
|
||
|
||
// 系统信息
|
||
GroupBox systemInfoGroupBox = new GroupBox
|
||
{
|
||
Text = "系统信息",
|
||
Location = new Point(10, currentY),
|
||
Size = new Size(320, 150),
|
||
Font = new Font("微软雅黑", 8, FontStyle.Bold)
|
||
};
|
||
scrollPanel.Controls.Add(systemInfoGroupBox);
|
||
CreateSystemInfoControls(systemInfoGroupBox);
|
||
|
||
tabControl.TabPages.Add(systemTab);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建路径列表管理控件
|
||
/// </summary>
|
||
private void CreatePathListManagement(GroupBox groupBox)
|
||
{
|
||
// 路径操作按钮
|
||
Button newButton = new Button
|
||
{
|
||
Text = "新建",
|
||
Location = new Point(15, 25),
|
||
Size = new Size(60, 25),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(newButton);
|
||
|
||
Button detailButton = new Button
|
||
{
|
||
Text = "详情",
|
||
Location = new Point(85, 25),
|
||
Size = new Size(60, 25),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(detailButton);
|
||
|
||
Button editButton = new Button
|
||
{
|
||
Text = "编辑",
|
||
Location = new Point(155, 25),
|
||
Size = new Size(60, 25),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(editButton);
|
||
|
||
Button deleteButton = new Button
|
||
{
|
||
Text = "删除",
|
||
Location = new Point(225, 25),
|
||
Size = new Size(60, 25),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(deleteButton);
|
||
|
||
// 路径列表
|
||
_pathListView = new ListView
|
||
{
|
||
Location = new Point(15, 60),
|
||
Size = new Size(290, 80),
|
||
View = System.Windows.Forms.View.Details,
|
||
FullRowSelect = true,
|
||
GridLines = true,
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
|
||
_pathListView.Columns.Add("路径名称", 150);
|
||
_pathListView.Columns.Add("创建时间", 80);
|
||
_pathListView.Columns.Add("点数", 50);
|
||
|
||
groupBox.Controls.Add(_pathListView);
|
||
|
||
// 添加事件处理
|
||
newButton.Click += (sender, e) => {
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
LogManager.Info("[新建按钮] ===== 新建按钮被点击 =====");
|
||
|
||
var pathManager = PathPlanningManager.GetActivePathManager() ?? new PathPlanningManager();
|
||
LogManager.Info($"[新建按钮] 获取到路径管理器: {pathManager != null}");
|
||
|
||
// 开始创建新路径
|
||
var newRoute = pathManager.StartCreatingNewRoute();
|
||
LogManager.Info($"[新建按钮] StartCreatingNewRoute调用完成,返回路径: {newRoute?.Name ?? "null"}");
|
||
|
||
if (newRoute != null)
|
||
{
|
||
// 更新UI状态显示
|
||
LogManager.Info("[新建按钮] 开始更新UI状态");
|
||
UpdateCurrentPathPointsList();
|
||
UpdatePathList();
|
||
LogManager.Info("[新建按钮] UI状态更新完成");
|
||
|
||
LogManager.Info("开始创建新路径,已进入创建状态");
|
||
MessageBox.Show("已进入新建路径模式!\n\n请在3D视图中点击物流通道来设置路径点。",
|
||
"新建路径", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
else
|
||
{
|
||
LogManager.Error("[新建按钮] 创建新路径失败");
|
||
MessageBox.Show("创建新路径失败,请查看日志", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
|
||
LogManager.Info("[新建按钮] ===== 新建按钮事件处理完成 =====");
|
||
|
||
}, "新建路径");
|
||
};
|
||
|
||
editButton.Click += (sender, e) => {
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
if (_pathListView.SelectedItems.Count == 0)
|
||
{
|
||
MessageBox.Show("请先选择要编辑的路径", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
var selectedRouteName = _pathListView.SelectedItems[0].Text;
|
||
|
||
// 查找对应的路径对象
|
||
var pathManager = PathPlanningManager.GetActivePathManager() ?? new PathPlanningManager();
|
||
var routeToEdit = pathManager.Routes.FirstOrDefault(r => r.Name == selectedRouteName);
|
||
|
||
if (routeToEdit != null)
|
||
{
|
||
// 切换到编辑状态
|
||
pathManager.SwitchToEditingState(routeToEdit);
|
||
|
||
// 更新UI状态显示
|
||
UpdateCurrentPathPointsList();
|
||
UpdatePathList();
|
||
|
||
LogManager.Info($"开始编辑路径: {selectedRouteName}");
|
||
MessageBox.Show($"已进入编辑模式!\n\n正在编辑路径: {selectedRouteName}\n\n可以在3D视图中修改路径点。",
|
||
"编辑路径", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
else
|
||
{
|
||
MessageBox.Show($"找不到路径: {selectedRouteName}", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
|
||
}, "编辑路径");
|
||
};
|
||
|
||
deleteButton.Click += (sender, e) => {
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
if (_pathListView.SelectedItems.Count == 0)
|
||
{
|
||
MessageBox.Show("请先选择要删除的路径", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
var result = MessageBox.Show($"确定要删除路径 '{_pathListView.SelectedItems[0].Text}' 吗?",
|
||
"确认删除", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
||
|
||
if (result == DialogResult.Yes)
|
||
{
|
||
// TODO: 实现删除路径的逻辑
|
||
LogManager.Info($"删除路径: {_pathListView.SelectedItems[0].Text}");
|
||
_pathListView.SelectedItems[0].Remove();
|
||
MessageBox.Show("路径已删除", "操作完成",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
|
||
}, "删除路径");
|
||
};
|
||
|
||
detailButton.Click += (sender, e) => {
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
if (_pathListView.SelectedItems.Count == 0)
|
||
{
|
||
MessageBox.Show("请先选择要查看的路径", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
var selectedPath = _pathListView.SelectedItems[0];
|
||
var detailInfo = $"路径名称: {selectedPath.SubItems[0].Text}\n" +
|
||
$"创建时间: {selectedPath.SubItems[1].Text}\n" +
|
||
$"路径点数: {selectedPath.SubItems[2].Text}";
|
||
|
||
MessageBox.Show(detailInfo, "路径详情",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
LogManager.Info($"查看路径详情: {selectedPath.Text}");
|
||
|
||
}, "查看路径详情");
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建当前路径编辑控件
|
||
/// </summary>
|
||
private void CreateCurrentPathEditor(GroupBox groupBox)
|
||
{
|
||
// 状态显示
|
||
_currentPathStatusLabel = new Label
|
||
{
|
||
Text = "状态: 查看模式",
|
||
Location = new Point(15, 25),
|
||
Size = new Size(200, 20),
|
||
Font = new Font("微软雅黑", 8),
|
||
ForeColor = System.Drawing.Color.Blue
|
||
};
|
||
groupBox.Controls.Add(_currentPathStatusLabel);
|
||
|
||
// 说明文字
|
||
Label instructionLabel = new Label
|
||
{
|
||
Text = "在3D视图中点击物流通道设置路径点",
|
||
Location = new Point(15, 50),
|
||
Size = new Size(290, 20),
|
||
Font = new Font("微软雅黑", 8),
|
||
ForeColor = System.Drawing.Color.Gray
|
||
};
|
||
groupBox.Controls.Add(instructionLabel);
|
||
|
||
// 路径点列表
|
||
Label pointsLabel = new Label
|
||
{
|
||
Text = "路径点列表:",
|
||
Location = new Point(15, 80),
|
||
Size = new Size(80, 20),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(pointsLabel);
|
||
|
||
_currentPathPointsListView = new ListView
|
||
{
|
||
Location = new Point(15, 105),
|
||
Size = new Size(290, 100),
|
||
Font = new Font("微软雅黑", 8),
|
||
View = System.Windows.Forms.View.Details, // 设置为详细信息视图
|
||
FullRowSelect = true,
|
||
GridLines = true
|
||
};
|
||
|
||
// 添加列
|
||
_currentPathPointsListView.Columns.Add("序号", 40, HorizontalAlignment.Left);
|
||
_currentPathPointsListView.Columns.Add("名称", 80, HorizontalAlignment.Left);
|
||
_currentPathPointsListView.Columns.Add("类型", 60, HorizontalAlignment.Left);
|
||
_currentPathPointsListView.Columns.Add("坐标 (X,Y,Z)", 110, HorizontalAlignment.Left);
|
||
|
||
groupBox.Controls.Add(_currentPathPointsListView);
|
||
|
||
// 操作按钮
|
||
Button finishButton = new Button
|
||
{
|
||
Text = "完成编辑",
|
||
Location = new Point(120, 215),
|
||
Size = new Size(80, 25),
|
||
Font = new Font("微软雅黑", 8),
|
||
Enabled = false
|
||
};
|
||
groupBox.Controls.Add(finishButton);
|
||
|
||
Button cancelButton = new Button
|
||
{
|
||
Text = "取消编辑",
|
||
Location = new Point(210, 215),
|
||
Size = new Size(80, 25),
|
||
Font = new Font("微软雅黑", 8),
|
||
Enabled = false
|
||
};
|
||
groupBox.Controls.Add(cancelButton);
|
||
|
||
// 添加事件处理
|
||
finishButton.Click += (sender, e) => {
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
var pathManager = PathPlanningManager.GetActivePathManager();
|
||
if (pathManager == null)
|
||
{
|
||
MessageBox.Show("路径管理器未初始化", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
return;
|
||
}
|
||
|
||
if (!pathManager.IsInEditableState)
|
||
{
|
||
MessageBox.Show("当前不在编辑状态", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
// 完成编辑并保存
|
||
bool success = pathManager.FinishEditing();
|
||
if (success)
|
||
{
|
||
// 更新UI状态显示
|
||
UpdateCurrentPathPointsList();
|
||
UpdatePathList();
|
||
|
||
LogManager.Info("路径编辑已完成并保存");
|
||
MessageBox.Show("路径编辑完成!", "操作完成",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
else
|
||
{
|
||
MessageBox.Show("完成编辑时发生错误,请查看日志", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
|
||
}, "完成编辑");
|
||
};
|
||
|
||
cancelButton.Click += (sender, e) => {
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
var pathManager = PathPlanningManager.GetActivePathManager();
|
||
if (pathManager == null)
|
||
{
|
||
MessageBox.Show("路径管理器未初始化", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
return;
|
||
}
|
||
|
||
if (!pathManager.IsInEditableState)
|
||
{
|
||
MessageBox.Show("当前不在编辑状态", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
var result = MessageBox.Show("确定要取消编辑吗?未保存的更改将丢失。",
|
||
"确认取消", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
||
|
||
if (result == DialogResult.Yes)
|
||
{
|
||
// 取消编辑并清理临时数据
|
||
bool success = pathManager.CancelEditing();
|
||
if (success)
|
||
{
|
||
// 更新UI状态显示
|
||
UpdateCurrentPathPointsList();
|
||
UpdatePathList();
|
||
|
||
LogManager.Info("路径编辑已取消");
|
||
MessageBox.Show("已取消编辑", "操作完成",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
else
|
||
{
|
||
MessageBox.Show("取消编辑时发生错误,请查看日志", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
}
|
||
|
||
}, "取消编辑");
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建路径文件管理控件
|
||
/// </summary>
|
||
private void CreatePathFileManagement(GroupBox groupBox)
|
||
{
|
||
Button saveButton = new Button
|
||
{
|
||
Text = "保存当前路径",
|
||
Location = new Point(15, 25),
|
||
Size = new Size(90, 30),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(saveButton);
|
||
|
||
Button importButton = new Button
|
||
{
|
||
Text = "导入路径",
|
||
Location = new Point(115, 25),
|
||
Size = new Size(80, 30),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(importButton);
|
||
|
||
Button exportButton = new Button
|
||
{
|
||
Text = "导出路径",
|
||
Location = new Point(205, 25),
|
||
Size = new Size(80, 30),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(exportButton);
|
||
|
||
Button historyButton = new Button
|
||
{
|
||
Text = "查看历史",
|
||
Location = new Point(15, 65),
|
||
Size = new Size(80, 30),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(historyButton);
|
||
|
||
// 添加事件处理
|
||
saveButton.Click += (sender, e) => {
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
var pathManager = PathPlanningManager.GetActivePathManager();
|
||
if (pathManager?.CurrentRoute?.Points == null || pathManager.CurrentRoute.Points.Count == 0)
|
||
{
|
||
MessageBox.Show("当前没有可保存的路径", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
// 显示保存对话框
|
||
SaveFileDialog saveDialog = new SaveFileDialog
|
||
{
|
||
Title = "保存路径文件",
|
||
Filter = "XML文件 (*.xml)|*.xml|JSON文件 (*.json)|*.json",
|
||
FilterIndex = 1,
|
||
DefaultExt = "xml"
|
||
};
|
||
|
||
if (saveDialog.ShowDialog() == DialogResult.OK)
|
||
{
|
||
bool saveResult = false;
|
||
var extension = System.IO.Path.GetExtension(saveDialog.FileName).ToLowerInvariant();
|
||
|
||
if (extension == ".json")
|
||
{
|
||
saveResult = PathFileSerializer.SaveToJson(pathManager.CurrentRoute, saveDialog.FileName);
|
||
}
|
||
else
|
||
{
|
||
saveResult = PathFileSerializer.SaveToXml(pathManager.CurrentRoute, saveDialog.FileName);
|
||
}
|
||
|
||
if (saveResult)
|
||
{
|
||
// 保存到历史记录
|
||
pathManager.SaveCurrentRouteToHistory($"手动保存到文件: {System.IO.Path.GetFileName(saveDialog.FileName)}");
|
||
|
||
LogManager.Info($"路径成功保存到: {saveDialog.FileName}");
|
||
MessageBox.Show($"路径已保存到: {saveDialog.FileName}", "保存成功",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
else
|
||
{
|
||
LogManager.Error($"保存路径失败: {saveDialog.FileName}");
|
||
MessageBox.Show("保存路径失败,请检查文件路径和权限", "保存失败",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
}
|
||
|
||
}, "保存当前路径");
|
||
};
|
||
|
||
importButton.Click += (sender, e) => {
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
var pathManager = PathPlanningManager.GetActivePathManager();
|
||
if (pathManager == null)
|
||
{
|
||
MessageBox.Show("路径管理器未初始化", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
return;
|
||
}
|
||
|
||
OpenFileDialog openDialog = new OpenFileDialog
|
||
{
|
||
Title = "导入路径文件",
|
||
Filter = "路径文件 (*.xml;*.json)|*.xml;*.json|XML文件 (*.xml)|*.xml|JSON文件 (*.json)|*.json|所有文件 (*.*)|*.*",
|
||
FilterIndex = 1
|
||
};
|
||
|
||
if (openDialog.ShowDialog() == DialogResult.OK)
|
||
{
|
||
PathRoute importedRoute = null;
|
||
var fileFormat = PathFileSerializer.DetectFileFormat(openDialog.FileName);
|
||
|
||
switch (fileFormat)
|
||
{
|
||
case "XML":
|
||
importedRoute = PathFileSerializer.LoadFromXml(openDialog.FileName);
|
||
break;
|
||
case "JSON":
|
||
importedRoute = PathFileSerializer.LoadFromJson(openDialog.FileName);
|
||
if (importedRoute == null)
|
||
{
|
||
MessageBox.Show("JSON格式导入功能简化,建议使用XML格式", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
break;
|
||
default:
|
||
MessageBox.Show($"不支持的文件格式: {fileFormat}", "导入失败",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
return;
|
||
}
|
||
|
||
if (importedRoute != null && importedRoute.Points.Count > 0)
|
||
{
|
||
// 添加到路径管理器
|
||
pathManager.AddRoute(importedRoute);
|
||
pathManager.CurrentRoute = importedRoute;
|
||
|
||
LogManager.Info($"成功导入路径: {importedRoute.Name},包含 {importedRoute.Points.Count} 个路径点");
|
||
MessageBox.Show($"路径 '{importedRoute.Name}' 已成功导入,包含 {importedRoute.Points.Count} 个路径点", "导入成功",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
else
|
||
{
|
||
LogManager.Error($"导入路径失败: {openDialog.FileName}");
|
||
MessageBox.Show("导入路径失败,文件格式可能不正确", "导入失败",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
}
|
||
|
||
}, "导入路径");
|
||
};
|
||
|
||
exportButton.Click += (sender, e) => {
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
var pathManager = PathPlanningManager.GetActivePathManager();
|
||
if (pathManager?.CurrentRoute?.Points == null || pathManager.CurrentRoute.Points.Count == 0)
|
||
{
|
||
MessageBox.Show("当前没有可导出的路径", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
SaveFileDialog exportDialog = new SaveFileDialog
|
||
{
|
||
Title = "导出路径文件",
|
||
Filter = "XML文件 (*.xml)|*.xml|JSON文件 (*.json)|*.json",
|
||
FilterIndex = 1,
|
||
DefaultExt = "xml"
|
||
};
|
||
|
||
if (exportDialog.ShowDialog() == DialogResult.OK)
|
||
{
|
||
bool exportResult = false;
|
||
var extension = System.IO.Path.GetExtension(exportDialog.FileName).ToLowerInvariant();
|
||
|
||
if (extension == ".json")
|
||
{
|
||
exportResult = PathFileSerializer.SaveToJson(pathManager.CurrentRoute, exportDialog.FileName);
|
||
}
|
||
else
|
||
{
|
||
exportResult = PathFileSerializer.SaveToXml(pathManager.CurrentRoute, exportDialog.FileName);
|
||
}
|
||
|
||
if (exportResult)
|
||
{
|
||
LogManager.Info($"路径成功导出到: {exportDialog.FileName}");
|
||
MessageBox.Show($"路径已导出到: {exportDialog.FileName}", "导出成功",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
else
|
||
{
|
||
LogManager.Error($"导出路径失败: {exportDialog.FileName}");
|
||
MessageBox.Show("导出路径失败,请检查文件路径和权限", "导出失败",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
}
|
||
|
||
}, "导出路径");
|
||
};
|
||
|
||
historyButton.Click += (sender, e) => {
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
var pathManager = PathPlanningManager.GetActivePathManager();
|
||
if (pathManager?.HistoryManager == null)
|
||
{
|
||
MessageBox.Show("历史记录管理器未初始化", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
return;
|
||
}
|
||
|
||
var historyEntries = pathManager.HistoryManager.GetAllHistoryEntries();
|
||
if (historyEntries.Count == 0)
|
||
{
|
||
MessageBox.Show("暂无历史记录", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
// 显示历史记录窗口
|
||
ShowPathHistoryDialog(historyEntries, pathManager.HistoryManager);
|
||
|
||
}, "查看历史记录");
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建播放控制控件
|
||
/// </summary>
|
||
private void CreatePlaybackControls(GroupBox groupBox)
|
||
{
|
||
Button playButton = new Button
|
||
{
|
||
Text = "▶ 播放",
|
||
Location = new Point(15, 25),
|
||
Size = new Size(60, 25),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(playButton);
|
||
|
||
Button pauseButton = new Button
|
||
{
|
||
Text = "⏸ 暂停",
|
||
Location = new Point(85, 25),
|
||
Size = new Size(60, 25),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(pauseButton);
|
||
|
||
Button stopButton = new Button
|
||
{
|
||
Text = "⏹ 停止",
|
||
Location = new Point(155, 25),
|
||
Size = new Size(60, 25),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(stopButton);
|
||
|
||
Button resetButton = new Button
|
||
{
|
||
Text = "🔄 重置",
|
||
Location = new Point(225, 25),
|
||
Size = new Size(60, 25),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(resetButton);
|
||
|
||
// 进度条
|
||
ProgressBar progressBar = new ProgressBar
|
||
{
|
||
Location = new Point(15, 65),
|
||
Size = new Size(270, 15)
|
||
};
|
||
groupBox.Controls.Add(progressBar);
|
||
|
||
// 事件处理
|
||
playButton.Click += (sender, e) =>
|
||
{
|
||
if (_animationManager != null)
|
||
{
|
||
_animationManager.StartAnimation();
|
||
LogManager.Info("动画播放开始");
|
||
}
|
||
};
|
||
|
||
pauseButton.Click += (sender, e) =>
|
||
{
|
||
LogManager.Info("动画暂停(功能待实现)");
|
||
};
|
||
|
||
stopButton.Click += (sender, e) =>
|
||
{
|
||
if (_animationManager != null)
|
||
{
|
||
_animationManager.StopAnimation();
|
||
LogManager.Info("动画停止");
|
||
}
|
||
};
|
||
|
||
resetButton.Click += (sender, e) =>
|
||
{
|
||
if (_animationManager != null)
|
||
{
|
||
_animationManager.ResetAnimation();
|
||
LogManager.Info("动画重置");
|
||
}
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新物流统计信息
|
||
/// </summary>
|
||
private void UpdateLogisticsStats(Label statsLabel)
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
var document = NavisApplication.ActiveDocument;
|
||
if (document?.Models == null)
|
||
{
|
||
statsLabel.Text = "统计: 无活动文档";
|
||
return;
|
||
}
|
||
|
||
int totalModels = 0;
|
||
int logisticsModels = 0;
|
||
|
||
// 统计所有模型和物流模型
|
||
foreach (ModelItem rootItem in document.Models.RootItems)
|
||
{
|
||
foreach (ModelItem item in rootItem.DescendantsAndSelf)
|
||
{
|
||
totalModels++;
|
||
if (CategoryAttributeManager.HasLogisticsAttributes(item))
|
||
{
|
||
logisticsModels++;
|
||
}
|
||
}
|
||
}
|
||
|
||
statsLabel.Text = $"统计: 总模型 {totalModels} 个,物流模型 {logisticsModels} 个";
|
||
|
||
}, "更新物流统计");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 刷新物流模型列表
|
||
/// </summary>
|
||
private void RefreshLogisticsModelList(ListView listView)
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
listView.Items.Clear();
|
||
|
||
var document = NavisApplication.ActiveDocument;
|
||
if (document?.Models == null) return;
|
||
|
||
foreach (ModelItem rootItem in document.Models.RootItems)
|
||
{
|
||
foreach (ModelItem item in rootItem.DescendantsAndSelf)
|
||
{
|
||
if (CategoryAttributeManager.HasLogisticsAttributes(item))
|
||
{
|
||
var category = CategoryAttributeManager.GetLogisticsPropertyValue(item, CategoryAttributeManager.LogisticsProperties.TYPE);
|
||
var listItem = new ListViewItem(new string[]
|
||
{
|
||
item.DisplayName.Length > 25 ? item.DisplayName.Substring(0, 25) + "..." : item.DisplayName,
|
||
string.IsNullOrEmpty(category) ? "未知" : category
|
||
});
|
||
listItem.Tag = item; // 保存ModelItem引用
|
||
listView.Items.Add(listItem);
|
||
}
|
||
}
|
||
}
|
||
|
||
LogManager.Info($"物流模型列表已刷新,共 {listView.Items.Count} 项");
|
||
|
||
}, "刷新物流模型列表");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 编辑选中的物流模型
|
||
/// </summary>
|
||
private void EditSelectedLogisticsModel(ListView listView)
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
if (listView.SelectedItems.Count == 0)
|
||
{
|
||
MessageBox.Show("请先选择要修改的物流模型", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
var selectedItem = listView.SelectedItems[0];
|
||
var modelItem = selectedItem.Tag as ModelItem;
|
||
|
||
if (modelItem != null)
|
||
{
|
||
// 这里可以打开一个编辑对话框,暂时用简单的消息框演示
|
||
var result = MessageBox.Show($"是否将模型 '{modelItem.DisplayName}' 的类别改为通道?",
|
||
"修改物流类别", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
||
|
||
if (result == DialogResult.Yes)
|
||
{
|
||
// 创建包含该模型的集合,然后添加物流属性
|
||
var items = new ModelItemCollection();
|
||
items.Add(modelItem);
|
||
CategoryAttributeManager.AddLogisticsAttributes(items, CategoryAttributeManager.LogisticsElementType.通道);
|
||
|
||
// 设置为绿色标记
|
||
var navisColor = new Autodesk.Navisworks.Api.Color(0.0, 1.0, 0.0); // 绿色
|
||
NavisApplication.ActiveDocument.Models.OverrideTemporaryColor(new ModelItem[] { modelItem }, navisColor);
|
||
|
||
RefreshLogisticsModelList(listView);
|
||
LogManager.Info($"已将模型 {modelItem.DisplayName} 设置为通道类别并标记为绿色");
|
||
}
|
||
}
|
||
|
||
}, "编辑物流模型");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除选中模型的物流属性
|
||
/// </summary>
|
||
private void ClearSelectedLogisticsModel(ListView listView)
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
if (listView.SelectedItems.Count == 0)
|
||
{
|
||
MessageBox.Show("请先选择要清除的物流模型", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
var selectedItem = listView.SelectedItems[0];
|
||
var modelItem = selectedItem.Tag as ModelItem;
|
||
|
||
if (modelItem != null)
|
||
{
|
||
var result = MessageBox.Show($"是否清除模型 '{modelItem.DisplayName}' 的物流属性?\n\n注意:当前版本暂不支持删除已设置的物流属性,只能重置显示颜色。",
|
||
"清除物流属性", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
||
|
||
if (result == DialogResult.Yes)
|
||
{
|
||
// 注意:目前CategoryAttributeManager类中没有清除属性的方法
|
||
// 作为临时方案,只重置颜色显示
|
||
|
||
// 重置颜色
|
||
NavisApplication.ActiveDocument.Models.ResetAllTemporaryMaterials();
|
||
|
||
RefreshLogisticsModelList(listView);
|
||
LogManager.Info($"已重置模型 {modelItem.DisplayName} 的显示颜色(物流属性仍保留)");
|
||
MessageBox.Show("已重置显示颜色。\n注意:物流属性数据仍保留在模型中。", "操作完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
}
|
||
|
||
}, "清除物流属性");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 高亮显示选中的物流模型
|
||
/// </summary>
|
||
private void HighlightSelectedLogisticsModel(ListView listView)
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
if (listView.SelectedItems.Count == 0)
|
||
{
|
||
MessageBox.Show("请先选择要高亮的物流模型", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
var selectedItem = listView.SelectedItems[0];
|
||
var modelItem = selectedItem.Tag as ModelItem;
|
||
|
||
if (modelItem != null)
|
||
{
|
||
// 先重置所有颜色
|
||
NavisApplication.ActiveDocument.Models.ResetAllTemporaryMaterials();
|
||
|
||
// 高亮选中的模型(黄色)
|
||
var highlightColor = new Autodesk.Navisworks.Api.Color(1.0, 1.0, 0.0); // 黄色
|
||
NavisApplication.ActiveDocument.Models.OverrideTemporaryColor(new ModelItem[] { modelItem }, highlightColor);
|
||
|
||
// 选中该模型
|
||
NavisApplication.ActiveDocument.CurrentSelection.Clear();
|
||
NavisApplication.ActiveDocument.CurrentSelection.Add(modelItem);
|
||
|
||
LogManager.Info($"已高亮显示模型 {modelItem.DisplayName}");
|
||
}
|
||
|
||
}, "高亮物流模型");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建物流模型列表
|
||
/// </summary>
|
||
private void CreateLogisticsModelList(GroupBox parent)
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
// 创建列表视图(保存引用)
|
||
_logisticsListView = new ListView
|
||
{
|
||
Location = new Point(10, 20),
|
||
Size = new Size(320, 120),
|
||
View = System.Windows.Forms.View.Details,
|
||
FullRowSelect = true,
|
||
GridLines = true,
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
|
||
// 添加列标题
|
||
_logisticsListView.Columns.Add("模型名称", 180);
|
||
_logisticsListView.Columns.Add("物流类型", 120);
|
||
|
||
parent.Controls.Add(_logisticsListView);
|
||
|
||
// 操作按钮区域
|
||
Button refreshButton = new Button
|
||
{
|
||
Text = "刷新列表",
|
||
Size = new Size(70, 25),
|
||
Location = new Point(10, 150),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
parent.Controls.Add(refreshButton);
|
||
|
||
Button editButton = new Button
|
||
{
|
||
Text = "修改类别",
|
||
Size = new Size(70, 25),
|
||
Location = new Point(90, 150),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
parent.Controls.Add(editButton);
|
||
|
||
Button clearButton = new Button
|
||
{
|
||
Text = "清除属性",
|
||
Size = new Size(70, 25),
|
||
Location = new Point(170, 150),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
parent.Controls.Add(clearButton);
|
||
|
||
Button highlightButton = new Button
|
||
{
|
||
Text = "高亮显示",
|
||
Size = new Size(70, 25),
|
||
Location = new Point(250, 150),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
parent.Controls.Add(highlightButton);
|
||
|
||
// 事件处理(使用静态方法)
|
||
refreshButton.Click += (sender, e) => RefreshLogisticsModelListStatic(_logisticsListView);
|
||
editButton.Click += (sender, e) => EditSelectedLogisticsModel(_logisticsListView);
|
||
clearButton.Click += (sender, e) => ClearSelectedLogisticsModel(_logisticsListView);
|
||
highlightButton.Click += (sender, e) => HighlightSelectedLogisticsModel(_logisticsListView);
|
||
|
||
// 初始加载
|
||
RefreshLogisticsModelListStatic(_logisticsListView);
|
||
|
||
}, "创建物流模型列表");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新物流统计信息
|
||
/// </summary>
|
||
private void CreateCollisionControls(GroupBox groupBox)
|
||
{
|
||
CheckBox enableCollisionCheckBox = new CheckBox
|
||
{
|
||
Text = "启用碰撞检测",
|
||
Location = new Point(15, 25),
|
||
Checked = true,
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(enableCollisionCheckBox);
|
||
|
||
CheckBox highlightCheckBox = new CheckBox
|
||
{
|
||
Text = "高亮显示碰撞",
|
||
Location = new Point(150, 25),
|
||
Checked = true,
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(highlightCheckBox);
|
||
|
||
Label collisionStatusLabel = new Label
|
||
{
|
||
Text = "碰撞状态: 未检测",
|
||
Location = new Point(15, 55),
|
||
Size = new Size(200, 20),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(collisionStatusLabel);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建日志管理控件
|
||
/// </summary>
|
||
private void CreateLogManagementControls(GroupBox groupBox)
|
||
{
|
||
Button viewLogButton = new Button
|
||
{
|
||
Text = "查看日志",
|
||
Location = new Point(15, 25),
|
||
Size = new Size(80, 30),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(viewLogButton);
|
||
|
||
Button clearLogButton = new Button
|
||
{
|
||
Text = "清空日志",
|
||
Location = new Point(105, 25),
|
||
Size = new Size(80, 30),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(clearLogButton);
|
||
|
||
Button exportLogButton = new Button
|
||
{
|
||
Text = "导出日志",
|
||
Location = new Point(195, 25),
|
||
Size = new Size(80, 30),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(exportLogButton);
|
||
|
||
ComboBox logLevelCombo = new ComboBox
|
||
{
|
||
Location = new Point(15, 65),
|
||
Size = new Size(120, 25),
|
||
DropDownStyle = ComboBoxStyle.DropDownList,
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
logLevelCombo.Items.AddRange(new[] { "详细", "信息", "警告", "错误" });
|
||
logLevelCombo.SelectedIndex = 1;
|
||
groupBox.Controls.Add(logLevelCombo);
|
||
|
||
Label logLevelLabel = new Label
|
||
{
|
||
Text = "日志级别:",
|
||
Location = new Point(145, 68),
|
||
Size = new Size(60, 20),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(logLevelLabel);
|
||
|
||
// 事件处理
|
||
viewLogButton.Click += (sender, e) =>
|
||
{
|
||
string logPath = LogManager.LogFilePath;
|
||
if (System.IO.File.Exists(logPath))
|
||
{
|
||
System.Diagnostics.Process.Start("notepad.exe", logPath);
|
||
}
|
||
else
|
||
{
|
||
MessageBox.Show("日志文件不存在", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
};
|
||
|
||
clearLogButton.Click += (sender, e) =>
|
||
{
|
||
if (MessageBox.Show("确定要清空所有日志吗?", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
|
||
{
|
||
LogManager.ClearLog();
|
||
MessageBox.Show("日志已清空", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建插件设置控件
|
||
/// </summary>
|
||
private void CreatePluginSettingsControls(GroupBox groupBox)
|
||
{
|
||
CheckBox autoSaveCheckBox = new CheckBox
|
||
{
|
||
Text = "自动保存路径",
|
||
Location = new Point(15, 25),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(autoSaveCheckBox);
|
||
|
||
CheckBox debugModeCheckBox = new CheckBox
|
||
{
|
||
Text = "调试模式",
|
||
Location = new Point(150, 25),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(debugModeCheckBox);
|
||
|
||
Button resetSettingsButton = new Button
|
||
{
|
||
Text = "重置设置",
|
||
Location = new Point(15, 55),
|
||
Size = new Size(80, 25),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(resetSettingsButton);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建系统信息控件
|
||
/// </summary>
|
||
private void CreateSystemInfoControls(GroupBox groupBox)
|
||
{
|
||
Label versionLabel = new Label
|
||
{
|
||
Text = "插件版本: v1.0",
|
||
Location = new Point(15, 25),
|
||
Size = new Size(150, 20),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(versionLabel);
|
||
|
||
Label navisVersionLabel = new Label
|
||
{
|
||
Text = $"Navisworks版本: {NavisApplication.Version}",
|
||
Location = new Point(15, 50),
|
||
Size = new Size(200, 20),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(navisVersionLabel);
|
||
|
||
Label osLabel = new Label
|
||
{
|
||
Text = $"操作系统: {Environment.OSVersion}",
|
||
Location = new Point(15, 75),
|
||
Size = new Size(300, 20),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(osLabel);
|
||
|
||
Label memoryLabel = new Label
|
||
{
|
||
Text = $"内存使用: {GC.GetTotalMemory(false) / 1024 / 1024} MB",
|
||
Location = new Point(15, 100),
|
||
Size = new Size(200, 20),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(memoryLabel);
|
||
|
||
Button refreshInfoButton = new Button
|
||
{
|
||
Text = "刷新信息",
|
||
Location = new Point(15, 120),
|
||
Size = new Size(80, 25),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
groupBox.Controls.Add(refreshInfoButton);
|
||
|
||
refreshInfoButton.Click += (sender, e) =>
|
||
{
|
||
memoryLabel.Text = $"内存使用: {GC.GetTotalMemory(false) / 1024 / 1024} MB";
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建3D交互控制界面
|
||
/// </summary>
|
||
/// <param name="parent">父容器</param>
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 创建路径管理控制界面
|
||
/// </summary>
|
||
/// <param name="parent">父容器</param>
|
||
private void CreatePathManagementControls(GroupBox parent)
|
||
{
|
||
// 导入路径按钮
|
||
Button importPathButton = new Button
|
||
{
|
||
Text = "导入路径",
|
||
Size = new Size(100, 30),
|
||
Location = new Point(20, 25),
|
||
Font = new Font("微软雅黑", 8),
|
||
UseVisualStyleBackColor = true
|
||
};
|
||
|
||
// 导出路径按钮
|
||
Button exportPathButton = new Button
|
||
{
|
||
Text = "导出路径",
|
||
Size = new Size(100, 30),
|
||
Location = new Point(130, 25),
|
||
Font = new Font("微软雅黑", 8),
|
||
UseVisualStyleBackColor = true
|
||
};
|
||
|
||
// 路径历史按钮
|
||
Button pathHistoryButton = new Button
|
||
{
|
||
Text = "路径历史",
|
||
Size = new Size(100, 30),
|
||
Location = new Point(240, 25),
|
||
Font = new Font("微软雅黑", 8),
|
||
UseVisualStyleBackColor = true
|
||
};
|
||
|
||
// 事件处理
|
||
importPathButton.Click += (sender, e) =>
|
||
{
|
||
try
|
||
{
|
||
OpenFileDialog openFileDialog = new OpenFileDialog
|
||
{
|
||
Title = "选择路径文件",
|
||
Filter = "XML文件 (*.xml)|*.xml|JSON文件 (*.json)|*.json|所有文件 (*.*)|*.*",
|
||
FilterIndex = 1
|
||
};
|
||
|
||
if (openFileDialog.ShowDialog() == DialogResult.OK)
|
||
{
|
||
var dataManager = new PathDataManager();
|
||
var routes = new List<PathRoute>();
|
||
|
||
string extension = System.IO.Path.GetExtension(openFileDialog.FileName).ToLower();
|
||
if (extension == ".xml")
|
||
{
|
||
routes = dataManager.ImportFromXml(openFileDialog.FileName);
|
||
}
|
||
else if (extension == ".json")
|
||
{
|
||
routes = dataManager.ImportFromJson(openFileDialog.FileName);
|
||
}
|
||
|
||
if (routes.Count > 0)
|
||
{
|
||
MessageBox.Show($"成功导入 {routes.Count} 条路径", "导入成功",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
else
|
||
{
|
||
MessageBox.Show("文件中未找到有效的路径数据", "导入提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"导入路径失败: {ex.Message}", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
};
|
||
|
||
exportPathButton.Click += (sender, e) =>
|
||
{
|
||
MessageBox.Show("导出功能正在开发中", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
};
|
||
|
||
pathHistoryButton.Click += (sender, e) =>
|
||
{
|
||
MessageBox.Show("路径历史功能正在开发中", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
};
|
||
|
||
// 添加控件到父容器
|
||
parent.Controls.Add(importPathButton);
|
||
parent.Controls.Add(exportPathButton);
|
||
parent.Controls.Add(pathHistoryButton);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建类别选择下拉框
|
||
/// </summary>
|
||
/// <param name="parent">父容器</param>
|
||
private void CreateCategoryDropdown(GroupBox parent)
|
||
{
|
||
// 类别标签
|
||
Label categoryLabel = new Label
|
||
{
|
||
Text = "设为类型:",
|
||
Location = new Point(10, 30),
|
||
Size = new Size(60, 20),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
parent.Controls.Add(categoryLabel);
|
||
|
||
// 类别下拉框
|
||
ComboBox categoryComboBox = new ComboBox
|
||
{
|
||
Location = new Point(80, 25),
|
||
Size = new Size(80, 25),
|
||
Font = new Font("微软雅黑", 8),
|
||
DropDownStyle = ComboBoxStyle.DropDownList
|
||
};
|
||
|
||
// 添加类别选项
|
||
categoryComboBox.Items.Add("门");
|
||
categoryComboBox.Items.Add("电梯");
|
||
categoryComboBox.Items.Add("楼梯");
|
||
categoryComboBox.Items.Add("通道");
|
||
categoryComboBox.Items.Add("障碍物");
|
||
categoryComboBox.Items.Add("装卸区");
|
||
categoryComboBox.Items.Add("停车位");
|
||
categoryComboBox.Items.Add("检查点");
|
||
categoryComboBox.SelectedIndex = 3; // 默认选择"通道"
|
||
|
||
parent.Controls.Add(categoryComboBox);
|
||
|
||
// 应用按钮
|
||
Button applyButton = new Button
|
||
{
|
||
Text = "应用类别",
|
||
Location = new Point(170, 25),
|
||
Size = new Size(80, 25),
|
||
Font = new Font("微软雅黑", 8),
|
||
UseVisualStyleBackColor = true
|
||
};
|
||
|
||
// 应用按钮点击事件
|
||
applyButton.Click += (sender, e) =>
|
||
{
|
||
try
|
||
{
|
||
if (categoryComboBox.SelectedIndex < 0)
|
||
{
|
||
MessageBox.Show("请先选择一个类别", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
// 获取当前选中的模型项
|
||
ModelItemCollection selectedItems = NavisApplication.ActiveDocument.CurrentSelection.SelectedItems;
|
||
|
||
if (selectedItems.Count == 0)
|
||
{
|
||
MessageBox.Show("请先选择要设置属性的模型项", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
// 将下拉框选择转换为枚举类型
|
||
CategoryAttributeManager.LogisticsElementType elementType;
|
||
switch (categoryComboBox.SelectedIndex)
|
||
{
|
||
case 0: elementType = CategoryAttributeManager.LogisticsElementType.门; break;
|
||
case 1: elementType = CategoryAttributeManager.LogisticsElementType.电梯; break;
|
||
case 2: elementType = CategoryAttributeManager.LogisticsElementType.楼梯; break;
|
||
case 3: elementType = CategoryAttributeManager.LogisticsElementType.通道; break;
|
||
case 4: elementType = CategoryAttributeManager.LogisticsElementType.障碍物; break;
|
||
case 5: elementType = CategoryAttributeManager.LogisticsElementType.装卸区; break;
|
||
case 6: elementType = CategoryAttributeManager.LogisticsElementType.停车位; break;
|
||
case 7: elementType = CategoryAttributeManager.LogisticsElementType.检查点; break;
|
||
default: elementType = CategoryAttributeManager.LogisticsElementType.通道; break;
|
||
}
|
||
|
||
// 执行属性添加操作
|
||
int successCount = CategoryAttributeManager.AddLogisticsAttributes(
|
||
selectedItems,
|
||
elementType,
|
||
elementType != CategoryAttributeManager.LogisticsElementType.障碍物, // 障碍物默认不可通行
|
||
5, // 默认优先级
|
||
"标准", // 默认车辆尺寸
|
||
10.0 // 默认速度限制
|
||
);
|
||
|
||
// 显示结果
|
||
if (successCount > 0)
|
||
{
|
||
// 设置为绿色标记(视觉反馈)
|
||
var navisColor = new Autodesk.Navisworks.Api.Color(0.0, 1.0, 0.0); // 绿色
|
||
NavisApplication.ActiveDocument.Models.OverrideTemporaryColor(selectedItems.ToArray(), navisColor);
|
||
|
||
// 自动刷新界面数据
|
||
RefreshInterfaceData();
|
||
|
||
LogManager.Info($"已为 {successCount} 个模型设置物流属性: {categoryComboBox.SelectedItem}");
|
||
}
|
||
else
|
||
{
|
||
MessageBox.Show("未能为任何模型项设置属性,请检查选择的模型项", "操作失败",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"设置属性时发生错误: {ex.Message}", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
LogManager.Error($"设置物流属性失败: {ex.Message}");
|
||
}
|
||
};
|
||
|
||
parent.Controls.Add(applyButton);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建动画控制界面
|
||
/// </summary>
|
||
/// <param name="parent">父容器</param>
|
||
private void CreateAnimationControls(GroupBox parent)
|
||
{
|
||
// 动画持续时间设置
|
||
Label durationLabel = new Label
|
||
{
|
||
Text = "动画时长(秒):",
|
||
Location = new Point(20, 25),
|
||
Size = new Size(80, 20),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
|
||
NumericUpDown durationNumeric = new NumericUpDown
|
||
{
|
||
Location = new Point(105, 23),
|
||
Size = new Size(60, 25),
|
||
Font = new Font("微软雅黑", 8),
|
||
Minimum = 1,
|
||
Maximum = 300,
|
||
Value = 10,
|
||
DecimalPlaces = 1
|
||
};
|
||
|
||
// 创建动画按钮
|
||
Button createAnimationButton = new Button
|
||
{
|
||
Text = "创建动画",
|
||
Location = new Point(175, 22),
|
||
Size = new Size(75, 27),
|
||
Font = new Font("微软雅黑", 8),
|
||
BackColor = System.Drawing.Color.LightGreen,
|
||
UseVisualStyleBackColor = false
|
||
};
|
||
|
||
// 播放控制按钮
|
||
Button startAnimationButton = new Button
|
||
{
|
||
Text = "播放动画",
|
||
Location = new Point(260, 22),
|
||
Size = new Size(75, 27),
|
||
Font = new Font("微软雅黑", 8),
|
||
Enabled = false
|
||
};
|
||
|
||
Button stopAnimationButton = new Button
|
||
{
|
||
Text = "停止动画",
|
||
Location = new Point(20, 55),
|
||
Size = new Size(75, 27),
|
||
Font = new Font("微软雅黑", 8),
|
||
Enabled = false
|
||
};
|
||
|
||
Button resetAnimationButton = new Button
|
||
{
|
||
Text = "重置动画",
|
||
Location = new Point(105, 55),
|
||
Size = new Size(75, 27),
|
||
Font = new Font("微软雅黑", 8),
|
||
Enabled = false
|
||
};
|
||
|
||
// 动画状态显示
|
||
Label statusLabel = new Label
|
||
{
|
||
Text = "状态: 未创建动画",
|
||
Location = new Point(190, 60),
|
||
Size = new Size(120, 20),
|
||
Font = new Font("微软雅黑", 8),
|
||
ForeColor = System.Drawing.Color.Gray
|
||
};
|
||
|
||
// 说明标签
|
||
Label instructionLabel = new Label
|
||
{
|
||
Text = "说明: 先选择路径,再选择动画对象,然后创建动画",
|
||
Location = new Point(20, 90),
|
||
Size = new Size(280, 20),
|
||
Font = new Font("微软雅黑", 8),
|
||
ForeColor = System.Drawing.Color.Gray
|
||
};
|
||
|
||
// 事件处理
|
||
createAnimationButton.Click += (sender, e) =>
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
// 获取当前选中的对象作为动画对象
|
||
var doc = NavisApplication.ActiveDocument;
|
||
var selectedItems = doc.CurrentSelection.SelectedItems;
|
||
|
||
if (selectedItems.Count == 0)
|
||
{
|
||
MessageBox.Show("请先选择要进行动画的模型对象", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
if (selectedItems.Count > 1)
|
||
{
|
||
MessageBox.Show("请只选择一个模型对象进行动画", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
// 检查是否有路径点
|
||
var activeManager = PathPlanningManager.GetActivePathManager();
|
||
if (activeManager?.CurrentRoute?.Points == null || activeManager.CurrentRoute.Points.Count < 2)
|
||
{
|
||
MessageBox.Show("请先在3D编辑模式中设置至少2个路径点", "提示",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
// 创建动画管理器(如果还没有)
|
||
if (_animationManager == null)
|
||
{
|
||
_animationManager = new PathAnimationManager();
|
||
}
|
||
|
||
// 设置动画参数
|
||
var animatedObject = selectedItems.First;
|
||
var pathPoints = activeManager.CurrentRoute.Points.Select(p => p.Position).ToList();
|
||
double duration = (double)durationNumeric.Value;
|
||
|
||
_animationManager.SetupAnimation(animatedObject, pathPoints, duration);
|
||
|
||
statusLabel.Text = "状态: 动画已创建";
|
||
statusLabel.ForeColor = System.Drawing.Color.Green;
|
||
|
||
// 启用播放控制按钮
|
||
startAnimationButton.Enabled = true;
|
||
resetAnimationButton.Enabled = true;
|
||
createAnimationButton.Enabled = false;
|
||
|
||
MessageBox.Show($"动画创建成功!\n对象: {animatedObject.DisplayName}\n路径点: {pathPoints.Count}个\n时长: {duration}秒",
|
||
"创建成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}, "创建动画");
|
||
};
|
||
|
||
startAnimationButton.Click += (sender, e) =>
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
if (_animationManager != null)
|
||
{
|
||
_animationManager.StartAnimation();
|
||
|
||
statusLabel.Text = "状态: 动画播放中";
|
||
statusLabel.ForeColor = System.Drawing.Color.Blue;
|
||
|
||
startAnimationButton.Enabled = false;
|
||
stopAnimationButton.Enabled = true;
|
||
createAnimationButton.Enabled = false;
|
||
}
|
||
}, "播放动画");
|
||
};
|
||
|
||
stopAnimationButton.Click += (sender, e) =>
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
if (_animationManager != null)
|
||
{
|
||
_animationManager.StopAnimation();
|
||
|
||
statusLabel.Text = "状态: 动画已停止";
|
||
statusLabel.ForeColor = System.Drawing.Color.Orange;
|
||
|
||
startAnimationButton.Enabled = true;
|
||
stopAnimationButton.Enabled = false;
|
||
createAnimationButton.Enabled = true;
|
||
}
|
||
}, "停止动画");
|
||
};
|
||
|
||
resetAnimationButton.Click += (sender, e) =>
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
if (_animationManager != null)
|
||
{
|
||
_animationManager.ResetAnimation();
|
||
|
||
statusLabel.Text = "状态: 动画已重置";
|
||
statusLabel.ForeColor = System.Drawing.Color.Gray;
|
||
|
||
startAnimationButton.Enabled = true;
|
||
stopAnimationButton.Enabled = false;
|
||
createAnimationButton.Enabled = true;
|
||
}
|
||
}, "重置动画");
|
||
};
|
||
|
||
// 添加控件到父容器
|
||
parent.Controls.Add(durationLabel);
|
||
parent.Controls.Add(durationNumeric);
|
||
parent.Controls.Add(createAnimationButton);
|
||
parent.Controls.Add(startAnimationButton);
|
||
parent.Controls.Add(stopAnimationButton);
|
||
parent.Controls.Add(resetAnimationButton);
|
||
parent.Controls.Add(statusLabel);
|
||
parent.Controls.Add(instructionLabel);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建可见性控制界面
|
||
/// </summary>
|
||
/// <param name="parent">父容器</param>
|
||
private void CreateVisibilityControls(GroupBox parent)
|
||
{
|
||
// 只显示物流分类项目复选框
|
||
CheckBox logisticsOnlyCheckBox = new CheckBox
|
||
{
|
||
Text = "只显示物流分类项目",
|
||
Size = new Size(200, 20),
|
||
Location = new Point(20, 30),
|
||
Font = new Font("微软雅黑", 8),
|
||
Checked = false,
|
||
UseVisualStyleBackColor = true
|
||
};
|
||
|
||
// 状态标签
|
||
Label statusLabel = new Label
|
||
{
|
||
Text = "状态: 显示所有项目",
|
||
Location = new Point(20, 70),
|
||
Size = new Size(250, 20),
|
||
Font = new Font("微软雅黑", 8),
|
||
ForeColor = System.Drawing.Color.DarkGreen
|
||
};
|
||
|
||
// 复选框事件处理
|
||
logisticsOnlyCheckBox.CheckedChanged += (sender, e) =>
|
||
{
|
||
try
|
||
{
|
||
logisticsOnlyCheckBox.Enabled = false;
|
||
statusLabel.Text = "状态: 正在处理...";
|
||
statusLabel.ForeColor = System.Drawing.Color.Orange;
|
||
|
||
VisibilityOperationResult result;
|
||
|
||
if (logisticsOnlyCheckBox.Checked)
|
||
{
|
||
// 勾选时:隐藏非物流分类项目
|
||
result = VisibilityManager.HideNonLogisticsItems();
|
||
if (result.Success)
|
||
{
|
||
statusLabel.Text = $"状态: 已隐藏 {result.HiddenCount} 个非物流项目";
|
||
statusLabel.ForeColor = System.Drawing.Color.DarkGreen;
|
||
}
|
||
else
|
||
{
|
||
statusLabel.Text = "状态: 隐藏操作失败";
|
||
statusLabel.ForeColor = System.Drawing.Color.Red;
|
||
logisticsOnlyCheckBox.Checked = false; // 回滚状态
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 取消勾选时:显示所有项目
|
||
result = VisibilityManager.ShowAllItems();
|
||
if (result.Success)
|
||
{
|
||
statusLabel.Text = "状态: 显示所有项目";
|
||
statusLabel.ForeColor = System.Drawing.Color.DarkGreen;
|
||
}
|
||
else
|
||
{
|
||
statusLabel.Text = "状态: 显示操作失败";
|
||
statusLabel.ForeColor = System.Drawing.Color.Red;
|
||
logisticsOnlyCheckBox.Checked = true; // 回滚状态
|
||
}
|
||
}
|
||
|
||
// 如果操作失败,显示错误信息
|
||
if (!result.Success)
|
||
{
|
||
MessageBox.Show(result.Message, "操作失败", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
statusLabel.Text = "状态: 发生错误";
|
||
statusLabel.ForeColor = System.Drawing.Color.Red;
|
||
logisticsOnlyCheckBox.Checked = !logisticsOnlyCheckBox.Checked; // 回滚状态
|
||
MessageBox.Show($"操作出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
finally
|
||
{
|
||
logisticsOnlyCheckBox.Enabled = true;
|
||
}
|
||
};
|
||
|
||
// 添加控件到父容器
|
||
parent.Controls.Add(logisticsOnlyCheckBox);
|
||
parent.Controls.Add(statusLabel);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 选择变化事件处理
|
||
/// </summary>
|
||
private static void OnSelectionChanged(object sender, EventArgs e)
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
// 更新选择显示
|
||
UpdateSelectionDisplay();
|
||
}, "选择变化事件处理");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新选择显示信息
|
||
/// </summary>
|
||
private static void UpdateSelectionDisplay()
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
if (_controlPanelForm == null || _controlPanelForm.IsDisposed) return;
|
||
|
||
// 获取当前选中的模型项
|
||
var selectedItems = NavisApplication.ActiveDocument.CurrentSelection.SelectedItems;
|
||
int selectedCount = selectedItems.Count;
|
||
|
||
// 更新指令标签
|
||
if (_instructionLabel != null && !_instructionLabel.IsDisposed)
|
||
{
|
||
_instructionLabel.Text = selectedCount == 0 ? "请在主界面中点击选择模型" : $"已选中 {selectedCount} 个模型";
|
||
_instructionLabel.ForeColor = selectedCount > 0 ? System.Drawing.Color.Blue : System.Drawing.Color.Orange;
|
||
}
|
||
|
||
// 更新选中模型标签
|
||
if (_selectedModelsLabel != null && !_selectedModelsLabel.IsDisposed)
|
||
{
|
||
if (selectedCount > 0)
|
||
{
|
||
string modelNames = string.Join(", ", selectedItems.Take(3).Select(item =>
|
||
item.DisplayName.Length > 15 ? item.DisplayName.Substring(0, 15) + "..." : item.DisplayName));
|
||
if (selectedCount > 3) modelNames += $" 等{selectedCount}项";
|
||
|
||
_selectedModelsLabel.Text = $"选中模型: {modelNames}";
|
||
_selectedModelsLabel.Visible = true;
|
||
}
|
||
else
|
||
{
|
||
_selectedModelsLabel.Visible = false;
|
||
}
|
||
}
|
||
|
||
}, "更新选择显示");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 刷新界面数据(包括物流模型列表和统计信息)
|
||
/// </summary>
|
||
private static void RefreshInterfaceData()
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
// 刷新物流模型列表
|
||
if (_logisticsListView != null && !_logisticsListView.IsDisposed)
|
||
{
|
||
RefreshLogisticsModelListStatic(_logisticsListView);
|
||
}
|
||
|
||
// 更新统计信息
|
||
if (_statsLabel != null && !_statsLabel.IsDisposed)
|
||
{
|
||
UpdateLogisticsStatsStatic(_statsLabel);
|
||
}
|
||
|
||
}, "刷新界面数据");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 刷新物流模型列表(静态版本)
|
||
/// </summary>
|
||
private static void RefreshLogisticsModelListStatic(ListView listView)
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
listView.Items.Clear();
|
||
|
||
var document = NavisApplication.ActiveDocument;
|
||
if (document?.Models == null) return;
|
||
|
||
foreach (ModelItem rootItem in document.Models.RootItems)
|
||
{
|
||
foreach (ModelItem item in rootItem.DescendantsAndSelf)
|
||
{
|
||
if (CategoryAttributeManager.HasLogisticsAttributes(item))
|
||
{
|
||
var category = CategoryAttributeManager.GetLogisticsPropertyValue(item, CategoryAttributeManager.LogisticsProperties.TYPE);
|
||
var listItem = new ListViewItem(new string[]
|
||
{
|
||
item.DisplayName.Length > 25 ? item.DisplayName.Substring(0, 25) + "..." : item.DisplayName,
|
||
string.IsNullOrEmpty(category) ? "未知" : category
|
||
});
|
||
listItem.Tag = item; // 保存ModelItem引用
|
||
listView.Items.Add(listItem);
|
||
}
|
||
}
|
||
}
|
||
|
||
LogManager.Info($"物流模型列表已刷新,共 {listView.Items.Count} 项");
|
||
|
||
}, "刷新物流模型列表");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新物流统计信息(静态版本)
|
||
/// </summary>
|
||
private static void UpdateLogisticsStatsStatic(Label statsLabel)
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
var document = NavisApplication.ActiveDocument;
|
||
if (document?.Models == null)
|
||
{
|
||
statsLabel.Text = "统计: 无活动文档";
|
||
return;
|
||
}
|
||
|
||
int totalModels = 0;
|
||
int logisticsModels = 0;
|
||
|
||
// 统计所有模型和物流模型
|
||
foreach (ModelItem rootItem in document.Models.RootItems)
|
||
{
|
||
foreach (ModelItem item in rootItem.DescendantsAndSelf)
|
||
{
|
||
totalModels++;
|
||
if (CategoryAttributeManager.HasLogisticsAttributes(item))
|
||
{
|
||
logisticsModels++;
|
||
}
|
||
}
|
||
}
|
||
|
||
statsLabel.Text = $"统计: 总模型 {totalModels} 个,物流模型 {logisticsModels} 个";
|
||
|
||
}, "更新物流统计");
|
||
}
|
||
|
||
#region PathPlanningManager 事件处理器
|
||
|
||
/// <summary>
|
||
/// 处理路径编辑状态变更事件
|
||
/// </summary>
|
||
private static void OnPathEditStateChanged(object sender, PathEditState newState)
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
LogManager.Info($"[UI同步] ===== 路径编辑状态变更事件触发 =====");
|
||
LogManager.Info($"[UI同步] 新状态: {newState}");
|
||
LogManager.Info($"[UI同步] 当前线程: {System.Threading.Thread.CurrentThread.ManagedThreadId}");
|
||
|
||
// 确保在UI线程上执行
|
||
if (_controlPanelForm != null && _controlPanelForm.InvokeRequired)
|
||
{
|
||
LogManager.Info("[UI同步] 需要跨线程调用,使用Invoke");
|
||
_controlPanelForm.Invoke(new Action(() => OnPathEditStateChanged(sender, newState)));
|
||
return;
|
||
}
|
||
|
||
LogManager.Info("[UI同步] 在UI线程上执行状态更新");
|
||
|
||
// 更新当前路径状态标签
|
||
if (_currentPathStatusLabel != null)
|
||
{
|
||
string stateText;
|
||
switch (newState)
|
||
{
|
||
case PathEditState.Viewing:
|
||
stateText = "查看状态";
|
||
break;
|
||
case PathEditState.Creating:
|
||
stateText = "正在新建路径";
|
||
break;
|
||
case PathEditState.Editing:
|
||
stateText = "正在编辑路径";
|
||
break;
|
||
default:
|
||
stateText = "未知状态";
|
||
break;
|
||
}
|
||
|
||
LogManager.Info($"[UI同步] 更新状态标签文本: {stateText}");
|
||
_currentPathStatusLabel.Text = $"当前状态: {stateText}";
|
||
|
||
System.Drawing.Color color;
|
||
switch (newState)
|
||
{
|
||
case PathEditState.Viewing:
|
||
color = System.Drawing.Color.Gray;
|
||
break;
|
||
case PathEditState.Creating:
|
||
color = System.Drawing.Color.Green;
|
||
break;
|
||
case PathEditState.Editing:
|
||
color = System.Drawing.Color.Blue;
|
||
break;
|
||
default:
|
||
color = System.Drawing.Color.Black;
|
||
break;
|
||
}
|
||
_currentPathStatusLabel.ForeColor = color;
|
||
LogManager.Info($"[UI同步] 状态标签颜色已更新: {color}");
|
||
}
|
||
else
|
||
{
|
||
LogManager.Warning("[UI同步] _currentPathStatusLabel为null,无法更新状态标签");
|
||
}
|
||
|
||
// 更新按钮状态
|
||
UpdateButtonStates(newState);
|
||
|
||
LogManager.Info("[UI同步] ===== 路径编辑状态变更事件处理完成 =====");
|
||
|
||
}, "处理路径编辑状态变更");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据编辑状态更新按钮状态
|
||
/// </summary>
|
||
/// <param name="editState">当前编辑状态</param>
|
||
private static void UpdateButtonStates(PathEditState editState)
|
||
{
|
||
try
|
||
{
|
||
// 查找完成编辑和取消编辑按钮
|
||
if (_controlPanelForm != null)
|
||
{
|
||
var finishButton = FindButtonByText(_controlPanelForm, "完成编辑");
|
||
var cancelButton = FindButtonByText(_controlPanelForm, "取消编辑");
|
||
|
||
bool isEditable = editState == PathEditState.Creating || editState == PathEditState.Editing;
|
||
|
||
if (finishButton != null)
|
||
{
|
||
finishButton.Enabled = isEditable;
|
||
}
|
||
|
||
if (cancelButton != null)
|
||
{
|
||
cancelButton.Enabled = isEditable;
|
||
}
|
||
|
||
LogManager.Info($"[UI同步] 按钮状态已更新,编辑状态: {editState}, 按钮启用: {isEditable}");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"[UI同步] 更新按钮状态失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据文本查找按钮控件
|
||
/// </summary>
|
||
/// <param name="parent">父控件</param>
|
||
/// <param name="buttonText">按钮文本</param>
|
||
/// <returns>找到的按钮,如果没找到返回null</returns>
|
||
private static Button FindButtonByText(Control parent, string buttonText)
|
||
{
|
||
foreach (Control control in parent.Controls)
|
||
{
|
||
if (control is Button button && button.Text == buttonText)
|
||
{
|
||
return button;
|
||
}
|
||
|
||
// 递归查找子控件
|
||
var foundInChild = FindButtonByText(control, buttonText);
|
||
if (foundInChild != null)
|
||
{
|
||
return foundInChild;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理3D路径点添加事件
|
||
/// </summary>
|
||
private static void OnPathPointAddedIn3D(object sender, PathPoint pathPoint)
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
LogManager.Info($"[UI同步] 3D路径点已添加: {pathPoint?.Name}");
|
||
|
||
// 更新当前路径点列表
|
||
UpdateCurrentPathPointsList();
|
||
|
||
}, "处理3D路径点添加");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理3D路径点删除事件
|
||
/// </summary>
|
||
private static void OnPathPointRemovedFrom3D(object sender, PathPoint pathPoint)
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
LogManager.Info($"[UI同步] 3D路径点已删除: {pathPoint?.Name}");
|
||
|
||
// 更新当前路径点列表
|
||
UpdateCurrentPathPointsList();
|
||
|
||
}, "处理3D路径点删除");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理路径点列表更新事件
|
||
/// </summary>
|
||
private static void OnPathPointsListUpdated(object sender, PathRoute updatedRoute)
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
LogManager.Info($"[UI同步] 路径点列表已更新: {updatedRoute?.Name ?? "空路径"}");
|
||
|
||
// 更新当前路径点列表
|
||
UpdateCurrentPathPointsList();
|
||
|
||
// 更新路径列表
|
||
UpdatePathList();
|
||
|
||
}, "处理路径点列表更新");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理当前路径变更事件
|
||
/// </summary>
|
||
private static void OnCurrentRouteChanged(object sender, PathRoute newRoute)
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
LogManager.Info($"[UI同步] 当前路径已变更: {newRoute?.Name ?? "无路径"}");
|
||
|
||
// 更新当前路径点列表
|
||
UpdateCurrentPathPointsList();
|
||
|
||
// 更新路径列表
|
||
UpdatePathList();
|
||
|
||
}, "处理当前路径变更");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理路径管理器状态变更事件
|
||
/// </summary>
|
||
private static void OnPathManagerStatusChanged(object sender, string status)
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
LogManager.Info($"[UI同步] 路径管理器状态: {status}");
|
||
|
||
// 可以在这里更新状态栏或其他UI元素
|
||
|
||
}, "处理路径管理器状态变更");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理路径管理器错误事件
|
||
/// </summary>
|
||
private static void OnPathManagerErrorOccurred(object sender, string error)
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
LogManager.Error($"[UI同步] 路径管理器错误: {error}");
|
||
|
||
// 显示错误信息
|
||
MessageBox.Show($"路径管理器错误: {error}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||
|
||
}, "处理路径管理器错误");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新当前路径点列表UI
|
||
/// </summary>
|
||
private static void UpdateCurrentPathPointsList()
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
if (_currentPathPointsListView == null || _pathPlanningManager == null)
|
||
return;
|
||
|
||
var currentRoute = _pathPlanningManager.CurrentRoute;
|
||
|
||
_currentPathPointsListView.Items.Clear();
|
||
|
||
if (currentRoute?.Points != null && currentRoute.Points.Count > 0)
|
||
{
|
||
for (int i = 0; i < currentRoute.Points.Count; i++)
|
||
{
|
||
var point = currentRoute.Points[i];
|
||
string typeText;
|
||
switch (point.Type)
|
||
{
|
||
case PathPointType.StartPoint:
|
||
typeText = "起点";
|
||
break;
|
||
case PathPointType.EndPoint:
|
||
typeText = "终点";
|
||
break;
|
||
case PathPointType.WayPoint:
|
||
typeText = "路径点";
|
||
break;
|
||
default:
|
||
typeText = "未知";
|
||
break;
|
||
}
|
||
|
||
// 创建ListViewItem
|
||
var item = new ListViewItem((i + 1).ToString()); // 序号
|
||
item.SubItems.Add(point.Name); // 名称
|
||
item.SubItems.Add(typeText); // 类型
|
||
item.SubItems.Add($"({point.Position.X:F1}, {point.Position.Y:F1}, {point.Position.Z:F1})"); // 坐标
|
||
|
||
_currentPathPointsListView.Items.Add(item);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 可选:添加一个提示项
|
||
var placeholder = new ListViewItem("暂无路径点");
|
||
placeholder.ForeColor = System.Drawing.Color.Gray;
|
||
_currentPathPointsListView.Items.Add(placeholder);
|
||
}
|
||
|
||
LogManager.Info($"[UI同步] 当前路径点列表已更新,共{currentRoute?.Points?.Count ?? 0}个点");
|
||
|
||
}, "更新当前路径点列表");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新路径列表UI
|
||
/// </summary>
|
||
private static void UpdatePathList()
|
||
{
|
||
GlobalExceptionHandler.SafeExecute(() =>
|
||
{
|
||
if (_pathListView == null || _pathPlanningManager == null)
|
||
return;
|
||
|
||
_pathListView.Items.Clear();
|
||
|
||
var routes = _pathPlanningManager.Routes;
|
||
if (routes != null && routes.Count > 0)
|
||
{
|
||
foreach (var route in routes)
|
||
{
|
||
var item = new ListViewItem(route.Name);
|
||
item.SubItems.Add(route.CreatedTime.ToString("MM-dd HH:mm"));
|
||
item.SubItems.Add(route.Points?.Count.ToString() ?? "0");
|
||
item.Tag = route; // 保存路径对象引用
|
||
|
||
_pathListView.Items.Add(item);
|
||
}
|
||
}
|
||
|
||
LogManager.Info($"[UI同步] 路径列表已更新,共{routes?.Count ?? 0}条路径");
|
||
|
||
}, "更新路径列表");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示路径历史记录对话框
|
||
/// </summary>
|
||
/// <param name="historyEntries">历史记录列表</param>
|
||
/// <param name="historyManager">历史记录管理器</param>
|
||
private static void ShowPathHistoryDialog(List<PathHistoryEntry> historyEntries, PathHistoryManager historyManager)
|
||
{
|
||
var historyForm = new Form
|
||
{
|
||
Text = "路径历史记录",
|
||
Size = new Size(600, 400),
|
||
StartPosition = FormStartPosition.CenterParent,
|
||
FormBorderStyle = FormBorderStyle.FixedDialog,
|
||
MaximizeBox = false,
|
||
MinimizeBox = false
|
||
};
|
||
|
||
// 创建历史记录列表
|
||
var historyListView = new ListView
|
||
{
|
||
Location = new Point(10, 10),
|
||
Size = new Size(565, 300),
|
||
View = System.Windows.Forms.View.Details,
|
||
FullRowSelect = true,
|
||
GridLines = true,
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
|
||
// 添加列标题
|
||
historyListView.Columns.Add("操作时间", 120);
|
||
historyListView.Columns.Add("路径ID", 80);
|
||
historyListView.Columns.Add("操作类型", 80);
|
||
historyListView.Columns.Add("描述", 260);
|
||
|
||
// 填充历史记录数据
|
||
foreach (var entry in historyEntries)
|
||
{
|
||
var item = new ListViewItem(new string[]
|
||
{
|
||
entry.OperationTime.ToString("MM-dd HH:mm:ss"),
|
||
entry.RouteId.Substring(0, Math.Min(8, entry.RouteId.Length)) + "...",
|
||
GetOperationTypeName(entry.OperationType),
|
||
entry.Description
|
||
});
|
||
item.Tag = entry;
|
||
historyListView.Items.Add(item);
|
||
}
|
||
|
||
historyForm.Controls.Add(historyListView);
|
||
|
||
// 操作按钮
|
||
var clearButton = new Button
|
||
{
|
||
Text = "清空历史",
|
||
Location = new Point(10, 320),
|
||
Size = new Size(80, 30),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
|
||
var exportButton = new Button
|
||
{
|
||
Text = "导出历史",
|
||
Location = new Point(100, 320),
|
||
Size = new Size(80, 30),
|
||
Font = new Font("微软雅黑", 8)
|
||
};
|
||
|
||
var closeButton = new Button
|
||
{
|
||
Text = "关闭",
|
||
Location = new Point(495, 320),
|
||
Size = new Size(80, 30),
|
||
Font = new Font("微软雅黑", 8),
|
||
DialogResult = DialogResult.OK
|
||
};
|
||
|
||
// 事件处理
|
||
clearButton.Click += (sender, e) => {
|
||
var result = MessageBox.Show("确定要清空所有历史记录吗?此操作不可撤销。",
|
||
"确认清空", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
|
||
if (result == DialogResult.Yes)
|
||
{
|
||
try
|
||
{
|
||
// 清空所有路径的历史记录
|
||
var pathManager = PathPlanningManager.GetActivePathManager();
|
||
if (pathManager?.Routes != null)
|
||
{
|
||
foreach (var route in pathManager.Routes)
|
||
{
|
||
historyManager.ClearRouteHistory(route.Id);
|
||
}
|
||
}
|
||
|
||
historyListView.Items.Clear();
|
||
MessageBox.Show("历史记录已清空", "操作完成",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
LogManager.Info("用户清空了路径历史记录");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"清空历史记录失败: {ex.Message}", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
LogManager.Error($"清空历史记录失败: {ex.Message}");
|
||
}
|
||
}
|
||
};
|
||
|
||
exportButton.Click += (sender, e) => {
|
||
try
|
||
{
|
||
SaveFileDialog saveDialog = new SaveFileDialog
|
||
{
|
||
Title = "导出历史记录",
|
||
Filter = "文本文件 (*.txt)|*.txt|CSV文件 (*.csv)|*.csv",
|
||
FilterIndex = 1,
|
||
DefaultExt = "txt"
|
||
};
|
||
|
||
if (saveDialog.ShowDialog() == DialogResult.OK)
|
||
{
|
||
var content = new StringBuilder();
|
||
content.AppendLine("路径历史记录导出");
|
||
content.AppendLine($"导出时间: {DateTime.Now}");
|
||
content.AppendLine($"总记录数: {historyEntries.Count}");
|
||
content.AppendLine();
|
||
content.AppendLine("操作时间\t路径ID\t操作类型\t描述");
|
||
|
||
foreach (var entry in historyEntries)
|
||
{
|
||
content.AppendLine($"{entry.OperationTime:yyyy-MM-dd HH:mm:ss}\t{entry.RouteId}\t{GetOperationTypeName(entry.OperationType)}\t{entry.Description}");
|
||
}
|
||
|
||
File.WriteAllText(saveDialog.FileName, content.ToString(), Encoding.UTF8);
|
||
MessageBox.Show($"历史记录已导出到: {saveDialog.FileName}", "导出成功",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
LogManager.Info($"历史记录已导出到: {saveDialog.FileName}");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"导出历史记录失败: {ex.Message}", "错误",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
LogManager.Error($"导出历史记录失败: {ex.Message}");
|
||
}
|
||
};
|
||
|
||
historyForm.Controls.Add(clearButton);
|
||
historyForm.Controls.Add(exportButton);
|
||
historyForm.Controls.Add(closeButton);
|
||
|
||
historyForm.ShowDialog();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取操作类型的显示名称
|
||
/// </summary>
|
||
/// <param name="operationType">操作类型</param>
|
||
/// <returns>显示名称</returns>
|
||
private static string GetOperationTypeName(PathHistoryOperationType operationType)
|
||
{
|
||
switch (operationType)
|
||
{
|
||
case PathHistoryOperationType.Created:
|
||
return "创建";
|
||
case PathHistoryOperationType.Edited:
|
||
return "编辑";
|
||
case PathHistoryOperationType.PointAdded:
|
||
return "添加点";
|
||
case PathHistoryOperationType.PointRemoved:
|
||
return "删除点";
|
||
case PathHistoryOperationType.Optimized:
|
||
return "优化";
|
||
case PathHistoryOperationType.ManualSave:
|
||
return "保存";
|
||
default:
|
||
return operationType.ToString();
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
}
|