modify path to sim
This commit is contained in:
parent
3d87cb7c55
commit
bb71bfb652
@ -62,14 +62,54 @@ void PathComponent::Begin() {
|
|||||||
|
|
||||||
animationPath_->clear();
|
animationPath_->clear();
|
||||||
|
|
||||||
const std::vector<double>& steps = timeStep_->GetSteps();
|
// 优先使用路径文件的时间列;若不存在则按当前时间范围等间距生成时间点
|
||||||
|
std::vector<double> mappedSteps;
|
||||||
|
const bool hasPathTimes = transformPath_ && !transformPath_->GetTimes().empty();
|
||||||
|
double rangeMin = 0.0, rangeMax = 0.0, rangeStep = 0.0;
|
||||||
|
timeStep_->GetRange(rangeMin, rangeMax, rangeStep);
|
||||||
|
if (hasPathTimes) {
|
||||||
|
const auto& times = transformPath_->GetTimes();
|
||||||
|
if (timeStep_->HasManualRange()) {
|
||||||
|
// 将路径文件时间列线性映射到用户指定的手动区间,保证相对时间关系不变
|
||||||
|
double srcMin = times.front();
|
||||||
|
double srcMax = times.back();
|
||||||
|
double dstMin = timeStep_->GetManualStart();
|
||||||
|
double dstMax = timeStep_->GetManualEnd();
|
||||||
|
double srcSpan = std::max(1e-9, srcMax - srcMin);
|
||||||
|
mappedSteps.reserve(times.size());
|
||||||
|
for (double t : times) {
|
||||||
|
double alpha = (t - srcMin) / srcSpan;
|
||||||
|
mappedSteps.push_back(dstMin + alpha * (dstMax - dstMin));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mappedSteps = times;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
const std::vector<Transform>& transforms = transformPath_->GetTransforms();
|
const std::vector<Transform>& transforms = transformPath_->GetTransforms();
|
||||||
int num = std::min(steps.size(), transforms.size());
|
int num = (int)transforms.size();
|
||||||
|
if (num > 0) {
|
||||||
|
mappedSteps.resize(num);
|
||||||
|
double start = timeStep_->HasManualRange() ? timeStep_->GetManualStart() : rangeMin;
|
||||||
|
double end = timeStep_->HasManualRange() ? timeStep_->GetManualEnd() : rangeMax;
|
||||||
|
double step = rangeStep;
|
||||||
|
// 若步长无效,则回退为均匀分布
|
||||||
|
if (step <= 0.0) {
|
||||||
|
step = (num > 1) ? std::max(0.0, (end - start)) / double(num - 1) : 0.0;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < num; ++i) {
|
||||||
|
double t = start + step * double(i);
|
||||||
|
if (t > end) t = end;
|
||||||
|
mappedSteps[i] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const std::vector<Transform>& transforms = transformPath_->GetTransforms();
|
||||||
|
int num = std::min(mappedSteps.size(), transforms.size());
|
||||||
for (int index = 0; index < num; ++index) {
|
for (int index = 0; index < num; ++index) {
|
||||||
const Transform& transform = transforms[index];
|
const Transform& transform = transforms[index];
|
||||||
osg::AnimationPath::ControlPoint controlPoint(transform.GetLocation() /*+ osg::Vec3(index * 10, 0, 0)*/,
|
osg::AnimationPath::ControlPoint controlPoint(transform.GetLocation() /*+ osg::Vec3(index * 10, 0, 0)*/,
|
||||||
OsgUtils::HPRToQuat(transform.GetRotation()), transform.GetScale());
|
OsgUtils::HPRToQuat(transform.GetRotation()), transform.GetScale());
|
||||||
animationPath_->insert(steps[index], controlPoint);
|
animationPath_->insert(mappedSteps[index], controlPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
deltaTime_ = 0;
|
deltaTime_ = 0;
|
||||||
|
|||||||
@ -139,6 +139,16 @@ void PlayManagerMenu::OnTimestepChanged(Timestep* timestep) {
|
|||||||
ui->lbUp->setText(QString("x%1").arg(step));
|
ui->lbUp->setText(QString("x%1").arg(step));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
// 当时间范围更新(例如用户在属性面板设置了起止时间)时,刷新显示与滑条范围
|
||||||
|
connect(timestep, &Timestep::RangeChanged, [this](double minTime, double maxTime, double step) {
|
||||||
|
minTime_ = minTime;
|
||||||
|
maxTime_ = maxTime;
|
||||||
|
ui->lbtime->setText(QString::number(minTime_, 'f', 3));
|
||||||
|
ui->lbtimeTotal->setText(QString("/%1(s)").arg(maxTime_));
|
||||||
|
ui->lbUp->setText(QString("x%1").arg(step));
|
||||||
|
ui->horizontalSlider->setRange((int)(minTime_ * 1000), (int)(maxTime_ * 1000));
|
||||||
|
ui->horizontalSlider->setValue((int)(minTime_ * 1000));
|
||||||
|
});
|
||||||
|
|
||||||
connect(timestep, &Timestep::StatusChanged, [this](int statue) {
|
connect(timestep, &Timestep::StatusChanged, [this](int statue) {
|
||||||
Timestep::PlayStatus state = static_cast<Timestep::PlayStatus>(statue);
|
Timestep::PlayStatus state = static_cast<Timestep::PlayStatus>(statue);
|
||||||
|
|||||||
@ -7916,7 +7916,6 @@ public:
|
|||||||
|
|
||||||
QMap<const QtProperty*, QtProperty*> m_properyToName;
|
QMap<const QtProperty*, QtProperty*> m_properyToName;
|
||||||
QMap<const QtProperty*, QtProperty*> m_properyToDescription;
|
QMap<const QtProperty*, QtProperty*> m_properyToDescription;
|
||||||
QMap<const QtProperty*, QtProperty*> m_properyToTimestep;
|
|
||||||
QMap<const QtProperty*, QtProperty*> m_properyToSimMatlab;
|
QMap<const QtProperty*, QtProperty*> m_properyToSimMatlab;
|
||||||
QMap<const QtProperty*, QtProperty*> m_properyToMatlabParam;
|
QMap<const QtProperty*, QtProperty*> m_properyToMatlabParam;
|
||||||
QMap<const QtProperty*, QtProperty*> m_properyToWavePath;
|
QMap<const QtProperty*, QtProperty*> m_properyToWavePath;
|
||||||
@ -7926,7 +7925,6 @@ public:
|
|||||||
|
|
||||||
QMap<const QtProperty*, QtProperty*> m_nameToPropery;
|
QMap<const QtProperty*, QtProperty*> m_nameToPropery;
|
||||||
QMap<const QtProperty*, QtProperty*> m_descriptionToPropery;
|
QMap<const QtProperty*, QtProperty*> m_descriptionToPropery;
|
||||||
QMap<const QtProperty*, QtProperty*> m_timestepToPropery;
|
|
||||||
QMap<const QtProperty*, QtProperty*> m_simMatlabToPropery;
|
QMap<const QtProperty*, QtProperty*> m_simMatlabToPropery;
|
||||||
QMap<const QtProperty*, QtProperty*> m_matlabParamToPropery;
|
QMap<const QtProperty*, QtProperty*> m_matlabParamToPropery;
|
||||||
QMap<const QtProperty*, QtProperty*> m_wavePathToPropery;
|
QMap<const QtProperty*, QtProperty*> m_wavePathToPropery;
|
||||||
@ -7951,6 +7949,16 @@ public:
|
|||||||
QMap<const QtProperty*, QtProperty*> m_properyToHomeRange;
|
QMap<const QtProperty*, QtProperty*> m_properyToHomeRange;
|
||||||
QMap<const QtProperty*, QtProperty*> m_homeRangeToPropery;
|
QMap<const QtProperty*, QtProperty*> m_homeRangeToPropery;
|
||||||
|
|
||||||
|
// Simulation Time group (manual range)
|
||||||
|
QMap<const QtProperty*, QtProperty*> m_properyToSimTimeGroup;
|
||||||
|
QMap<const QtProperty*, QtProperty*> m_simTimeGroupToPropery;
|
||||||
|
QMap<const QtProperty*, QtProperty*> m_properyToSimStart;
|
||||||
|
QMap<const QtProperty*, QtProperty*> m_simStartToPropery;
|
||||||
|
QMap<const QtProperty*, QtProperty*> m_properyToSimEnd;
|
||||||
|
QMap<const QtProperty*, QtProperty*> m_simEndToPropery;
|
||||||
|
QMap<const QtProperty*, QtProperty*> m_properyToSimStep;
|
||||||
|
QMap<const QtProperty*, QtProperty*> m_simStepToPropery;
|
||||||
|
|
||||||
// Grouped file entries: Curve
|
// Grouped file entries: Curve
|
||||||
QMap<const QtProperty*, QtProperty*> m_properyToCurveGroup;
|
QMap<const QtProperty*, QtProperty*> m_properyToCurveGroup;
|
||||||
QMap<const QtProperty*, QtProperty*> m_curveGroupToPropery;
|
QMap<const QtProperty*, QtProperty*> m_curveGroupToPropery;
|
||||||
@ -8015,10 +8023,6 @@ void QtWorkspacePropertyManagerPrivate::slotStringChanged(QtProperty* property,
|
|||||||
QWorkspaceAttribute c = m_values[prop];
|
QWorkspaceAttribute c = m_values[prop];
|
||||||
c.SetDescription(value);
|
c.SetDescription(value);
|
||||||
q_ptr->setValue(prop, c);
|
q_ptr->setValue(prop, c);
|
||||||
} else if (QtProperty* prop = m_timestepToPropery.value(property, 0)) {
|
|
||||||
QWorkspaceAttribute c = m_values[prop];
|
|
||||||
c.SetTimeStep(value);
|
|
||||||
q_ptr->setValue(prop, c);
|
|
||||||
} else if (QtProperty* prop = m_commondPathToPropery.value(property, 0)) {
|
} else if (QtProperty* prop = m_commondPathToPropery.value(property, 0)) {
|
||||||
QWorkspaceAttribute c = m_values[prop];
|
QWorkspaceAttribute c = m_values[prop];
|
||||||
c.SetCommondFilePath(value);
|
c.SetCommondFilePath(value);
|
||||||
@ -8145,6 +8149,18 @@ void QtWorkspacePropertyManagerPrivate::slotDoubleChanged(QtProperty* property,
|
|||||||
QWorkspaceAttribute c = m_values[prop];
|
QWorkspaceAttribute c = m_values[prop];
|
||||||
c.SetHomeViewpointRange(value);
|
c.SetHomeViewpointRange(value);
|
||||||
q_ptr->setValue(prop, c);
|
q_ptr->setValue(prop, c);
|
||||||
|
} else if (QtProperty* prop = m_simStartToPropery.value(property, 0)) {
|
||||||
|
QWorkspaceAttribute c = m_values[prop];
|
||||||
|
c.SetSimulationStart(value);
|
||||||
|
q_ptr->setValue(prop, c);
|
||||||
|
} else if (QtProperty* prop = m_simEndToPropery.value(property, 0)) {
|
||||||
|
QWorkspaceAttribute c = m_values[prop];
|
||||||
|
c.SetSimulationEnd(value);
|
||||||
|
q_ptr->setValue(prop, c);
|
||||||
|
} else if (QtProperty* prop = m_simStepToPropery.value(property, 0)) {
|
||||||
|
QWorkspaceAttribute c = m_values[prop];
|
||||||
|
c.SetSimulationStep(value);
|
||||||
|
q_ptr->setValue(prop, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8159,10 +8175,7 @@ void QtWorkspacePropertyManagerPrivate::slotPropertyDestroyed(QtProperty* proper
|
|||||||
m_descriptionToPropery.remove(property);
|
m_descriptionToPropery.remove(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (QtProperty* subProp = m_timestepToPropery.value(property, nullptr)) {
|
// Removed: timestep property mapping cleanup (no longer tracked)
|
||||||
m_timestepToPropery[subProp] = 0;
|
|
||||||
m_timestepToPropery.remove(property);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (QtProperty* subProp = m_simMatlabToPropery.value(property, nullptr)) {
|
if (QtProperty* subProp = m_simMatlabToPropery.value(property, nullptr)) {
|
||||||
m_simMatlabToPropery[subProp] = 0;
|
m_simMatlabToPropery[subProp] = 0;
|
||||||
@ -8184,6 +8197,44 @@ void QtWorkspacePropertyManagerPrivate::slotPropertyDestroyed(QtProperty* proper
|
|||||||
m_rdPathToPropery[subProp] = 0;
|
m_rdPathToPropery[subProp] = 0;
|
||||||
m_rdPathToPropery.remove(property);
|
m_rdPathToPropery.remove(property);
|
||||||
}
|
}
|
||||||
|
// HomeViewpoint numeric children
|
||||||
|
if (QtProperty* subProp = m_homeLonToPropery.value(property, nullptr)) {
|
||||||
|
m_homeLonToPropery[subProp] = 0;
|
||||||
|
m_homeLonToPropery.remove(property);
|
||||||
|
}
|
||||||
|
if (QtProperty* subProp = m_homeLatToPropery.value(property, nullptr)) {
|
||||||
|
m_homeLatToPropery[subProp] = 0;
|
||||||
|
m_homeLatToPropery.remove(property);
|
||||||
|
}
|
||||||
|
if (QtProperty* subProp = m_homeAltToPropery.value(property, nullptr)) {
|
||||||
|
m_homeAltToPropery[subProp] = 0;
|
||||||
|
m_homeAltToPropery.remove(property);
|
||||||
|
}
|
||||||
|
if (QtProperty* subProp = m_homeHeadingToPropery.value(property, nullptr)) {
|
||||||
|
m_homeHeadingToPropery[subProp] = 0;
|
||||||
|
m_homeHeadingToPropery.remove(property);
|
||||||
|
}
|
||||||
|
if (QtProperty* subProp = m_homePitchToPropery.value(property, nullptr)) {
|
||||||
|
m_homePitchToPropery[subProp] = 0;
|
||||||
|
m_homePitchToPropery.remove(property);
|
||||||
|
}
|
||||||
|
if (QtProperty* subProp = m_homeRangeToPropery.value(property, nullptr)) {
|
||||||
|
m_homeRangeToPropery[subProp] = 0;
|
||||||
|
m_homeRangeToPropery.remove(property);
|
||||||
|
}
|
||||||
|
// Simulation Time children
|
||||||
|
if (QtProperty* subProp = m_simStartToPropery.value(property, nullptr)) {
|
||||||
|
m_simStartToPropery[subProp] = 0;
|
||||||
|
m_simStartToPropery.remove(property);
|
||||||
|
}
|
||||||
|
if (QtProperty* subProp = m_simEndToPropery.value(property, nullptr)) {
|
||||||
|
m_simEndToPropery[subProp] = 0;
|
||||||
|
m_simEndToPropery.remove(property);
|
||||||
|
}
|
||||||
|
if (QtProperty* subProp = m_simStepToPropery.value(property, nullptr)) {
|
||||||
|
m_simStepToPropery[subProp] = 0;
|
||||||
|
m_simStepToPropery.remove(property);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QtWorkspacePropertyManager::QtWorkspacePropertyManager(QObject* parent)
|
QtWorkspacePropertyManager::QtWorkspacePropertyManager(QObject* parent)
|
||||||
@ -8286,7 +8337,6 @@ void QtWorkspacePropertyManager::setValue(QtProperty* property, const QWorkspace
|
|||||||
|
|
||||||
d_ptr->m_stringProperyManager->setValue(d_ptr->m_properyToName[property], value.GetName());
|
d_ptr->m_stringProperyManager->setValue(d_ptr->m_properyToName[property], value.GetName());
|
||||||
d_ptr->m_stringProperyManager->setValue(d_ptr->m_properyToDescription[property], value.GetDescription());
|
d_ptr->m_stringProperyManager->setValue(d_ptr->m_properyToDescription[property], value.GetDescription());
|
||||||
d_ptr->m_filesProperyManager->setValue(d_ptr->m_properyToTimestep[property], value.GetTimeStep());
|
|
||||||
d_ptr->m_filesProperyManager->setValue(d_ptr->m_properyToCommondPath[property], value.GetCommondFilePath());
|
d_ptr->m_filesProperyManager->setValue(d_ptr->m_properyToCommondPath[property], value.GetCommondFilePath());
|
||||||
// Sync HomeViewpoint numeric fields
|
// Sync HomeViewpoint numeric fields
|
||||||
if (QtProperty* p = d_ptr->m_properyToHomeLon.value(property, nullptr))
|
if (QtProperty* p = d_ptr->m_properyToHomeLon.value(property, nullptr))
|
||||||
@ -8301,6 +8351,13 @@ void QtWorkspacePropertyManager::setValue(QtProperty* property, const QWorkspace
|
|||||||
d_ptr->m_doubleProperyManager->setValueOnly(p, value.GetHomeViewpointPitch());
|
d_ptr->m_doubleProperyManager->setValueOnly(p, value.GetHomeViewpointPitch());
|
||||||
if (QtProperty* p = d_ptr->m_properyToHomeRange.value(property, nullptr))
|
if (QtProperty* p = d_ptr->m_properyToHomeRange.value(property, nullptr))
|
||||||
d_ptr->m_doubleProperyManager->setValueOnly(p, value.GetHomeViewpointRange());
|
d_ptr->m_doubleProperyManager->setValueOnly(p, value.GetHomeViewpointRange());
|
||||||
|
// Sync Simulation Time Start/End
|
||||||
|
if (QtProperty* p = d_ptr->m_properyToSimStart.value(property, nullptr))
|
||||||
|
d_ptr->m_doubleProperyManager->setValueOnly(p, value.GetSimulationStart());
|
||||||
|
if (QtProperty* p = d_ptr->m_properyToSimEnd.value(property, nullptr))
|
||||||
|
d_ptr->m_doubleProperyManager->setValueOnly(p, value.GetSimulationEnd());
|
||||||
|
if (QtProperty* p = d_ptr->m_properyToSimStep.value(property, nullptr))
|
||||||
|
d_ptr->m_doubleProperyManager->setValueOnly(p, value.GetSimulationStep());
|
||||||
|
|
||||||
auto syncGroup = [&](FileEntryType type,
|
auto syncGroup = [&](FileEntryType type,
|
||||||
QMap<const QtProperty*, QtProperty*>& propToGroup,
|
QMap<const QtProperty*, QtProperty*>& propToGroup,
|
||||||
@ -8383,12 +8440,7 @@ void QtWorkspacePropertyManager::initializeProperty(QtProperty* property) {
|
|||||||
d_ptr->m_descriptionToPropery[prop] = property;
|
d_ptr->m_descriptionToPropery[prop] = property;
|
||||||
property->addSubProperty(prop);
|
property->addSubProperty(prop);
|
||||||
|
|
||||||
prop = d_ptr->m_filesProperyManager->addProperty();
|
// Removed: Timestep file path property (no longer file-based)
|
||||||
prop->setPropertyName(tr("Timestep"));
|
|
||||||
d_ptr->m_filesProperyManager->setValueOnly(prop, val.GetTimeStep());
|
|
||||||
d_ptr->m_properyToTimestep[property] = prop;
|
|
||||||
d_ptr->m_timestepToPropery[prop] = property;
|
|
||||||
property->addSubProperty(prop);
|
|
||||||
|
|
||||||
// Deprecated properties (SimMatlab/MatlabParam/WavePath/ReportPath/RDPath) removed from UI
|
// Deprecated properties (SimMatlab/MatlabParam/WavePath/ReportPath/RDPath) removed from UI
|
||||||
|
|
||||||
@ -8435,6 +8487,41 @@ void QtWorkspacePropertyManager::initializeProperty(QtProperty* property) {
|
|||||||
addDouble(tr("Range"), val.GetHomeViewpointRange(), d_ptr->m_properyToHomeRange, d_ptr->m_homeRangeToPropery,
|
addDouble(tr("Range"), val.GetHomeViewpointRange(), d_ptr->m_properyToHomeRange, d_ptr->m_homeRangeToPropery,
|
||||||
0.0, 1000000.0, 2, 10.0);
|
0.0, 1000000.0, 2, 10.0);
|
||||||
|
|
||||||
|
// Simulation Time group (English labels)
|
||||||
|
QtProperty* simGroup = d_ptr->m_groupProperyManager->addProperty();
|
||||||
|
simGroup->setPropertyName(tr("Simulation Time"));
|
||||||
|
d_ptr->m_properyToSimTimeGroup[property] = simGroup;
|
||||||
|
d_ptr->m_simTimeGroupToPropery[simGroup] = property;
|
||||||
|
property->addSubProperty(simGroup);
|
||||||
|
|
||||||
|
auto addSimDouble = [&](const QString& name, double init,
|
||||||
|
QMap<const QtProperty*, QtProperty*>& propToChild,
|
||||||
|
QMap<const QtProperty*, QtProperty*>& childToProp) {
|
||||||
|
QtProperty* dp = d_ptr->m_doubleProperyManager->addProperty();
|
||||||
|
dp->setPropertyName(name);
|
||||||
|
d_ptr->m_doubleProperyManager->setValueOnly(dp, init);
|
||||||
|
d_ptr->m_doubleProperyManager->setRange(dp, -1e12, 1e12);
|
||||||
|
d_ptr->m_doubleProperyManager->setDecimals(dp, 6);
|
||||||
|
d_ptr->m_doubleProperyManager->setSingleStep(dp, 0.1);
|
||||||
|
simGroup->addSubProperty(dp);
|
||||||
|
propToChild[property] = dp;
|
||||||
|
childToProp[dp] = property;
|
||||||
|
};
|
||||||
|
addSimDouble(tr("Simulation Start"), val.GetSimulationStart(), d_ptr->m_properyToSimStart, d_ptr->m_simStartToPropery);
|
||||||
|
addSimDouble(tr("Simulation End"), val.GetSimulationEnd(), d_ptr->m_properyToSimEnd, d_ptr->m_simEndToPropery);
|
||||||
|
// Simulation Step (playback speed multiplier)
|
||||||
|
{
|
||||||
|
QtProperty* dp = d_ptr->m_doubleProperyManager->addProperty();
|
||||||
|
dp->setPropertyName(tr("Simulation Step"));
|
||||||
|
d_ptr->m_doubleProperyManager->setValueOnly(dp, val.GetSimulationStep());
|
||||||
|
d_ptr->m_doubleProperyManager->setRange(dp, 0.25, 8.0);
|
||||||
|
d_ptr->m_doubleProperyManager->setDecimals(dp, 2);
|
||||||
|
d_ptr->m_doubleProperyManager->setSingleStep(dp, 0.25);
|
||||||
|
simGroup->addSubProperty(dp);
|
||||||
|
d_ptr->m_properyToSimStep[property] = dp;
|
||||||
|
d_ptr->m_simStepToPropery[dp] = property;
|
||||||
|
}
|
||||||
|
|
||||||
// Add grouped file sections
|
// Add grouped file sections
|
||||||
#if 0 // Hide resource groups (Curves/Surfaces/Tables/Lights/Polars/Images) in workspace property box
|
#if 0 // Hide resource groups (Curves/Surfaces/Tables/Lights/Polars/Images) in workspace property box
|
||||||
auto addGroup = [&](FileEntryType type, const QString& groupName,
|
auto addGroup = [&](FileEntryType type, const QString& groupName,
|
||||||
@ -8523,12 +8610,7 @@ void QtWorkspacePropertyManager::uninitializeProperty(QtProperty* property) {
|
|||||||
}
|
}
|
||||||
d_ptr->m_properyToDescription.remove(property);
|
d_ptr->m_properyToDescription.remove(property);
|
||||||
|
|
||||||
prop = d_ptr->m_timestepToPropery[property];
|
// Removed: Timestep file path cleanup
|
||||||
if (prop) {
|
|
||||||
d_ptr->m_timestepToPropery.remove(prop);
|
|
||||||
delete prop;
|
|
||||||
}
|
|
||||||
d_ptr->m_properyToTimestep.remove(property);
|
|
||||||
|
|
||||||
prop = d_ptr->m_simMatlabToPropery[property];
|
prop = d_ptr->m_simMatlabToPropery[property];
|
||||||
if (prop) {
|
if (prop) {
|
||||||
@ -8597,6 +8679,26 @@ void QtWorkspacePropertyManager::uninitializeProperty(QtProperty* property) {
|
|||||||
}
|
}
|
||||||
d_ptr->m_properyToHomeViewGroup.remove(property);
|
d_ptr->m_properyToHomeViewGroup.remove(property);
|
||||||
|
|
||||||
|
// Simulation Time cleanup
|
||||||
|
auto removeSimChild = [&](QMap<const QtProperty*, QtProperty*>& propToChild,
|
||||||
|
QMap<const QtProperty*, QtProperty*>& childToProp) {
|
||||||
|
QtProperty* child = propToChild.value(property, nullptr);
|
||||||
|
if (child) {
|
||||||
|
childToProp.remove(child);
|
||||||
|
delete child;
|
||||||
|
}
|
||||||
|
propToChild.remove(property);
|
||||||
|
};
|
||||||
|
removeSimChild(d_ptr->m_properyToSimStart, d_ptr->m_simStartToPropery);
|
||||||
|
removeSimChild(d_ptr->m_properyToSimEnd, d_ptr->m_simEndToPropery);
|
||||||
|
removeSimChild(d_ptr->m_properyToSimStep, d_ptr->m_simStepToPropery);
|
||||||
|
QtProperty* simGroup = d_ptr->m_properyToSimTimeGroup.value(property, nullptr);
|
||||||
|
if (simGroup) {
|
||||||
|
d_ptr->m_simTimeGroupToPropery.remove(simGroup);
|
||||||
|
delete simGroup;
|
||||||
|
}
|
||||||
|
d_ptr->m_properyToSimTimeGroup.remove(property);
|
||||||
|
|
||||||
// Cleanup grouped file properties
|
// Cleanup grouped file properties
|
||||||
auto cleanupGroup = [&](QMap<const QtProperty*, QtProperty*>& propToGroup,
|
auto cleanupGroup = [&](QMap<const QtProperty*, QtProperty*>& propToGroup,
|
||||||
QMap<const QtProperty*, QtProperty*>& groupToProp,
|
QMap<const QtProperty*, QtProperty*>& groupToProp,
|
||||||
|
|||||||
@ -62,35 +62,65 @@ const QString QWorkspaceAttribute::GetDescription() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void QWorkspaceAttribute::SetTimeStep(const QString& timestep) {
|
// 已移除:时间步长文件路径设置/获取(不再从文件读取)
|
||||||
if (nullptr == workspace_) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Timestep* obj = workspace_->GetTimestep();
|
void QWorkspaceAttribute::SetSimulationStart(double start) {
|
||||||
if (nullptr == obj) {
|
if (!workspace_) return;
|
||||||
workspace_->SetTimestepPath(timestep);
|
Timestep* t = workspace_->GetTimestep();
|
||||||
return;
|
if (!t) return;
|
||||||
}
|
double minTime = 0.0, maxTime = 0.0, step = 0.0;
|
||||||
|
t->GetRange(minTime, maxTime, step);
|
||||||
const QString& path = obj->GetPath();
|
t->SetManualRange(start, maxTime);
|
||||||
if (path == timestep) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
workspace_->SetTimestepPath(timestep);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString QWorkspaceAttribute::GetTimeStep() const {
|
double QWorkspaceAttribute::GetSimulationStart() const {
|
||||||
if (nullptr == workspace_) {
|
if (!workspace_) return 0.0;
|
||||||
return "";
|
Timestep* t = workspace_->GetTimestep();
|
||||||
}
|
if (!t) return 0.0;
|
||||||
|
double minTime = 0.0, maxTime = 0.0, step = 0.0;
|
||||||
|
t->GetRange(minTime, maxTime, step);
|
||||||
|
return minTime;
|
||||||
|
}
|
||||||
|
|
||||||
Timestep* timestep = workspace_->GetTimestep();
|
void QWorkspaceAttribute::SetSimulationEnd(double end) {
|
||||||
if (nullptr == timestep) {
|
if (!workspace_) return;
|
||||||
return "";
|
Timestep* t = workspace_->GetTimestep();
|
||||||
}
|
if (!t) return;
|
||||||
return timestep->GetPath();
|
double minTime = 0.0, maxTime = 0.0, step = 0.0;
|
||||||
|
t->GetRange(minTime, maxTime, step);
|
||||||
|
t->SetManualRange(minTime, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
double QWorkspaceAttribute::GetSimulationEnd() const {
|
||||||
|
if (!workspace_) return 0.0;
|
||||||
|
Timestep* t = workspace_->GetTimestep();
|
||||||
|
if (!t) return 0.0;
|
||||||
|
double minTime = 0.0, maxTime = 0.0, step = 0.0;
|
||||||
|
t->GetRange(minTime, maxTime, step);
|
||||||
|
return maxTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QWorkspaceAttribute::SetSimulationRange(double start, double end) {
|
||||||
|
if (!workspace_) return;
|
||||||
|
Timestep* t = workspace_->GetTimestep();
|
||||||
|
if (!t) return;
|
||||||
|
t->SetManualRange(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QWorkspaceAttribute::SetSimulationStep(double step) {
|
||||||
|
if (!workspace_) return;
|
||||||
|
Timestep* t = workspace_->GetTimestep();
|
||||||
|
if (!t) return;
|
||||||
|
t->SetSpeed(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
double QWorkspaceAttribute::GetSimulationStep() const {
|
||||||
|
if (!workspace_) return 1.0;
|
||||||
|
Timestep* t = workspace_->GetTimestep();
|
||||||
|
if (!t) return 1.0;
|
||||||
|
double minTime = 0.0, maxTime = 0.0, step = 0.0;
|
||||||
|
t->GetRange(minTime, maxTime, step);
|
||||||
|
return step;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated workspace path setters/getters removed
|
// Deprecated workspace path setters/getters removed
|
||||||
|
|||||||
@ -62,8 +62,17 @@ public:
|
|||||||
void SetDescription(const QString& desc);
|
void SetDescription(const QString& desc);
|
||||||
const QString GetDescription() const;
|
const QString GetDescription() const;
|
||||||
|
|
||||||
void SetTimeStep(const QString& timestep);
|
// 已移除:时间步长文件路径(不再从文件读取)
|
||||||
const QString GetTimeStep() const;
|
|
||||||
|
// Simulation time (manual range) for playback
|
||||||
|
void SetSimulationStart(double start);
|
||||||
|
double GetSimulationStart() const;
|
||||||
|
void SetSimulationEnd(double end);
|
||||||
|
double GetSimulationEnd() const;
|
||||||
|
void SetSimulationRange(double start, double end);
|
||||||
|
// Playback speed (step multiplier)
|
||||||
|
void SetSimulationStep(double step);
|
||||||
|
double GetSimulationStep() const;
|
||||||
|
|
||||||
// Deprecated fields removed: SimMatlab/MatlabParam/WavePath/ReportPath/RDPath
|
// Deprecated fields removed: SimMatlab/MatlabParam/WavePath/ReportPath/RDPath
|
||||||
|
|
||||||
|
|||||||
@ -36,6 +36,8 @@ TransformPath* TransformPath::LoadFromFile(const QString& path, QObject* parent)
|
|||||||
|
|
||||||
std::vector<Transform> transforms;
|
std::vector<Transform> transforms;
|
||||||
|
|
||||||
|
std::vector<double> times;
|
||||||
|
|
||||||
while (!in.atEnd()) {
|
while (!in.atEnd()) {
|
||||||
QString line = in.readLine();
|
QString line = in.readLine();
|
||||||
if (line.trimmed().isEmpty()) {
|
if (line.trimmed().isEmpty()) {
|
||||||
@ -67,11 +69,14 @@ TransformPath* TransformPath::LoadFromFile(const QString& path, QObject* parent)
|
|||||||
transform.GetRotation().set(pitch, roll, heading);
|
transform.GetRotation().set(pitch, roll, heading);
|
||||||
|
|
||||||
// 当前 PathComponent 使用 WorkSpace 的 Timestep 作为时间轴,这里暂不保存 time 字段
|
// 当前 PathComponent 使用 WorkSpace 的 Timestep 作为时间轴,这里暂不保存 time 字段
|
||||||
// 若未来需要按文件时间驱动,可扩展 TransformPath 结构以记录时间。
|
// 现在记录时间以支持按路径文件驱动回放
|
||||||
|
times.push_back(time);
|
||||||
|
|
||||||
transforms.push_back(transform);
|
transforms.push_back(transform);
|
||||||
}
|
}
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
return new TransformPath(std::move(transforms), parent);
|
TransformPath* tp = new TransformPath(std::move(transforms), parent);
|
||||||
|
tp->SetTimes(std::move(times));
|
||||||
|
return tp;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,15 @@ public:
|
|||||||
return transforms_;
|
return transforms_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<double>& GetTimes() const {
|
||||||
|
return times_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTimes(std::vector<double> times) {
|
||||||
|
times_ = std::move(times);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Transform> transforms_;
|
std::vector<Transform> transforms_;
|
||||||
|
std::vector<double> times_;
|
||||||
};
|
};
|
||||||
@ -1,6 +1,8 @@
|
|||||||
#include "workspace/Timestep.h"
|
#include "workspace/Timestep.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <limits>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
@ -10,51 +12,47 @@
|
|||||||
#include "common/RecourceHelper.h"
|
#include "common/RecourceHelper.h"
|
||||||
#include "common/SpdLogger.h"
|
#include "common/SpdLogger.h"
|
||||||
|
|
||||||
Timestep::Timestep(const std::vector<double>& steps, const QString& path, WorkSpace* parent /*= nullptr*/) noexcept
|
Timestep::Timestep(WorkSpace* parent /*= nullptr*/) noexcept
|
||||||
: QObject((QObject*)parent)
|
: QObject((QObject*)parent)
|
||||||
, steps_(steps)
|
|
||||||
, path_(path)
|
|
||||||
, workSpace_(parent) {
|
, workSpace_(parent) {
|
||||||
maxTime_ = *steps_.rbegin();
|
// 默认最大时间为 0,由数据或手动区间设置
|
||||||
// 初始化为 1.0x,如果列表中没有 1.0,则取最接近中间的默认索引
|
// 初始化为 1.0x,如果列表中没有 1.0,则取最接近中间的默认索引
|
||||||
auto it = std::find(speedLevels_.begin(), speedLevels_.end(), 1.0);
|
auto it = std::find(speedLevels_.begin(), speedLevels_.end(), 1.0);
|
||||||
speedIndex_ = it != speedLevels_.end() ? int(std::distance(speedLevels_.begin(), it)) : speedIndex_;
|
speedIndex_ = it != speedLevels_.end() ? int(std::distance(speedLevels_.begin(), it)) : speedIndex_;
|
||||||
currentStep_ = speedLevels_[speedIndex_];
|
currentStep_ = speedLevels_[speedIndex_];
|
||||||
}
|
}
|
||||||
|
|
||||||
Timestep* Timestep::Load(const QString& path, WorkSpace* workSpace) {
|
void Timestep::SetManualRange(double start, double end) {
|
||||||
const QString filePath = QString("%1/%2").arg(workSpace->GetDir()).arg(path);
|
hasManualRange_ = true;
|
||||||
LOG_INFO("Load timestep: {}", filePath.toStdString());
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
QFile file(filePath);
|
void Timestep::ClearManualRange() {
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
hasManualRange_ = false;
|
||||||
LOG_WARN("Cannot open file for reading: {}", file.errorString().toLocal8Bit().constData());
|
manualStart_ = 0.0;
|
||||||
return nullptr;
|
manualEnd_ = 0.0;
|
||||||
}
|
// 恢复为数据驱动的最大时间,保留当前 maxTime_
|
||||||
|
// 通知 UI 更新范围与步进
|
||||||
QTextStream in(&file);
|
double minTime = 0.0, maxTime = 0.0, step = 0.0;
|
||||||
std::vector<double> numbers;
|
GetRange(minTime, maxTime, step);
|
||||||
|
emit RangeChanged(minTime, maxTime, step);
|
||||||
while (!in.atEnd()) {
|
|
||||||
QString line = in.readLine();
|
|
||||||
bool ok;
|
|
||||||
double value = line.toDouble(&ok);
|
|
||||||
if (ok) {
|
|
||||||
numbers.push_back(value);
|
|
||||||
} else {
|
|
||||||
LOG_WARN("Cannot open file for reading: {}", line.toStdString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
Timestep* timestep = new Timestep(numbers, path, workSpace);
|
|
||||||
return timestep;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timestep::GetRange(double& minTime, double& maxTime, double& step) {
|
void Timestep::GetRange(double& minTime, double& maxTime, double& step) {
|
||||||
minTime = *steps_.begin();
|
if (hasManualRange_) {
|
||||||
|
minTime = manualStart_;
|
||||||
|
maxTime = manualEnd_;
|
||||||
|
} else {
|
||||||
|
minTime = 0.0;
|
||||||
maxTime = maxTime_;
|
maxTime = maxTime_;
|
||||||
|
}
|
||||||
step = currentStep_;
|
step = currentStep_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +88,7 @@ bool Timestep::IsStoped() {
|
|||||||
void Timestep::Start() {
|
void Timestep::Start() {
|
||||||
LOG_INFO("enter");
|
LOG_INFO("enter");
|
||||||
playStatus_ = PlayStatus::PS_Started;
|
playStatus_ = PlayStatus::PS_Started;
|
||||||
current_ = 0.0;
|
current_ = hasManualRange_ ? manualStart_ : 0.0;
|
||||||
|
|
||||||
if (nullptr == workSpace_) {
|
if (nullptr == workSpace_) {
|
||||||
LOG_WARN("workSpace_ is nullptr");
|
LOG_WARN("workSpace_ is nullptr");
|
||||||
@ -127,7 +125,7 @@ void Timestep::Pause() {
|
|||||||
|
|
||||||
void Timestep::Stop() {
|
void Timestep::Stop() {
|
||||||
LOG_INFO("enter");
|
LOG_INFO("enter");
|
||||||
current_ = maxTime_;
|
current_ = hasManualRange_ ? manualEnd_ : maxTime_;
|
||||||
playStatus_ = PlayStatus::PS_Stoped;
|
playStatus_ = PlayStatus::PS_Stoped;
|
||||||
if (nullptr == workSpace_) {
|
if (nullptr == workSpace_) {
|
||||||
LOG_WARN("workSpace_ is nullptr");
|
LOG_WARN("workSpace_ is nullptr");
|
||||||
@ -151,6 +149,13 @@ void Timestep::Up() {
|
|||||||
emit StepChanged(currentStep_);
|
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() {
|
void Timestep::Down() {
|
||||||
// 降到上一个倍率(保底)
|
// 降到上一个倍率(保底)
|
||||||
if (speedIndex_ > 0) {
|
if (speedIndex_ > 0) {
|
||||||
@ -159,3 +164,21 @@ void Timestep::Down() {
|
|||||||
currentStep_ = speedLevels_[speedIndex_];
|
currentStep_ = speedLevels_[speedIndex_];
|
||||||
emit StepChanged(currentStep_);
|
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_);
|
||||||
|
}
|
||||||
|
|||||||
@ -17,18 +17,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Timestep(const std::vector<double>& steps, const QString& path, WorkSpace* parent = nullptr) noexcept;
|
explicit Timestep(WorkSpace* parent = nullptr) noexcept;
|
||||||
~Timestep() override = default;
|
~Timestep() override = default;
|
||||||
|
|
||||||
static Timestep* Load(const QString& path, WorkSpace* workSpace = nullptr);
|
|
||||||
|
|
||||||
const std::vector<double>& GetSteps() const {
|
|
||||||
return steps_;
|
|
||||||
}
|
|
||||||
const QString& GetPath() const {
|
|
||||||
return path_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetRange(double& minTime, double& maxTime, double& step);
|
void GetRange(double& minTime, double& maxTime, double& step);
|
||||||
void Update(double dt);
|
void Update(double dt);
|
||||||
double GetCurrent() const {
|
double GetCurrent() const {
|
||||||
@ -44,20 +35,32 @@ public:
|
|||||||
|
|
||||||
void Up();
|
void Up();
|
||||||
void Down();
|
void Down();
|
||||||
|
// 设置播放速度(倍率),会选取最接近的预设倍率并触发 StepChanged
|
||||||
|
void SetSpeed(double speed);
|
||||||
|
|
||||||
|
// 设置数据驱动的默认最大时间(非手动区间),用于没有文件步长时的播放边界
|
||||||
|
void SetDataMaxTime(double end);
|
||||||
|
|
||||||
WorkSpace* GetWorkSpace() const {
|
WorkSpace* GetWorkSpace() const {
|
||||||
return workSpace_;
|
return workSpace_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 手动时间区间(可选):允许用户指定起止时间,替代或重映射步骤
|
||||||
|
void SetManualRange(double start, double end);
|
||||||
|
void ClearManualRange();
|
||||||
|
bool HasManualRange() const { return hasManualRange_; }
|
||||||
|
double GetManualStart() const { return manualStart_; }
|
||||||
|
double GetManualEnd() const { return manualEnd_; }
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void StatusChanged(int);
|
void StatusChanged(int);
|
||||||
void StepChanged(double);
|
void StepChanged(double);
|
||||||
void TimeChanged(double);
|
void TimeChanged(double);
|
||||||
|
// 当时间范围或步进倍率更新时通知 UI(例如设置手动区间或清除)
|
||||||
|
void RangeChanged(double minTime, double maxTime, double step);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<double> steps_;
|
|
||||||
QString path_;
|
|
||||||
double current_{ 0.0 };
|
double current_{ 0.0 };
|
||||||
double maxTime_{ 0.0 };
|
double maxTime_{ 0.0 };
|
||||||
// 播放速度(倍率),与 UI 显示一致,比如 0.5x、1x、2x
|
// 播放速度(倍率),与 UI 显示一致,比如 0.5x、1x、2x
|
||||||
@ -69,5 +72,9 @@ private:
|
|||||||
|
|
||||||
PlayStatus playStatus_{ PlayStatus::PS_Stoped };
|
PlayStatus playStatus_{ PlayStatus::PS_Stoped };
|
||||||
WorkSpace* workSpace_{ nullptr };
|
WorkSpace* workSpace_{ nullptr };
|
||||||
|
|
||||||
|
bool hasManualRange_{ false };
|
||||||
|
double manualStart_{ 0.0 };
|
||||||
|
double manualEnd_{ 0.0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -263,24 +263,11 @@ void WorkSpace::SetActiveScene(OEScene* scene) {
|
|||||||
//homeViewpoint_ = vp;
|
//homeViewpoint_ = vp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorkSpace::SetTimestep(Timestep* timestep) {
|
void WorkSpace::EnsureTimestep() {
|
||||||
if (!timestep) {
|
if (nullptr == timestep_) {
|
||||||
return false;
|
timestep_ = new Timestep(this);
|
||||||
}
|
|
||||||
|
|
||||||
if (nullptr != timestep_ && timestep_ != timestep) {
|
|
||||||
timestep_->deleteLater();
|
|
||||||
}
|
|
||||||
|
|
||||||
timestep_ = timestep;
|
|
||||||
emit TimestepChanged(timestep_);
|
emit TimestepChanged(timestep_);
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool WorkSpace::SetTimestepPath(const QString& path) {
|
|
||||||
Timestep* timestep = Timestep::Load(path, this);
|
|
||||||
|
|
||||||
return SetTimestep(timestep);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorkSpace::SetLampStatus(class LampStatus* lampStatus) {
|
bool WorkSpace::SetLampStatus(class LampStatus* lampStatus) {
|
||||||
@ -368,9 +355,7 @@ void WorkSpace::OnLoaded() {
|
|||||||
if (nullptr != lampStatus_) {
|
if (nullptr != lampStatus_) {
|
||||||
emit LampStatusChanged(lampStatus_);
|
emit LampStatusChanged(lampStatus_);
|
||||||
}
|
}
|
||||||
if (nullptr != timestep_) {
|
EnsureTimestep();
|
||||||
emit TimestepChanged(timestep_);
|
|
||||||
}
|
|
||||||
// Execute commands configured for onLoad
|
// Execute commands configured for onLoad
|
||||||
ExecuteCommands(CommandWhen::OnLoad);
|
ExecuteCommands(CommandWhen::OnLoad);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -100,8 +100,7 @@ public:
|
|||||||
dyt_check(nullptr != scene_);
|
dyt_check(nullptr != scene_);
|
||||||
return scene_;
|
return scene_;
|
||||||
}
|
}
|
||||||
bool SetTimestep(class Timestep* timestep);
|
// Timestep lifecycle is managed internally; external setting removed
|
||||||
bool SetTimestepPath(const QString& path);
|
|
||||||
class Timestep* GetTimestep() const {
|
class Timestep* GetTimestep() const {
|
||||||
return timestep_;
|
return timestep_;
|
||||||
}
|
}
|
||||||
@ -132,8 +131,9 @@ public:
|
|||||||
|
|
||||||
void OnLoaded();
|
void OnLoaded();
|
||||||
|
|
||||||
// 通知:某类型的文件条目属性已更新(不改变数量,仅触发刷新)
|
|
||||||
void NotifyFileEntryUpdated(FileEntryType type, std::shared_ptr<FileEntry> fileEntry = nullptr);
|
void NotifyFileEntryUpdated(FileEntryType type, std::shared_ptr<FileEntry> fileEntry = nullptr);
|
||||||
|
// Ensure a timestep exists; create if missing and emit change
|
||||||
|
void EnsureTimestep();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void EntityAdded(class Entity* entity);
|
void EntityAdded(class Entity* entity);
|
||||||
@ -171,3 +171,5 @@ public:
|
|||||||
friend class WorkSpaceXMLParse;
|
friend class WorkSpaceXMLParse;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "workspace/WorkSpace.h"
|
#include "workspace/WorkSpace.h"
|
||||||
#include "entities/EntitiesManager.h"
|
#include "entities/EntitiesManager.h"
|
||||||
|
#include "workspace/Timestep.h"
|
||||||
|
|
||||||
#include "common/SpdLogger.h"
|
#include "common/SpdLogger.h"
|
||||||
#include "workspace/WorkSpaceManager.h"
|
#include "workspace/WorkSpaceManager.h"
|
||||||
@ -59,14 +60,35 @@ bool WorkSpaceXMLParse::ParseTimestep(const tinyxml2::XMLElement* element) {
|
|||||||
LOG_WARN("element is nullptr");
|
LOG_WARN("element is nullptr");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// 确保存在 Timestep 实例
|
||||||
const char* path = element->Attribute("path");
|
workSpace_->EnsureTimestep();
|
||||||
if (nullptr == path) {
|
Timestep* t = workSpace_->GetTimestep();
|
||||||
LOG_WARN("element not has path");
|
if (!t) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return workSpace_->SetTimestepPath(path);
|
// 解析属性:manual(0/1)、start、end、step
|
||||||
|
int manualFlag = 0;
|
||||||
|
element->QueryIntAttribute("manual", &manualFlag);
|
||||||
|
double start = 0.0;
|
||||||
|
double end = 0.0;
|
||||||
|
double step = 0.0;
|
||||||
|
bool hasStart = (element->QueryDoubleAttribute("start", &start) == tinyxml2::XML_SUCCESS);
|
||||||
|
bool hasEnd = (element->QueryDoubleAttribute("end", &end) == tinyxml2::XML_SUCCESS);
|
||||||
|
bool hasStep = (element->QueryDoubleAttribute("step", &step) == tinyxml2::XML_SUCCESS);
|
||||||
|
|
||||||
|
if (hasStep) {
|
||||||
|
t->SetSpeed(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 若标记为手动或具有完整的 start/end,则设置手动范围;否则按数据最大时间设置边界
|
||||||
|
if (manualFlag != 0 || (hasStart && hasEnd)) {
|
||||||
|
t->SetManualRange(hasStart ? start : 0.0, hasEnd ? end : 0.0);
|
||||||
|
} else if (hasEnd) {
|
||||||
|
t->SetDataMaxTime(end);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorkSpaceXMLParse::ParseLamp(const tinyxml2::XMLElement* element) {
|
bool WorkSpaceXMLParse::ParseLamp(const tinyxml2::XMLElement* element) {
|
||||||
|
|||||||
@ -34,9 +34,9 @@ bool WorkSpaceXMLWrite::Save(const QString& path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
doc.LinkEndChild(scene);
|
doc.LinkEndChild(scene);
|
||||||
|
SaveTimeStep(scene);
|
||||||
|
|
||||||
SaveChart(scene, &doc);
|
SaveChart(scene, &doc);
|
||||||
SaveTimeStep(scene);
|
|
||||||
SaveLamp(scene);
|
SaveLamp(scene);
|
||||||
SaveCommond(scene);
|
SaveCommond(scene);
|
||||||
SaveFiles(scene, &doc);
|
SaveFiles(scene, &doc);
|
||||||
@ -66,13 +66,31 @@ bool WorkSpaceXMLWrite::SaveScene(tinyxml2::XMLElement* scene) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Removed: SaveTimeStep — timestep is no longer file-based
|
||||||
|
// 新增:保存 Timestep 的手动范围与步长倍率
|
||||||
bool WorkSpaceXMLWrite::SaveTimeStep(tinyxml2::XMLElement* scene) {
|
bool WorkSpaceXMLWrite::SaveTimeStep(tinyxml2::XMLElement* scene) {
|
||||||
Timestep* timestep = workSpace_->GetTimestep();
|
if (nullptr == workSpace_) {
|
||||||
if (nullptr == timestep) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
tinyxml2::XMLElement* timestepXml = scene->InsertNewChildElement("timestep");
|
auto* t = workSpace_->GetTimestep();
|
||||||
timestepXml->SetAttribute("path", timestep->GetPath().toStdString().c_str());
|
if (!t) {
|
||||||
|
// 若尚未创建,确保存在一个默认实例,以保证文件的一致性
|
||||||
|
workSpace_->EnsureTimestep();
|
||||||
|
t = workSpace_->GetTimestep();
|
||||||
|
}
|
||||||
|
if (!t) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
double start = 0.0, end = 0.0, step = 1.0;
|
||||||
|
t->GetRange(start, end, step);
|
||||||
|
|
||||||
|
tinyxml2::XMLElement* timestep = scene->InsertNewChildElement("timestep");
|
||||||
|
timestep->SetAttribute("manual", t->HasManualRange() ? 1 : 0);
|
||||||
|
timestep->SetAttribute("start", start);
|
||||||
|
timestep->SetAttribute("end", end);
|
||||||
|
timestep->SetAttribute("step", step);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user