Entity parent/child hierarchies implemented

master
Joey Pollack 3 years ago
parent d893849dc3
commit 2279b3ff45

@ -1,5 +1,6 @@
High Importance: High Importance:
☐ Colors are not saved accurately
✔ Add Component button on properties view no longer works @critical @done(22-09-07 13:44) ✔ Add Component button on properties view no longer works @critical @done(22-09-07 13:44)
✔ AssetBrowser back button does not stop at the asset root directory @high @done(22-07-05 13:53) ✔ AssetBrowser back button does not stop at the asset root directory @high @done(22-07-05 13:53)
✔ Editor does not get absolute paths from the file browser - replace with NFD dialogs @critical @done(22-05-20 18:36) ✔ Editor does not get absolute paths from the file browser - replace with NFD dialogs @critical @done(22-05-20 18:36)

@ -52,15 +52,15 @@ int main(int argc, char** argv)
} }
//std::cout << "\nEngine core successfully initialized!\n"; //std::cout << "\nEngine core successfully initialized!\n";
try
{
core.RunGameLoop(); core.RunGameLoop();
} // try
catch(const std::exception& e) // {
{ // core.RunGameLoop();
lunarium::Logger::Fatal(lunarium::LogCategory::CORE, "Unhandled exception: %s", e.what()); // }
} // catch(const std::exception& e)
// {
// lunarium::Logger::Fatal(lunarium::LogCategory::CORE, "Unhandled exception: %s", e.what());
// }
core.Shutdown(); core.Shutdown();

@ -120,12 +120,16 @@ namespace lunarium { namespace editor
was_clicked = ImGui::IsItemClicked(ImGuiMouseButton_Left); was_clicked = ImGui::IsItemClicked(ImGuiMouseButton_Left);
was_right_clicked = ImGui::IsItemClicked(ImGuiMouseButton_Right); was_right_clicked = ImGui::IsItemClicked(ImGuiMouseButton_Right);
if (pEnt->HasChildren())
{
const std::vector<LUUID>& children = pEnt->GetChildren(); const std::vector<LUUID>& children = pEnt->GetChildren();
for (auto iter = children.begin(); iter != children.end(); iter++) for (auto iter = children.begin(); iter != children.end(); iter++)
{ {
Entity* pe = mpWorld->GetEntity((*iter)); Entity* pe = mpWorld->GetEntity((*iter));
ShowEntity(pe); ShowEntity(pe);
} }
}
ImGui::TreePop(); ImGui::TreePop();
} }

@ -19,6 +19,7 @@
#include <renderer/orthographic_camera.h> #include <renderer/orthographic_camera.h>
#include <string> #include <string>
#include <vector>
namespace lunarium namespace lunarium
{ {
@ -86,13 +87,30 @@ namespace lunarium
// UTILITY COMPONENTS // UTILITY COMPONENTS
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
// These components are for internal use only. They do not show up in the editor. // These components are for internal use only. They do not show up in the editor.
struct UUIDComponent
{
LUUID UUID;
UUIDComponent() = default;
UUIDComponent(const UUIDComponent&) = default;
};
struct ParentEntityComponent struct ParentEntityComponent
{ {
LUUID parent; LUUID Parent;
ParentEntityComponent() = default; ParentEntityComponent() = default;
ParentEntityComponent(const ParentEntityComponent&) = default; ParentEntityComponent(const ParentEntityComponent&) = default;
}; };
struct ChildrenComponent
{
std::vector<LUUID> Children;
ChildrenComponent() = default;
ChildrenComponent(const ChildrenComponent&) = default;
};
} }
#endif // LUNARIUM_COMPONENTS_H_ #endif // LUNARIUM_COMPONENTS_H_

@ -42,6 +42,11 @@ namespace lunarium
return mUUID; return mUUID;
} }
entt::entity Entity::GetEnttHandle() const
{
return mHandle;
}
std::string Entity::GetName() const std::string Entity::GetName() const
{ {
return mName; return mName;
@ -53,9 +58,10 @@ namespace lunarium
} }
bool Entity::HasChildren() const bool Entity::HasChildren()
{ {
return mChildren.size() > 0; return HasComponent<ChildrenComponent>();
//return mChildren.size() > 0;
} }
@ -63,7 +69,16 @@ namespace lunarium
{ {
Entity* e = mWorld.GetEntity(child); Entity* e = mWorld.GetEntity(child);
e->AddComponent<ParentEntityComponent>(mUUID); e->AddComponent<ParentEntityComponent>(mUUID);
mChildren.push_back(child);
if (!HasComponent<ChildrenComponent>())
{
AddComponent<ChildrenComponent>();
}
ChildrenComponent& ccomp = GetComponent<ChildrenComponent>();
ccomp.Children.push_back(child);
//mChildren.push_back(child);
} }
@ -71,40 +86,61 @@ namespace lunarium
{ {
Entity* e = mWorld.GetEntity(child); Entity* e = mWorld.GetEntity(child);
e->ClearParent(); e->ClearParent();
for (auto iter = mChildren.begin(); iter != mChildren.end(); iter++)
if (!HasChildren())
{
Logger::Error(LogCategory::GAME_SYSTEM, "RemoveChild called on entity that does not have children");
return;
}
ChildrenComponent& ccomp = GetComponent<ChildrenComponent>();
for (auto iter = ccomp.Children.begin(); iter != ccomp.Children.end(); iter++)
{ {
if ((*iter) == child) if ((*iter) == child)
{ {
mChildren.erase(iter); ccomp.Children.erase(iter);
break; break;
} }
} }
}
const std::vector<LUUID>& Entity::GetChildren() const if (ccomp.Children.size() < 1)
{ {
return mChildren; RemoveComponent<ChildrenComponent>();
} }
bool Entity::HasParent() const
{
return mParentSet;
} }
LUUID Entity::GetParent() const
std::vector<LUUID>& Entity::GetChildren()
{ {
return mParent; if (!HasChildren())
{
Logger::Error(LogCategory::GAME_SYSTEM, "GetChildren called on entity that does not have children");
return std::move(std::vector<LUUID>());
} }
void Entity::SetParent(LUUID parent) ChildrenComponent& ccomp = GetComponent<ChildrenComponent>();
{ return ccomp.Children;
mParent = parent;
} }
// bool Entity::HasParent() const
// {
// return mParentSet;
// }
// LUUID Entity::GetParent() const
// {
// return mParent;
// }
// void Entity::SetParent(LUUID parent)
// {
// mParent = parent;
// }
void Entity::ClearParent() void Entity::ClearParent()
{ {
mParentSet = false; mParentSet = false;
RemoveComponent<ParentEntityComponent>();
} }
@ -119,6 +155,15 @@ namespace lunarium
node["name"] = mName; node["name"] = mName;
auto& components = node["components"]; auto& components = node["components"];
if (HasComponent<UUIDComponent>())
{
nlohmann::ordered_json uuid;
uuid["type_name"] = "UUIDComponent";
uuid["UUID"] = (u64)GetComponent<UUIDComponent>().UUID;
components.emplace_back(uuid);
}
if (HasComponent<TagComponent>()) if (HasComponent<TagComponent>())
{ {
nlohmann::ordered_json tag; nlohmann::ordered_json tag;
@ -210,23 +255,40 @@ namespace lunarium
nlohmann::ordered_json parent; nlohmann::ordered_json parent;
ParentEntityComponent& comp = GetComponent<ParentEntityComponent>(); ParentEntityComponent& comp = GetComponent<ParentEntityComponent>();
parent["type_name"] = "ParentEntityComponent"; parent["type_name"] = "ParentEntityComponent";
parent["UUID"] = (u64)comp.parent; parent["UUID"] = (u64)comp.Parent;
components.emplace_back(parent); components.emplace_back(parent);
} }
// TODO: ADD CODE TO SERIALIZE ANY NEW COMPONENTS if (HasComponent<ChildrenComponent>())
{
nlohmann::ordered_json children_node;
ChildrenComponent& comp = GetComponent<ChildrenComponent>();
children_node["type_name"] = "ChildrenComponent";
// Children auto& children = children_node["children"];
auto& children = node["children"]; for (int i = 0; i < comp.Children.size(); i++)
for (int i = 0; i < mChildren.size(); i++)
{ {
nlohmann::ordered_json child; nlohmann::ordered_json child;
child["UUID"] = mChildren[i]; child["UUID"] = comp.Children[i];
children.emplace_back(child); 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 #endif
return OpRes::OK(); return OpRes::OK();
} }
@ -246,6 +308,12 @@ namespace lunarium
std::string comp_type_name = comp["type_name"].get<std::string>(); std::string comp_type_name = comp["type_name"].get<std::string>();
if ("UUIDComponent" == comp_type_name)
{
LUUID uuid = comp["UUID"].get<u64>();
AddComponent<UUIDComponent>(uuid);
}
if ("TagComponent" == comp_type_name) if ("TagComponent" == comp_type_name)
{ {
std::string info = comp["info"].get<std::string>(); std::string info = comp["info"].get<std::string>();
@ -325,21 +393,36 @@ namespace lunarium
AddComponent<ParentEntityComponent>(parent); AddComponent<ParentEntityComponent>(parent);
} }
// TODO: ADD CODE TO DESERIALIZE ANY NEW COMPONENTS if ("ChildrenComponent" == comp_type_name)
} {
auto& children = comp["children"];
std::vector<LUUID> children_vec;
// TODO: Load children
auto& children = node["children"];
for (auto iter = children.begin(); iter != children.end(); iter++) for (auto iter = children.begin(); iter != children.end(); iter++)
{ {
auto& child = *iter; auto& child = *iter;
LUUID ne = child["UUID"].get<u64>(); LUUID ne = child["UUID"].get<u64>();
mChildren.push_back(ne); children_vec.push_back(ne);
}
AddComponent<ChildrenComponent>(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<u64>();
// mChildren.push_back(ne);
// }
#endif #endif
return OpRes::OK(); return OpRes::OK();
} }

@ -65,17 +65,18 @@ namespace lunarium // TODO: : public JSONSerializable
} }
LUUID GetUUID() const; LUUID GetUUID() const;
entt::entity GetEnttHandle() const;
std::string GetName() const; std::string GetName() const;
void SetName(std::string name); void SetName(std::string name);
bool HasChildren() const; bool HasChildren();
void AddChild(LUUID child); void AddChild(LUUID child);
void RemoveChild(LUUID child); void RemoveChild(LUUID child);
const std::vector<LUUID>& GetChildren() const; std::vector<LUUID>& GetChildren();
bool HasParent() const; // bool HasParent() const;
LUUID GetParent() const; // LUUID GetParent() const;
void SetParent(LUUID parent); // void SetParent(LUUID parent);
void ClearParent(); void ClearParent();
// Serializing // Serializing
@ -91,7 +92,7 @@ namespace lunarium // TODO: : public JSONSerializable
std::string mName; std::string mName;
entt::entity mHandle; entt::entity mHandle;
World& mWorld; // The world the entity is contained within World& mWorld; // The world the entity is contained within
std::vector<LUUID> mChildren; //std::vector<LUUID> mChildren;
private: private:
void Init(); void Init();

@ -16,7 +16,6 @@
#include <renderer/renderer2D.h> #include <renderer/renderer2D.h>
#include <renderer/orthographic_camera.h> #include <renderer/orthographic_camera.h>
#include "entity.h" #include "entity.h"
#include "components.h"
namespace lunarium namespace lunarium
{ {
@ -58,24 +57,37 @@ namespace lunarium
} }
void World::Render(lunarium::Renderer2D* pGraphics) const void World::Render(lunarium::Renderer2D* pGraphics)
{ {
// switch (mMode) // Draw the Renderables that also have a transform
// Code from:
// https://github.com/skypjack/entt/wiki/Crash-Course:-entity-component-system#views-and-groups
// mECSRegistry.view<TransformComponent, BlockOutComponent>().each([&](auto entity, auto &transform, auto &blockout)
// { // {
// case RunMode::EDITOR: RenderEditor(pGraphics); break; // Rectangle rect(transform.Position.x, transform.Position.y, blockout.Size.x, blockout.Size.y);
// } // Color color(blockout.Color.x, blockout.Color.y, blockout.Color.z, blockout.Color.w);
// TODO: Modify to handle parent/child rendering // glm::mat4 parent_transform(1.0f);
// if (mECSRegistry.all_of<ParentEntityComponent>(entity))
// {
// // UUIDComponent uuid = mECSRegistry.get<UUIDComponent>(entity);
// // LUUID uid = uuid.UUID;
// ParentEntityComponent& parent = mECSRegistry.get<ParentEntityComponent>(entity);
// parent_transform = GetParentTransform(parent.Parent);
// }
// pGraphics->DrawQuad(rect, color, nullptr, 0.0f, Rectangle(-1, -1, -1, -1), parent_transform);
// });
// Draw the Renderables that also have a transform
// Code from:
// https://github.com/skypjack/entt/wiki/Crash-Course:-entity-component-system#views-and-groups
mECSRegistry.view<TransformComponent, BlockOutComponent>().each([&](auto entity, auto &transform, auto &blockout) mECSRegistry.view<TransformComponent, BlockOutComponent>().each([&](auto entity, auto &transform, auto &blockout)
{ {
Rectangle rect(transform.Position.x, transform.Position.y, blockout.Size.x, blockout.Size.y); Rectangle rect(transform.Position.x, transform.Position.y, blockout.Size.x, blockout.Size.y);
Color color(blockout.Color.x, blockout.Color.y, blockout.Color.z, blockout.Color.w); Color color(blockout.Color.x, blockout.Color.y, blockout.Color.z, blockout.Color.w);
pGraphics->DrawQuad(rect, color);
if (!mECSRegistry.all_of<ParentEntityComponent>(entity))
{
DrawHeirarchy(pGraphics, entity, transform, blockout, glm::mat4(1.0f));
}
}); });
} }
@ -135,6 +147,59 @@ namespace lunarium
// RUN MODE HELPERS // RUN MODE HELPERS
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
void World::DrawHeirarchy(lunarium::Renderer2D* g, entt::entity& entity, TransformComponent& my_trans, BlockOutComponent& bo_comp, glm::mat4 current_transform)
{
// Draw current entity
Rectangle rect(my_trans.Position.x, my_trans.Position.y, bo_comp.Size.x, bo_comp.Size.y);
Color color(bo_comp.Color.x, bo_comp.Color.y, bo_comp.Color.z, bo_comp.Color.w);
g->DrawQuad(rect, color, nullptr, -my_trans.Rotation.z, Rectangle(-1, -1, -1, -1), current_transform);
// Apply transform to children's transforms
current_transform *= my_trans.GetTransform();
// Iterate and draw children
if (mECSRegistry.all_of<ChildrenComponent>(entity))
{
ChildrenComponent& children_comp = mECSRegistry.get<ChildrenComponent>(entity);
for (int i = 0; i < children_comp.Children.size(); i++)
{
Entity* pEnt = GetEntity(children_comp.Children[i]);
entt::entity handle = pEnt->GetEnttHandle();
if (pEnt->HasComponent<TransformComponent>() && pEnt->HasComponent<BlockOutComponent>())
{
TransformComponent& trans_comp = pEnt->GetComponent<TransformComponent>();
BlockOutComponent& bo_comp = pEnt->GetComponent<BlockOutComponent>();
DrawHeirarchy(g, handle, trans_comp, bo_comp, current_transform);
}
}
}
}
glm::mat4 World::GetParentTransform(LUUID parent)
{
glm::mat4 transform(1.0f);
Entity* p = GetEntity(parent);
if (p->HasComponent<TransformComponent>())
{
TransformComponent t = p->GetComponent<TransformComponent>();
transform = t.GetTransform();
if (p->HasComponent<ParentEntityComponent>())
{
transform *= GetParentTransform(p->GetComponent<ParentEntityComponent>().Parent);
}
}
return transform;
}
void World::RenderEditor(lunarium::Renderer2D* pGraphics) const void World::RenderEditor(lunarium::Renderer2D* pGraphics) const
{ {
// NOTE: MAY BE REMOVED // NOTE: MAY BE REMOVED

@ -17,6 +17,7 @@
#include <assets/serializing/json_serializable.h> #include <assets/serializing/json_serializable.h>
#include <utils/op_res.h> #include <utils/op_res.h>
#include <entt/entt.hpp> #include <entt/entt.hpp>
#include "components.h"
#include <vector> #include <vector>
#include <map> #include <map>
@ -68,7 +69,7 @@ namespace lunarium
void OnLoad(); void OnLoad();
void OnUnload(); void OnUnload();
void Update(float dt); void Update(float dt);
void Render(lunarium::Renderer2D* pGraphics) const; void Render(lunarium::Renderer2D* pGraphics);
void SetActiveCamera(OrthographicCamera* pCam); void SetActiveCamera(OrthographicCamera* pCam);
void SetRunMode(RunMode mode); void SetRunMode(RunMode mode);
@ -109,6 +110,8 @@ namespace lunarium
private: // HELPERS private: // HELPERS
void RenderEditor(lunarium::Renderer2D* pGraphics) const; void RenderEditor(lunarium::Renderer2D* pGraphics) const;
glm::mat4 GetParentTransform(LUUID parent);
void DrawHeirarchy(lunarium::Renderer2D* g, entt::entity& entity, TransformComponent& my_trans, BlockOutComponent& bo_comp, glm::mat4 current_transform);
}; };
} }

Loading…
Cancel
Save