From f53a794b2c603c8b2ad271adf5b850d29cb28c6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivar=20J=C3=B6nsson?= Date: Thu, 28 Sep 2023 23:31:58 +0200 Subject: [PATCH] Started work on implementing prefab -> prefab support * Kinda doesn't work --- Project/Assets/Prefabs/NewCapsule.vtprefab | 148 +++++++++++++ .../Assets/Prefabs/NewCapsule.vtprefab.vtmeta | 8 + Project/Assets/Prefabs/NewCube.vtprefab | 152 ++++++++++++++ .../Assets/Prefabs/NewCube.vtprefab.vtmeta | 8 + .../Scenes/TestScene2/Layers/layer_0.vtlayer | 196 ++++++++++++++++++ .../Scenes/TestScene2/TestScene2.vtscene | 2 + .../TestScene2/TestScene2.vtscene.vtmeta | 8 + .../Volt/Asset/Importers/PrefabImporter.cpp | 19 ++ Volt/Volt/src/Volt/Asset/Prefab.cpp | 83 ++++++-- Volt/Volt/src/Volt/Asset/Prefab.h | 1 + .../Volt/Utility/FileIO/YAMLStreamWriter.h | 10 +- 11 files changed, 618 insertions(+), 17 deletions(-) create mode 100644 Project/Assets/Prefabs/NewCapsule.vtprefab create mode 100644 Project/Assets/Prefabs/NewCapsule.vtprefab.vtmeta create mode 100644 Project/Assets/Prefabs/NewCube.vtprefab create mode 100644 Project/Assets/Prefabs/NewCube.vtprefab.vtmeta create mode 100644 Project/Assets/Scenes/TestScene2/Layers/layer_0.vtlayer create mode 100644 Project/Assets/Scenes/TestScene2/TestScene2.vtscene create mode 100644 Project/Assets/Scenes/TestScene2/TestScene2.vtscene.vtmeta diff --git a/Project/Assets/Prefabs/NewCapsule.vtprefab b/Project/Assets/Prefabs/NewCapsule.vtprefab new file mode 100644 index 000000000..80dea0994 --- /dev/null +++ b/Project/Assets/Prefabs/NewCapsule.vtprefab @@ -0,0 +1,148 @@ +Prefab: + version: 2 + rootEntityId: 4 + Entities: + - Entity: + id: 9 + components: + - guid: [5152712443922219371, 10617432012782403218] + members: + - name: position + data: [192.596344, 0, 0] + - name: rotation + data: [0, 0, 0, 1] + - name: scale + data: [1, 1, 1] + - name: visible + data: true + - name: locked + data: false + - guid: [5177849256600380923, 13689713549658374275] + members: + - name: tag + data: New Cylinder + - guid: [5115013315947959062, 13305215203298195585] + members: + - name: layerid + data: 0 + - guid: [5086337540049333714, 3220959922222851753] + members: + - name: parent + data: 4 + - name: children + data: array + values: + [] + - guid: [5579790378469427390, 5138106327942809248] + members: + - name: handle + data: 2900881217054044389 + - name: material + data: 0 + - guid: [5521397521163238095, 15170572550557146765] + members: + - name: prefabAsset + data: 10877938401218740657 + - name: prefabEntity + data: 9 + - name: sceneRootEntity + data: 4294967295 + - name: version + data: 0 + - Entity: + id: 8 + components: + - guid: [5152712443922219371, 10617432012782403218] + members: + - name: position + data: [470.222565, 0, 0] + - name: rotation + data: [0, 0, 0, 1] + - name: scale + data: [1, 1, 1] + - name: visible + data: true + - name: locked + data: false + - guid: [5177849256600380923, 13689713549658374275] + members: + - name: tag + data: New Cube + - guid: [5115013315947959062, 13305215203298195585] + members: + - name: layerid + data: 0 + - guid: [5086337540049333714, 3220959922222851753] + members: + - name: parent + data: 4 + - name: children + data: array + values: + [] + - guid: [5579790378469427390, 5138106327942809248] + members: + - name: handle + data: 10149696181569838305 + - name: material + data: 0 + - guid: [5521397521163238095, 15170572550557146765] + members: + - name: prefabAsset + data: 10877938401218740657 + - name: prefabEntity + data: 8 + - name: sceneRootEntity + data: 4294967295 + - name: version + data: 0 + - Entity: + id: 4 + components: + - guid: [5152712443922219371, 10617432012782403218] + members: + - name: position + data: [390.92569, 0, 201.899323] + - name: rotation + data: [0, 0, 0, 1] + - name: scale + data: [1, 1, 1] + - name: visible + data: true + - name: locked + data: false + - guid: [5177849256600380923, 13689713549658374275] + members: + - name: tag + data: New Capsule + - guid: [5115013315947959062, 13305215203298195585] + members: + - name: layerid + data: 0 + - guid: [5086337540049333714, 3220959922222851753] + members: + - name: parent + data: 4294967295 + - name: children + data: array + values: + - data: 8 + - data: 9 + - guid: [5579790378469427390, 5138106327942809248] + members: + - name: handle + data: 4818559880424341597 + - name: material + data: 0 + - guid: [5521397521163238095, 15170572550557146765] + members: + - name: prefabAsset + data: 10877938401218740657 + - name: prefabEntity + data: 4 + - name: sceneRootEntity + data: 4294967295 + - name: version + data: 0 + PrefabReferences: + [] \ No newline at end of file diff --git a/Project/Assets/Prefabs/NewCapsule.vtprefab.vtmeta b/Project/Assets/Prefabs/NewCapsule.vtprefab.vtmeta new file mode 100644 index 000000000..3db8e70e5 --- /dev/null +++ b/Project/Assets/Prefabs/NewCapsule.vtprefab.vtmeta @@ -0,0 +1,8 @@ +Metadata: + assetHandle: 10877938401218740657 + filePath: Assets/Prefabs/NewCapsule.vtprefab + type: 2048 + Dependencies: + [] + Properties: + {} \ No newline at end of file diff --git a/Project/Assets/Prefabs/NewCube.vtprefab b/Project/Assets/Prefabs/NewCube.vtprefab new file mode 100644 index 000000000..45170731b --- /dev/null +++ b/Project/Assets/Prefabs/NewCube.vtprefab @@ -0,0 +1,152 @@ +Prefab: + version: 1 + rootEntityId: 2097152 + Entities: + - Entity: + id: 1048586 + components: + - guid: [5152712443922219371, 10617432012782403218] + members: + - name: position + data: [303.147369, 0, 0] + - name: rotation + data: [0, 0, 0, 1] + - name: scale + data: [1, 1, 1] + - name: visible + data: true + - name: locked + data: false + - guid: [5177849256600380923, 13689713549658374275] + members: + - name: tag + data: New Cylinder + - guid: [5115013315947959062, 13305215203298195585] + members: + - name: layerid + data: 0 + - guid: [5086337540049333714, 3220959922222851753] + members: + - name: parent + data: 2097152 + - name: children + data: array + values: + [] + - guid: [5521397521163238095, 15170572550557146765] + members: + - name: prefabAsset + data: 3182644094646103757 + - name: prefabEntity + data: 1048586 + - name: sceneRootEntity + data: 4294967295 + - name: version + data: 0 + - guid: [5579790378469427390, 5138106327942809248] + members: + - name: handle + data: 2900881217054044389 + - name: material + data: 0 + - Entity: + id: 3 + components: + - guid: [5524573352483143404, 11007889460122951339] + members: + - name: fieldOfView + data: 255 + - name: nearPlane + data: 1 + - name: farPlane + data: 100000 + - name: priority + data: 0 + - guid: [5152712443922219371, 10617432012782403218] + members: + - name: position + data: [952.199524, 0, -728.397705] + - name: rotation + data: [0, 0, 0, 1] + - name: scale + data: [1, 1, 1] + - name: visible + data: true + - name: locked + data: false + - guid: [5177849256600380923, 13689713549658374275] + members: + - name: tag + data: Camera + - guid: [5115013315947959062, 13305215203298195585] + members: + - name: layerid + data: 0 + - guid: [5086337540049333714, 3220959922222851753] + members: + - name: parent + data: 2097152 + - name: children + data: array + values: + [] + - guid: [5521397521163238095, 15170572550557146765] + members: + - name: prefabAsset + data: 3182644094646103757 + - name: prefabEntity + data: 3 + - name: sceneRootEntity + data: 4294967295 + - name: version + data: 0 + - Entity: + id: 2097152 + components: + - guid: [5152712443922219371, 10617432012782403218] + members: + - name: position + data: [2244.06543, 0, 606.14563] + - name: rotation + data: [0, 0, 0, 1] + - name: scale + data: [1, 1, 1] + - name: visible + data: true + - name: locked + data: false + - guid: [5177849256600380923, 13689713549658374275] + members: + - name: tag + data: New Cube + - guid: [5115013315947959062, 13305215203298195585] + members: + - name: layerid + data: 0 + - guid: [5086337540049333714, 3220959922222851753] + members: + - name: parent + data: 4294967295 + - name: children + data: array + values: + - data: 3 + - data: 1048586 + - guid: [5521397521163238095, 15170572550557146765] + members: + - name: prefabAsset + data: 3182644094646103757 + - name: prefabEntity + data: 2097152 + - name: sceneRootEntity + data: 4294967295 + - name: version + data: 0 + - guid: [5579790378469427390, 5138106327942809248] + members: + - name: handle + data: 10149696181569838305 + - name: material + data: 0 + PrefabReferences: + [] \ No newline at end of file diff --git a/Project/Assets/Prefabs/NewCube.vtprefab.vtmeta b/Project/Assets/Prefabs/NewCube.vtprefab.vtmeta new file mode 100644 index 000000000..72e3ec29d --- /dev/null +++ b/Project/Assets/Prefabs/NewCube.vtprefab.vtmeta @@ -0,0 +1,8 @@ +Metadata: + assetHandle: 3182644094646103757 + filePath: Assets/Prefabs/NewCube.vtprefab + type: 2048 + Dependencies: + [] + Properties: + {} \ No newline at end of file diff --git a/Project/Assets/Scenes/TestScene2/Layers/layer_0.vtlayer b/Project/Assets/Scenes/TestScene2/Layers/layer_0.vtlayer new file mode 100644 index 000000000..1dd8ca95c --- /dev/null +++ b/Project/Assets/Scenes/TestScene2/Layers/layer_0.vtlayer @@ -0,0 +1,196 @@ +Layer: + name: Main + id: 0 + visible: true + locked: false + Entities: + - Entity: + id: 3 + components: + - guid: [5524573352483143404, 11007889460122951339] + members: + - name: fieldOfView + data: 60 + - name: nearPlane + data: 1 + - name: farPlane + data: 100000 + - name: priority + data: 0 + - guid: [5152712443922219371, 10617432012782403218] + members: + - name: position + data: [0, 0, -500] + - name: rotation + data: [0, 0, 0, 1] + - name: scale + data: [1, 1, 1] + - name: visible + data: true + - name: locked + data: false + - guid: [5177849256600380923, 13689713549658374275] + members: + - name: tag + data: Camera + - guid: [5115013315947959062, 13305215203298195585] + members: + - name: layerid + data: 0 + - guid: [5086337540049333714, 3220959922222851753] + members: + - name: parent + data: 4294967295 + - name: children + data: array + values: + [] + - Entity: + id: 2 + components: + - guid: [5152712443922219371, 10617432012782403218] + members: + - name: position + data: [0, 0, 0] + - name: rotation + data: [0, 0, 0, 1] + - name: scale + data: [1, 1, 1] + - name: visible + data: true + - name: locked + data: false + - guid: [5177849256600380923, 13689713549658374275] + members: + - name: tag + data: Skylight + - guid: [5115013315947959062, 13305215203298195585] + members: + - name: layerid + data: 0 + - guid: [5086337540049333714, 3220959922222851753] + members: + - name: parent + data: 4294967295 + - name: children + data: array + values: + [] + - guid: [5130770350572262273, 9533246575187293344] + members: + - name: environmentHandle + data: 0 + - name: intensity + data: 1 + - name: lod + data: 0 + - name: turbidity + data: 2 + - name: azimuth + data: 0 + - name: inclination + data: 0 + - name: show + data: true + - Entity: + id: 1 + components: + - guid: [5152712443922219371, 10617432012782403218] + members: + - name: position + data: [0, 0, 0] + - name: rotation + data: [0.866025448, 0, 0, 0.49999997] + - name: scale + data: [1, 1, 1] + - name: visible + data: true + - name: locked + data: false + - guid: [5177849256600380923, 13689713549658374275] + members: + - name: tag + data: Directional Light + - guid: [5115013315947959062, 13305215203298195585] + members: + - name: layerid + data: 0 + - guid: [5086337540049333714, 3220959922222851753] + members: + - name: parent + data: 4294967295 + - name: children + data: array + values: + [] + - guid: [4956947959302657279, 6431008363526150588] + members: + - name: intensity + data: 1 + - name: color + data: [1, 1, 1] + - name: lightSize + data: 1 + - name: softShadows + data: true + - name: castShadows + data: true + - Entity: + id: 0 + components: + - guid: [5241627842114713378, 11179844935521484427] + members: + - name: bodyType + data: enum + enumValue: 0 + - name: layerId + data: 0 + - name: mass + data: 1 + - name: linearDrag + data: 0.00999999978 + - name: lockFlags + data: 0 + - name: angularDrag + data: 0.0500000007 + - name: collisionType + data: enum + enumValue: 0 + - name: disableGravity + data: false + - name: isKinematic + data: false + - guid: [5152712443922219371, 10617432012782403218] + members: + - name: position + data: [0, 0, 0] + - name: rotation + data: [0, 0, 0, 1] + - name: scale + data: [1, 1, 1] + - name: visible + data: true + - name: locked + data: false + - guid: [5177849256600380923, 13689713549658374275] + members: + - name: tag + data: Cube + - guid: [5115013315947959062, 13305215203298195585] + members: + - name: layerid + data: 0 + - guid: [5086337540049333714, 3220959922222851753] + members: + - name: parent + data: 4294967295 + - name: children + data: array + values: + [] + - guid: [5579790378469427390, 5138106327942809248] + members: + - name: handle + data: 10149696181569838305 + - name: material + data: 0 \ No newline at end of file diff --git a/Project/Assets/Scenes/TestScene2/TestScene2.vtscene b/Project/Assets/Scenes/TestScene2/TestScene2.vtscene new file mode 100644 index 000000000..54371a988 --- /dev/null +++ b/Project/Assets/Scenes/TestScene2/TestScene2.vtscene @@ -0,0 +1,2 @@ +Scene: + name: TestScene2 \ No newline at end of file diff --git a/Project/Assets/Scenes/TestScene2/TestScene2.vtscene.vtmeta b/Project/Assets/Scenes/TestScene2/TestScene2.vtscene.vtmeta new file mode 100644 index 000000000..4d89418e9 --- /dev/null +++ b/Project/Assets/Scenes/TestScene2/TestScene2.vtscene.vtmeta @@ -0,0 +1,8 @@ +Metadata: + assetHandle: 11605711901206634942 + filePath: Assets/Scenes/TestScene2/TestScene2.vtscene + type: 256 + Dependencies: + [] + Properties: + {} \ No newline at end of file diff --git a/Volt/Volt/src/Volt/Asset/Importers/PrefabImporter.cpp b/Volt/Volt/src/Volt/Asset/Importers/PrefabImporter.cpp index 4c8e83499..a920d0e5d 100644 --- a/Volt/Volt/src/Volt/Asset/Importers/PrefabImporter.cpp +++ b/Volt/Volt/src/Volt/Asset/Importers/PrefabImporter.cpp @@ -37,6 +37,13 @@ namespace Volt { SceneImporter::Get().DeserializeEntity(prefabScene, metadata, streamReader); }); + + streamReader.ForEach("PrefabReferences", [&]() + { + entt::entity entityId = streamReader.ReadKey("entity", (entt::entity)entt::null); + AssetHandle prefabHandle = streamReader.ReadKey("prefabHandle", Asset::Null()); + prefab->m_prefabReferencesMap[entityId] = prefabHandle; + }); } streamReader.ExitScope(); @@ -65,6 +72,18 @@ namespace Volt } streamWriter.EndSequence(); + streamWriter.BeginSequence("PrefabReferences"); + { + for (const auto& ref : prefab->m_prefabReferencesMap) + { + streamWriter.BeginMap(); + streamWriter.SetKey("entity", ref.first); + streamWriter.SetKey("prefabHandle", ref.second); + streamWriter.EndMap(); + } + } + streamWriter.EndSequence(); + streamWriter.EndMap(); streamWriter.EndMap(); diff --git a/Volt/Volt/src/Volt/Asset/Prefab.cpp b/Volt/Volt/src/Volt/Asset/Prefab.cpp index d52b5f435..de3cb39b5 100644 --- a/Volt/Volt/src/Volt/Asset/Prefab.cpp +++ b/Volt/Volt/src/Volt/Asset/Prefab.cpp @@ -38,12 +38,20 @@ namespace Volt InitializeComponents(newEntity); } - // Set scene root entity + // Set scene root entity & update prefab references { std::vector flatInstantiatedHeirarchy = FlattenEntityHeirarchy(newEntity); for (auto& entity : flatInstantiatedHeirarchy) { - entity.GetComponent().sceneRootEntity = newEntity.GetID(); + if (m_prefabReferencesMap.contains(entity.GetComponent().prefabEntity)) + { + Ref prefabRefAsset = AssetManager::GetAsset(entity.GetComponent().prefabAsset); + prefabRefAsset->UpdateEntityInScene(entity); + } + else + { + entity.GetComponent().sceneRootEntity = newEntity.GetID(); + } } } @@ -65,6 +73,18 @@ namespace Volt ValidatePrefabUpdate(srcEntity); } + // Increase prefab version, because we made a change + m_version++; + + // Update all entities prefab versions + { + std::vector flatHeirarchy = FlattenEntityHeirarchy(srcEntity); + for (auto& entity : flatHeirarchy) + { + entity.GetComponent().version = m_version; + } + } + return updateSucceded; } @@ -78,6 +98,12 @@ namespace Volt const auto& scenePrefabComp = sceneEntity.GetComponent(); if (scenePrefabComp.prefabAsset != handle) { + if (m_prefabReferencesMap.contains(scenePrefabComp.prefabEntity)) + { + Ref prefabRefAsset = AssetManager::GetAsset(scenePrefabComp.prefabAsset); + prefabRefAsset->UpdateEntityInScene(sceneEntity); + } + return; } @@ -261,22 +287,29 @@ namespace Volt void Prefab::AddEntityToPrefabRecursive(Entity srcEntity, Entity parentPrefabEntity) { entt::entity newEntityId = srcEntity.GetID(); + auto newEntity = m_prefabScene->CreateEntity("", newEntityId); + // If this entity already has a prefab component, it probably is another prefab. Add it as a reference if (srcEntity.HasComponent()) { - newEntityId = srcEntity.GetComponent().prefabEntity; + const auto& prefabComp = srcEntity.GetComponent(); + if (prefabComp.prefabAsset != handle) + { + m_prefabReferencesMap[newEntity.GetID()] = prefabComp.prefabAsset; + } } else { srcEntity.AddComponent(); } - auto newEntity = m_prefabScene->CreateEntity("", newEntityId); - auto& srcPrefabComp = srcEntity.GetComponent(); - srcPrefabComp.prefabAsset = handle; - srcPrefabComp.prefabEntity = newEntity.GetID(); - srcPrefabComp.version = m_version; + if (!m_prefabReferencesMap.contains(newEntity.GetID())) + { + srcPrefabComp.prefabAsset = handle; + srcPrefabComp.prefabEntity = newEntity.GetID(); + srcPrefabComp.version = m_version; + } Entity::Copy(srcEntity, newEntity, true); @@ -328,13 +361,41 @@ namespace Volt for (const auto& id : entitiesToRemove) { + auto entity = Entity{ id, m_prefabScene }; + const auto& prefabComp = entity.GetComponent(); + + // It's a prefab reference, remove if it's the root + if (prefabComp.prefabAsset != handle) + { + Ref prefabAssetRef = AssetManager::GetAsset(prefabComp.prefabAsset); + if (prefabAssetRef && prefabAssetRef->IsValid()) + { + if (prefabAssetRef->IsEntityRoot(entity)) + { + if (m_prefabReferencesMap.contains(id)) + { + m_prefabReferencesMap.erase(id); + } + } + } + } + m_prefabScene->RemoveEntity(Entity{ id, m_prefabScene }); } } const bool Prefab::UpdateEntityInPrefabInternal(Entity srcEntity, entt::entity sceneRootId) { - if (!srcEntity.HasComponent()) + bool shouldAddEntity = !srcEntity.HasComponent(); + if (!shouldAddEntity) + { + if (srcEntity.GetComponent().prefabAsset != handle) + { + shouldAddEntity = true; + } + } + + if (shouldAddEntity) { Entity prefabParent = Entity::Null(); @@ -347,10 +408,6 @@ namespace Volt } auto& srcPrefabComp = srcEntity.GetComponent(); - if (srcPrefabComp.prefabAsset != handle) - { - return false; - } if (srcPrefabComp.sceneRootEntity != sceneRootId) { diff --git a/Volt/Volt/src/Volt/Asset/Prefab.h b/Volt/Volt/src/Volt/Asset/Prefab.h index 57e170a6d..3ecf0745f 100644 --- a/Volt/Volt/src/Volt/Asset/Prefab.h +++ b/Volt/Volt/src/Volt/Asset/Prefab.h @@ -43,6 +43,7 @@ namespace Volt const std::vector FlattenEntityHeirarchy(Entity entity); Ref m_prefabScene; + std::unordered_map m_prefabReferencesMap; entt::entity m_rootEntityId = entt::null; uint32_t m_version = 0; diff --git a/Volt/Volt/src/Volt/Utility/FileIO/YAMLStreamWriter.h b/Volt/Volt/src/Volt/Utility/FileIO/YAMLStreamWriter.h index 5c36afca7..e674262ac 100644 --- a/Volt/Volt/src/Volt/Utility/FileIO/YAMLStreamWriter.h +++ b/Volt/Volt/src/Volt/Utility/FileIO/YAMLStreamWriter.h @@ -21,8 +21,10 @@ namespace Volt void BeginMapNamned(const std::string& mapName); - template - void SetKey(const std::string& key, const T& value); + template + void SetKey(const K& key, const T& value); + + const bool WriteToDisk(); @@ -31,8 +33,8 @@ namespace Volt YAML::Emitter m_emitter; }; - template - inline void YAMLStreamWriter::SetKey(const std::string& key, const T& value) + template + inline void YAMLStreamWriter::SetKey(const K& key, const T& value) { m_emitter << YAML::Key << key << YAML::Value << value; }