#include "workspace/Timestep.h" #include #include #include #include #include #include "workspace/WorkSpace.h" #include "common/RecourceHelper.h" #include "common/SpdLogger.h" Timestep::Timestep(WorkSpace* parent /*= nullptr*/) noexcept : QObject((QObject*)parent) , workSpace_(parent) { // 默认最大时间为 0,由数据或手动区间设置 // 初始化为 1.0x,如果列表中没有 1.0,则取最接近中间的默认索引 auto it = std::find(speedLevels_.begin(), speedLevels_.end(), 1.0); speedIndex_ = it != speedLevels_.end() ? int(std::distance(speedLevels_.begin(), it)) : speedIndex_; currentStep_ = speedLevels_[speedIndex_]; } void Timestep::SetManualRange(double start, double end) { hasManualRange_ = true; manualStart_ = start; manualEnd_ = end; // 当设置手动区间时,更新最大时间使播放边界正确 maxTime_ = end; // 通知 UI 更新范围与步进 double minTime = 0.0, maxTime = 0.0, step = 0.0; GetRange(minTime, maxTime, step); emit RangeChanged(minTime, maxTime, step); } void Timestep::ClearManualRange() { hasManualRange_ = false; manualStart_ = 0.0; manualEnd_ = 0.0; // 恢复为数据驱动的最大时间,保留当前 maxTime_ // 通知 UI 更新范围与步进 double minTime = 0.0, maxTime = 0.0, step = 0.0; GetRange(minTime, maxTime, step); emit RangeChanged(minTime, maxTime, step); } void Timestep::GetRange(double& minTime, double& maxTime, double& step) { if (hasManualRange_) { minTime = manualStart_; maxTime = manualEnd_; } else { minTime = 0.0; maxTime = maxTime_; } step = currentStep_; } void Timestep::Update(double dt) { if (playStatus_ != PlayStatus::PS_Started) { return; } if (nullptr == workSpace_) { LOG_WARN("workSpace_ is nullptr"); return; } double deltaTime = dt * currentStep_; current_ += deltaTime; workSpace_->OnFrame(deltaTime); if (current_ >= maxTime_ && playStatus_ != PlayStatus::PS_Stoped) { current_ = maxTime_; Stop(); } emit TimeChanged(current_); } bool Timestep::IsPause() { return playStatus_ == PlayStatus::PS_Suspended && playStatus_ != PlayStatus::PS_Started; } bool Timestep::IsStoped() { return playStatus_ == PlayStatus::PS_Stoped; } void Timestep::Start() { LOG_INFO("enter"); playStatus_ = PlayStatus::PS_Started; current_ = hasManualRange_ ? manualStart_ : 0.0; if (nullptr == workSpace_) { LOG_WARN("workSpace_ is nullptr"); return; } workSpace_->Begin(); // 保持当前倍速,不在开始时重置为 1x emit StatusChanged((int)playStatus_); } void Timestep::Resume() { LOG_INFO("enter"); if (PlayStatus::PS_Suspended != playStatus_) { LOG_WARN("play status is not suspended"); return; } playStatus_ = PlayStatus::PS_Started; emit StatusChanged((int)playStatus_); } void Timestep::Pause() { LOG_INFO("enter"); if (PlayStatus::PS_Started == playStatus_) { playStatus_ = PlayStatus::PS_Suspended; } else if (PlayStatus::PS_Suspended == playStatus_) { playStatus_ = PlayStatus::PS_Started; } emit StatusChanged((int)playStatus_); } void Timestep::Stop() { LOG_INFO("enter"); current_ = hasManualRange_ ? manualEnd_ : maxTime_; playStatus_ = PlayStatus::PS_Stoped; if (nullptr == workSpace_) { LOG_WARN("workSpace_ is nullptr"); return; } workSpace_->End(); // 停止时也恢复为 1x,避免停后再次播放仍是异常倍率 auto it = std::find(speedLevels_.begin(), speedLevels_.end(), 1.0); speedIndex_ = it != speedLevels_.end() ? int(std::distance(speedLevels_.begin(), it)) : speedIndex_; currentStep_ = speedLevels_[speedIndex_]; emit StepChanged(currentStep_); emit StatusChanged((int)playStatus_); } void Timestep::Up() { // 提升到下一个倍率(封顶) if (speedIndex_ < int(speedLevels_.size()) - 1) { ++speedIndex_; } currentStep_ = speedLevels_[speedIndex_]; emit StepChanged(currentStep_); } void Timestep::SetDataMaxTime(double end) { maxTime_ = end; double minTime = 0.0, maxTime = 0.0, step = 0.0; GetRange(minTime, maxTime, step); emit RangeChanged(minTime, maxTime, step); } void Timestep::Down() { // 降到上一个倍率(保底) if (speedIndex_ > 0) { --speedIndex_; } currentStep_ = speedLevels_[speedIndex_]; emit StepChanged(currentStep_); } void Timestep::SetSpeed(double speed) { if (speedLevels_.empty()) { return; } int bestIdx = 0; double bestDiff = std::numeric_limits::max(); for (int i = 0; i < static_cast(speedLevels_.size()); ++i) { double diff = std::fabs(speedLevels_[i] - speed); if (diff < bestDiff) { bestDiff = diff; bestIdx = i; } } speedIndex_ = bestIdx; currentStep_ = speedLevels_[speedIndex_]; emit StepChanged(currentStep_); }