aboutsummaryrefslogtreecommitdiff
path: root/source/30-game/GameObject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/30-game/GameObject.cpp')
-rw-r--r--source/30-game/GameObject.cpp230
1 files changed, 230 insertions, 0 deletions
diff --git a/source/30-game/GameObject.cpp b/source/30-game/GameObject.cpp
new file mode 100644
index 0000000..3b15111
--- /dev/null
+++ b/source/30-game/GameObject.cpp
@@ -0,0 +1,230 @@
+#include "GameObject.hpp"
+
+#include "Level.hpp"
+#include "Player.hpp"
+#include "SceneThings.hpp"
+#include "World.hpp"
+
+#include <Metadata.hpp>
+#include <RapidJsonHelper.hpp>
+
+#include <rapidjson/document.h>
+#include <cassert>
+#include <string_view>
+#include <utility>
+
+using namespace std::literals;
+
+namespace ProjectBrussel_UNITY_ID {
+GameObject* CreateGameObject(GameObject::Kind kind, GameWorld* world) {
+ using enum Tags::GameObjectKind;
+ switch (kind) {
+ case KD_Generic: return new GameObject(world);
+ case KD_SimpleGeometry: return new SimpleGeometryObject(world);
+ case KD_Building: return new BuildingObject(world);
+ case 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
+ }
+}
+
+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(Metadata::EnumToString(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 = Metadata::EnumFromString<Kind>(rapidjson::AsStringView(*rvType));
+ assert(kind.has_value());
+ auto obj = std::unique_ptr<GameObject>(CreateGameObject(kind.value(), 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();
+ }
+}
+
+#include <generated/GameObject.gs.inl>