diff --git a/src/Core/Animation/PathAnimationManager.cs b/src/Core/Animation/PathAnimationManager.cs
index 6685823..d975c71 100644
--- a/src/Core/Animation/PathAnimationManager.cs
+++ b/src/Core/Animation/PathAnimationManager.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
+using System.Windows.Threading;
using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api.Clash;
using NavisApplication = Autodesk.Navisworks.Api.Application;
@@ -92,9 +93,7 @@ namespace NavisworksTransport.Core.Animation
// === 动画播放机制 ===
private double _frameInterval; // 帧间隔(毫秒)
private DateTime _lastFrameTime = DateTime.MinValue; // 上一帧时间
- private Timer _animationTimer; // 备用Timer定时器
- private bool _isUsingTimer = false; // 是否使用Timer模式
- private const double _fpsThreshold = 10.0; // FPS阈值,低于此值切换到Timer模式
+ private DispatcherTimer _animationTimer; // 备用DispatcherTimer定时器
// === 动画参数 ===
private double _animationDuration = 10.0; // 动画总时长(秒)
@@ -156,16 +155,18 @@ namespace NavisworksTransport.Core.Animation
_lastFrameTime = DateTime.MinValue;
_fpsCounterStart = DateTime.Now;
- // 初始化备用Timer
- _animationTimer = new Timer();
+ // 初始化备用DispatcherTimer
+ _animationTimer = new DispatcherTimer(DispatcherPriority.Render)
+ {
+ Interval = TimeSpan.FromMilliseconds(_frameInterval)
+ };
_animationTimer.Tick += OnTimerTick;
- _animationTimer.Interval = (int)_frameInterval;
// 初始化 TimeLiner 集成
try
{
_timeLinerManager = new TimeLinerIntegrationManager();
- LogManager.Info($"PathAnimationManager 初始化完成 - Idle事件模式, 目标FPS: {_animationFrameRate}");
+ LogManager.Info($"PathAnimationManager 初始化完成 - DispatcherTimer模式, 目标FPS: {_animationFrameRate}");
}
catch (Exception ex)
{
@@ -633,6 +634,7 @@ namespace NavisworksTransport.Core.Animation
// 初始化动画状态
_animationStartTime = DateTime.Now;
_animationFrameCount = 0; // 重置帧计数
+ _currentFrameIndex = 0; // 重置当前帧索引,确保从第一帧开始
_pausedProgress = 0.0; // 重置暂停进度
// 重置动画状态
@@ -640,14 +642,13 @@ namespace NavisworksTransport.Core.Animation
_fpsFrameCount = 0;
_fpsCounterStart = DateTime.Now;
_frameInterval = 1000.0 / _animationFrameRate;
- _isUsingTimer = false; // 优先使用Idle事件
_lastHighlightState = false; // 重置高亮状态
// 启动动画播放
StartAnimationPlayback();
SetState(AnimationState.Playing);
- LogManager.Info($"动画开始播放 - {(_isUsingTimer ? "Timer" : "Idle事件")}模式");
+ LogManager.Info($"动画开始播放 - DispatcherTimer模式");
}
catch (Exception ex)
{
@@ -657,7 +658,7 @@ namespace NavisworksTransport.Core.Animation
}
///
- /// 启动动画播放(Idle事件或Timer)
+ /// 启动动画播放(DispatcherTimer)
///
private void StartAnimationPlayback()
{
@@ -666,18 +667,10 @@ namespace NavisworksTransport.Core.Animation
// 停止之前的播放
StopAnimationPlayback();
- if (_isUsingTimer)
- {
- // 使用Timer模式
- _animationTimer.Start();
- LogManager.Debug("[播放模式] 启动Timer模式");
- }
- else
- {
- // 使用Idle事件模式
- NavisApplication.Idle += OnApplicationIdle;
- LogManager.Debug("[播放模式] 启动Idle事件模式");
- }
+ // 使用DispatcherTimer模式
+ _animationTimer.Interval = TimeSpan.FromMilliseconds(_frameInterval);
+ _animationTimer.Start();
+ LogManager.Debug("[播放模式] 启动DispatcherTimer模式");
}
catch (Exception ex)
{
@@ -686,22 +679,19 @@ namespace NavisworksTransport.Core.Animation
}
///
- /// 停止动画播放(清理事件和定时器)
+ /// 停止动画播放(停止DispatcherTimer)
///
private void StopAnimationPlayback()
{
try
{
- // 停止Timer
+ // 停止DispatcherTimer
if (_animationTimer != null)
{
_animationTimer.Stop();
}
- // 注销Idle事件
- NavisApplication.Idle -= OnApplicationIdle;
-
- LogManager.Debug("[播放模式] 已停止所有播放机制");
+ LogManager.Debug("[播放模式] 已停止DispatcherTimer");
}
catch (Exception ex)
{
@@ -710,54 +700,31 @@ namespace NavisworksTransport.Core.Animation
}
///
- /// Timer事件处理器 - 备用动画机制
+ /// DispatcherTimer事件处理器 - 主要动画机制
///
private void OnTimerTick(object sender, EventArgs e)
{
try
{
- // 调用相同的动画更新逻辑
+ // 处理动画帧
ProcessAnimationFrame();
+
+ // 关键改进:显式请求重绘,解决卡顿
+ NavisApplication.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.All);
}
catch (Exception ex)
{
- LogManager.Error($"[Timer模式] 动画更新异常: {ex.Message}");
+ LogManager.Error($"[DispatcherTimer模式] 动画更新异常: {ex.Message}");
// 发生异常时停止动画
ShutdownAnimation();
}
}
- ///
- /// 切换到Timer模式
- ///
- private void SwitchToTimerMode()
- {
- try
- {
- if (!_isUsingTimer && _currentState == AnimationState.Playing)
- {
- LogManager.Info("[播放模式] 检测到Idle事件不稳定,切换到Timer模式");
-
- // 停止Idle事件
- NavisApplication.Idle -= OnApplicationIdle;
-
- // 启动Timer
- _isUsingTimer = true;
- _animationTimer.Start();
-
- LogManager.Info("[播放模式] 已切换到Timer模式");
- }
- }
- catch (Exception ex)
- {
- LogManager.Error($"切换到Timer模式失败: {ex.Message}");
- }
- }
///
/// 停止动画
///
- public void StopAnimation()
+ public void CancelAnimation()
{
try
{
@@ -851,7 +818,6 @@ namespace NavisworksTransport.Core.Animation
try
{
if (_animationTimer != null) _animationTimer.Stop();
- NavisApplication.Idle -= OnApplicationIdle;
}
catch (Exception stopEx)
{
@@ -902,6 +868,13 @@ namespace NavisworksTransport.Core.Animation
LogManager.Info("动画完成,路径上无碰撞对象");
}
+ // 将物体移回起点位置
+ if (_pathPoints != null && _pathPoints.Count > 0 && _animatedObject != null)
+ {
+ UpdateObjectPosition(_pathPoints[0]);
+ LogManager.Info($"动画完成,物体已移回起点位置: ({_pathPoints[0].X:F2},{_pathPoints[0].Y:F2},{_pathPoints[0].Z:F2})");
+ }
+
// 直接设置为完成状态,避免中间状态切换
SetState(AnimationState.Finished);
@@ -1001,7 +974,7 @@ namespace NavisworksTransport.Core.Animation
// 只在需要时停止动画,避免重复调用
if (_currentState == AnimationState.Playing || _currentState == AnimationState.Paused)
{
- StopAnimation(); // 停止当前动画
+ CancelAnimation(); // 停止当前动画
}
// 恢复对象的原始变换(安全检查Navisworks对象可用性)
@@ -1750,19 +1723,19 @@ namespace NavisworksTransport.Core.Animation
}
}
- // 4. 清理Timer资源
+ // 4. 清理DispatcherTimer资源
if (_animationTimer != null)
{
try
{
_animationTimer.Stop();
- _animationTimer.Dispose();
+ // DispatcherTimer不需要Dispose
_animationTimer = null;
- LogManager.Info("动画Timer资源已清理");
+ LogManager.Info("DispatcherTimer资源已清理");
}
catch (Exception ex)
{
- LogManager.Warning($"清理Timer资源时出现警告: {ex.Message}");
+ LogManager.Warning($"清理DispatcherTimer资源时出现警告: {ex.Message}");
}
}
@@ -1893,7 +1866,16 @@ namespace NavisworksTransport.Core.Animation
public void SetAnimationFrameRate(int frameRate)
{
_animationFrameRate = Math.Max(10, Math.Min(60, frameRate)); // 限制在10-60FPS之间
- LogManager.Info($"动画帧率设置为: {_animationFrameRate}FPS");
+ _frameInterval = 1000.0 / _animationFrameRate; // 重新计算帧间隔
+
+ // 动态更新DispatcherTimer间隔
+ if (_animationTimer != null)
+ {
+ _animationTimer.Interval = TimeSpan.FromMilliseconds(_frameInterval);
+ LogManager.Info($"DispatcherTimer间隔已更新: {_frameInterval:F1}ms");
+ }
+
+ LogManager.Info($"动画帧率设置为: {_animationFrameRate}FPS (间隔: {_frameInterval:F1}ms)");
}
///
@@ -1978,7 +1960,7 @@ namespace NavisworksTransport.Core.Animation
///
- /// Idle事件处理器 - 新的动画核心
+ /// DispatcherTimer动画处理核心
///
///
/// 根据当前帧索引更新碰撞高亮(状态跟踪优化版本)
@@ -2031,7 +2013,7 @@ namespace NavisworksTransport.Core.Animation
}
///
- /// 统一的动画帧处理逻辑(Idle事件和Timer共用)
+ /// 统一的动画帧处理逻辑(DispatcherTimer专用)
///
private void ProcessAnimationFrame()
{
@@ -2049,16 +2031,8 @@ namespace NavisworksTransport.Core.Animation
return;
}
- // 帧率控制(仅对Idle事件有效,Timer有自己的间隔控制)
+ // DispatcherTimer已经控制了调用间隔,无需手动帧率控制
var now = DateTime.Now;
- if (!_isUsingTimer) // Idle事件模式需要手动控制帧率
- {
- var elapsed = (now - _lastFrameTime).TotalMilliseconds;
- if (elapsed < _frameInterval)
- {
- return; // 还没到下一帧时间,跳过本次处理
- }
- }
// 计算下一帧索引(考虑播放方向和速度)
int nextFrameIndex = _currentFrameIndex;
@@ -2125,23 +2099,9 @@ namespace NavisworksTransport.Core.Animation
UpdateFPSCounterAndCheckSwitch();
}
- private void OnApplicationIdle(object sender, EventArgs e)
- {
- try
- {
- // 调用统一的帧处理逻辑
- ProcessAnimationFrame();
- }
- catch (Exception ex)
- {
- LogManager.Error($"[Idle模式] 动画更新异常: {ex.Message}");
- // 发生异常时停止动画,避免持续错误
- ShutdownAnimation();
- }
- }
///
- /// 更新FPS计数器并检查是否需要切换播放模式
+ /// 更新FPS计数器(DispatcherTimer模式)
///
private void UpdateFPSCounterAndCheckSwitch()
{
@@ -2152,14 +2112,7 @@ namespace NavisworksTransport.Core.Animation
if (elapsed >= 1.0)
{
_actualFPS = _fpsFrameCount / elapsed;
- LogManager.Debug($"[性能监控] 实际FPS: {_actualFPS:F1} (目标: {_animationFrameRate}) - {(_isUsingTimer ? "Timer" : "Idle")}模式");
-
- // 检查是否需要切换到Timer模式
- if (!_isUsingTimer && _actualFPS < _fpsThreshold)
- {
- LogManager.Warning($"[性能监控] FPS过低 ({_actualFPS:F1} < {_fpsThreshold}),切换到Timer模式");
- SwitchToTimerMode();
- }
+ LogManager.Debug($"[性能监控] 实际FPS: {_actualFPS:F1} (目标: {_animationFrameRate}) - DispatcherTimer模式");
// 重置计数器
_fpsFrameCount = 0;
diff --git a/src/Core/Collision/ClashDetectiveIntegration.cs b/src/Core/Collision/ClashDetectiveIntegration.cs
index f3974ca..ad3fe11 100644
--- a/src/Core/Collision/ClashDetectiveIntegration.cs
+++ b/src/Core/Collision/ClashDetectiveIntegration.cs
@@ -400,9 +400,7 @@ namespace NavisworksTransport
resultCount++;
try
- {
- LogManager.Info($"[分组测试-{resultCount:00}] 处理碰撞: {collision.Item1?.DisplayName} <-> {collision.Item2?.DisplayName}");
-
+ {
// 临时移动动画对象到碰撞位置以执行测试
var testAnimatedObject = collision.Item1;
var modelItems = new ModelItemCollection { testAnimatedObject };
@@ -456,7 +454,6 @@ namespace NavisworksTransport
copyTest.SelectionA.PrimitiveTypes = PrimitiveTypes.Triangles | PrimitiveTypes.Lines | PrimitiveTypes.Points;
copyTest.SelectionB.PrimitiveTypes = PrimitiveTypes.Triangles | PrimitiveTypes.Lines | PrimitiveTypes.Points;
_documentClash.TestsData.TestsEditTestFromCopy(addedTempTest, copyTest);
- LogManager.Debug($"[分组测试-{resultCount:00}] 几何类型设置完成");
}
catch (Exception geomEx)
{
@@ -469,9 +466,7 @@ namespace NavisworksTransport
// 获取刷新后的测试结果
var refreshedTempTest = _documentClash.TestsData.Tests.FirstOrDefault(t => t.DisplayName == tempTestName) as ClashTest;
if (refreshedTempTest != null && refreshedTempTest.Children.Count > 0)
- {
- LogManager.Info($"[分组测试-{resultCount:00}] 临时测试检测到 {refreshedTempTest.Children.Count} 个碰撞");
-
+ {
// 将碰撞结果复制到分组中,并设置唯一名称
int subResultIndex = 1;
foreach (var child in refreshedTempTest.Children)
@@ -488,22 +483,15 @@ namespace NavisworksTransport
copiedResult.DisplayName = $"路径碰撞#{resultCount:00}-{subResultIndex:00}_{timeStamp}: {object1Name} ↔ {object2Name}";
collisionGroup.Children.Add(copiedResult);
- LogManager.Debug($"[分组测试-{resultCount:00}] 复制碰撞结果到分组: {copiedResult.DisplayName}");
subResultIndex++;
}
}
}
- else
- {
- LogManager.Info($"[分组测试-{resultCount:00}] 临时测试未检测到碰撞,跳过此项");
- // 🔧 修复:如果没有检测到碰撞,直接跳过,不创建手动结果
- }
// 删除临时测试
try
{
_documentClash.TestsData.TestsRemove(refreshedTempTest ?? addedTempTest);
- LogManager.Debug($"[分组测试-{resultCount:00}] 临时测试已清理");
}
catch (Exception cleanEx)
{
@@ -522,7 +510,6 @@ namespace NavisworksTransport
if (collisionGroup.Children.Count > 0)
{
_documentClash.TestsData.TestsAddCopy(addedMainTest, collisionGroup);
- LogManager.Info($"[分组测试] 分组已添加到主测试,包含 {collisionGroup.Children.Count} 个碰撞结果");
}
else
{
@@ -531,7 +518,6 @@ namespace NavisworksTransport
// 提交事务
transaction.Commit();
- LogManager.Info("[分组测试] 事务已提交,测试创建完成");
}
}
catch (Exception groupEx)
diff --git a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
index a314a26..8ba24ac 100644
--- a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
+++ b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
@@ -287,7 +287,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
try
{
- _pathAnimationManager.StopAnimation(); // 这会将状态设置为Stopped,需要重新生成动画
+ _pathAnimationManager.CancelAnimation(); // 这会将状态设置为Stopped,需要重新生成动画
LogManager.Info("移动物体更改,已清除之前生成的动画");
}
catch (Exception ex)
@@ -712,7 +712,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
});
// 停止当前动画
- _pathAnimationManager.StopAnimation();
+ _pathAnimationManager.CancelAnimation();
}
catch (Exception ex)
{
@@ -980,7 +980,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
try
{
- _pathAnimationManager.StopAnimation(); // 这会将状态设置为Stopped,需要重新生成动画
+ _pathAnimationManager.CancelAnimation(); // 这会将状态设置为Stopped,需要重新生成动画
LogManager.Info("路径更改,已清除之前生成的动画");
}
catch (Exception ex)
@@ -1159,7 +1159,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
try
{
- _pathAnimationManager.StopAnimation();
+ _pathAnimationManager.CancelAnimation();
LogManager.Info("已停止当前播放的动画");
}
catch (Exception stopEx)
@@ -1909,7 +1909,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 停止动画
if (_pathAnimationManager != null && _pathAnimationManager.IsAnimating)
{
- _pathAnimationManager.StopAnimation();
+ _pathAnimationManager.CancelAnimation();
}
// 清空选中对象