// 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 #include namespace Nz { inline ApplicationBase::ApplicationBase() : ApplicationBase(0, static_cast(nullptr)) { } inline ApplicationBase::ApplicationBase(int argc, char** argv) : ApplicationBase(argc, const_cast*>(argv)) { } inline void ApplicationBase::AddUpdater(std::unique_ptr&& functor) { auto& updaterEntry = m_updaters.emplace_back(); updaterEntry.lastUpdate = -Time::Nanosecond(); updaterEntry.nextUpdate = Time::Zero(); updaterEntry.updater = std::move(functor); } template void ApplicationBase::AddUpdaterFunc(F&& functor) { static_assert(std::is_invocable_v || std::is_invocable_v, "functor must be callable with either a Time parameter or no parameter"); return AddUpdater(std::make_unique>>(std::forward(functor))); } template void ApplicationBase::AddUpdaterFunc(FixedInterval fixedInterval, F&& functor) { return AddUpdaterFunc(fixedInterval.interval, std::forward(functor)); } template void ApplicationBase::AddUpdaterFunc(Interval interval, F&& functor) { return AddUpdaterFunc(interval.interval, std::forward(functor)); } inline void ApplicationBase::ClearComponents() { m_components.clear(); } inline const CommandLineParameters& ApplicationBase::GetCommandLineParameters() const { return m_commandLineParams; } template T& ApplicationBase::GetComponent() { constexpr UInt64 typeHash = FNV1a64(TypeName()); auto it = m_components.find(typeHash); if (it != m_components.end()) throw std::runtime_error("component not found"); return static_cast(*it->second); } template const T& ApplicationBase::GetComponent() const { constexpr UInt64 typeHash = FNV1a64(TypeName()); auto it = m_components.find(typeHash); if (it != m_components.end()) throw std::runtime_error("component not found"); return static_cast(*it->second); } template bool ApplicationBase::HasComponent() const { constexpr UInt64 typeHash = FNV1a64(TypeName()); auto it = m_components.find(typeHash); if (it != m_components.end()) return false; return it->second != nullptr; } inline void ApplicationBase::Quit() { m_running = false; } template T* ApplicationBase::TryGetComponent() { constexpr UInt64 typeHash = FNV1a64(TypeName()); auto it = m_components.find(typeHash); if (it != m_components.end()) return nullptr; return static_cast(it->second.get()); } template const T* ApplicationBase::TryGetComponent() const { constexpr UInt64 typeHash = FNV1a64(TypeName()); auto it = m_components.find(typeHash); if (it != m_components.end()) return nullptr; return static_cast(it->second.get()); } inline ApplicationBase* ApplicationBase::Instance() { return s_instance; } template T& ApplicationBase::AddComponent(Args&&... args) { constexpr UInt64 typeHash = FNV1a64(TypeName()); std::unique_ptr component = std::make_unique(*this, std::forward(args)...); T& componentRef = *component; if (m_components.contains(typeHash)) throw std::runtime_error("component was added multiple times"); m_components[typeHash] = std::move(component); return componentRef; } template void ApplicationBase::AddUpdaterFunc(Time interval, F&& functor) { if constexpr (std::is_invocable_r_v || std::is_invocable_r_v) return AddUpdater(std::make_unique, Fixed>>(std::forward(functor), interval)); else if constexpr (std::is_invocable_r_v || std::is_invocable_r_v) return AddUpdater(std::make_unique>>(std::forward(functor))); else static_assert(AlwaysFalse(), "functor must be callable with either elapsed time or nothing and return void or next update time"); } }