diff --git a/src/Core/Animation/PathAnimationManager.cs b/src/Core/Animation/PathAnimationManager.cs index c71cf2e..1c0a966 100644 --- a/src/Core/Animation/PathAnimationManager.cs +++ b/src/Core/Animation/PathAnimationManager.cs @@ -361,9 +361,6 @@ namespace NavisworksTransport.Core.Animation _allCollisionResults = new List(); _currentFrameIndex = 0; - // 初始化碰撞检测系统 - ClashDetectiveIntegration.Instance.Initialize(); - // 获取动画对象的包围盒信息 var originalBoundingBox = _animatedObject.BoundingBox(); var boundingBoxSize = new Vector3D( @@ -466,9 +463,8 @@ namespace NavisworksTransport.Core.Animation try { LogManager.Info("开始获取潜在碰撞对象"); - - // 确保ClashDetectiveIntegration已初始化并构建了通道缓存 - ClashDetectiveIntegration.Instance.Initialize(); + + // 构建通道缓存 ClashDetectiveIntegration.Instance.BuildChannelObjectsCache(); ClashDetectiveIntegration.BuildAllGeometryItemsCache(); @@ -600,11 +596,11 @@ namespace NavisworksTransport.Core.Animation } - // 创建 TimeLiner 任务(如果可用) + // 创建 TimeLiner 任务(如果可用且未创建过) if (_timeLinerManager != null && _timeLinerManager.IsTimeLinerAvailable) { string objectName = "UnknownObject"; - try + try { objectName = _animatedObject?.DisplayName ?? "UnknownObject"; } @@ -612,24 +608,38 @@ namespace NavisworksTransport.Core.Animation { objectName = "DisposedObject"; } - var taskName = $"{objectName}_运输_{DateTime.Now:HHmmss}"; - var duration = TimeSpan.FromSeconds(_animationDuration); - - LogManager.Info($"创建 TimeLiner 任务: {taskName}"); - - _currentTaskId = _timeLinerManager.CreateTransportTask( - taskName, - _pathPoints, - duration, - _animatedObject); - - if (!string.IsNullOrEmpty(_currentTaskId)) + + // 使用动画配置hash作为任务标识 + var hashPrefix = _currentAnimationHash.Substring(0, Math.Min(8, _currentAnimationHash.Length)); + var taskName = $"{objectName}_运输_{hashPrefix}"; + + // 检查是否已存在相同配置的任务 + var existingTaskId = _timeLinerManager.FindTaskByName(taskName); + if (!string.IsNullOrEmpty(existingTaskId)) { - LogManager.Info($"✓ TimeLiner 任务创建成功: {taskName} (ID: {_currentTaskId})"); + _currentTaskId = existingTaskId; + LogManager.Info($"复用现有 TimeLiner 任务: {taskName} (ID: {_currentTaskId})"); } else { - LogManager.Warning("TimeLiner 任务创建失败,继续使用基础动画功能"); + // 创建新任务 + var duration = TimeSpan.FromSeconds(_animationDuration); + LogManager.Info($"创建 TimeLiner 任务: {taskName}"); + + _currentTaskId = _timeLinerManager.CreateTransportTask( + taskName, + _pathPoints, + duration, + _animatedObject); + + if (!string.IsNullOrEmpty(_currentTaskId)) + { + LogManager.Info($"✓ TimeLiner 任务创建成功: {taskName} (ID: {_currentTaskId})"); + } + else + { + LogManager.Warning("TimeLiner 任务创建失败,继续使用基础动画功能"); + } } } else @@ -1326,9 +1336,6 @@ namespace NavisworksTransport.Core.Animation { try { - // 初始化 Clash Detective 集成 - ClashDetectiveIntegration.Instance.Initialize(); - // 订阅碰撞检测事件 ClashDetectiveIntegration.Instance.CollisionDetected += OnClashDetectiveCollisionDetected; diff --git a/src/Core/Animation/TimeLinerIntegrationManager.cs b/src/Core/Animation/TimeLinerIntegrationManager.cs index df4e3a4..72b94aa 100644 --- a/src/Core/Animation/TimeLinerIntegrationManager.cs +++ b/src/Core/Animation/TimeLinerIntegrationManager.cs @@ -309,6 +309,34 @@ namespace NavisworksTransport.Core.Animation return new Dictionary(_transportTasks); } + /// + /// 根据任务名称查找现有任务ID + /// + /// 要查找的任务名称 + /// 找到的任务ID,如果不存在则返回null + public string FindTaskByName(string taskName) + { + try + { + foreach (var kvp in _transportTasks) + { + if (kvp.Value != null && kvp.Value.DisplayName != null && kvp.Value.DisplayName.Contains(taskName)) + { + LogManager.Debug($"找到现有任务: {kvp.Value.DisplayName} (ID: {kvp.Key})"); + return kvp.Key; + } + } + + LogManager.Debug($"未找到名称为 '{taskName}' 的任务"); + return null; + } + catch (Exception ex) + { + LogManager.Error($"查找任务失败: {ex.Message}"); + return null; + } + } + /// /// 检查 TimeLiner 可用性 /// diff --git a/src/Core/Collision/ClashDetectiveIntegration.cs b/src/Core/Collision/ClashDetectiveIntegration.cs index ad3fe11..1d2f131 100644 --- a/src/Core/Collision/ClashDetectiveIntegration.cs +++ b/src/Core/Collision/ClashDetectiveIntegration.cs @@ -77,17 +77,12 @@ namespace NavisworksTransport { _currentCollisions = new List(); _cachedResults = new List(); - } - /// - /// 初始化Clash Detective集成 - 纯.NET API模式 - /// - public void Initialize() - { + // 自动初始化 Clash Detective 集成 try { LogManager.Info("初始化Clash Detective集成(.NET API模式)..."); - + // 直接使用.NET API获取Clash文档 _documentClash = Application.ActiveDocument.GetClash(); if (_documentClash != null) @@ -103,10 +98,10 @@ namespace NavisworksTransport catch (Exception ex) { LogManager.Error($"初始化Clash Detective集成失败: {ex.Message}"); + _documentClash = null; } } - /// /// 创建碰撞快照(动画结束后一次性更新结果) /// diff --git a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs index 8ba24ac..1be3d14 100644 --- a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs +++ b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs @@ -7,13 +7,8 @@ using System.Windows.Input; using System.Windows.Threading; using Autodesk.Navisworks.Api; using Autodesk.Navisworks.Api.Clash; -using NavisworksTransport.Commands; -using NavisworksTransport.Core.Animation; using NavisworksTransport.Core; -using NavisworksTransport.UI.WPF.Commands; using NavisworksTransport.UI.WPF.Collections; -using NavisworksTransport.UI.WPF.Models; -using NavisworksTransport.Utils; namespace NavisworksTransport.UI.WPF.ViewModels { @@ -91,10 +86,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels private int _animationFrameRate = 30; // 动画帧率(FPS) private double _collisionDetectionFrequency = 10.0; // 检测频率(次/秒) - // 防抖机制相关字段 - private DispatcherTimer _parameterUpdateTimer; - private readonly object _parameterUpdateLock = new object(); - private volatile bool _hasParameterChanges = false; // 当前选中路径 private PathRouteViewModel _currentPathRoute; @@ -184,14 +175,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels public double CollisionDetectionAccuracy { get => _collisionDetectionAccuracy; - set - { + set + { // 限制精度到2位小数 var roundedValue = Math.Round(value, 2); if (SetProperty(ref _collisionDetectionAccuracy, roundedValue)) { UpdateCollisionDetectionFrequency(); - ScheduleParameterUpdate(); } } } @@ -202,14 +192,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels public double MovementSpeed { get => _movementSpeed; - set - { + set + { // 限制精度到1位小数 var roundedValue = Math.Round(value, 1); if (SetProperty(ref _movementSpeed, roundedValue)) { UpdateCollisionDetectionFrequency(); - ScheduleParameterUpdate(); } } } @@ -220,14 +209,11 @@ namespace NavisworksTransport.UI.WPF.ViewModels public double DetectionGap { get => _detectionGap; - set - { + set + { // 限制精度到2位小数 var roundedValue = Math.Round(value, 2); - if (SetProperty(ref _detectionGap, roundedValue)) - { - ScheduleParameterUpdate(); - } + SetProperty(ref _detectionGap, roundedValue); } } @@ -237,12 +223,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels public int AnimationFrameRate { get => _animationFrameRate; - set - { - if (SetProperty(ref _animationFrameRate, value)) - { - UpdatePathAnimationManagerSettings(); - } + set + { + SetProperty(ref _animationFrameRate, value); } } @@ -447,11 +430,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 初始化命令 InitializeCommands(); - // 初始化碰撞检测集成 - InitializeClashIntegration(); - - // 初始化防抖定时器 - InitializeParameterUpdateTimer(); + // 订阅碰撞检测事件 + _clashIntegration.CollisionDetected += OnCollisionDetected; LogManager.Info("AnimationControlViewModel初始化完成(含缓存管理)"); } @@ -492,12 +472,9 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 初始化命令 InitializeCommands(); - // 初始化碰撞检测集成 - InitializeClashIntegration(); - - // 初始化防抖定时器 - InitializeParameterUpdateTimer(); - + // 订阅碰撞检测事件 + _clashIntegration.CollisionDetected += OnCollisionDetected; + // 订阅文档状态事件 DocumentStateManager.Instance.DocumentInvalidated += OnDocumentInvalidated; DocumentStateManager.Instance.DocumentReady += OnDocumentReady; @@ -547,9 +524,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels DetectionGap = 0.05; // 0.05米 AnimationFrameRate = 30; // 30FPS UpdateCollisionDetectionFrequency(); // 计算初始检测频率 - - // 初始化动画管理器设置 - UpdatePathAnimationManagerSettings(); // 修改: 使用新的按钮状态更新方法来设置正确的初始状态 UpdateAnimationButtonStates(); @@ -584,22 +558,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels LogManager.Info("动画控制命令初始化完成"); } - /// - /// 初始化碰撞检测集成 - /// - private void InitializeClashIntegration() - { - try - { - _clashIntegration.Initialize(); - _clashIntegration.CollisionDetected += OnCollisionDetected; - LogManager.Info("碰撞检测集成初始化完成"); - } - catch (Exception ex) - { - LogManager.Error($"碰撞检测集成初始化失败: {ex.Message}"); - } - } #endregion @@ -1055,8 +1013,6 @@ namespace NavisworksTransport.UI.WPF.ViewModels CanPauseAnimation = false; CanStopAnimation = false; UpdateMainStatus("动画已完成"); - // 动画完成后更新碰撞检测状态 - UpdateCollisionStatusAfterAnimation(); UpdateMediaControlProperties(); // 更新媒体控制属性 break; case NavisworksTransport.Core.Animation.AnimationState.Stopped: @@ -1345,7 +1301,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels // 原有的动画生成逻辑 UpdateMainStatus("正在生成路径动画...", -1, true); - + + // 设置动画参数到PathAnimationManager + _pathAnimationManager.SetAnimationFrameRate(_animationFrameRate); + _pathAnimationManager.SetCollisionDetectionAccuracy(_collisionDetectionAccuracy); + _pathAnimationManager.SetMovementSpeed(_movementSpeed); + _pathAnimationManager.SetDetectionGap(_detectionGap); + // 将PathRouteViewModel的点转换为Point3D列表 var pathPoints = CurrentPathRoute.Points.Select(p => new Point3D(p.X, p.Y, p.Z)).ToList(); @@ -1530,138 +1492,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels LogManager.Error($"更新动画按钮状态时发生错误: {ex.Message}", ex); } } - - /// - /// 初始化参数更新防抖定时器 - /// - private void InitializeParameterUpdateTimer() - { - _parameterUpdateTimer = new DispatcherTimer - { - Interval = TimeSpan.FromMilliseconds(150) // 150毫秒防抖延迟 - }; - _parameterUpdateTimer.Tick += OnParameterUpdateTimerTick; - } - - /// - /// 定时器触发时执行参数更新 - /// - private void OnParameterUpdateTimerTick(object sender, EventArgs e) - { - _parameterUpdateTimer.Stop(); - lock (_parameterUpdateLock) - { - if (_hasParameterChanges) - { - _hasParameterChanges = false; - UpdatePathAnimationManagerSettings(); - } - } - } - - /// - /// 计划参数更新(防抖机制) - /// - private void ScheduleParameterUpdate() - { - lock (_parameterUpdateLock) - { - _hasParameterChanges = true; - _parameterUpdateTimer.Stop(); - _parameterUpdateTimer.Start(); - } - } - /// - /// 更新PathAnimationManager的设置 - /// - private void UpdatePathAnimationManagerSettings() - { - try - { - if (_pathAnimationManager != null) - { - _pathAnimationManager.SetAnimationFrameRate(_animationFrameRate); - _pathAnimationManager.SetCollisionDetectionAccuracy(_collisionDetectionAccuracy); - _pathAnimationManager.SetMovementSpeed(_movementSpeed); - _pathAnimationManager.SetDetectionGap(_detectionGap); - - LogManager.Debug($"碰撞检测参数已更新: 动画帧率={_animationFrameRate}FPS, 精度={_collisionDetectionAccuracy:F2}m, 速度={_movementSpeed:F1}m/s, 间隙={_detectionGap:F2}m"); - } - } - catch (Exception ex) - { - LogManager.Error($"更新动画管理器设置失败: {ex.Message}"); - } - } - - /// - /// 动画完成后更新碰撞检测状态 - /// - /// - /// 动画完成后更新碰撞检测状态 - /// - private void UpdateCollisionStatusAfterAnimation() - { - try - { - // 使用Idle事件监听碰撞检测完成状态,替代固定延迟 - const string taskId = "AnimationViewModel_WaitForCollisionResults"; - - IdleEventManager.Instance.RegisterOnceTask( - taskId, - () => IsCollisionDetectionComplete(), // 检查条件 - () => _uiStateManager.ExecuteUIUpdateAsync(() => - { - // 检查ClashDetectiveIntegration是否有缓存结果 - var clashIntegration = _clashIntegration; - if (clashIntegration != null) - { - // 通过检查是否有任何动画相关的碰撞测试来判断是否有结果 - HasCollisionResults = true; // 假设动画完成后总是有结果可查看 - UpdateMainStatus("动画完成,碰撞检测已完成"); - LogManager.Info("动画完成后碰撞状态已更新"); - } - else - { - UpdateMainStatus("碰撞检测未就绪"); - LogManager.Warning("ClashDetectiveIntegration实例不可用"); - } - }), // 执行操作 - 10 // 高优先级 - ); - - LogManager.Info("已注册Idle事件监听碰撞检测完成状态"); - } - catch (Exception ex) - { - LogManager.Error($"动画完成后更新碰撞状态失败: {ex.Message}"); - } - } - - /// - /// 检查碰撞检测是否完成 - /// - private bool IsCollisionDetectionComplete() - { - try - { - // 检查ClashDetectiveIntegration是否完成了碰撞测试创建 - if (_clashIntegration != null) - { - // 简单的完成检查:假设动画结束后1秒内碰撞检测应该完成 - // 这里可以添加更具体的完成检查逻辑 - return true; // 临时返回true,表示可以立即处理 - } - - return false; - } - catch (Exception ex) - { - LogManager.Error($"检查碰撞检测完成状态失败: {ex.Message}"); - return true; // 出错时认为已完成,避免无限等待 - } - } /// /// 生成碰撞检测报告数据 @@ -1962,24 +1793,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels try { LogManager.Info("开始清理AnimationControlViewModel资源"); - - // 1. 优先清理防抖定时器,避免在清理过程中触发更新 - if (_parameterUpdateTimer != null) - { - try - { - _parameterUpdateTimer.Stop(); - _parameterUpdateTimer.Tick -= OnParameterUpdateTimerTick; - _parameterUpdateTimer = null; - LogManager.Debug("防抖定时器清理完成"); - } - catch (Exception timerEx) - { - LogManager.Warning($"清理防抖定时器时出现警告: {timerEx.Message}"); - } - } - - // 2. 取消事件订阅(在停止动画之前,避免事件处理中访问已释放的对象) + + // 1. 取消事件订阅(在停止动画之前,避免事件处理中访问已释放的对象) // 取消DocumentStateManager事件订阅 try