Core/ApplicationBase: Replace component indices with hashes

Fixes usage of components across DLL
This commit is contained in:
SirLynix 2024-02-23 22:40:13 +01:00
parent 1cb1750a74
commit 23ea1989ef
6 changed files with 33 additions and 73 deletions

View File

@ -38,7 +38,6 @@
#include <Nazara/Core/Application.hpp> #include <Nazara/Core/Application.hpp>
#include <Nazara/Core/ApplicationBase.hpp> #include <Nazara/Core/ApplicationBase.hpp>
#include <Nazara/Core/ApplicationComponent.hpp> #include <Nazara/Core/ApplicationComponent.hpp>
#include <Nazara/Core/ApplicationComponentRegistry.hpp>
#include <Nazara/Core/ApplicationUpdater.hpp> #include <Nazara/Core/ApplicationUpdater.hpp>
#include <Nazara/Core/Buffer.hpp> #include <Nazara/Core/Buffer.hpp>
#include <Nazara/Core/BufferMapper.hpp> #include <Nazara/Core/BufferMapper.hpp>

View File

@ -14,7 +14,7 @@
#include <Nazara/Core/CommandLineParameters.hpp> #include <Nazara/Core/CommandLineParameters.hpp>
#include <atomic> #include <atomic>
#include <string> #include <string>
#include <vector> #include <unordered_map>
namespace Nz namespace Nz
{ {
@ -72,7 +72,7 @@ namespace Nz
}; };
std::atomic_bool m_running; std::atomic_bool m_running;
std::vector<std::unique_ptr<ApplicationComponent>> m_components; std::unordered_map<UInt64 /*typehash*/, std::unique_ptr<ApplicationComponent>> m_components;
std::vector<Updater> m_updaters; std::vector<Updater> m_updaters;
CommandLineParameters m_commandLineParams; CommandLineParameters m_commandLineParams;
HighPrecisionClock m_clock; HighPrecisionClock m_clock;

View File

@ -2,7 +2,6 @@
// This file is part of the "Nazara Engine - Core module" // This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Export.hpp // For conditions of distribution and use, see copyright notice in Export.hpp
#include <Nazara/Core/ApplicationComponentRegistry.hpp>
#include <stdexcept> #include <stdexcept>
namespace Nz namespace Nz
@ -57,31 +56,37 @@ namespace Nz
template<typename T> template<typename T>
T& ApplicationBase::GetComponent() T& ApplicationBase::GetComponent()
{ {
std::size_t componentIndex = ApplicationComponentRegistry<T>::GetComponentId(); constexpr UInt64 typeHash = FNV1a64(TypeName<T>());
if (componentIndex >= m_components.size() || !m_components[componentIndex])
auto it = m_components.find(typeHash);
if (it != m_components.end())
throw std::runtime_error("component not found"); throw std::runtime_error("component not found");
return static_cast<T&>(*m_components[componentIndex]); return static_cast<T&>(*it->second);
} }
template<typename T> template<typename T>
const T& ApplicationBase::GetComponent() const const T& ApplicationBase::GetComponent() const
{ {
std::size_t componentIndex = ApplicationComponentRegistry<T>::GetComponentId(); constexpr UInt64 typeHash = FNV1a64(TypeName<T>());
if (componentIndex >= m_components.size() || !m_components[componentIndex])
auto it = m_components.find(typeHash);
if (it != m_components.end())
throw std::runtime_error("component not found"); throw std::runtime_error("component not found");
return static_cast<const T&>(*m_components[componentIndex]); return static_cast<const T&>(*it->second);
} }
template<typename T> template<typename T>
bool ApplicationBase::HasComponent() const bool ApplicationBase::HasComponent() const
{ {
std::size_t componentIndex = ApplicationComponentRegistry<T>::GetComponentId(); constexpr UInt64 typeHash = FNV1a64(TypeName<T>());
if (componentIndex >= m_components.size())
auto it = m_components.find(typeHash);
if (it != m_components.end())
return false; return false;
return m_components[componentIndex] != nullptr; return it->second != nullptr;
} }
inline void ApplicationBase::Quit() inline void ApplicationBase::Quit()
@ -92,21 +97,25 @@ namespace Nz
template<typename T> template<typename T>
T* ApplicationBase::TryGetComponent() T* ApplicationBase::TryGetComponent()
{ {
std::size_t componentIndex = ApplicationComponentRegistry<T>::GetComponentId(); constexpr UInt64 typeHash = FNV1a64(TypeName<T>());
if (componentIndex >= m_components.size())
auto it = m_components.find(typeHash);
if (it != m_components.end())
return nullptr; return nullptr;
return static_cast<T*>(m_components[componentIndex].get()); return static_cast<T*>(it->second.get());
} }
template<typename T> template<typename T>
const T* ApplicationBase::TryGetComponent() const const T* ApplicationBase::TryGetComponent() const
{ {
std::size_t componentIndex = ApplicationComponentRegistry<T>::GetComponentId(); constexpr UInt64 typeHash = FNV1a64(TypeName<T>());
if (componentIndex >= m_components.size())
auto it = m_components.find(typeHash);
if (it != m_components.end())
return nullptr; return nullptr;
return static_cast<const T*>(m_components[componentIndex].get()); return static_cast<const T*>(it->second.get());
} }
inline ApplicationBase* ApplicationBase::Instance() inline ApplicationBase* ApplicationBase::Instance()
@ -117,17 +126,15 @@ namespace Nz
template<typename T, typename... Args> template<typename T, typename... Args>
T& ApplicationBase::AddComponent(Args&&... args) T& ApplicationBase::AddComponent(Args&&... args)
{ {
std::size_t componentIndex = ApplicationComponentRegistry<T>::GetComponentId(); constexpr UInt64 typeHash = FNV1a64(TypeName<T>());
std::unique_ptr<T> component = std::make_unique<T>(*this, std::forward<Args>(args)...); std::unique_ptr<T> component = std::make_unique<T>(*this, std::forward<Args>(args)...);
T& componentRef = *component; T& componentRef = *component;
if (componentIndex >= m_components.size()) if (m_components.contains(typeHash))
m_components.resize(componentIndex + 1);
else if (m_components[componentIndex] != nullptr)
throw std::runtime_error("component was added multiple times"); throw std::runtime_error("component was added multiple times");
m_components[componentIndex] = std::move(component); m_components[typeHash] = std::move(component);
return componentRef; return componentRef;
} }

View File

@ -1,24 +0,0 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Export.hpp
#pragma once
#ifndef NAZARA_CORE_APPLICATIONCOMPONENTREGISTRY_HPP
#define NAZARA_CORE_APPLICATIONCOMPONENTREGISTRY_HPP
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/Core/Export.hpp>
namespace Nz
{
template<typename T>
struct ApplicationComponentRegistry
{
static std::size_t GetComponentId();
};
}
#include <Nazara/Core/ApplicationComponentRegistry.inl>
#endif // NAZARA_CORE_APPLICATIONCOMPONENTREGISTRY_HPP

View File

@ -1,24 +0,0 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Export.hpp
namespace Nz
{
namespace Detail
{
inline std::size_t ComponentCounter()
{
static std::size_t counter = 0;
return counter++;
}
}
template<typename T>
std::size_t ApplicationComponentRegistry<T>::GetComponentId()
{
static std::size_t typeId = Detail::ComponentCounter();
return typeId;
}
}

View File

@ -90,8 +90,10 @@ namespace Nz
updaterEntry.nextUpdate = std::max(updaterEntry.nextUpdate, m_currentTime); updaterEntry.nextUpdate = std::max(updaterEntry.nextUpdate, m_currentTime);
} }
for (auto& componentPtr : m_components) for (auto&& [typeHash, componentPtr] : m_components)
{ {
NazaraUnused(typeHash);
if (componentPtr) if (componentPtr)
componentPtr->Update(elapsedTime); componentPtr->Update(elapsedTime);
} }