/****************************************************************************** * File - entity.cpp * Author - Joey Pollack * Date - 2022/05/23 (y/m/d) * Mod Date - 2022/05/23 (y/m/d) * Description - Provides functionality to work with world entities ******************************************************************************/ #include "entity.h" #include "world.h" #include "components.h" #include namespace lunarium { Entity::Entity(World& w) : mHandle(entt::null), mWorld(w), mParent(0), mParentSet(false) { mUUID = UUID::GetNewID(); Init(); } Entity::Entity(World& w, LUUID uuid, entt::entity handle) : mHandle(handle), mWorld(w), mUUID(uuid) { Init(); } void Entity::Init() { auto prev = mHandle; mHandle = mWorld.GetEntityRegistry()->create(mHandle); if (prev != mHandle && prev != entt::null) { Logger::Warn(LogCategory::GAME_SYSTEM, "Requested entity handle was not used"); } } LUUID Entity::GetUUID() const { return mUUID; } entt::entity Entity::GetEnttHandle() const { return mHandle; } std::string Entity::GetName() const { return mName; } void Entity::SetName(std::string name) { mName = name; } bool Entity::HasChildren() { return HasComponent(); //return mChildren.size() > 0; } void Entity::AddChild(LUUID child) { Entity* e = mWorld.GetEntity(child); e->AddComponent(mUUID); if (!HasComponent()) { AddComponent(); } ChildrenComponent& ccomp = GetComponent(); ccomp.Children.push_back(child); //mChildren.push_back(child); } void Entity::RemoveChild(LUUID child) { Entity* e = mWorld.GetEntity(child); e->ClearParent(); if (!HasChildren()) { Logger::Error(LogCategory::GAME_SYSTEM, "RemoveChild called on entity that does not have children"); return; } ChildrenComponent& ccomp = GetComponent(); for (auto iter = ccomp.Children.begin(); iter != ccomp.Children.end(); iter++) { if ((*iter) == child) { ccomp.Children.erase(iter); break; } } if (ccomp.Children.size() < 1) { RemoveComponent(); } } std::vector& Entity::GetChildren() { if (!HasChildren()) { Logger::Error(LogCategory::GAME_SYSTEM, "GetChildren called on entity that does not have children"); return std::move(std::vector()); } ChildrenComponent& ccomp = GetComponent(); return ccomp.Children; } // bool Entity::HasParent() const // { // return mParentSet; // } // LUUID Entity::GetParent() const // { // return mParent; // } // void Entity::SetParent(LUUID parent) // { // mParent = parent; // } void Entity::ClearParent() { mParentSet = false; RemoveComponent(); } ///////////////////////////////////////////////////////////////////// // SERIALIZING ///////////////////////////////////////////////////////////////////// OpRes Entity::Serialize(nlohmann::ordered_json& node) { #if !BUILD_NO_EDITOR // Only does this when this is an editor build node["UUID"] = mUUID; node["name"] = mName; auto& components = node["components"]; if (HasComponent()) { nlohmann::ordered_json uuid; uuid["type_name"] = "UUIDComponent"; uuid["UUID"] = (u64)GetComponent().UUID; components.emplace_back(uuid); } if (HasComponent()) { nlohmann::ordered_json tag; tag["type_name"] = "TagComponent"; tag["info"] = GetComponent().Info; components.emplace_back(tag); } if (HasComponent()) { nlohmann::ordered_json transform; TransformComponent& comp = GetComponent(); transform["type_name"] = "TransformComponent"; auto& pos = transform["position"]; pos["x"] = comp.Position.x; pos["y"] = comp.Position.y; pos["z"] = comp.Position.z; auto& rot = transform["rotation"]; rot["x"] = comp.Rotation.x; rot["y"] = comp.Rotation.y; rot["z"] = comp.Rotation.z; auto& scale = transform["scale"]; scale["x"] = comp.Scale.x; scale["y"] = comp.Scale.y; scale["z"] = comp.Scale.z; components.emplace_back(transform); } if (HasComponent()) { nlohmann::ordered_json velocity; VelocityComponent& comp = GetComponent(); velocity["type_name"] = "VelocityComponent"; auto& pos = velocity["velocity"]; pos["x"] = comp.Velocity.x; pos["y"] = comp.Velocity.y; pos["z"] = comp.Velocity.z; components.emplace_back(velocity); } if (HasComponent()) { nlohmann::ordered_json camera; CameraComponent& comp = GetComponent(); camera["type_name"] = "CameraComponent"; auto& pos = camera["position"]; pos["x"] = comp.Camera.GetPosition().X; pos["y"] = comp.Camera.GetPosition().Y; pos["z"] = 0.0f; auto& rot = camera["rotation"]; rot["degrees"] = comp.Camera.GetRotation(); auto& vpsize = camera["viewport_size"]; vpsize["width"] = comp.Camera.GetViewportSize().Width; vpsize["height"] = comp.Camera.GetViewportSize().Height; components.emplace_back(camera); } if (HasComponent()) { nlohmann::ordered_json blockout; BlockOutComponent& comp = GetComponent(); blockout["type_name"] = "BlockOutComponent"; auto& color = blockout["color"]; color["r"] = comp.Color.x; color["g"] = comp.Color.y; color["b"] = comp.Color.a; color["a"] = comp.Color.w; auto& size = blockout["size"]; size["width"] = comp.Size.x; size["height"] = comp.Size.y; components.emplace_back(blockout); } if (HasComponent()) { nlohmann::ordered_json parent; ParentEntityComponent& comp = GetComponent(); parent["type_name"] = "ParentEntityComponent"; parent["UUID"] = (u64)comp.Parent; components.emplace_back(parent); } if (HasComponent()) { nlohmann::ordered_json children_node; ChildrenComponent& comp = GetComponent(); children_node["type_name"] = "ChildrenComponent"; auto& children = children_node["children"]; for (int i = 0; i < comp.Children.size(); i++) { nlohmann::ordered_json child; child["UUID"] = comp.Children[i]; children.emplace_back(child); } components.emplace_back(children_node); } // TODO: ADD CODE TO SERIALIZE ANY NEW COMPONENTS // Children // auto& children = node["children"]; // for (int i = 0; i < mChildren.size(); i++) // { // nlohmann::ordered_json child; // child["UUID"] = mChildren[i]; // children.emplace_back(child); // } #endif return OpRes::OK(); } OpRes Entity::Deserialize(nlohmann::ordered_json& node) { #if !BUILD_NO_EDITOR // Only does this when this is an editor build mUUID = node["UUID"].get(); mName = node["name"].get(); // TODO: Load components auto& components = node["components"]; for (auto iter = components.begin(); iter != components.end(); iter++) { auto& comp = *iter; std::string comp_type_name = comp["type_name"].get(); if ("UUIDComponent" == comp_type_name) { LUUID uuid = comp["UUID"].get(); AddComponent(uuid); } if ("TagComponent" == comp_type_name) { std::string info = comp["info"].get(); AddComponent(info); } if ("TransformComponent" == comp_type_name) { auto& pos = comp["position"]; float x = pos["x"].get(); float y = pos["y"].get(); float z = pos["z"].get(); glm::vec3 position(x, y, z); auto& rot = comp["rotation"]; x = rot["x"].get(); y = rot["y"].get(); z = rot["z"].get(); glm::vec3 rotation(x, y, z); auto& sc = comp["scale"]; x = sc["x"].get(); y = sc["y"].get(); z = sc["z"].get(); glm::vec3 scale(x, y, z); AddComponent(position, rotation, scale); } if ("VelocityComponent" == comp_type_name) { auto& vel = comp["velocity"]; float x = vel["x"].get(); float y = vel["y"].get(); float z = vel["z"].get(); glm::vec3 velocity(x, y, z); AddComponent(velocity); } if ("CameraComponent" == comp_type_name) { auto& pos = comp["position"]; float x = pos["x"].get(); float y = pos["y"].get(); float z = pos["z"].get(); glm::vec3 position(x, y, z); auto& rot = comp["rotation"]; float deg = rot["degrees"]; auto& vps = comp["viewport_size"]; float width = vps["width"].get(); float height = vps["height"].get(); OrthographicCamera cam({x, y}, {width, height}); cam.SetRotation(deg); AddComponent(cam); } if ("BlockOutComponent" == comp_type_name) { auto& color = comp["color"]; glm::vec4 Color(color["r"].get(), color["g"].get(), color["b"].get(), color["a"].get()); auto& size = comp["size"]; glm::vec2 Size(size["width"].get(), size["height"].get()); AddComponent(Color, Size); } if ("ParentEntityComponent" == comp_type_name) { LUUID parent = comp["UUID"].get(); AddComponent(parent); } if ("ChildrenComponent" == comp_type_name) { auto& children = comp["children"]; std::vector children_vec; for (auto iter = children.begin(); iter != children.end(); iter++) { auto& child = *iter; LUUID ne = child["UUID"].get(); children_vec.push_back(ne); } AddComponent(children_vec); } // TODO: ADD CODE TO DESERIALIZE ANY NEW COMPONENTS } // TODO: Load children // auto& children = node["children"]; // for (auto iter = children.begin(); iter != children.end(); iter++) // { // auto& child = *iter; // LUUID ne = child["UUID"].get(); // mChildren.push_back(ne); // } #endif return OpRes::OK(); } bool Entity::IsValidNode(nlohmann::ordered_json& node) { if (node["UUID"].is_null()) { return false; } if (!node["UUID"].is_number()) { return false; } return true; } nlohmann::ordered_json Entity::AsJSON() { #if !BUILD_NO_EDITOR // Only does this when this is an editor build nlohmann::ordered_json node; Serialize(node).LogIfFailed(LogCategory::GAME_SYSTEM); return node; #endif return nlohmann::ordered_json(); } }