Serialize/Deserialize SHCollider & SHColliderComponent

This commit is contained in:
Sri Sham Haran 2022-10-25 15:09:45 +08:00
parent f64f13521b
commit 8466309e2f
4 changed files with 221 additions and 27 deletions

View File

@ -48,15 +48,28 @@ namespace SHADE
if (Begin()) if (Begin())
{ {
if(skipFrame)
{
ImGui::End();
skipFrame = false;
return;
}
DrawMenuBar(); DrawMenuBar();
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
if(const auto root = sceneGraph.GetRoot())
if (const auto root = sceneGraph.GetRoot())
{ {
auto const& children = root->GetChildren(); auto const& children = root->GetChildren();
for (const auto child : children) for (const auto child : children)
{ {
RecursivelyDrawEntityNode(child); if(child)
RecursivelyDrawEntityNode(child);
if(skipFrame)
{
ImGui::End();
return;
}
} }
} }
else else
@ -120,8 +133,10 @@ namespace SHADE
} }
} }
ImRect SHHierarchyPanel::RecursivelyDrawEntityNode(SHSceneNode* currentNode) ImRect SHHierarchyPanel::RecursivelyDrawEntityNode(SHSceneNode* const currentNode)
{ {
if(currentNode == nullptr)
return {};
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
//Get node data (Children, eid, selected) //Get node data (Children, eid, selected)
@ -193,10 +208,16 @@ namespace SHADE
if(ImGui::Selectable("Paste")) if(ImGui::Selectable("Paste"))
{ {
SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard())); SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard()));
skipFrame = true;
ImGui::EndPopup();
if(isNodeOpen)
ImGui::TreePop();
return nodeRect;
} }
if(ImGui::Selectable("Paste as Child")) if(ImGui::Selectable("Paste as Child"))
{ {
SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard(), eid)); SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard(), eid));
skipFrame = true;
} }
if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data())) if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data()))
{ {

View File

@ -26,10 +26,12 @@ namespace SHADE
void SetScrollTo(EntityID eid); void SetScrollTo(EntityID eid);
private: private:
void DrawMenuBar() const noexcept; void DrawMenuBar() const noexcept;
ImRect RecursivelyDrawEntityNode(SHSceneNode*); ImRect RecursivelyDrawEntityNode(SHSceneNode* const);
void CreateChildEntity(EntityID parentEID) const noexcept; void CreateChildEntity(EntityID parentEID) const noexcept;
void ParentSelectedEntities(EntityID parentEID) const noexcept; void ParentSelectedEntities(EntityID parentEID) const noexcept;
void SelectRangeOfEntities(EntityID beginEID, EntityID EndEID); void SelectRangeOfEntities(EntityID beginEID, EntityID EndEID);
bool skipFrame = false;
std::string filter; std::string filter;
bool isAnyNodeSelected = false; bool isAnyNodeSelected = false;
EntityID scrollTo = MAX_EID; EntityID scrollTo = MAX_EID;

View File

@ -85,6 +85,8 @@ namespace SHADE
// Deserialise scripts // Deserialise scripts
if (node[ScriptsNode]) if (node[ScriptsNode])
SHSystemManager::GetSystem<SHScriptEngine>()->DeserialiseScripts(eid, node[ScriptsNode]); SHSystemManager::GetSystem<SHScriptEngine>()->DeserialiseScripts(eid, node[ScriptsNode]);
return eid;
} }
void SHSerialization::DeserializeSceneFromFile(std::filesystem::path const& path) void SHSerialization::DeserializeSceneFromFile(std::filesystem::path const& path)
@ -192,9 +194,9 @@ namespace SHADE
{ {
components[rttr::type::get<SHRigidBodyComponent>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(rigidbody); components[rttr::type::get<SHRigidBodyComponent>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(rigidbody);
} }
if (const auto collisionComp = SHComponentManager::GetComponent_s<SHColliderComponent>(eid)) if (auto collisionComp = SHComponentManager::GetComponent_s<SHColliderComponent>(eid))
{ {
components[rttr::type::get<SHColliderComponent>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(collisionComp); components[rttr::type::get<SHColliderComponent>().get_name().data()] = YAML::convert<SHColliderComponent>::encode(*collisionComp);
} }
node[ComponentsNode] = components; node[ComponentsNode] = components;
@ -254,6 +256,10 @@ namespace SHADE
if (id.has_value()) if (id.has_value())
componentIDList.push_back(id.value()); componentIDList.push_back(id.value());
id = GetComponentID<SHColliderComponent>(componentsNode);
if(id.has_value())
componentIDList.push_back(id.value());
return componentIDList; return componentIDList;
} }
@ -263,5 +269,7 @@ namespace SHADE
if (!componentsNode) if (!componentsNode)
return; return;
SHSerializationHelper::InitializeComponentFromNode<SHTransformComponent>(componentsNode, eid); SHSerializationHelper::InitializeComponentFromNode<SHTransformComponent>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHRigidBodyComponent>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNodeData<SHColliderComponent>(componentsNode, eid);
} }
} }

View File

@ -35,13 +35,13 @@ namespace YAML
} }
static bool decode(Node const& node, SHVec4& rhs) static bool decode(Node const& node, SHVec4& rhs)
{ {
if(node[x]) if (node[x])
rhs.x = node[x].as<float>(); rhs.x = node[x].as<float>();
if(node[y]) if (node[y])
rhs.y = node[y].as<float>(); rhs.y = node[y].as<float>();
if(node[z]) if (node[z])
rhs.z = node[z].as<float>(); rhs.z = node[z].as<float>();
if(node[w]) if (node[w])
rhs.w = node[w].as<float>(); rhs.w = node[w].as<float>();
return true; return true;
} }
@ -65,11 +65,11 @@ namespace YAML
} }
static bool decode(Node const& node, SHVec3& rhs) static bool decode(Node const& node, SHVec3& rhs)
{ {
if(node[x]) if (node[x])
rhs.x = node[x].as<float>(); rhs.x = node[x].as<float>();
if(node[y]) if (node[y])
rhs.y = node[y].as<float>(); rhs.y = node[y].as<float>();
if(node[z]) if (node[z])
rhs.z = node[z].as<float>(); rhs.z = node[z].as<float>();
return true; return true;
} }
@ -91,13 +91,162 @@ namespace YAML
} }
static bool decode(Node const& node, SHVec2& rhs) static bool decode(Node const& node, SHVec2& rhs)
{ {
if(node[x]) if (node[x])
rhs.x = node[x].as<float>(); rhs.x = node[x].as<float>();
if(node[y]) if (node[y])
rhs.y = node[y].as<float>(); rhs.y = node[y].as<float>();
return true; return true;
} }
}; };
template<>
struct convert<SHCollider>
{
static constexpr const char* IsTrigger = "Is Trigger";
static constexpr const char* Type = "Type";
static constexpr const char* HalfExtents = "Half Extents";
static constexpr const char* Radius = "Radius";
static constexpr const char* Friction = "Friction";
static constexpr const char* Bounciness = "Bounciness";
static constexpr const char* Density = "Density";
static constexpr const char* PositionOffset = "Position Offset";
static Node encode(SHCollider& rhs)
{
Node node;
node[IsTrigger] = rhs.IsTrigger();
rttr::type const shapeRttrType = rttr::type::get<SHCollider::Type>();
rttr::enumeration const enumAlign = shapeRttrType.get_enumeration();
SHCollider::Type colliderType = rhs.GetType();
node[Type] = enumAlign.value_to_name(colliderType).data();
switch (colliderType)
{
case SHCollider::Type::BOX:
{
auto const bb = reinterpret_cast<SHBoundingBox*>(rhs.GetShape());
node[HalfExtents] = bb->GetHalfExtents();
}
break;
case SHCollider::Type::SPHERE:
{
auto const bs = reinterpret_cast<SHBoundingSphere*>(rhs.GetShape());
node[Radius] = bs->GetRadius();
}
break;
case SHCollider::Type::CAPSULE: break;
default:;
}
node[Friction] = rhs.GetFriction();
node[Bounciness] = rhs.GetBounciness();
node[Density] = rhs.GetDensity();
node[PositionOffset] = rhs.GetPositionOffset();
return node;
}
static bool decode(Node const& node, SHCollider& rhs)
{
if (node[IsTrigger])
rhs.SetIsTrigger(node[IsTrigger].as<bool>());
if (!node[Type])
return false;
rttr::type const shapeRttrType = rttr::type::get<SHCollider::Type>();
rttr::enumeration const enumAlign = shapeRttrType.get_enumeration();
bool ok;
const SHCollider::Type colliderType = enumAlign.name_to_value(node[Type].as<std::string>()).convert<SHCollider::Type>(&ok);
if (!ok)
return false;
switch (colliderType)
{
case SHCollider::Type::BOX:
{
if(auto const bb = dynamic_cast<SHBoundingBox*>(rhs.GetShape()); bb)
{
if (node[HalfExtents])
{
bb->SetHalfExtents(node[HalfExtents].as<SHVec3>());
}
}
}
break;
case SHCollider::Type::SPHERE:
{
if(auto const bs = dynamic_cast<SHBoundingSphere*>(rhs.GetShape()); bs)
{
if (node[Radius])
{
bs->SetRadius(node[Radius].as<float>());
}
}
}
break;
case SHCollider::Type::CAPSULE: break;
default:;
}
if (node[Friction])
rhs.SetFriction(node[Friction].as<float>());
if (node[Bounciness])
rhs.SetBounciness(rhs.GetBounciness());
if (node[Density])
rhs.SetDensity(node[Density].as<float>());
if (node[PositionOffset])
rhs.SetPositionOffset(node[PositionOffset].as<SHVec3>());
return true;
}
};
template<>
struct convert<SHColliderComponent>
{
static constexpr const char* Colliders = "Colliders";
static Node encode(SHColliderComponent& rhs)
{
Node node, collidersNode;
auto const& colliders = rhs.GetColliders();
int const numColliders = static_cast<int>(colliders.size());
for (int i = 0; i < numColliders; ++i)
{
auto& collider = rhs.GetCollider(i);
Node colliderNode = convert<SHCollider>::encode(collider);
if (colliderNode.IsDefined())
collidersNode[i] = colliderNode;
}
node[Colliders] = collidersNode;
return node;
}
static bool decode(Node const& node, SHColliderComponent& rhs)
{
if(node.IsNull())
return false;
if (node[Colliders])
{
int numColliders{};
for (auto const& colliderNode : node[Colliders])
{
rttr::type const shapeRttrType = rttr::type::get<SHCollider::Type>();
rttr::enumeration const enumAlign = shapeRttrType.get_enumeration();
bool ok;
const SHCollider::Type colliderType = enumAlign.name_to_value(colliderNode[convert<SHCollider>::Type].as<std::string>()).convert<SHCollider::Type>(&ok);
if (!ok)
return false;
switch (colliderType)
{
case SHCollider::Type::BOX: rhs.AddBoundingBox(); break;
case SHCollider::Type::SPHERE: rhs.AddBoundingSphere(); break;
case SHCollider::Type::CAPSULE: break;
default:;
}
rhs.GetCollider(numColliders++) = colliderNode.as<SHCollider>();
}
}
}
};
} }
namespace SHADE namespace SHADE
@ -110,11 +259,11 @@ namespace SHADE
{ {
YAML::Node node; YAML::Node node;
auto varType = var.get_type(); auto varType = var.get_type();
if(varType.is_sequential_container()) if (varType.is_sequential_container())
{ {
for(auto const& elem : var.create_sequential_view()) for (auto const& elem : var.create_sequential_view())
{ {
node.push_back(RTTRToNode(elem)); node.push_back(RTTRToNode(elem));
} }
} }
if (varType == rttr::type::get<SHVec4>()) if (varType == rttr::type::get<SHVec4>())
@ -178,7 +327,7 @@ namespace SHADE
else else
{ {
auto properties = var.get_type().get_properties(); auto properties = var.get_type().get_properties();
for (auto property : properties) for (auto const& property : properties)
{ {
node[property.get_name().data()] = RTTRToNode(property.get_value(var)); node[property.get_name().data()] = RTTRToNode(property.get_value(var));
} }
@ -186,7 +335,7 @@ namespace SHADE
return node; return node;
} }
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true> template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static std::string SerializeComponentToString(ComponentType* component) static std::string SerializeComponentToString(ComponentType* component)
{ {
return std::string(); return std::string();
@ -216,17 +365,17 @@ namespace SHADE
auto propType = prop.get_type(); auto propType = prop.get_type();
if (propType == rttr::type::get<SHVec4>()) if (propType == rttr::type::get<SHVec4>())
{ {
SHVec4 vec{ propertyNode["X"].as<float>(), propertyNode["Y"].as<float>(), propertyNode["Z"].as<float>(), propertyNode["W"].as<float>() }; SHVec4 vec = propertyNode.as<SHVec4>();
prop.set_value(component, vec); prop.set_value(component, vec);
} }
else if (propType == rttr::type::get<SHVec3>()) else if (propType == rttr::type::get<SHVec3>())
{ {
SHVec3 vec{ propertyNode["X"].as<float>(), propertyNode["Y"].as<float>(), propertyNode["Z"].as<float>() }; SHVec3 vec = propertyNode.as<SHVec3>();
prop.set_value(component, vec); prop.set_value(component, vec);
} }
else if (propType == rttr::type::get<SHVec2>()) else if (propType == rttr::type::get<SHVec2>())
{ {
SHVec2 vec{ propertyNode["X"].as<float>(), propertyNode["Y"].as<float>() }; SHVec2 vec = propertyNode.as<SHVec2>();
prop.set_value(component, vec); prop.set_value(component, vec);
} }
else if (propType.is_arithmetic()) else if (propType.is_arithmetic())
@ -263,7 +412,7 @@ namespace SHADE
else else
{ {
auto properties = propType.get_properties(); auto properties = propType.get_properties();
for (auto property : properties) for (auto const& property : properties)
{ {
InitializeProperty(component, property, propertyNode[property.get_name().data()]); InitializeProperty(component, property, propertyNode[property.get_name().data()]);
} }
@ -273,7 +422,7 @@ namespace SHADE
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true> template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void InitializeComponentFromNode(YAML::Node const& componentsNode, EntityID const& eid) static void InitializeComponentFromNode(YAML::Node const& componentsNode, EntityID const& eid)
{ {
auto component = SHComponentManager::GetComponent_s<ComponentType>(eid); ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid);
if (componentsNode.IsNull() && !component) if (componentsNode.IsNull() && !component)
return; return;
auto rttrType = rttr::type::get<ComponentType>(); auto rttrType = rttr::type::get<ComponentType>();
@ -283,12 +432,26 @@ namespace SHADE
auto properties = rttrType.get_properties(); auto properties = rttrType.get_properties();
for (auto const& prop : properties) for (auto const& prop : properties)
{ {
if (componentNode[prop.get_name().data()])
if (componentNode[prop.get_name().data()].IsDefined())
{ {
InitializeProperty<ComponentType>(component, prop, componentNode[prop.get_name().data()]); InitializeProperty<ComponentType>(component, prop, componentNode[prop.get_name().data()]);
} }
} }
} }
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void InitializeComponentFromNodeData(YAML::Node const& componentsNode, EntityID const& eid)
{
ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid);
if (componentsNode.IsNull() && !component)
return;
auto rttrType = rttr::type::get<ComponentType>();
auto componentNode = componentsNode[rttrType.get_name().data()];
if (componentsNode.IsNull())
return;
YAML::convert<ComponentType>::decode(componentNode, *component);
}
}; };
} }