Added rudimentary prefabs (no resolution) #367
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue