2025-01-04 04:12:51 +00:00
|
|
|
|
#include "workspace/Timestep.h"
|
|
|
|
|
|
|
2025-11-10 15:19:13 +00:00
|
|
|
|
#include <algorithm>
|
2025-11-10 23:16:13 +00:00
|
|
|
|
#include <limits>
|
|
|
|
|
|
#include <cmath>
|
2025-11-10 15:19:13 +00:00
|
|
|
|
|
2025-01-04 04:12:51 +00:00
|
|
|
|
#include <QFile>
|
|
|
|
|
|
#include <QTextStream>
|
|
|
|
|
|
|
|
|
|
|
|
#include "workspace/WorkSpace.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "common/RecourceHelper.h"
|
|
|
|
|
|
#include "common/SpdLogger.h"
|
|
|
|
|
|
|
2025-11-10 23:16:13 +00:00
|
|
|
|
Timestep::Timestep(WorkSpace* parent /*= nullptr*/) noexcept
|
2025-01-04 04:12:51 +00:00
|
|
|
|
: QObject((QObject*)parent)
|
|
|
|
|
|
, workSpace_(parent) {
|
2025-11-10 23:16:13 +00:00
|
|
|
|
// 默认最大时间为 0,由数据或手动区间设置
|
2025-11-10 15:19:13 +00:00
|
|
|
|
// 初始化为 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_];
|
2025-01-04 04:12:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-10 23:16:13 +00:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
2025-01-04 04:12:51 +00:00
|
|
|
|
|
2025-11-10 23:16:13 +00:00
|
|
|
|
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);
|
2025-01-04 04:12:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Timestep::GetRange(double& minTime, double& maxTime, double& step) {
|
2025-11-10 23:16:13 +00:00
|
|
|
|
if (hasManualRange_) {
|
|
|
|
|
|
minTime = manualStart_;
|
|
|
|
|
|
maxTime = manualEnd_;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
minTime = 0.0;
|
|
|
|
|
|
maxTime = maxTime_;
|
|
|
|
|
|
}
|
2025-01-04 04:12:51 +00:00
|
|
|
|
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;
|
2025-11-10 23:16:13 +00:00
|
|
|
|
current_ = hasManualRange_ ? manualStart_ : 0.0;
|
2025-01-04 04:12:51 +00:00
|
|
|
|
|
|
|
|
|
|
if (nullptr == workSpace_) {
|
|
|
|
|
|
LOG_WARN("workSpace_ is nullptr");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
workSpace_->Begin();
|
2025-11-12 13:10:37 +00:00
|
|
|
|
// 保持当前倍速,不在开始时重置为 1x
|
2025-01-04 04:12:51 +00:00
|
|
|
|
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");
|
2025-11-10 23:16:13 +00:00
|
|
|
|
current_ = hasManualRange_ ? manualEnd_ : maxTime_;
|
2025-01-04 04:12:51 +00:00
|
|
|
|
playStatus_ = PlayStatus::PS_Stoped;
|
|
|
|
|
|
if (nullptr == workSpace_) {
|
|
|
|
|
|
LOG_WARN("workSpace_ is nullptr");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
workSpace_->End();
|
2025-11-10 15:19:13 +00:00
|
|
|
|
// 停止时也恢复为 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_);
|
2025-01-04 04:12:51 +00:00
|
|
|
|
emit StatusChanged((int)playStatus_);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Timestep::Up() {
|
2025-11-10 15:19:13 +00:00
|
|
|
|
// 提升到下一个倍率(封顶)
|
|
|
|
|
|
if (speedIndex_ < int(speedLevels_.size()) - 1) {
|
|
|
|
|
|
++speedIndex_;
|
|
|
|
|
|
}
|
|
|
|
|
|
currentStep_ = speedLevels_[speedIndex_];
|
|
|
|
|
|
emit StepChanged(currentStep_);
|
2025-01-04 04:12:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-10 23:16:13 +00:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-01-04 04:12:51 +00:00
|
|
|
|
void Timestep::Down() {
|
2025-11-10 15:19:13 +00:00
|
|
|
|
// 降到上一个倍率(保底)
|
|
|
|
|
|
if (speedIndex_ > 0) {
|
|
|
|
|
|
--speedIndex_;
|
|
|
|
|
|
}
|
|
|
|
|
|
currentStep_ = speedLevels_[speedIndex_];
|
|
|
|
|
|
emit StepChanged(currentStep_);
|
2025-01-04 04:12:51 +00:00
|
|
|
|
}
|
2025-11-10 23:16:13 +00:00
|
|
|
|
|
|
|
|
|
|
void Timestep::SetSpeed(double speed) {
|
|
|
|
|
|
if (speedLevels_.empty()) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
int bestIdx = 0;
|
|
|
|
|
|
double bestDiff = std::numeric_limits<double>::max();
|
|
|
|
|
|
for (int i = 0; i < static_cast<int>(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_);
|
|
|
|
|
|
}
|