#include "MetaCoreRuntimeData/MetaCoreRuntimeDataDispatcher.h" #include "MetaCoreScene/MetaCoreComponents.h" #include namespace MetaCore { MetaCoreRuntimeDataDispatcher::MetaCoreRuntimeDataDispatcher(MetaCoreScene& scene) : Scene_(scene) { } void MetaCoreRuntimeDataDispatcher::SetDataPointDefinitions(std::vector dataPointDefinitions) { DataPointDefinitions_ = std::move(dataPointDefinitions); } void MetaCoreRuntimeDataDispatcher::SetBindingDefinitions(std::vector bindingDefinitions) { BindingDefinitions_ = std::move(bindingDefinitions); RebuildBindingStatuses(); } void MetaCoreRuntimeDataDispatcher::ApplyUpdates(const std::vector& 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(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& 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& 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