#include "GameObject.hpp" #include "GameObjectTypeTag.hpp" #include "World.hpp" #include #include namespace ProjectBrussel_UNITY_ID { const char* kNamesGOMM[] = { "None" /* GOMM_None */, "AllChildren" /* GOMM_AllChildren */, "SelfAndAllChildren" /* GOMM_SelfAndAllChildren */, }; const char* kNamesGOT[] = { "GameObject" /* GOT_Generic */, "Player" /* GOT_Player */, "Building" /* GOT_Building */, "LevelWrapper" /* GOT_LevelWrapper */, }; bool ValidateGameObjectChild(GameObject* parent, GameObject* child) { return parent->GetWorld() == child->GetWorld(); } } // namespace ProjectBrussel_UNITY_ID const char* Tags::NameOf(GameObjectMemoryManagement value) { return ProjectBrussel_UNITY_ID::kNamesGOMM[value]; } const char* Tags::NameOf(GameObjectType value) { return ProjectBrussel_UNITY_ID::kNamesGOT[value]; } void GameObject::FreeRecursive(GameObject* obj) { auto gomm = obj->GetMemoryManagement(); bool freeSelf = gomm != Tags::GOMM_SelfAndAllChildren; bool freeChildren = gomm != Tags::GOMM_SelfAndAllChildren && gomm != Tags::GOMM_AllChildren; if (freeChildren) { for (auto child : obj->GetChildren()) { FreeRecursive(obj); } } if (freeSelf) { delete obj; } } GameObject::GameObject(GameWorld* world) : mWorld{ world } { } GameObject::~GameObject() { RemoveAllChildren(); if (mParent) { mParent->RemoveChild(this); // NOTE: from this point on, mParent will be nullptr } } GameWorld* GameObject::GetWorld() const { return mWorld; } GameObject* GameObject::GetParent() const { return mParent; } const PodVector& GameObject::GetChildren() const { return mChildren; } void GameObject::AddChild(GameObject* child) { if (child->mParent) { return; } if (!ProjectBrussel_UNITY_ID::ValidateGameObjectChild(this, child)) { return; } mChildren.push_back(child); child->SetParent(this); } GameObject* GameObject::RemoveChild(int index) { if (index < 0 || index >= mChildren.size()) { return nullptr; } auto it = mChildren.begin() + index; auto child = *it; // cancelUpdate(ret); std::swap(*it, mChildren.back()); mChildren.pop_back(); child->SetParent(nullptr); return child; } GameObject* GameObject::RemoveChild(GameObject* child) { if (child) { for (auto it = mChildren.begin(); it != mChildren.end(); ++it) { if (*it == child) { // cancelUpdate(child); std::swap(*it, mChildren.back()); mChildren.pop_back(); child->SetParent(nullptr); return child; } } } return nullptr; } PodVector GameObject::RemoveAllChildren() { for (auto& child : mChildren) { child->SetParent(nullptr); } auto result = std::move(mChildren); // Moving from STL object leaves it in a valid but _unspecified_ state, call std::vector::clear() to guarantee it's empty // NOTE: even though we have the source code of PodVector, we still do this to follow convention mChildren.clear(); return result; } Tags::GameObjectMemoryManagement GameObject::GetMemoryManagement() const { return Tags::GOMM_None; }; Tags::GameObjectType GameObject::GetTypeTag() const { return Tags::GOT_Generic; } const Material* GameObject::GetMeshMaterial() const { return nullptr; } const GpuMesh* GameObject::GetMesh() const { return nullptr; } void GameObject::Awaken() { } void GameObject::Resleep() { } void GameObject::Update() { } void GameObject::SetParent(GameObject* parent) { if (mParent != parent) { mParent = parent; // needUpdate(); } }