Compare commits

...

5 Commits

Author SHA1 Message Date
SHAM-DP a833de2c91 add node merge 2023-03-03 21:50:00 +08:00
SHAM-DP f27dbb92b3 Merge branch 'main' into SP3-8-serialization 2023-03-02 10:29:24 +08:00
SHAM-DP 23c6f57899 Prefab Data Resolution WIP 2023-02-28 21:30:24 +08:00
SHAM-DP 49ef701994 Merge branch 'main' into SP3-8-serialization 2023-02-28 18:24:33 +08:00
SHAM-DP ad875050cd ID Resolution for prefabs 2023-02-27 15:00:03 +08:00
10 changed files with 244 additions and 204 deletions

View File

@ -1,147 +0,0 @@
- EID: 0
PrefabID: 117058283
Name: ====Raccoon====
IsActive: true
NumberOfChildren: 2
Components: ~
Scripts: ~
- EID: 1
Name: Player
IsActive: true
NumberOfChildren: 3
Components:
Transform Component:
Translate: {x: 2.35245037, y: 0.38365531, z: 7.10571432}
Rotate: {x: -0, y: 0, z: -0}
Scale: {x: 0.999999881, y: 1, z: 0.999999881}
IsActive: true
Renderable Component:
Mesh: 149697411
Material: 126974645
IsActive: true
RigidBody Component:
Type: Dynamic
Drag: 0.00999999978
Angular Drag: 0.100000001
Use Gravity: false
Interpolate: false
Sleeping Enabled: true
Freeze Position X: false
Freeze Position Y: true
Freeze Position Z: false
Freeze Rotation X: true
Freeze Rotation Y: true
Freeze Rotation Z: true
IsActive: true
Collider Component:
Colliders:
- Is Trigger: false
Collision Tag: 0
Type: Box
Half Extents: {x: 0.400000006, y: 0.5, z: 0.300000012}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0.25, z: 0}
Rotation Offset: {x: 0, y: 0, z: 0}
IsActive: true
Scripts:
- Type: PlayerController
Enabled: true
respawnPoint: 239
currentState: 0
maxMoveVel: 3
moveForce: 50
sprintMultiplier: 1.5
rotationFactorPerFrame: 5
maxJumpHeight: 2
maxJumpTime: 0.75
fallMultipler: 3
lightMultiper: 0.899999976
mediumMultiper: 0.699999988
heavyMultiper: 0.5
- Type: PickAndThrow
Enabled: true
throwForce: [10, 8, 10]
cameraArmOffSet: [0.25, 0.600000024, 0.200000003]
delayTimer: 1
aimingLength: 1
throwItem: false
rayDistance: 0.75
rayHeight: 0.100000001
- EID: 2
Name: HoldingPoint
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: 0.899999976, z: 0.200000286}
Rotate: {x: 0, y: 0, z: -0}
Scale: {x: 1, y: 1, z: 1}
IsActive: true
Scripts: ~
- EID: 3
Name: PlayerCamera
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: -5.96046448e-08, z: 0}
Rotate: {x: 0, y: 6.28318548, z: 2.23517329e-08}
Scale: {x: 1, y: 1, z: 1}
IsActive: true
Camera Component:
Position: {x: 2.12735963, y: 0.362327784, z: 7.98933029}
Pitch: 0
Yaw: 360
Roll: 1.28065994e-06
Width: 2560
Near: 0.00999999978
Far: 10000
Perspective: true
FOV: 45
IsActive: true
Camera Arm Component:
Arm Pitch: 0
Arm Yaw: 0
Arm Length: 3
Look At Camera Origin: true
Target Offset: {x: 0, y: 0.75, z: 0}
Camera Collision: true
IsActive: true
Scripts:
- Type: SHADE_Scripting.ThirdPersonCamera
Enabled: true
armLength: 3
turnSpeedPitch: 0.200000003
turnSpeedYaw: 0.400000006
pitchClamp: 45
inverseXControls: false
inverseYControls: false
lowerClamp: 5
- EID: 4
Name: PlayerBag
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: -2.98023224e-08, z: 4.76837158e-07}
Rotate: {x: 0, y: 0, z: -0}
Scale: {x: 1, y: 1, z: 1}
IsActive: true
Renderable Component:
Mesh: 144838771
Material: 123745521
IsActive: true
Scripts: ~
- EID: 5
Name: RespawnPoint
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 2.5, y: 0.660660267, z: 7}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 1, y: 1, z: 1}
IsActive: true
Scripts: ~

View File

@ -1,3 +0,0 @@
Name: ====Raccoon====
ID: 117058283
Type: 6

View File

@ -23,6 +23,7 @@
#include "Serialization/SHSerialization.h" #include "Serialization/SHSerialization.h"
#include <Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h> #include <Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h>
#include "Serialization/Prefab/SHPrefabManager.h" #include "Serialization/Prefab/SHPrefabManager.h"
#include <Scene/SHSceneManager.h>
namespace SHADE namespace SHADE
{ {
@ -415,7 +416,10 @@ namespace SHADE
{ {
auto createdEntitiesList = SHSerialization::DeserializeEntitiesFromString(SHAssetManager::GetData<SHPrefabAsset>(asset->id)->data); auto createdEntitiesList = SHSerialization::DeserializeEntitiesFromString(SHAssetManager::GetData<SHPrefabAsset>(asset->id)->data);
SHEditorWindowManager::GetEditorWindow<SHHierarchyPanel>()->SetScrollTo(createdEntitiesList.begin()->second); SHEditorWindowManager::GetEditorWindow<SHHierarchyPanel>()->SetScrollTo(createdEntitiesList.begin()->second);
SHPrefabManager::AddEntity(asset->id, createdEntitiesList.begin()->second); std::vector<EntityID> eidList;
SHPrefabManager::RecursivelyFlattenEntityHierarchy(SHSceneManager::GetCurrentSceneGraph().GetNode(createdEntitiesList.begin()->second), eidList);
SHPrefabManager::AddPrefabInstance(asset->id, eidList);
//SHPrefabManager::AddEntity(asset->id, createdEntitiesList.begin()->second);
} }
} }
break; break;

View File

@ -390,7 +390,8 @@ namespace SHADE
std::ranges::transform(createdEntitiesList, std::back_inserter(eidList), [](std::pair<EntityID, EntityID> pair){return pair.second;} ); std::ranges::transform(createdEntitiesList, std::back_inserter(eidList), [](std::pair<EntityID, EntityID> pair){return pair.second;} );
ParentSelectedEntities(eid, eidList); ParentSelectedEntities(eid, eidList);
SetScrollTo(createdEntitiesList.begin()->second); SetScrollTo(createdEntitiesList.begin()->second);
SHPrefabManager::AddEntity(assetId, createdEntitiesList.begin()->second); SHPrefabManager::AddPrefabInstance(assetId, eidList);
//SHPrefabManager::AddEntity(assetId, createdEntitiesList.begin()->second);
skipFrame = true; skipFrame = true;
} }
} }

View File

@ -8,22 +8,26 @@
namespace SHADE namespace SHADE
{ {
SHPrefabManager::PrefabMap SHPrefabManager::prefabMap{}; SHPrefabManager::PrefabMap SHPrefabManager::prefabMap{};
SHPrefabManager::PrefabEntityDatabase SHPrefabManager::prefabEntityDatabase{};
AssetID SHPrefabManager::GetPrefabAssetID(EntityID eid) noexcept AssetID SHPrefabManager::GetPrefabAssetID(EntityID eid) noexcept
{ {
for(auto const& [assetId, entityList] : prefabMap) for (auto const& [assetId, entityList] : prefabMap)
{ {
if(std::ranges::find(entityList, eid) != entityList.end()) if (std::ranges::find(entityList, eid) != entityList.end())
{ {
return assetId; return assetId;
} }
} }
return 0; return 0;
} }
void SHPrefabManager::AddPrefab(AssetID const& prefabAssetID) noexcept void SHPrefabManager::AddPrefab(AssetID const& prefabAssetID) noexcept
{ {
prefabMap[prefabAssetID] = {}; //if (prefabMap.contains(prefabAssetID))
//{
// prefabMap.insert(prefabAssetID, {});
//}
} }
void SHPrefabManager::RemovePrefab(AssetID const& prefabAssetID) noexcept void SHPrefabManager::RemovePrefab(AssetID const& prefabAssetID) noexcept
@ -35,37 +39,61 @@ namespace SHADE
{ {
if (prefabMap.contains(prefabAssetID)) if (prefabMap.contains(prefabAssetID))
{ {
prefabMap[prefabAssetID].clear(); prefabMap.erase(prefabAssetID);
} }
} }
void SHPrefabManager::UpdateAllPrefabEntities(AssetID const& prefabAssetID) noexcept void SHPrefabManager::UpdateAllPrefabEntities(AssetID const& prefabAssetID) noexcept
{ {
//Loop through all entities and deserialize new data
} }
void SHPrefabManager::AddEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept void SHPrefabManager::AddPrefabInstance(AssetID prefabAssetID, std::vector<EntityID> eidList)
{ {
prefabMap.insert({ prefabAssetID, eidList });
prefabMap[prefabAssetID].push_back(eid); std::size_t size = eidList.size();
for (std::size_t i = 0; i < size; ++i)
}
void SHPrefabManager::RemoveEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept
{
if (prefabMap.contains(prefabAssetID))
{ {
(void)std::ranges::remove(prefabMap[prefabAssetID], eid); prefabEntityDatabase[eidList[i]] = { prefabAssetID, i };
}
}
void SHPrefabManager::RemovePrefabInstance(AssetID prefabAssetID, EntityID rootEid)
{
if (auto iter = prefabMap.find(prefabAssetID); iter != prefabMap.end())
{
while (iter != prefabMap.upper_bound(prefabAssetID))
{
if (std::ranges::find(iter->second, rootEid) != iter->second.end())
{
prefabMap.erase(iter);
}
++iter;
}
}
}
void SHPrefabManager::RecursivelyFlattenEntityHierarchy(SHSceneNode* node, std::vector<EntityID>& eidList)
{
if (!node)
return;
eidList.push_back(node->GetEntityID());
auto const& children = node->GetChildren();
for (auto childNode : children)
{
RecursivelyFlattenEntityHierarchy(childNode, eidList);
} }
} }
void SHPrefabManager::SaveEntityAsPrefab(EntityID const& eid) noexcept void SHPrefabManager::SaveEntityAsPrefab(EntityID const& eid) noexcept
{ {
SHEntity* const entity = SHEntityManager::GetEntityByID(eid); SHEntity* const entity = SHEntityManager::GetEntityByID(eid);
SHSceneNode* entityNode = SHSceneManager::GetCurrentSceneGraph().GetNode(eid);
AssetID const assetID = SHAssetManager::CreateNewAsset(AssetType::PREFAB, entity->name); AssetID const assetID = SHAssetManager::CreateNewAsset(AssetType::PREFAB, entity->name);
AddEntity(assetID, eid); std::vector<EntityID> eidList;
RecursivelyFlattenEntityHierarchy(entityNode, eidList);
AddPrefabInstance(assetID, eidList);
auto assetData = SHAssetManager::GetData<SHPrefabAsset>(assetID); auto assetData = SHAssetManager::GetData<SHPrefabAsset>(assetID);
assetData->data = SHSerialization::SerializeEntityToString(eid); assetData->data = SHSerialization::SerializeEntityToString(eid, assetID);
SHAssetManager::SaveAsset(assetID); SHAssetManager::SaveAsset(assetID);
} }

View File

@ -5,7 +5,7 @@
#include "ECS_Base/General/SHFamily.h" #include "ECS_Base/General/SHFamily.h"
#include "ECS_Base/Components/SHComponent.h" #include "ECS_Base/Components/SHComponent.h"
#include <unordered_map> #include <unordered_map>
#include <Scene/SHSceneNode.h>
namespace SHADE namespace SHADE
{ {
@ -17,27 +17,29 @@ namespace SHADE
{ {
PES_UNCHANGED = 0, PES_UNCHANGED = 0,
PES_MODIFIED, PES_MODIFIED,
PES_ADDED, PES_ADDED
PES_REMOVED
}; };
using PrefabMap = std::unordered_map<AssetID, std::vector<EntityID>>; using PrefabMap = std::unordered_multimap<AssetID, std::vector<EntityID>>;
using PrefabEntitiesComponentStatusData = std::unordered_map<EntityID, std::unordered_map<SHFamilyID<SHComponent>,PrefabEntityComponentStatus>>; using PrefabEntityDatabase = std::unordered_map<EntityID, std::pair<AssetID, EntityID>>;
static AssetID GetPrefabAssetID(EntityID eid) noexcept; static AssetID GetPrefabAssetID(EntityID eid) noexcept;
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;
static void ClearPrefab(AssetID const& prefabAssetID) noexcept; static void ClearPrefab(AssetID const& prefabAssetID) noexcept;
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 AddPrefabInstance(AssetID prefabAssetID, std::vector<EntityID> eidList);
static void RemoveEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept; static void RemovePrefabInstance(AssetID prefabAssetID, EntityID rootEid);
static void RecursivelyFlattenEntityHierarchy(SHSceneNode* node, std::vector<EntityID>& eidList);
//static void AddEntity(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 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; static PrefabEntityDatabase prefabEntityDatabase;
friend class SHSerialization; friend class SHSerialization;
friend struct SHSerializationHelper; friend struct SHSerializationHelper;

View File

@ -16,6 +16,7 @@
#include "Scripting/SHScriptEngine.h" #include "Scripting/SHScriptEngine.h"
#include "Tools/FileIO/SHFileIO.h" #include "Tools/FileIO/SHFileIO.h"
#include "Prefab/SHPrefabManager.h" #include "Prefab/SHPrefabManager.h"
#include "Assets/Asset Types/SHPrefabAsset.h"
namespace SHADE namespace SHADE
{ {
@ -51,6 +52,7 @@ namespace SHADE
auto const& children = root->GetChildren(); auto const& children = root->GetChildren();
out << YAML::BeginSeq; out << YAML::BeginSeq;
//auto pred = [&out](SHSceneNode* node) {out << SerializeEntityToNode(node); };
auto pred = [&out](SHSceneNode* node) {out << SerializeEntityToNode(node); }; auto pred = [&out](SHSceneNode* node) {out << SerializeEntityToNode(node); };
sceneGraph.Traverse(pred); sceneGraph.Traverse(pred);
//out << SerializeEntityToNode(child); //out << SerializeEntityToNode(child);
@ -58,6 +60,33 @@ namespace SHADE
out << YAML::EndSeq; out << YAML::EndSeq;
} }
void RecursivelyResolveEntityIDs(YAML::iterator nodeIt, SHSerialization::CreatedEntitiesList& createdEntities)
{
for (YAML::iterator it = nodeIt->begin(); it != nodeIt->end(); ++it)
{
if(it->second.IsDefined())
{
auto tag = it->second.Tag();
if (!tag.empty() && tag == "EID") //Node has EID tag
{
EntityID eid = it->second.as<EntityID>();
if(createdEntities.contains(eid))
it->second = createdEntities[eid];
}
}
RecursivelyResolveEntityIDs(it, createdEntities);
for (YAML::iterator it2 = it->first.begin(); it2 != it->first.end(); ++it2)
{
RecursivelyResolveEntityIDs(it2, createdEntities);
}
for (YAML::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2)
{
RecursivelyResolveEntityIDs(it2, createdEntities);
}
}
}
static EntityID DeserializeEntity(YAML::iterator& it, YAML::Node const& node, SHSerialization::CreatedEntitiesList& createdEntities, EntityID parentEID = MAX_EID) static EntityID DeserializeEntity(YAML::iterator& it, YAML::Node const& node, SHSerialization::CreatedEntitiesList& createdEntities, EntityID parentEID = MAX_EID)
{ {
EntityID eid{MAX_EID}, oldEID{MAX_EID}; EntityID eid{MAX_EID}, oldEID{MAX_EID};
@ -69,6 +98,14 @@ namespace SHADE
std::string name = "UnnamedEntitiy"; std::string name = "UnnamedEntitiy";
if (node[EntityNameNode]) if (node[EntityNameNode])
name = node[EntityNameNode].as<std::string>(); name = node[EntityNameNode].as<std::string>();
//if(node[PrefabID].IsDefined())
//{
// AssetID prefabAssetID = node[PrefabID].as<AssetID>();
// YAML::Node prefabNode = YAML::Load(SHAssetManager::GetData<SHPrefabAsset>(prefabAssetID)->data);
//
//}
//Compile component IDs //Compile component IDs
const auto componentIDList = SHSerialization::GetComponentIDList(node[ComponentsNode]); const auto componentIDList = SHSerialization::GetComponentIDList(node[ComponentsNode]);
eid = SHEntityManager::CreateEntity(componentIDList, eid, name, parentEID); eid = SHEntityManager::CreateEntity(componentIDList, eid, name, parentEID);
@ -89,10 +126,6 @@ namespace SHADE
} }
} }
// Deserialise scripts
if (node[ScriptsNode])
SHSystemManager::GetSystem<SHScriptEngine>()->DeserialiseScripts(eid, node[ScriptsNode]);
auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
if (node[IsActiveNode]) if (node[IsActiveNode])
{ {
@ -128,9 +161,15 @@ namespace SHADE
AssetQueue assetQueue; AssetQueue assetQueue;
for (auto it = entities.begin(); it != entities.end(); ++it) for (auto it = entities.begin(); it != entities.end(); ++it)
{ {
SHSerializationHelper::FetchAssetsFromComponent<SHRenderable>((*it)[ComponentsNode], createdEntities[(*it)[EIDNode].as<EntityID>()], assetQueue); SHSerializationHelper::FetchAssetsFromComponent<SHRenderable>((*it)[ComponentsNode], createdEntities[(*it)[EIDNode].as<EntityID>()], assetQueue);
} }
LoadAssetsFromAssetQueue(assetQueue); LoadAssetsFromAssetQueue(assetQueue);
for (auto it = entities.begin(); it != entities.end(); ++it)
{
RecursivelyResolveEntityIDs(it, createdEntities);
}
//Initialize Entity //Initialize Entity
entityVecIt = createdEntities.begin(); entityVecIt = createdEntities.begin();
for (auto it = entities.begin(); it != entities.end(); ++it) for (auto it = entities.begin(); it != entities.end(); ++it)
@ -141,16 +180,16 @@ namespace SHADE
return assetData->name; return assetData->name;
} }
void SHSerialization::EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out, bool isPrefab /*= false*/, EntityID* entityIndex /*= nullptr*/) void SHSerialization::EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out, CreatedEntitiesList* createdEntitiesList /*= nullptr*/, bool isPrefab /*= false*/, EntityID* entityIndex /*= nullptr*/)
{ {
out << SerializeEntityToNode(entityNode, isPrefab, entityIndex); out << SerializeEntityToNode(entityNode, createdEntitiesList, isPrefab, entityIndex);
if(isPrefab) if(isPrefab)
++(*entityIndex); ++(*entityIndex);
auto const& children = entityNode->GetChildren(); auto const& children = entityNode->GetChildren();
for (auto const& child : children) for (auto const& child : children)
{ {
EmitEntity(child, out, isPrefab, entityIndex); EmitEntity(child, out, createdEntitiesList, isPrefab, entityIndex);
} }
} }
@ -159,6 +198,7 @@ namespace SHADE
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; EntityID entityIndex = 0;
for (auto const& eid : entities) for (auto const& eid : entities)
@ -167,10 +207,11 @@ namespace SHADE
EmitEntity(entityNode, out); EmitEntity(entityNode, out);
} }
out << YAML::EndSeq; out << YAML::EndSeq;
return std::string(out.c_str()); return std::string(out.c_str());
} }
std::string SHSerialization::SerializeEntityToString(EntityID eid) noexcept std::string SHSerialization::SerializeEntityToString(EntityID eid, AssetID prefabAssetID /*= 0*/) noexcept
{ {
YAML::Emitter out; YAML::Emitter out;
YAML::Node node; YAML::Node node;
@ -179,9 +220,12 @@ namespace SHADE
EntityID entityIndex = 0; EntityID entityIndex = 0;
auto entityNode = sceneGraph.GetNode(eid); auto entityNode = sceneGraph.GetNode(eid);
EmitEntity(entityNode, out, true, &entityIndex); CreatedEntitiesList list;
EmitEntity(entityNode, out, &list, true, &entityIndex);
out << YAML::EndSeq; out << YAML::EndSeq;
node = YAML::Load(out.c_str());
for(auto it = node.begin(); it != node.end(); ++it)
RecursivelyResolveEntityIDs(it, list);
return std::string(out.c_str()); return std::string(out.c_str());
} }
@ -200,7 +244,7 @@ namespace SHADE
} }
} }
YAML::Node SHSerialization::SerializeEntityToNode(SHSceneNode* sceneNode, bool isPrefab /*= false*/, EntityID* entityIndex /*= nullptr*/) YAML::Node SHSerialization::SerializeEntityToNode(SHSceneNode* sceneNode, CreatedEntitiesList* createdEntitiesList /*= nullptr*/, bool isPrefab /*= false*/, EntityID* entityIndex /*= nullptr*/)
{ {
if(!sceneNode) if(!sceneNode)
return YAML::Node(); return YAML::Node();
@ -216,7 +260,10 @@ namespace SHADE
node.SetStyle(YAML::EmitterStyle::Block); node.SetStyle(YAML::EmitterStyle::Block);
node[EIDNode] = (entityIndex) ? *entityIndex : eid; node[EIDNode] = (entityIndex) ? *entityIndex : eid;
if(createdEntitiesList && entityIndex)
{
createdEntitiesList->insert({eid, *entityIndex});
}
AssetID prefabAssetID = SHPrefabManager::GetPrefabAssetID(eid); AssetID prefabAssetID = SHPrefabManager::GetPrefabAssetID(eid);
if(prefabAssetID != 0) if(prefabAssetID != 0)
{ {
@ -275,6 +322,10 @@ namespace SHADE
} }
//auto entityVecIt = createdEntities.begin(); //auto entityVecIt = createdEntities.begin();
for (auto it = entities.begin(); it != entities.end(); ++it) for (auto it = entities.begin(); it != entities.end(); ++it)
{
RecursivelyResolveEntityIDs(it, createdEntities);
}
for (auto it = entities.begin(); it != entities.end(); ++it)
{ {
InitializeEntity(*it, createdEntities[(*it)[EIDNode].as<EntityID>()]); InitializeEntity(*it, createdEntities[(*it)[EIDNode].as<EntityID>()]);
} }
@ -371,20 +422,40 @@ namespace SHADE
ResolveSerializedEntityID(out, it, (*it), createdEntities); ResolveSerializedEntityID(out, it, (*it), createdEntities);
} }
out << YAML::EndSeq; out << YAML::EndSeq;
return out.c_str(); return out.c_str();
} }
void SHSerialization::InitializeEntity(YAML::Node const& entityNode, EntityID const& eid) void SHSerialization::InitializeEntity(YAML::Node const& entityNode, EntityID const& eid)
{ {
auto const componentsNode = entityNode[ComponentsNode]; auto componentsNode = entityNode[ComponentsNode];
if (!componentsNode) if (!componentsNode.IsDefined())
return; return;
SHSerializationHelper::InitializeComponentFromNode<SHTransformComponent>(componentsNode, eid); SHSerializationHelper::InitializeComponentFromNode<SHTransformComponent>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHColliderComponent>(componentsNode, eid);
bool isPrefab = entityNode[PrefabID].IsDefined();
if(isPrefab)
{
auto prefabAssetID = entityNode[PrefabID].as<AssetID>();
if(auto prefabAsset = SHAssetManager::GetData<SHPrefabAsset>(prefabAssetID))
{
auto prefabNode = YAML::Load(prefabAsset->data);
if(prefabNode[ComponentsNode].IsDefined())
{
componentsNode = prefabNode[ComponentsNode];
}
if (prefabNode[ScriptsNode].IsDefined())
SHSystemManager::GetSystem<SHScriptEngine>()->DeserialiseScripts(eid, prefabNode[ScriptsNode]);
}
}
SHSerializationHelper::InitializeComponentFromNode<SHCameraComponent>(componentsNode, eid); SHSerializationHelper::InitializeComponentFromNode<SHCameraComponent>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHCameraArmComponent>(componentsNode, eid); SHSerializationHelper::InitializeComponentFromNode<SHCameraArmComponent>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHRigidBodyComponent>(componentsNode, eid); SHSerializationHelper::InitializeComponentFromNode<SHRigidBodyComponent>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHRenderable>(componentsNode, eid); SHSerializationHelper::InitializeComponentFromNode<SHRenderable>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHColliderComponent>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHCanvasComponent>(componentsNode, eid); SHSerializationHelper::InitializeComponentFromNode<SHCanvasComponent>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHButtonComponent>(componentsNode, eid); SHSerializationHelper::InitializeComponentFromNode<SHButtonComponent>(componentsNode, eid);
@ -395,5 +466,49 @@ namespace SHADE
SHSerializationHelper::InitializeComponentFromNode<SHAnimatorComponent>(componentsNode, eid); SHSerializationHelper::InitializeComponentFromNode<SHAnimatorComponent>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHUIComponent>(componentsNode, eid); SHSerializationHelper::InitializeComponentFromNode<SHUIComponent>(componentsNode, eid);
SHSerializationHelper::InitializeComponentFromNode<SHAudioListenerComponent>(componentsNode, eid); SHSerializationHelper::InitializeComponentFromNode<SHAudioListenerComponent>(componentsNode, eid);
if (!isPrefab && entityNode[ScriptsNode].IsDefined())
SHSystemManager::GetSystem<SHScriptEngine>()->DeserialiseScripts(eid, entityNode[ScriptsNode]);
} }
const YAML::Node& cnode(const YAML::Node& n) {
return n;
}
YAML::Node SHSerialization::MergeNodes(YAML::Node a, YAML::Node b)
{
if (!b.IsMap()) {
return b.IsNull() ? a : b;
}
if (!a.IsMap()) {
return b;
}
if (!b.size()) {
return a;
}
auto c = YAML::Node(YAML::NodeType::Map);
for (auto n : a) {
if (n.first.IsScalar()) {
const std::string& key = n.first.Scalar();
auto t = YAML::Node(cnode(b)[key]);
if (t) {
c[n.first] = MergeNodes(n.second, t);
continue;
}
}
c[n.first] = n.second;
}
for (auto n : b) {
if (!n.first.IsScalar() || !cnode(c)[n.first.Scalar()]) {
c[n.first] = n.second;
}
}
return c;
}
} }

View File

@ -38,13 +38,13 @@ 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, bool isPrefab = false, EntityID* entityIndex = nullptr); static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out, CreatedEntitiesList* createdEntitiesList = nullptr, 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) noexcept;
static std::string SerializeEntityToString(EntityID eid) noexcept; static std::string SerializeEntityToString(EntityID eid, AssetID prefabAssetID = 0) noexcept;
//static void SerializeEntityToFile(std::filesystem::path const& path); //static void SerializeEntityToFile(std::filesystem::path const& path);
static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode, bool isPrefab = false, EntityID* entityIndex = nullptr); static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode, CreatedEntitiesList* createdEntitiesList = nullptr, 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;
@ -56,7 +56,7 @@ namespace SHADE
private: private:
//static void ResolveSerializedEntityID(YAML::Emitter& out, YAML::iterator& it, YAML::Node const& entityNode, CreatedEntitiesList const& createdEntities); //static void ResolveSerializedEntityID(YAML::Emitter& out, YAML::iterator& it, YAML::Node const& entityNode, CreatedEntitiesList const& createdEntities);
static void InitializeEntity(YAML::Node const& entityNode, EntityID const& eid); static void InitializeEntity(YAML::Node const& entityNode, EntityID const& eid);
static YAML::Node MergeNodes(YAML::Node lhsNode, YAML::Node rhsNode);
static constexpr std::string_view NewSceneName = "New Scene"; static constexpr std::string_view NewSceneName = "New Scene";
}; };
} }

View File

@ -209,7 +209,7 @@ namespace SHADE
auto component = SHComponentManager::GetComponent_s<ComponentType>(eid); auto component = SHComponentManager::GetComponent_s<ComponentType>(eid);
if (componentsNode.IsNull() || !component) if (componentsNode.IsNull() || !component)
return false; return false;
auto componentNode = GetComponentNode<ComponentType>(componentsNode, eid); auto componentNode = GetComponentNode<ComponentType>(componentsNode, component);
if (componentNode.IsNull() || !componentNode.IsDefined()) if (componentNode.IsNull() || !componentNode.IsDefined())
return false; return false;
if (componentNode[IsActive.data()].IsDefined()) if (componentNode[IsActive.data()].IsDefined())
@ -242,9 +242,46 @@ 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 YAML::Node GetComponentNode(YAML::Node const& componentsNode, EntityID const& eid) static bool InitializeComponentFromNode(YAML::Node const& componentsNode, ComponentType* component)
{
if constexpr (YAML::HasYAMLConv<ComponentType>())
{
if (componentsNode.IsNull() || !component)
return false;
auto componentNode = GetComponentNode<ComponentType>(componentsNode, component);
if (componentNode.IsNull() || !componentNode.IsDefined())
return false;
if (componentNode[IsActive.data()].IsDefined())
component->isActive = componentNode[IsActive.data()].as<bool>();
YAML::convert<ComponentType>::decode(componentNode, *component);
return true;
}
else
{
if (componentsNode.IsNull() && !component)
return false;
auto rttrType = rttr::type::get<ComponentType>();
auto componentNode = componentsNode[rttrType.get_name().data()];
if (!componentNode.IsDefined())
return false;
if (componentNode[IsActive.data()].IsDefined())
component->isActive = componentNode[IsActive.data()].as<bool>();
auto properties = rttrType.get_properties();
for (auto const& prop : properties)
{
if (componentNode[prop.get_name().data()].IsDefined())
{
InitializeProperty<ComponentType>(component, prop, componentNode[prop.get_name().data()]);
}
}
}
return true;
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static YAML::Node GetComponentNode(YAML::Node const& componentsNode, ComponentType* component)
{ {
auto 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>();
@ -307,7 +344,8 @@ namespace SHADE
template<> template<>
static void FetchAssetsFromComponent<SHRenderable>(YAML::Node const& componentsNode, EntityID const& eid, AssetQueue& assetQueue) static void FetchAssetsFromComponent<SHRenderable>(YAML::Node const& componentsNode, EntityID const& eid, AssetQueue& assetQueue)
{ {
auto node = GetComponentNode<SHRenderable>(componentsNode, eid); SHRenderable* renderableComponent = SHComponentManager::GetComponent_s<SHRenderable>(eid);
auto node = GetComponentNode<SHRenderable>(componentsNode, renderableComponent);
if(!node.IsDefined()) if(!node.IsDefined())
return; return;
if (auto const& meshNode = node[YAML::convert<SHRenderable>::MESH_YAML_TAG.data()]; meshNode.IsDefined()) if (auto const& meshNode = node[YAML::convert<SHRenderable>::MESH_YAML_TAG.data()]; meshNode.IsDefined())

View File

@ -59,6 +59,7 @@ namespace SHADE
else if constexpr (std::is_same_v<FieldType, GameObject>) else if constexpr (std::is_same_v<FieldType, GameObject>)
{ {
fieldNode = MAX_EID; fieldNode = MAX_EID;
fieldNode.SetTag("EID");
} }
else if constexpr (std::is_same_v<FieldType, FontAsset> || else if constexpr (std::is_same_v<FieldType, FontAsset> ||
std::is_same_v<FieldType, MaterialAsset> || std::is_same_v<FieldType, MaterialAsset> ||
@ -125,6 +126,7 @@ namespace SHADE
{ {
GameObject gameObj = safe_cast<GameObject>(object); GameObject gameObj = safe_cast<GameObject>(object);
fieldNode = gameObj ? gameObj.GetEntity() : MAX_EID; fieldNode = gameObj ? gameObj.GetEntity() : MAX_EID;
fieldNode.SetTag("EID");
return true; return true;
} }
} }