diff options
author | rtk0c <[email protected]> | 2022-05-30 17:03:20 -0700 |
---|---|---|
committer | rtk0c <[email protected]> | 2022-05-30 17:03:20 -0700 |
commit | e66286ebe30afc9acc4531fc2bea29b7fb924f93 (patch) | |
tree | fa6b76554c3eb88bc8f088fbab68e20c40118ca7 /source/30-game/GameObject.cpp | |
parent | 366ef5a5450c6e0e680c924c3454943a9ae9814d (diff) |
Changeset: 56 Buildsystem cleanup: change to layered structure for different targets
Diffstat (limited to 'source/30-game/GameObject.cpp')
-rw-r--r-- | source/30-game/GameObject.cpp | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/source/30-game/GameObject.cpp b/source/30-game/GameObject.cpp new file mode 100644 index 0000000..8bb3ec7 --- /dev/null +++ b/source/30-game/GameObject.cpp @@ -0,0 +1,244 @@ +#include "GameObject.hpp" + +#include "Level.hpp" +#include "Player.hpp" +#include "RapidJsonHelper.hpp" +#include "SceneThings.hpp" +#include "World.hpp" + +#include <rapidjson/document.h> +#include <string_view> +#include <utility> + +using namespace std::literals; + +namespace ProjectBrussel_UNITY_ID { +GameObject* CreateGameObject(GameObject::Kind kind, GameWorld* world) { + switch (kind) { + case GameObject::KD_Generic: return new GameObject(world); + case GameObject::KD_SimpleGeometry: return new SimpleGeometryObject(world); + case GameObject::KD_Building: return new BuildingObject(world); + case GameObject::KD_LevelWrapper: return new LevelWrapperObject(world); + default: break; + } + return nullptr; +} + +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*>& 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*> 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<T>, 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<const RenderObject> GameObject::GetRenderObjects() const { + return {}; +} + +void GameObject::OnInitialized() { +} + +void GameObject::Awaken() { +} + +void GameObject::Resleep() { +} + +void GameObject::Update() { +} + +rapidjson::Value GameObject::Serialize(GameObject* obj, rapidjson::Document& root) { + rapidjson::Value result(rapidjson::kObjectType); + + result.AddMember("Type", rapidjson::StringRef(ToString(obj->GetKind())), root.GetAllocator()); + + rapidjson::Value rvValue(rapidjson::kObjectType); + obj->WriteSaveFormat(rvValue, root); + result.AddMember("Value", rvValue, root.GetAllocator()); + + return result; +} + +std::unique_ptr<GameObject> GameObject::Deserialize(const rapidjson::Value& value, GameWorld* world) { + using namespace ProjectBrussel_UNITY_ID; + + auto rvType = rapidjson::GetProperty(value, rapidjson::kStringType, "Type"sv); + if (!rvType) return nullptr; + + auto rvValue = rapidjson::GetProperty(value, rapidjson::kObjectType, "Value"sv); + if (!rvValue) return nullptr; + + auto kind = FromString(rapidjson::AsStringView(*rvType)); + auto obj = std::unique_ptr<GameObject>(CreateGameObject(kind, world)); + if (!obj) return nullptr; + obj->ReadSaveFormat(*rvValue); + + return obj; +} + +void GameObject::ReadSaveFormat(const rapidjson::Value& value) { +} + +void GameObject::WriteSaveFormat(rapidjson::Value& value, rapidjson::Document& root) { +} + +void GameObject::SetParent(GameObject* parent) { + if (mParent != parent) { + mParent = parent; + // needUpdate(); + } +} |