完善timer机制

This commit is contained in:
tian 2025-09-14 01:23:05 +08:00
parent 69336e2996
commit 403a7ac03b
3 changed files with 59 additions and 120 deletions

View File

@ -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
}
/// <summary>
/// 启动动画播放(Idle事件或Timer
/// 启动动画播放(DispatcherTimer
/// </summary>
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
}
/// <summary>
/// 停止动画播放(清理事件和定时器
/// 停止动画播放(停止DispatcherTimer
/// </summary>
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
}
/// <summary>
/// Timer事件处理器 - 备用动画机制
/// DispatcherTimer事件处理器 - 主要动画机制
/// </summary>
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();
}
}
/// <summary>
/// 切换到Timer模式
/// </summary>
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}");
}
}
/// <summary>
/// 停止动画
/// </summary>
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)");
}
/// <summary>
@ -1978,7 +1960,7 @@ namespace NavisworksTransport.Core.Animation
/// <summary>
/// Idle事件处理器 - 新的动画核心
/// DispatcherTimer动画处理核心
/// </summary>
/// <summary>
/// 根据当前帧索引更新碰撞高亮(状态跟踪优化版本)
@ -2031,7 +2013,7 @@ namespace NavisworksTransport.Core.Animation
}
/// <summary>
/// 统一的动画帧处理逻辑(Idle事件和Timer共用)
/// 统一的动画帧处理逻辑(DispatcherTimer专用)
/// </summary>
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();
}
}
/// <summary>
/// 更新FPS计数器并检查是否需要切换播放模式
/// 更新FPS计数器DispatcherTimer模式
/// </summary>
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;

View File

@ -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)

View File

@ -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();
}
// 清空选中对象