#include "GameObject.hpp" #include "Player.hpp" #include "SceneThings.hpp" #include "World.hpp" #include #include using namespace std::literals; namespace ProjectBrussel_UNITY_ID { bool ValidateGameObjectChild(GameObject* parent, GameObject* child) { return parent->GetWorld() == child->GetWorld(); } } // namespace ProjectBrussel_UNITY_ID void GameObject::FreeRecursive(GameObject* obj) { if (!obj->mStopFreePropagation) { for (auto child : obj->GetChildren()) { FreeRecursive(obj); } } delete obj; } GameObject::GameObject(GameWorld* world) : GameObject(KD_Generic, world) { } GameObject::GameObject(Kind kind, GameWorld* world) : mEditorAttachment{ nullptr } , mWorld{ world } , mParent{ nullptr } , mRot(1.0f, 0.0f, 0.0f, 0.0f) , mPos(0.0f, 0.0f, 0.0f) , mScale(1.0f, 1.0f, 1.0f) , mKind{ kind } { } GameObject::~GameObject() { RemoveAllChildren(); if (mParent) { mParent->RemoveChild(this); // NOTE: from this point on, mParent will be nullptr } } std::string_view GameObject::ToString(Kind kind) { switch (kind) { case KD_Generic: return "GameObject"sv; case KD_Player: return "Player"sv; case KD_SimpleGeometry: return "SimpleGeometry"sv; case KD_Building: return "Building"sv; case KD_LevelWrapper: return "LevelWrapper"sv; case KD_COUNT: break; } return std::string_view(); } GameObject::Kind GameObject::FromString(std::string_view name) { if (name == "GameObject"sv) return KD_Generic; if (name == "Player"sv) return KD_Player; if (name == "SimpleGeometry"sv) return KD_SimpleGeometry; if (name == "Building"sv) return KD_Building; if (name == "LevelWrapper"sv) return KD_LevelWrapper; return KD_COUNT; } GameObject::Kind GameObject::GetKind() const { return mKind; } GameWorld* GameObject::GetWorld() const { return mWorld; } GameObject* GameObject::GetParent() const { return mParent; } const PodVector& GameObject::GetChildren() const { return mChildren; } void GameObject::AddChild(GameObject* child) { using namespace ProjectBrussel_UNITY_ID; if (child->mParent) { return; } if (!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; } void GameObject::RemoveSelfFromParent() { if (mParent) { mParent->RemoveChild(this); } } 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; } const glm::vec3& GameObject::GetPos() const { return mPos; } void GameObject::SetPos(const glm::vec3& pos) { mPos = pos; } const glm::quat& GameObject::GetRotation() const { return mRot; } void GameObject::SetRotation(const glm::quat& rotation) { mRot = rotation; } const glm::vec3& GameObject::GetScale() const { return mScale; } void GameObject::SetScale(const glm::vec3& scale) { mScale = scale; } std::span GameObject::GetRenderObjects() const { return {}; } void GameObject::OnInitialized() { } void GameObject::Awaken() { } void GameObject::Resleep() { } void GameObject::Update() { } void GameObject::SetParent(GameObject* parent) { if (mParent != parent) { mParent = parent; // needUpdate(); } }