DYTSrouce/src/workspace/Timestep.cpp
2025-11-12 21:10:37 +08:00

181 lines
5.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "workspace/Timestep.h"
#include <algorithm>
#include <limits>
#include <cmath>
#include <QFile>
#include <QTextStream>
#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<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_);
}