优化插件启动时的动作
This commit is contained in:
parent
b7a112354d
commit
3aaa176ce6
@ -2,6 +2,11 @@
|
||||
|
||||
## 功能点
|
||||
|
||||
### [2025/10/14]
|
||||
|
||||
1. [x] (功能优化)用空间索引优化碰撞路径预处理
|
||||
2. [x] (功能优化)规范文档打开前/后的初始化行为
|
||||
|
||||
### [2025/10/12]
|
||||
|
||||
1. [x] (实验性功能)用体素网格实现3D路径规划
|
||||
|
||||
@ -484,7 +484,7 @@ namespace NavisworksTransport
|
||||
var pathManager = PathPlanningManager.GetActivePathManager();
|
||||
if (pathManager != null)
|
||||
{
|
||||
pathManager.EnsureDatabaseInitialized();
|
||||
pathManager.DatabaseInitialize();
|
||||
LogManager.Info("[文档管理] 已触发PathDatabase初始化");
|
||||
}
|
||||
}, "初始化PathDatabase");
|
||||
|
||||
@ -443,80 +443,16 @@ namespace NavisworksTransport
|
||||
{
|
||||
// 设置静态实例
|
||||
Instance = this;
|
||||
|
||||
|
||||
_floorDetector = new FloorDetector();
|
||||
|
||||
|
||||
// 初始化缓存
|
||||
_floorCache = new Dictionary<string, List<SplitPreviewResult>>();
|
||||
_cacheLock = new object();
|
||||
|
||||
// 验证Navisworks运行时环境
|
||||
ValidateNavisworksRuntime();
|
||||
|
||||
LogManager.Info("[SimplifiedModelSplitter] 简化分层管理器已初始化,包含缓存机制和运行时验证");
|
||||
LogManager.Debug("[ModelSplitterManager] 分层管理器已初始化");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证Navisworks运行时环境 - 基于示例中的最佳实践
|
||||
/// </summary>
|
||||
private void ValidateNavisworksRuntime()
|
||||
{
|
||||
try
|
||||
{
|
||||
LogManager.Info("[SimplifiedModelSplitter] 开始验证Navisworks运行时环境...");
|
||||
|
||||
// 1. 检查线程模型 - 必须在STA线程中
|
||||
var apartmentState = System.Threading.Thread.CurrentThread.GetApartmentState();
|
||||
LogManager.Info($"[分层管理器] 当前线程状态: {apartmentState}");
|
||||
if (apartmentState != System.Threading.ApartmentState.STA)
|
||||
{
|
||||
LogManager.Warning("[SimplifiedModelSplitter] 警告:当前不在STA线程中,这可能导致API调用失败");
|
||||
LogManager.Warning("[SimplifiedModelSplitter] 建议:确保主线程标记为[STAThread]");
|
||||
}
|
||||
|
||||
// 2. 检查Navisworks API可用性 - 适用于Navisworks 2026
|
||||
try
|
||||
{
|
||||
// 尝试访问Navisworks Application来验证API是否可用
|
||||
var app = NavisApplication.ActiveDocument;
|
||||
LogManager.Info("[SimplifiedModelSplitter] Navisworks API可用性检查通过");
|
||||
}
|
||||
catch (Exception apiEx)
|
||||
{
|
||||
LogManager.Error($"[分层管理器] Navisworks API不可用: {apiEx.Message}");
|
||||
LogManager.Error("[SimplifiedModelSplitter] 解决方案:确保在Navisworks环境中运行此插件");
|
||||
}
|
||||
|
||||
// 3. 检查文档状态
|
||||
try
|
||||
{
|
||||
var document = NavisApplication.ActiveDocument;
|
||||
if (document != null)
|
||||
{
|
||||
LogManager.Info($"[分层管理器] 活动文档: {document.FileName ?? "未命名"}");
|
||||
LogManager.Info($"[分层管理器] 文档模型数量: {document.Models?.Count ?? 0}");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning("[SimplifiedModelSplitter] 当前没有活动文档");
|
||||
}
|
||||
}
|
||||
catch (Exception docEx)
|
||||
{
|
||||
LogManager.Warning($"[分层管理器] 检查文档状态时出错: {docEx.Message}");
|
||||
}
|
||||
|
||||
// 4. 内存状态检查
|
||||
long memoryMB = GC.GetTotalMemory(false) / 1024 / 1024;
|
||||
LogManager.Info($"[分层管理器] 当前内存使用: {memoryMB} MB");
|
||||
|
||||
LogManager.Info("[SimplifiedModelSplitter] Navisworks运行时环境验证完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[分层管理器] 运行时环境验证失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@ -117,40 +117,6 @@ namespace NavisworksTransport
|
||||
_activePathManager = this;
|
||||
LogManager.Debug($"[路径管理] 设置_activePathManager静态引用, ManagerId: {_managerId}");
|
||||
|
||||
// 尝试初始化路径分析数据库
|
||||
EnsureDatabaseInitialized();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确保路径分析数据库已初始化(支持延迟初始化)
|
||||
/// </summary>
|
||||
public void EnsureDatabaseInitialized()
|
||||
{
|
||||
if (_pathDatabase != null && _analysisService != null)
|
||||
{
|
||||
LogManager.Info("路径分析数据库已初始化,跳过");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var documentPath = Autodesk.Navisworks.Api.Application.ActiveDocument?.FileName;
|
||||
if (!string.IsNullOrEmpty(documentPath))
|
||||
{
|
||||
_pathDatabase = new PathDatabase(documentPath);
|
||||
_analysisService = new PathAnalysisService(_pathDatabase);
|
||||
LogManager.Info($"路径分析数据库初始化成功,文档路径: {documentPath}");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Warning("文档路径为空,路径分析数据库初始化将延迟到文档加载后");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"初始化路径分析数据库失败: {ex.Message}", ex);
|
||||
}
|
||||
|
||||
// 获取已注册的圆形渲染插件实例
|
||||
try
|
||||
{
|
||||
@ -175,6 +141,7 @@ namespace NavisworksTransport
|
||||
_renderPlugin = null;
|
||||
}
|
||||
|
||||
// 初始化核心数据结构
|
||||
_walkableAreas = new List<ModelItem>();
|
||||
_routes = new List<PathRoute>();
|
||||
_currentRoute = new PathRoute("默认路径");
|
||||
@ -182,10 +149,47 @@ namespace NavisworksTransport
|
||||
_coordinateConverter = null; // 将在需要时初始化
|
||||
_pathPointMarkers = new List<PathPointMarker>();
|
||||
|
||||
// 从数据库加载历史路径到内存
|
||||
LoadHistoricalRoutesFromDatabase();
|
||||
|
||||
LogManager.Info($"PathPlanningManager初始化完成,ManagerId: {_managerId}");
|
||||
|
||||
// 注意:数据库初始化延迟到文档加载完成后
|
||||
// 在 MainPlugin.OnModelsCollectionChanged 中会调用 DatabaseInitialize()
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 路径分析数据库初始化
|
||||
/// 此方法应在文档加载完成后调用
|
||||
/// </summary>
|
||||
public void DatabaseInitialize()
|
||||
{
|
||||
// 如果已经初始化,直接返回
|
||||
if (_pathDatabase != null && _analysisService != null)
|
||||
{
|
||||
LogManager.Debug("路径分析数据库已初始化,跳过");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var documentPath = Application.ActiveDocument?.FileName;
|
||||
if (!string.IsNullOrEmpty(documentPath))
|
||||
{
|
||||
_pathDatabase = new PathDatabase(documentPath);
|
||||
_analysisService = new PathAnalysisService(_pathDatabase);
|
||||
LogManager.Info($"路径分析数据库初始化成功,文档路径: {documentPath}");
|
||||
|
||||
// 从数据库加载历史路径到内存
|
||||
LoadHistoricalRoutesFromDatabase();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 文档路径为空时,静默跳过(这种情况不应该发生,因为调用者应该确保文档已加载)
|
||||
LogManager.Debug("文档路径为空,跳过数据库初始化");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"初始化路径分析数据库失败: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -200,8 +200,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
return Math.Round(pathLength / (_animationFrameRate * _animationDuration), 3);
|
||||
}
|
||||
|
||||
// 无法计算时返回0,让问题暴露
|
||||
if (pathLength <= 0 || _animationFrameRate <= 0 || _animationDuration <= 0)
|
||||
// 无法计算时返回0
|
||||
// 注意:如果路径为空(pathLength==0),这是正常的初始状态,不输出警告
|
||||
// 只有在配置参数异常时才输出警告
|
||||
if (pathLength > 0 && (_animationFrameRate <= 0 || _animationDuration <= 0))
|
||||
{
|
||||
LogManager.Warning($"[AnimationControlViewModel] 无法计算碰撞检测精度 - 路径长度:{pathLength}m, 帧率:{_animationFrameRate}fps, 时长:{_animationDuration}s");
|
||||
}
|
||||
@ -224,8 +226,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
return Math.Round(pathLength / _animationDuration, 2);
|
||||
}
|
||||
|
||||
// 无法计算时返回0,让问题暴露
|
||||
if (pathLength <= 0 || _animationDuration <= 0)
|
||||
// 无法计算时返回0
|
||||
// 注意:如果路径为空(pathLength==0),这是正常的初始状态,不输出警告
|
||||
// 只有在配置参数异常时才输出警告
|
||||
if (pathLength > 0 && _animationDuration <= 0)
|
||||
{
|
||||
LogManager.Warning($"[AnimationControlViewModel] 无法计算运动速度 - 路径长度:{pathLength}m, 时长:{_animationDuration}s");
|
||||
}
|
||||
|
||||
@ -944,7 +944,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
async () => await ShowAllLayersAsync(),
|
||||
() => IsNotProcessing);
|
||||
|
||||
LogManager.Info("分层管理命令初始化完成 - 使用统一Command Pattern框架");
|
||||
LogManager.Info("分层管理命令初始化完成");
|
||||
}, "初始化命令");
|
||||
}
|
||||
|
||||
@ -2718,20 +2718,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
{
|
||||
// 设置默认输出目录
|
||||
var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
|
||||
|
||||
|
||||
await _uiStateManager.ExecuteUIUpdateAsync(() =>
|
||||
{
|
||||
OutputDirectory = Path.Combine(documentsPath, "NavisworksTransport", "分层输出");
|
||||
});
|
||||
|
||||
// 刷新可用属性
|
||||
await RefreshAttributesAsync();
|
||||
|
||||
// 更新选择状态
|
||||
await UpdateCurrentSelectionAsync();
|
||||
|
||||
// 刷新楼层属性模型选择状态
|
||||
await RefreshSelectionAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@ -33,10 +33,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
#region 私有字段和依赖注入
|
||||
|
||||
private readonly UIStateManager _uiStateManager;
|
||||
|
||||
|
||||
// 选择事件订阅管理器
|
||||
private SelectionEventSubscription _selectionEventSubscription;
|
||||
|
||||
|
||||
// 文档模型集合变化事件订阅标志
|
||||
private bool _modelsCollectionEventSubscribed;
|
||||
|
||||
// 资源释放状态标志
|
||||
private bool _disposed;
|
||||
|
||||
@ -395,6 +398,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
// 订阅Navisworks选择变化事件 - 使用新的选择管理服务
|
||||
SubscribeToSelectionEvents();
|
||||
|
||||
// 订阅文档模型集合变化事件
|
||||
SubscribeToDocumentModelsEvents();
|
||||
|
||||
// 异步初始化
|
||||
InitializeAsync();
|
||||
|
||||
@ -920,6 +926,83 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
|
||||
// 选择状态格式化方法已移至NavisworksSelectionHelper中
|
||||
|
||||
#region 文档模型集合事件处理
|
||||
|
||||
/// <summary>
|
||||
/// 订阅文档模型集合变化事件
|
||||
/// </summary>
|
||||
private void SubscribeToDocumentModelsEvents()
|
||||
{
|
||||
try
|
||||
{
|
||||
var document = NavisApplication.ActiveDocument;
|
||||
if (document?.Models != null && !_modelsCollectionEventSubscribed)
|
||||
{
|
||||
document.Models.CollectionChanged += OnDocumentModelsCollectionChanged;
|
||||
_modelsCollectionEventSubscribed = true;
|
||||
LogManager.Info("[ModelSettingsViewModel] 已订阅文档Models.CollectionChanged事件");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[ModelSettingsViewModel] 订阅文档模型集合事件失败: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取消订阅文档模型集合变化事件
|
||||
/// </summary>
|
||||
private void UnsubscribeFromDocumentModelsEvents()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_modelsCollectionEventSubscribed)
|
||||
{
|
||||
var document = NavisApplication.ActiveDocument;
|
||||
if (document?.Models != null)
|
||||
{
|
||||
document.Models.CollectionChanged -= OnDocumentModelsCollectionChanged;
|
||||
}
|
||||
_modelsCollectionEventSubscribed = false;
|
||||
LogManager.Info("[ModelSettingsViewModel] 已取消订阅文档Models.CollectionChanged事件");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[ModelSettingsViewModel] 取消订阅文档模型集合事件失败: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文档模型集合变化事件处理器
|
||||
/// </summary>
|
||||
private async void OnDocumentModelsCollectionChanged(object sender, EventArgs e)
|
||||
{
|
||||
// 如果已经释放,直接返回
|
||||
if (_disposed) return;
|
||||
|
||||
try
|
||||
{
|
||||
var document = NavisApplication.ActiveDocument;
|
||||
var modelsCount = document?.Models?.Count ?? 0;
|
||||
|
||||
LogManager.Info($"[ModelSettingsViewModel] 文档模型集合变化,当前模型数量: {modelsCount}");
|
||||
|
||||
// 只有在有模型的情况下才刷新物流模型列表
|
||||
if (modelsCount > 0)
|
||||
{
|
||||
LogManager.Info("[ModelSettingsViewModel] 检测到文档模型加载完成,自动刷新物流模型列表");
|
||||
await RefreshLogisticsModelsAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"[ModelSettingsViewModel] 处理文档模型集合变化事件异常: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 选择事件处理
|
||||
|
||||
/// <summary>
|
||||
@ -1053,17 +1136,16 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
}
|
||||
});
|
||||
|
||||
// 刷新选择状态
|
||||
await RefreshSelectionAsync();
|
||||
// 注意:不在初始化时刷新选择状态和物流模型列表
|
||||
// 刷新会在以下情况自动触发:
|
||||
// 1. 选择状态 - 通过 NavisworksSelectionHelper 的选择变化事件自动刷新
|
||||
// 2. 物流模型列表 - 通过 Models.CollectionChanged 事件在文档加载后自动刷新
|
||||
|
||||
// 刷新物流模型列表
|
||||
await RefreshLogisticsModelsAsync();
|
||||
|
||||
// 🔧 确保初始化完成后所有Command状态正确
|
||||
await _uiStateManager.ExecuteUIUpdateAsync(() =>
|
||||
{
|
||||
RefreshAllCommands();
|
||||
UpdateMainStatus("分层属性设置已就绪");
|
||||
UpdateMainStatus("类别设置已就绪");
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -1253,6 +1335,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
// 取消选择事件订阅
|
||||
UnsubscribeFromSelectionEvents();
|
||||
|
||||
// 取消文档模型集合事件订阅
|
||||
UnsubscribeFromDocumentModelsEvents();
|
||||
|
||||
LogManager.Info("[ModelSettingsViewModel] 资源清理完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@ -174,7 +174,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
try
|
||||
{
|
||||
var manager = PathPlanningManager.Instance;
|
||||
manager.EnsureDatabaseInitialized();
|
||||
manager.DatabaseInitialize();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@ -2148,14 +2148,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
{
|
||||
if (_pathPlanningManager == null)
|
||||
{
|
||||
LogManager.Info("PathPlanningManager为null,跳过事件订阅");
|
||||
LogManager.Debug("PathPlanningManager尚未设置,跳过事件订阅");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
LogManager.Info($"*** 开始订阅PathPlanningManager事件,Manager实例: {_pathPlanningManager.GetType().Name} ***");
|
||||
|
||||
// 订阅路径点操作事件(用于手工路径编辑)
|
||||
_pathPlanningManager.PathPointOperation += OnPathPointOperation;
|
||||
|
||||
@ -2174,22 +2172,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
// 添加错误事件订阅 - 用于处理自动路径规划失败等错误
|
||||
_pathPlanningManager.ErrorOccurred += OnPathPlanningError;
|
||||
|
||||
LogManager.Info("*** PathEditingViewModel已成功订阅PathPlanningManager事件,包括RouteGenerated和ErrorOccurred ***");
|
||||
|
||||
// 验证事件订阅是否成功
|
||||
var routeGeneratedField = _pathPlanningManager.GetType().GetEvent("RouteGenerated");
|
||||
if (routeGeneratedField != null)
|
||||
{
|
||||
LogManager.Info($"*** RouteGenerated事件存在,事件类型: {routeGeneratedField.EventHandlerType?.Name} ***");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogManager.Error("*** RouteGenerated事件不存在!!! ***");
|
||||
}
|
||||
|
||||
// 初始化加载现有路径(包括从数据库加载的历史路径)
|
||||
RefreshPathRoutes();
|
||||
LogManager.Info("*** 已从PathPlanningManager加载现有路径到UI ***");
|
||||
LogManager.Debug("PathEditingViewModel已成功订阅PathPlanningManager事件");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@ -460,82 +460,10 @@ namespace NavisworksTransport.UI.WPF.ViewModels
|
||||
UpdateMainStatus("系统管理初始化完成");
|
||||
});
|
||||
|
||||
// 启动性能监控
|
||||
StartPerformanceMonitoring();
|
||||
|
||||
LogManager.Info("系统管理设置初始化完成");
|
||||
}, "初始化系统管理设置");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动性能监控 (已优化为Idle事件)
|
||||
/// </summary>
|
||||
private void StartPerformanceMonitoring()
|
||||
{
|
||||
// 如果已经释放,不启动监控
|
||||
if (_disposed)
|
||||
{
|
||||
LogManager.Info("SystemManagementViewModel已释放,跳过性能监控启动");
|
||||
return;
|
||||
}
|
||||
|
||||
_startTime = DateTime.Now;
|
||||
_lastPerformanceUpdate = DateTime.MinValue;
|
||||
|
||||
// 使用IdleEventManager注册性能监控任务,替代DispatcherTimer
|
||||
const string taskId = "SystemManagement_PerformanceMonitor";
|
||||
|
||||
IdleEventManager.Instance.RegisterTask(
|
||||
taskId,
|
||||
UpdatePerformanceMetrics, // 要执行的操作
|
||||
30000, // 30秒间隔 (毫秒)
|
||||
5 // 中等优先级
|
||||
);
|
||||
|
||||
LogManager.Info("SystemManagementViewModel性能监控已启动 (Idle事件模式)");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新性能指标 (Idle事件回调方法)
|
||||
/// </summary>
|
||||
private void UpdatePerformanceMetrics()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 检查释放状态,避免在释放后继续更新UI
|
||||
if (_disposed)
|
||||
{
|
||||
LogManager.Info("SystemManagementViewModel已释放,停止性能监控更新");
|
||||
IdleEventManager.Instance.UnregisterTask("SystemManagement_PerformanceMonitor");
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新内存使用
|
||||
var process = System.Diagnostics.Process.GetCurrentProcess();
|
||||
var memoryMB = process.WorkingSet64 / (1024 * 1024);
|
||||
MemoryUsage = $"{memoryMB} MB";
|
||||
|
||||
// 更新运行时间
|
||||
var runTime = DateTime.Now - _startTime;
|
||||
RunningTime = $"{runTime.Hours:D2}:{runTime.Minutes:D2}:{runTime.Seconds:D2}";
|
||||
|
||||
// 记录上次更新时间
|
||||
_lastPerformanceUpdate = DateTime.Now;
|
||||
|
||||
LogManager.Debug($"性能指标已更新: 内存={MemoryUsage}, 运行时间={RunningTime}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"性能监控更新失败: {ex.Message}");
|
||||
|
||||
// 发生异常时停止监控,避免持续错误
|
||||
if (!_disposed)
|
||||
{
|
||||
IdleEventManager.Instance.UnregisterTask("SystemManagement_PerformanceMonitor");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 命令实现
|
||||
|
||||
Loading…
Reference in New Issue
Block a user