DYTSrouce/src/entities/PathComponent.cpp

154 lines
4.6 KiB
C++

#include "entities/PathComponent.h"
#include <QFileInfo>
#include <QFile>
#include <QMessageBox>
#include "common/SpdLogger.h"
#include "common/RecourceHelper.h"
#include "utils/TransformPath.h"
#include "utils/OsgUtils.h"
#include "utils/FileUtils.h"
#include "entities/Entity.h"
#include "workspace/WorkSpace.h"
#include "workspace/Timestep.h"
PathComponent::PathComponent(SceneComponent* parent)
: SceneComponent(parent) {
animationPath_ = new osg::AnimationPath();
animationPath_->setLoopMode(osg::AnimationPath::NO_LOOPING);
}
PathComponent::~PathComponent() {
}
std::string PathComponent::GetTypeName() {
return "PathComponent";
}
bool PathComponent::SetAttribute(const char* name, const char* value) {
if (0 == strcmp(name, "path")) {
SetPath(value);
return nullptr != transformPath_;
}
return SceneComponent::SetAttribute(name, value);
}
bool PathComponent::SaveAttribute(tinyxml2::XMLElement* element) {
element->SetAttribute("path", path_.toStdString().c_str());
return SceneComponent::SaveAttribute(element);
}
void PathComponent::Begin() {
WorkSpace* workspace = GetEntity()->GetWorkspace();
if (nullptr == workspace) {
LOG_WARN("workspace is nullptr");
return;
}
timeStep_ = workspace->GetTimestep();
if (nullptr == timeStep_) {
LOG_WARN("timeStep is nullptr");
return;
}
if (nullptr == transformPath_) {
LOG_WARN("transformPath_ is nullptr");
return;
}
animationPath_->clear();
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 dstMin = timeStep_->GetManualStart();
double dstMax = timeStep_->GetManualEnd();
mappedSteps.reserve(times.size());
for (double t : times) {
if (t >= dstMin && t <= dstMax) {
mappedSteps.push_back(t);
}
}
if (mappedSteps.empty()) {
mappedSteps = times;
}
} else {
mappedSteps = times;
}
} else {
const std::vector<Transform>& transforms = transformPath_->GetTransforms();
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) {
const Transform& transform = transforms[index];
osg::AnimationPath::ControlPoint controlPoint(transform.GetLocation() /*+ osg::Vec3(index * 10, 0, 0)*/,
OsgUtils::HPRToQuat(transform.GetRotation()), transform.GetScale());
animationPath_->insert(mappedSteps[index], controlPoint);
}
deltaTime_ = 0;
}
void PathComponent::Update(double dt) {
deltaTime_ += dt;
if (nullptr == timeStep_) {
return;
}
double st = timeStep_->GetCurrent();
osg::AnimationPath::ControlPoint cp;
if (!animationPath_->getInterpolatedControlPoint(st, cp)) {
return;
}
Transform* transform = owner_->GetTransform();
transform->SetLocation(cp.getPosition());
osg::Vec3 angle;
OsgUtils::QuatToHPR(cp.getRotation(), &angle);
transform->SetRotation(angle);
}
void PathComponent::SetPath(const QString& path) {
if (path == path_ || path.isEmpty()) {
LOG_INFO("path is the same, file:{}", path.toLocal8Bit().constData());
return;
}
if (nullptr != transformPath_) {
transformPath_->deleteLater();
}
const QString workPath = GetEntity()->GetWorkspace()->GetDir();
const QString filePath = QString("%1/%2").arg(workPath).arg(path);
transformPath_ = TransformPath::LoadFromFile(filePath, this);
path_ = path;
}
const QString& PathComponent::GetPath() const {
return path_;
}