9#ifdef COMPONENT_THREAD_SAFE
14#include <unordered_set>
15#include <nlohmann/json.hpp>
34class Component :
public Part,
public std::enable_shared_from_this<Component> {
40 explicit Component(
const std::string& name, std::shared_ptr<Context> context =
nullptr);
60 void Init(
const nlohmann::json& initArgs = nlohmann::json::object());
86 explicit operator std::string()
const;
138 template <typename T> std::shared_ptr<std::vector<std::shared_ptr<T>>>
GetInChildren() const;
161 template <typename T> std::shared_ptr<std::vector<std::shared_ptr<T>>>
GetInParents() const;
179 virtual
void OnInit(const nlohmann::json& initArgs = nlohmann::json::
object());
200 template <typename T>
201 std::shared_ptr<T>
RequireDependency(const std::shared_ptr<T>& dependency, const std::
string& dependencyName) const;
210 std::
string ToTreeStringImpl(
int depth, std::unordered_set<uint64_t>& visited) const;
214#ifdef COMPONENT_THREAD_SAFE
215 std::atomic<bool> mIsInitialized{
false };
216 mutable std::recursive_mutex mInitMutex;
218 bool mIsInitialized =
false;
230 std::queue<std::shared_ptr<const Component>> queue;
231 std::unordered_set<uint64_t> visited;
232 visited.insert(
GetId());
238 for (
const auto& child : *seed) {
239 if (visited.insert(child->GetId()).second) {
240 if (std::dynamic_pointer_cast<T>(child)) {
250 while (!queue.empty()) {
251 auto current = queue.front();
254 auto currentChildren = current->GetChildren().Get();
255 for (
const auto& child : *currentChildren) {
256 if (visited.insert(child->GetId()).second) {
257 if (std::dynamic_pointer_cast<T>(child)) {
269 const std::string& dependencyName)
const {
270 static_assert(std::is_base_of_v<Component, T>,
"RequireDependency only supports Component dependencies");
273 throw std::runtime_error(
"Component '" +
GetName() +
"' requires dependency '" + dependencyName +
274 "' to exist before use");
277 if (!dependency->IsInitialized()) {
278 throw std::runtime_error(
"Component '" +
GetName() +
"' requires dependency '" + dependencyName +
279 "' to be initialized before use");
286 std::queue<std::shared_ptr<const Component>> queue;
287 std::unordered_set<uint64_t> visited;
288 visited.insert(
GetId());
291 for (
const auto& child : *seed) {
292 if (visited.insert(child->GetId()).second) {
293 auto typed = std::dynamic_pointer_cast<T>(child);
301 while (!queue.empty()) {
302 auto current = queue.front();
305 auto currentChildren = current->GetChildren().Get();
306 for (
const auto& child : *currentChildren) {
307 if (visited.insert(child->GetId()).second) {
308 auto typed = std::dynamic_pointer_cast<T>(child);
320 auto result = std::make_shared<std::vector<std::shared_ptr<T>>>();
321 std::queue<std::shared_ptr<const Component>> queue;
322 std::unordered_set<uint64_t> visited;
323 visited.insert(
GetId());
326 for (
const auto& child : *seed) {
327 if (visited.insert(child->GetId()).second) {
328 auto typed = std::dynamic_pointer_cast<T>(child);
330 result->push_back(typed);
336 while (!queue.empty()) {
337 auto current = queue.front();
340 auto currentChildren = current->GetChildren().Get();
341 for (
const auto& child : *currentChildren) {
342 if (visited.insert(child->GetId()).second) {
343 auto typed = std::dynamic_pointer_cast<T>(child);
345 result->push_back(typed);
358 std::queue<std::shared_ptr<const Component>> queue;
359 std::unordered_set<uint64_t> visited;
360 visited.insert(
GetId());
363 for (
const auto& parent : *seed) {
364 if (visited.insert(parent->GetId()).second) {
365 if (std::dynamic_pointer_cast<T>(parent)) {
372 while (!queue.empty()) {
373 auto current = queue.front();
376 auto currentParents = current->GetParents().Get();
377 for (
const auto& parent : *currentParents) {
378 if (visited.insert(parent->GetId()).second) {
379 if (std::dynamic_pointer_cast<T>(parent)) {
390 std::queue<std::shared_ptr<const Component>> queue;
391 std::unordered_set<uint64_t> visited;
392 visited.insert(
GetId());
395 for (
const auto& parent : *seed) {
396 if (visited.insert(parent->GetId()).second) {
397 auto typed = std::dynamic_pointer_cast<T>(parent);
405 while (!queue.empty()) {
406 auto current = queue.front();
409 auto currentParents = current->GetParents().Get();
410 for (
const auto& parent : *currentParents) {
411 if (visited.insert(parent->GetId()).second) {
412 auto typed = std::dynamic_pointer_cast<T>(parent);
424 auto result = std::make_shared<std::vector<std::shared_ptr<T>>>();
425 std::queue<std::shared_ptr<const Component>> queue;
426 std::unordered_set<uint64_t> visited;
427 visited.insert(
GetId());
430 for (
const auto& parent : *seed) {
431 if (visited.insert(parent->GetId()).second) {
432 auto typed = std::dynamic_pointer_cast<T>(parent);
434 result->push_back(typed);
440 while (!queue.empty()) {
441 auto current = queue.front();
444 auto currentParents = current->GetParents().Get();
445 for (
const auto& parent : *currentParents) {
446 if (visited.insert(parent->GetId()).second) {
447 auto typed = std::dynamic_pointer_cast<T>(parent);
449 result->push_back(typed);
463template <
typename StoredPtr>
466#ifdef COMPONENT_THREAD_SAFE
467 const std::lock_guard<std::recursive_mutex> lock(this->GetMutex());
469 auto list = this->Get();
470 return std::find_if(list->begin(), list->end(), [&name](
const std::shared_ptr<Component>& c) {
471 return c->GetName() == name && std::dynamic_pointer_cast<T>(c) != nullptr;
475template <
typename StoredPtr>
478#ifdef COMPONENT_THREAD_SAFE
479 const std::lock_guard<std::recursive_mutex> lock(this->GetMutex());
481 auto result = std::make_shared<std::vector<std::shared_ptr<T>>>();
482 auto list = this->Get();
483 for (
const auto& c : *list) {
484 auto typed = std::dynamic_pointer_cast<T>(c);
485 if (typed && c->GetName() == name) {
486 result->push_back(typed);
std::shared_ptr< std::vector< std::shared_ptr< Component > > > Get(const std::string &name) const
Returns all components with the given name.
A named Part with a parent/child hierarchy and optional thread safety.
Definition Component.h:34
Component(const std::string &name, std::shared_ptr< Context > context=nullptr)
Constructs a Component with the given name.
bool IsInitialized() const
Returns true once Init() (or MarkInitialized()) has completed successfully.
virtual void OnInit(const nlohmann::json &initArgs=nlohmann::json::object())
Override this to implement component-specific initialization logic.
std::shared_ptr< T > GetFirstInChildren() const
Returns the first descendant that matches type T via BFS.
Definition Component.h:285
void Init(const nlohmann::json &initArgs=nlohmann::json::object())
Performs one-time initialization of this component.
bool HasInParents() const
Checks whether any ancestor Component matches type T via BFS.
Definition Component.h:357
std::shared_ptr< std::vector< std::shared_ptr< T > > > GetInChildren() const
Returns all descendants that match type T via BFS.
Definition Component.h:319
const ComponentList & GetChildren() const
Returns a const reference to the child list.
ParentComponentList & GetParents()
Returns a mutable reference to the parent list.
virtual std::shared_ptr< Component > GetSharedComponent()
Returns a shared_ptr to this Component via the correct enable_shared_from_this base.
const std::string & GetName() const
Returns the name of this Component.
void MarkInitialized()
Marks this component as initialized without going through Init().
std::shared_ptr< T > GetFirstInParents() const
Returns the first ancestor that matches type T via BFS.
Definition Component.h:389
std::shared_ptr< std::vector< std::shared_ptr< T > > > GetInParents() const
Returns all ancestors that match type T via BFS.
Definition Component.h:423
std::shared_ptr< T > RequireDependency(const std::shared_ptr< T > &dependency, const std::string &dependencyName) const
Returns a cached dependency after validating it exists and is initialized.
Definition Component.h:268
ComponentList & GetChildren()
Returns a mutable reference to the child list.
std::string ToString() const
Returns a human-readable string representation (e.g. "Name (id)").
std::string ToTreeString(int depth=0) const
Returns a human-readable tree representation of this component and its children.
const ParentComponentList & GetParents() const
Returns a const reference to the parent list.
virtual std::shared_ptr< Component > TryGetSharedComponent() noexcept
Returns a shared_ptr to this Component when available, otherwise nullptr.
bool HasInChildren() const
Checks whether any descendant Component matches type T via BFS.
Definition Component.h:229
bool Has() const
Checks whether any Part of type T is in the list.
Definition PartList.h:777
std::shared_ptr< std::vector< std::shared_ptr< Component > > > Get() const
Returns a snapshot (copy) of all currently live Parts in the list.
Definition PartList.h:825
Base class for all identifiable objects in the component system.
Definition Part.h:27
uint64_t GetId() const
Returns the unique identifier for this Part.
Core namespace for the libultraship engine framework.
Definition gfx_direct3d_common.h:14