Dawn/src/dawn/scene/SceneItem.hpp
2023-05-21 15:11:51 -07:00

167 lines
5.5 KiB
C++

// Copyright (c) 2022 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "display/Transform.hpp"
#include "event/Event.hpp"
#include "scene/Scene.hpp"
#include "util/array.hpp"
namespace Dawn {
class SceneItemComponent;
class SceneItem : public StateOwner {
private:
std::vector<SceneItemComponent*> components;
public:
Scene *scene;
sceneitemid_t id;
Transform transform;
/**
* Constructor for a SceneItem. Scene Items should only be called and
* initialized by the scene itself.
*
* @param scene Weak pointer to the Scene that this SceneItem belongs to.
* @param id Scene Item ID that the Scene assigned this SceneItem.
*/
SceneItem(Scene *scene, sceneitemid_t id);
/**
* Called by the Scene the frame after we were constructed so we can begin
* existing.
*/
void init();
/**
* Called by the Scene when cleanup needs to occur but before anything in
* the scene has been disposed.
*/
void destroy();
/**
* Adds a component to this scene item. Components will only have their
* init methods invoked on the first frame we enter the scene. If you add
* a component to this item after this time you will either need to try
* manually invoking its' init method, or ensure the component is aware of
* the entire SceneItem lifecycle and listen for added callbacks.
*
* @tparam T Type of component being added to this scene item.
* @return A shared pointer to the newly added component.
*/
template<class T>
T * addComponent() {
auto component = new T(this);
assertNotNull(component);
this->components.push_back(component);
return component;
}
/**
* Returns a component attached to this SceneItem. This method will return
* either a shared pointer to the component, or nullptr if the item does
* not have the queried component.
*
* @tparam T Type of component to be fetched.
* @return A shared pointer to the component, or nullptr if not found.
*/
template<class T>
T * getComponent() {
auto it = this->components.begin();
while(it != this->components.end()) {
T *castedAs = dynamic_cast<T*>(*it);
if(castedAs != nullptr) return castedAs;
++it;
}
return nullptr;
}
/**
* Returns all components attached to this SceneItem that match the
* queried component type. This method will return an array of shared
* pointers to the components, or an empty array if the item does not have
* any components of the queried type.
*
* @tparam T Type of component to be fetched.
* @return An array of pointers to the components.
*/
template<class T>
std::vector<T*> getComponents() {
std::vector<T*> components;
auto it = this->components.begin();
while(it != this->components.end()) {
T *castedAs = dynamic_cast<T*>(*it);
if(castedAs != nullptr) components.push_back(castedAs);
++it;
}
return components;
}
/**
* Finds a (direct) child of this component that has a matching component.
*
* @tparam T Component to find child of.
* @return Pointer to the child, or nullptr if not found.
*/
template<class T>
T * findChild() {
auto it = this->transform.children.begin();
while(it != this->transform.children.end()) {
auto child = (*it)->item->getComponent<T>();
if(child != nullptr) return child;
++it;
}
return nullptr;
}
/**
* Finds all (direct) children of this component that match the queried
* component.
*
* @tparam T Component to find children for.
* @return Array of pointers to matching children.
*/
template<class T>
std::vector<T*> findChildren() {
auto it = this->transform.children.begin();
std::vector<T*> children;
while(it != this->transform.children.end()) {
auto child = (*it)->item->getComponent<T>();
if(child != nullptr) children.push_back(child);
++it;
}
return children;
}
/**
* Finds all children, and children of children, recursively that match
* the queried component.
*
* @tparam T Component Type to find.
* @return Array of pointers to matching children components.
*/
template<class T>
std::vector<T*> findChildrenDeep() {
std::vector<Transform*> transformsToCheck = this->transform.children;
std::vector<T*> itemsFound;
while(transformsToCheck.size() > 0) {
Transform *tras = *transformsToCheck.begin();
vectorAppend(&transformsToCheck, tras->children);
auto component = tras->item->getComponent<T>();
if(component != nullptr) itemsFound.push_back(component);
transformsToCheck.erase(transformsToCheck.begin());
}
return itemsFound;
}
/**
* Destroy this SceneItem.
*/
~SceneItem();
};
}