Added rudimentary prefabs (no resolution) #367

Merged
srishamharan merged 3 commits from SP3-8-serialization into main 2023-02-27 11:53:46 +08:00
4 changed files with 66 additions and 17 deletions
Showing only changes of commit 38c6cb6fed - Show all commits

View File

@ -1,5 +1,9 @@
#include "SHpch.h" #include "SHpch.h"
#include "SHPrefabManager.h" #include "SHPrefabManager.h"
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Assets/SHAssetManager.h"
#include "Assets/Asset Types/SHPrefabAsset.h"
#include "Serialization/SHSerialization.h"
namespace SHADE namespace SHADE
{ {
@ -32,7 +36,7 @@ namespace SHADE
{ {
if (prefabMap.contains(prefabAssetID)) if (prefabMap.contains(prefabAssetID))
{ {
prefabMap[prefabAssetID].insert(eid); prefabMap[prefabAssetID].push_back(eid);
} }
} }
@ -40,10 +44,21 @@ namespace SHADE
{ {
if (prefabMap.contains(prefabAssetID)) if (prefabMap.contains(prefabAssetID))
{ {
prefabMap[prefabAssetID].erase(eid); std::ranges::remove(prefabMap[prefabAssetID], eid);
} }
} }
void SHPrefabManager::SaveEntityAsPrefab(EntityID const& eid) noexcept
{
SHEntity* const entity = SHEntityManager::GetEntityByID(eid);
AssetID const assetID = SHAssetManager::CreateNewAsset(AssetType::PREFAB, entity->name);
auto assetData = SHAssetManager::GetData<SHPrefabAsset>(assetID);
assetData->data = SHSerialization::SerializeEntitiesToString({eid});
SHAssetManager::SaveAsset(assetID);
}
void SHPrefabManager::Clear() noexcept void SHPrefabManager::Clear() noexcept
{ {
prefabMap.clear(); prefabMap.clear();

View File

@ -2,7 +2,8 @@
#include "Assets/SHAssetMacros.h" #include "Assets/SHAssetMacros.h"
#include "ECS_Base/SHECSMacros.h" #include "ECS_Base/SHECSMacros.h"
#include <unordered_set> #include "ECS_Base/General/SHFamily.h"
#include "ECS_Base/Components/SHComponent.h"
#include <unordered_map> #include <unordered_map>
@ -11,7 +12,17 @@ namespace SHADE
class SHPrefabManager class SHPrefabManager
{ {
public: public:
using PrefabMap = std::unordered_map<AssetID, std::unordered_set<EntityID>>;
enum class PrefabEntityComponentStatus : uint8_t
{
PES_UNCHANGED = 0,
PES_MODIFIED,
PES_ADDED,
PES_REMOVED
};
using PrefabMap = std::unordered_map<AssetID, std::vector<EntityID>>;
using PrefabEntitiesComponentStatusData = std::unordered_map<EntityID, std::unordered_map<SHFamilyID<SHComponent>,PrefabEntityComponentStatus>>;
static void AddPrefab(AssetID const& prefabAssetID) noexcept; static void AddPrefab(AssetID const& prefabAssetID) noexcept;
static void RemovePrefab(AssetID const& prefabAssetID) noexcept; static void RemovePrefab(AssetID const& prefabAssetID) noexcept;
@ -19,10 +30,15 @@ namespace SHADE
static void UpdateAllPrefabEntities(AssetID const& prefabAssetID) noexcept; static void UpdateAllPrefabEntities(AssetID const& prefabAssetID) noexcept;
static void AddEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept; static void AddEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept;
static void RemoveEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept; static void RemoveEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept;
static void SaveEntityAsPrefab(EntityID const& eid) noexcept;
static void Clear() noexcept; static void Clear() noexcept;
static bool Empty() noexcept; static bool Empty() noexcept;
private: private:
static PrefabMap prefabMap; static PrefabMap prefabMap;
static PrefabEntitiesComponentStatusData prefabEntitiesComponentStatusData;
friend class SHSerialization;
friend class SHSerializationHelper;
}; };
} }

View File

@ -23,7 +23,7 @@ namespace SHADE
auto assetData = SHAssetManager::GetData<SHSceneAsset>(sceneAssetID); auto assetData = SHAssetManager::GetData<SHSceneAsset>(sceneAssetID);
if(!assetData) if(!assetData)
{ {
SHLOG_ERROR("Asset does not exist: {}", sceneAssetID); SHLOG_ERROR("Serialization: Asset does not exist: {}", sceneAssetID);
return false; return false;
} }
YAML::Emitter out; YAML::Emitter out;
@ -45,7 +45,7 @@ namespace SHADE
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
auto root = sceneGraph.GetRoot(); auto root = sceneGraph.GetRoot();
SHASSERT(root != nullptr, "Root is null. Failed to serialize scene to node."); SHASSERT(root != nullptr, "Serialization: Root is null. Failed to serialize scene to node.");
auto const& children = root->GetChildren(); auto const& children = root->GetChildren();
out << YAML::BeginSeq; out << YAML::BeginSeq;
@ -105,7 +105,7 @@ namespace SHADE
auto assetData = SHAssetManager::GetData<SHSceneAsset>(sceneAssetID); auto assetData = SHAssetManager::GetData<SHSceneAsset>(sceneAssetID);
if(!assetData) if(!assetData)
{ {
SHLOG_ERROR("Attempted to load scene that doesn't exist {}", sceneAssetID) SHLOG_ERROR("Serialization: Attempted to load scene that doesn't exist {}", sceneAssetID)
SHSceneManager::SetCurrentSceneAssetID(0); SHSceneManager::SetCurrentSceneAssetID(0);
return NewSceneName.data(); return NewSceneName.data();
} }
@ -119,7 +119,7 @@ namespace SHADE
} }
if (createdEntities.empty()) if (createdEntities.empty())
{ {
SHLOG_ERROR("Failed to create entities from deserializaiton") SHLOG_ERROR("Serialization: Failed to create entities from deserialization")
return NewSceneName.data(); return NewSceneName.data();
} }
auto entityVecIt = createdEntities.begin(); auto entityVecIt = createdEntities.begin();
@ -139,26 +139,33 @@ namespace SHADE
return assetData->name; return assetData->name;
} }
void SHSerialization::EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out) void SHSerialization::EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out, bool isPrefab /*= false*/, EntityID* entityIndex /*= nullptr*/)
{ {
out << SerializeEntityToNode(entityNode); out << SerializeEntityToNode(entityNode);
if(isPrefab)
++(*entityIndex);
auto const& children = entityNode->GetChildren(); auto const& children = entityNode->GetChildren();
for (auto const& child : children) for (auto const& child : children)
{ {
EmitEntity(child, out); EmitEntity(child, out, isPrefab);
} }
} }
std::string SHSerialization::SerializeEntitiesToString(std::vector<EntityID> const& entities) noexcept std::string SHSerialization::SerializeEntitiesToString(std::vector<EntityID> const& entities, bool isPrefab) noexcept
{ {
YAML::Emitter out; YAML::Emitter out;
YAML::Node node; YAML::Node node;
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
out << YAML::BeginSeq; out << YAML::BeginSeq;
EntityID entityIndex = 0;
for (auto const& eid : entities) for (auto const& eid : entities)
{ {
auto entityNode = sceneGraph.GetNode(eid); auto entityNode = sceneGraph.GetNode(eid);
EmitEntity(entityNode, out); if(isPrefab)
EmitEntity(entityNode, out, isPrefab);
else
EmitEntity(entityNode, out);
} }
out << YAML::EndSeq; out << YAML::EndSeq;
return std::string(out.c_str()); return std::string(out.c_str());
@ -179,8 +186,11 @@ namespace SHADE
} }
} }
YAML::Node SHSerialization::SerializeEntityToNode(SHSceneNode* sceneNode) YAML::Node SHSerialization::SerializeEntityToNode(SHSceneNode* sceneNode, bool isPrefab /*= false*/, EntityID* entityIndex /*= nullptr*/)
{ {
if(!sceneNode)
return YAML::Node();
YAML::Node node; YAML::Node node;
auto eid = sceneNode->GetEntityID(); auto eid = sceneNode->GetEntityID();
auto entity = SHEntityManager::GetEntityByID(eid); auto entity = SHEntityManager::GetEntityByID(eid);
@ -190,7 +200,14 @@ namespace SHADE
return node; return node;
} }
node.SetStyle(YAML::EmitterStyle::Block); node.SetStyle(YAML::EmitterStyle::Block);
node[EIDNode] = eid; node[EIDNode] = eid;
if(isPrefab) //TODO: Set asset id for top level prefab entity only
{
node[PrefabID] = 0;
}
node[EntityNameNode] = entity->name; node[EntityNameNode] = entity->name;
node[IsActiveNode] = sceneNode->IsActive(); node[IsActiveNode] = sceneNode->IsActive();
auto const& children = sceneNode->GetChildren(); auto const& children = sceneNode->GetChildren();
@ -236,7 +253,7 @@ namespace SHADE
} }
if (createdEntities.empty()) if (createdEntities.empty())
{ {
SHLOG_ERROR("Failed to create entities from deserializaiton") SHLOG_ERROR("Failed to create entities from deserialization")
return createdEntities; return createdEntities;
} }
//auto entityVecIt = createdEntities.begin(); //auto entityVecIt = createdEntities.begin();

View File

@ -24,6 +24,7 @@ namespace SHADE
constexpr const char* IsActiveNode = "IsActive"; constexpr const char* IsActiveNode = "IsActive";
constexpr const char* NumberOfChildrenNode = "NumberOfChildren"; constexpr const char* NumberOfChildrenNode = "NumberOfChildren";
constexpr const char* ScriptsNode = "Scripts"; constexpr const char* ScriptsNode = "Scripts";
constexpr const char* PrefabID = "PrefabID";
class SH_API SHSerialization class SH_API SHSerialization
{ {
@ -38,11 +39,11 @@ namespace SHADE
static std::string DeserializeSceneFromFile(AssetID const& sceneAssetID) noexcept; static std::string DeserializeSceneFromFile(AssetID const& sceneAssetID) noexcept;
static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out); static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out, bool isPrefab = false, EntityID* entityIndex = nullptr);
static std::string SerializeEntitiesToString(std::vector<EntityID> const& entities) noexcept; static std::string SerializeEntitiesToString(std::vector<EntityID> const& entities, bool isPrefab = false) noexcept;
//static void SerializeEntityToFile(std::filesystem::path const& path); //static void SerializeEntityToFile(std::filesystem::path const& path);
static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode); static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode, bool isPrefab = false, EntityID* entityIndex = nullptr);
static CreatedEntitiesList DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID = MAX_EID) noexcept; static CreatedEntitiesList DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID = MAX_EID) noexcept;