Separating state out of the location
This commit is contained in:
1 parent
5e9a663812
commit
297bd7377f
45 files changed
+2114
-778
No files matched your search
@@ -0,0 +1,181 @@
|
||||
#include "InteractiveObjectState.h"
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
namespace FRG {
|
||||
|
||||
void InteractiveObjectState::moveTo(
|
||||
const Eigen::Vector3f& target, float durationSec, std::string onCompleteName)
|
||||
{
|
||||
if (isAnimating) return;
|
||||
AnimTask task;
|
||||
task.type = AnimTask::Type::Move;
|
||||
task.startPos = position;
|
||||
task.startRotY = rotationY;
|
||||
task.startScale = scale;
|
||||
task.targetPos = target;
|
||||
task.targetRotY = rotationY;
|
||||
task.targetScale = scale;
|
||||
task.durationMs = durationSec * 1000.f;
|
||||
task.onCompleteName = std::move(onCompleteName);
|
||||
animTask = std::move(task);
|
||||
isAnimating = true;
|
||||
}
|
||||
|
||||
void InteractiveObjectState::rotateTo(
|
||||
float targetRotY, float durationSec, std::string onCompleteName)
|
||||
{
|
||||
if (isAnimating) return;
|
||||
AnimTask task;
|
||||
task.type = AnimTask::Type::Rotate;
|
||||
task.startPos = position;
|
||||
task.startRotY = rotationY;
|
||||
task.startScale = scale;
|
||||
task.targetPos = position;
|
||||
task.targetRotY = targetRotY;
|
||||
task.targetScale = scale;
|
||||
task.durationMs = durationSec * 1000.f;
|
||||
task.onCompleteName = std::move(onCompleteName);
|
||||
animTask = std::move(task);
|
||||
isAnimating = true;
|
||||
}
|
||||
|
||||
void InteractiveObjectState::scaleTo(
|
||||
float targetScale, float durationSec, std::string onCompleteName)
|
||||
{
|
||||
if (isAnimating) return;
|
||||
AnimTask task;
|
||||
task.type = AnimTask::Type::Scale;
|
||||
task.startPos = position;
|
||||
task.startRotY = rotationY;
|
||||
task.startScale = scale;
|
||||
task.targetPos = position;
|
||||
task.targetRotY = rotationY;
|
||||
task.targetScale = targetScale;
|
||||
task.durationMs = durationSec * 1000.f;
|
||||
task.onCompleteName = std::move(onCompleteName);
|
||||
animTask = std::move(task);
|
||||
isAnimating = true;
|
||||
}
|
||||
|
||||
void InteractiveObjectState::fadeTo(
|
||||
float targetAlpha, float durationSec, std::string onCompleteName)
|
||||
{
|
||||
if (isAnimating) return;
|
||||
AnimTask task;
|
||||
task.type = AnimTask::Type::Fade;
|
||||
task.startPos = position;
|
||||
task.startRotY = rotationY;
|
||||
task.startScale = alpha;
|
||||
task.targetPos = position;
|
||||
task.targetRotY = rotationY;
|
||||
task.targetScale = targetAlpha;
|
||||
task.durationMs = durationSec * 1000.f;
|
||||
task.onCompleteName = std::move(onCompleteName);
|
||||
animTask = std::move(task);
|
||||
isAnimating = true;
|
||||
}
|
||||
|
||||
InteractiveObjectUpdateEvents InteractiveObjectState::update(std::int64_t deltaMs)
|
||||
{
|
||||
InteractiveObjectUpdateEvents events;
|
||||
if (!isAnimating || !animTask) return events;
|
||||
|
||||
AnimTask& task = *animTask;
|
||||
task.elapsedMs += static_cast<float>(deltaMs);
|
||||
const float duration = (std::max)(task.durationMs, 0.001f);
|
||||
const float t = (std::min)(task.elapsedMs / duration, 1.0f);
|
||||
|
||||
switch (task.type) {
|
||||
case AnimTask::Type::Move:
|
||||
position = task.startPos + (task.targetPos - task.startPos) * t;
|
||||
break;
|
||||
case AnimTask::Type::Rotate:
|
||||
rotationY = task.startRotY + (task.targetRotY - task.startRotY) * t;
|
||||
break;
|
||||
case AnimTask::Type::Scale:
|
||||
scale = task.startScale + (task.targetScale - task.startScale) * t;
|
||||
break;
|
||||
case AnimTask::Type::Fade:
|
||||
alpha = task.startScale + (task.targetScale - task.startScale) * t;
|
||||
break;
|
||||
}
|
||||
|
||||
if (t < 1.0f) return events;
|
||||
position = task.targetPos;
|
||||
rotationY = task.targetRotY;
|
||||
if (task.type == AnimTask::Type::Fade)
|
||||
alpha = task.targetScale;
|
||||
else
|
||||
scale = task.targetScale;
|
||||
events.onCompleteName = std::move(task.onCompleteName);
|
||||
animTask.reset();
|
||||
isAnimating = false;
|
||||
return events;
|
||||
}
|
||||
|
||||
void InteractiveObjectState::save(nlohmann::json& out) const
|
||||
{
|
||||
out["positionX"] = position.x();
|
||||
out["positionY"] = position.y();
|
||||
out["positionZ"] = position.z();
|
||||
out["rotationY"] = rotationY;
|
||||
out["scale"] = scale;
|
||||
out["alpha"] = alpha;
|
||||
out["isActive"] = isActive;
|
||||
out["isAnimating"] = isAnimating;
|
||||
|
||||
if (isAnimating && animTask) {
|
||||
out["animTask"] = {
|
||||
{"type", static_cast<int>(animTask->type)},
|
||||
{"startPosX", animTask->startPos.x()},
|
||||
{"startPosY", animTask->startPos.y()},
|
||||
{"startPosZ", animTask->startPos.z()},
|
||||
{"startRotY", animTask->startRotY},
|
||||
{"startScale", animTask->startScale},
|
||||
{"targetPosX", animTask->targetPos.x()},
|
||||
{"targetPosY", animTask->targetPos.y()},
|
||||
{"targetPosZ", animTask->targetPos.z()},
|
||||
{"targetRotY", animTask->targetRotY},
|
||||
{"targetScale", animTask->targetScale},
|
||||
{"durationMs", animTask->durationMs},
|
||||
{"elapsedMs", animTask->elapsedMs},
|
||||
{"onCompleteName", animTask->onCompleteName}};
|
||||
}
|
||||
}
|
||||
|
||||
void InteractiveObjectState::load(const nlohmann::json& in)
|
||||
{
|
||||
position.x() = in.value("positionX", position.x());
|
||||
position.y() = in.value("positionY", position.y());
|
||||
position.z() = in.value("positionZ", position.z());
|
||||
rotationY = in.value("rotationY", rotationY);
|
||||
scale = in.value("scale", scale);
|
||||
alpha = in.value("alpha", alpha);
|
||||
isActive = in.value("isActive", isActive);
|
||||
isAnimating = in.value("isAnimating", false);
|
||||
animTask.reset();
|
||||
|
||||
if (!isAnimating || !in.contains("animTask") ||
|
||||
!in["animTask"].is_object()) {
|
||||
return;
|
||||
}
|
||||
const auto& value = in["animTask"];
|
||||
AnimTask task;
|
||||
task.type = static_cast<AnimTask::Type>(value.value("type", 0));
|
||||
task.startPos = {value.value("startPosX", 0.f),
|
||||
value.value("startPosY", 0.f), value.value("startPosZ", 0.f)};
|
||||
task.startRotY = value.value("startRotY", 0.f);
|
||||
task.startScale = value.value("startScale", 1.f);
|
||||
task.targetPos = {value.value("targetPosX", 0.f),
|
||||
value.value("targetPosY", 0.f), value.value("targetPosZ", 0.f)};
|
||||
task.targetRotY = value.value("targetRotY", 0.f);
|
||||
task.targetScale = value.value("targetScale", 1.f);
|
||||
task.durationMs = value.value("durationMs", 1000.f);
|
||||
task.elapsedMs = value.value("elapsedMs", 0.f);
|
||||
task.onCompleteName =
|
||||
value.value("onCompleteName", std::string());
|
||||
animTask = std::move(task);
|
||||
}
|
||||
|
||||
} // namespace FRG
|
||||
Reference in new issue
Block a user