146 lines
4.6 KiB
C++
146 lines
4.6 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 {
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
auto tras = transformsToCheck.begin();
|
|
vectorAppend(&transformsToCheck, (*tras)->children);
|
|
auto component = (*tras)->item->getComponent<T>();
|
|
if(component != nullptr) itemsFound.push_back(component);
|
|
transformsToCheck.erase(tras);
|
|
}
|
|
|
|
return itemsFound;
|
|
}
|
|
|
|
/**
|
|
* Destroy this SceneItem.
|
|
*/
|
|
~SceneItem();
|
|
};
|
|
} |