MetaCore/Source/MetaCoreRuntimeData/Private/MetaCoreRuntimeDataDispatcher.cpp

184 lines
7.0 KiB
C++

#include "MetaCoreRuntimeData/MetaCoreRuntimeDataDispatcher.h"
#include "MetaCoreScene/MetaCoreComponents.h"
#include <algorithm>
namespace MetaCore {
MetaCoreRuntimeDataDispatcher::MetaCoreRuntimeDataDispatcher(MetaCoreScene& scene)
: Scene_(scene) {
}
void MetaCoreRuntimeDataDispatcher::SetDataPointDefinitions(std::vector<MetaCoreDataPointDefinition> dataPointDefinitions) {
DataPointDefinitions_ = std::move(dataPointDefinitions);
}
void MetaCoreRuntimeDataDispatcher::SetBindingDefinitions(std::vector<MetaCoreSceneBindingDefinition> bindingDefinitions) {
BindingDefinitions_ = std::move(bindingDefinitions);
RebuildBindingStatuses();
}
void MetaCoreRuntimeDataDispatcher::ApplyUpdates(const std::vector<MetaCoreRuntimeDataUpdate>& updates) {
for (const MetaCoreRuntimeDataUpdate& update : updates) {
const MetaCoreDataPointDefinition* dataPointDefinition = FindDataPointDefinition(update.DataPointId);
if (dataPointDefinition == nullptr) {
continue;
}
for (const MetaCoreSceneBindingDefinition& bindingDefinition : BindingDefinitions_) {
if (bindingDefinition.DataPointId != update.DataPointId) {
continue;
}
MetaCoreGameObject* gameObject = Scene_.FindGameObject(bindingDefinition.TargetObjectId);
if (gameObject == nullptr) {
MarkBindingFault(bindingDefinition.BindingId, "Target object missing");
continue;
}
bool applied = false;
switch (bindingDefinition.Target) {
case MetaCoreRuntimeBindingTarget::TransformPosition:
if (update.Value.Type == MetaCoreRuntimeValueType::Vec3) {
gameObject->Transform.Position = update.Value.Vec3Value;
applied = true;
}
break;
case MetaCoreRuntimeBindingTarget::MeshRendererVisible:
if (update.Value.Type == MetaCoreRuntimeValueType::Bool && gameObject->MeshRenderer.has_value()) {
gameObject->MeshRenderer->Visible = update.Value.BoolValue;
applied = true;
}
break;
case MetaCoreRuntimeBindingTarget::MeshRendererBaseColor:
if (update.Value.Type == MetaCoreRuntimeValueType::Vec3 && gameObject->MeshRenderer.has_value()) {
gameObject->MeshRenderer->BaseColor = update.Value.Vec3Value;
applied = true;
}
break;
case MetaCoreRuntimeBindingTarget::LightIntensity:
if (update.Value.Type == MetaCoreRuntimeValueType::Double && gameObject->Light.has_value()) {
gameObject->Light->Intensity = static_cast<float>(update.Value.DoubleValue);
applied = true;
}
break;
case MetaCoreRuntimeBindingTarget::LightColor:
if (update.Value.Type == MetaCoreRuntimeValueType::Vec3 && gameObject->Light.has_value()) {
gameObject->Light->Color = update.Value.Vec3Value;
applied = true;
}
break;
}
if (!applied) {
MarkBindingFault(bindingDefinition.BindingId, "Update type incompatible with binding target");
continue;
}
MarkBindingHealthy(bindingDefinition.BindingId, update.Value.SourceTimestamp);
}
}
}
void MetaCoreRuntimeDataDispatcher::TickStaleness(std::uint64_t currentTimestamp) {
for (MetaCoreRuntimeBindingStatus& bindingStatus : BindingStatuses_) {
if (bindingStatus.LastAppliedAt == 0) {
bindingStatus.Stale = true;
continue;
}
bindingStatus.Stale =
currentTimestamp > bindingStatus.LastAppliedAt &&
(currentTimestamp - bindingStatus.LastAppliedAt) > bindingStatus.StaleAfterMs;
}
}
const std::vector<MetaCoreRuntimeBindingStatus>& MetaCoreRuntimeDataDispatcher::GetBindingStatuses() const {
return BindingStatuses_;
}
bool MetaCoreRuntimeDataDispatcher::HasBindingFaults() const {
return std::any_of(
BindingStatuses_.begin(),
BindingStatuses_.end(),
[](const MetaCoreRuntimeBindingStatus& bindingStatus) {
return !bindingStatus.Healthy || bindingStatus.Stale;
}
);
}
MetaCoreRuntimeDiagnosticsSnapshot MetaCoreRuntimeDataDispatcher::BuildDiagnosticsSnapshot(
const std::vector<MetaCoreRuntimeDataSourceStatus>& sourceStatuses
) const {
MetaCoreRuntimeDiagnosticsSnapshot snapshot;
snapshot.SourceStatuses = sourceStatuses;
snapshot.BindingStatuses = BindingStatuses_;
snapshot.HasFaults = HasBindingFaults();
snapshot.HasFaults = snapshot.HasFaults || std::any_of(
snapshot.SourceStatuses.begin(),
snapshot.SourceStatuses.end(),
[](const MetaCoreRuntimeDataSourceStatus& sourceStatus) {
return sourceStatus.State == MetaCoreRuntimeDataSourceState::Degraded ||
sourceStatus.State == MetaCoreRuntimeDataSourceState::Faulted;
}
);
return snapshot;
}
void MetaCoreRuntimeDataDispatcher::RebuildBindingStatuses() {
BindingStatuses_.clear();
BindingStatusIndexById_.clear();
BindingStatuses_.reserve(BindingDefinitions_.size());
for (const MetaCoreSceneBindingDefinition& bindingDefinition : BindingDefinitions_) {
BindingStatusIndexById_[bindingDefinition.BindingId] = BindingStatuses_.size();
BindingStatuses_.push_back(MetaCoreRuntimeBindingStatus{
bindingDefinition.BindingId,
true,
false,
0,
1000,
{}
});
}
}
void MetaCoreRuntimeDataDispatcher::MarkBindingFault(const std::string& bindingId, const std::string& error) {
const auto iterator = BindingStatusIndexById_.find(bindingId);
if (iterator == BindingStatusIndexById_.end()) {
return;
}
MetaCoreRuntimeBindingStatus& status = BindingStatuses_[iterator->second];
status.Healthy = false;
status.Stale = false;
status.LastError = error;
}
void MetaCoreRuntimeDataDispatcher::MarkBindingHealthy(const std::string& bindingId, std::uint64_t appliedAt) {
const auto iterator = BindingStatusIndexById_.find(bindingId);
if (iterator == BindingStatusIndexById_.end()) {
return;
}
MetaCoreRuntimeBindingStatus& status = BindingStatuses_[iterator->second];
status.Healthy = true;
status.Stale = false;
status.LastAppliedAt = appliedAt;
status.LastError.clear();
}
const MetaCoreDataPointDefinition* MetaCoreRuntimeDataDispatcher::FindDataPointDefinition(const std::string& dataPointId) const {
const auto iterator = std::find_if(
DataPointDefinitions_.begin(),
DataPointDefinitions_.end(),
[&](const MetaCoreDataPointDefinition& definition) {
return definition.Id == dataPointId;
}
);
return iterator == DataPointDefinitions_.end() ? nullptr : &(*iterator);
}
} // namespace MetaCore