From 8aeed3e17f92ece71c3647113c3d92bbb2e083cf Mon Sep 17 00:00:00 2001 From: Megumumpkin Date: Wed, 17 Aug 2022 16:13:13 +0700 Subject: [PATCH] Add ComponentLibrary and Component Interfaces (#511) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add ComponentLibrary and Component Interfaces * Component Interface removal * ComponentLibrary Fat Trimming * ComponentLibrary Fixes * ComponentLibrary Fixes * Add versioning in ComponentLibrary * ComponentLibrary fixes * Tidying up ComponentLibrary * removed version arrays because they were unused; changed componentVersion check to libraryVersion >= componentVersion; and some refactors * we also tell how many component managers were serialized * Make Serializing Dynamic I've added a function in wiArchive for retrieving the DATA array directly. Used to serialize dynamically the archive by choosing to read datablock or not. Integer hash from string will be used to determine the existence of the component on the engine's scene or not. * Make Serialization Dynamic * archive can jump over unregistered component data; component versioning; refactors; * component version will be jumped over too Co-authored-by: Turánszki János --- WickedEngine/ArchiveVersionHistory.txt | 1 + WickedEngine/wiArchive.cpp | 2 +- WickedEngine/wiArchive.h | 25 + WickedEngine/wiECS.h | 185 ++- WickedEngine/wiScene.cpp | 128 +- WickedEngine/wiScene.h | 58 +- WickedEngine/wiScene_Serializers.cpp | 1479 +++++++++++++----------- WickedEngine/wiVersion.cpp | 2 +- 8 files changed, 1035 insertions(+), 845 deletions(-) diff --git a/WickedEngine/ArchiveVersionHistory.txt b/WickedEngine/ArchiveVersionHistory.txt index 2fa2df4b9..49059e020 100644 --- a/WickedEngine/ArchiveVersionHistory.txt +++ b/WickedEngine/ArchiveVersionHistory.txt @@ -1,5 +1,6 @@ This file contains changelog of wi::Archive versions +84: component library serialization 83: physical light units 82: serialized LightComponent::fov_inner 81: serialized LightComponent::forced_shadow_resolution diff --git a/WickedEngine/wiArchive.cpp b/WickedEngine/wiArchive.cpp index 850233550..951257a12 100644 --- a/WickedEngine/wiArchive.cpp +++ b/WickedEngine/wiArchive.cpp @@ -5,7 +5,7 @@ namespace wi { // this should always be only INCREMENTED and only if a new serialization is implemeted somewhere! - static constexpr uint64_t __archiveVersion = 83; + static constexpr uint64_t __archiveVersion = 84; // this is the version number of which below the archive is not compatible with the current version static constexpr uint64_t __archiveVersionBarrier = 22; diff --git a/WickedEngine/wiArchive.h b/WickedEngine/wiArchive.h index 099ea8e95..ab472cae5 100644 --- a/WickedEngine/wiArchive.h +++ b/WickedEngine/wiArchive.h @@ -64,6 +64,31 @@ namespace wi // The file's name will include the directory as well const std::string& GetSourceFileName() const; + // Appends the current archive write offset as uint64_t to the archive + // Returns the previous write offset of the archive, which can be used by PatchUnknownJumpPosition() + // to write the current archive position to that previous position + size_t WriteUnknownJumpPosition() + { + size_t pos_prev = pos; + _write(uint64_t(pos)); + return pos_prev; + } + // Writes the current archive write offset to the specified archive write offset. + // It can be used with Jump() to skip parts of the archive when reading + void PatchUnknownJumpPosition(size_t offset) + { + assert(!readMode); + assert(!DATA.empty()); + assert(offset + sizeof(uint64_t) < DATA.size()); + *(uint64_t*)(DATA.data() + offset) = uint64_t(pos); + } + // Modifies the current archive offset + // It can be used in conjunction with WriteUnknownJumpPosition() and PatchUnknownJumpPosition() + void Jump(uint64_t jump_pos) + { + pos = jump_pos; + } + // It could be templated but we have to be extremely careful of different datasizes on different platforms // because serialized data should be interchangeable! // So providing exact copy operations for exact types enforces platform agnosticism diff --git a/WickedEngine/wiECS.h b/WickedEngine/wiECS.h index e665026c2..538e7b956 100644 --- a/WickedEngine/wiECS.h +++ b/WickedEngine/wiECS.h @@ -2,6 +2,7 @@ #define WI_ENTITY_COMPONENT_SYSTEM_H #include "wiArchive.h" +#include "wiHelper.h" #include "wiJobSystem.h" #include "wiUnorderedMap.h" #include "wiVector.h" @@ -9,6 +10,8 @@ #include #include #include +#include +#include // Entity-Component System namespace wi::ecs @@ -31,11 +34,19 @@ namespace wi::ecs wi::jobsystem::context ctx; // allow components to spawn serialization subtasks wi::unordered_map remap; bool allow_remap = true; + uint64_t version = 0; // The ComponentLibrary serialization will modify this by the registered component's version number ~EntitySerializer() { wi::jobsystem::Wait(ctx); // automatically wait for all subtasks after serialization } + + // Returns the library version of the currently serializing Component + // If not using ComponentLibrary, it returns version set by the user. + uint64_t GetVersion() const + { + return version; + } }; // This is the safe way to serialize an entity inline void SerializeEntity(wi::Archive& archive, Entity& entity, EntitySerializer& seri) @@ -70,9 +81,29 @@ namespace wi::ecs } } + // This is an interface class to implement a ComponentManager, + // inherit this class if you want to work with ComponentLibrary + class ComponentManager_Interface + { + public: + virtual void Copy(const ComponentManager_Interface& other) = 0; + virtual void Merge(ComponentManager_Interface& other) = 0; + virtual void Clear() = 0; + virtual void Serialize(wi::Archive& archive, EntitySerializer& seri) = 0; + virtual void Component_Serialize(Entity entity, wi::Archive& archive, EntitySerializer& seri) = 0; + virtual void Remove(Entity entity) = 0; + virtual void Remove_KeepSorted(Entity entity) = 0; + virtual void MoveItem(size_t index_from, size_t index_to) = 0; + virtual bool Contains(Entity entity) const = 0; + virtual size_t GetIndex(Entity entity) const = 0; + virtual size_t GetCount() const = 0; + virtual Entity GetEntity(size_t index) const = 0; + virtual const wi::vector& GetEntityArray() const = 0; + }; + // The ComponentManager is a container that stores components and matches them with entities template - class ComponentManager + class ComponentManager : public ComponentManager_Interface { public: @@ -122,6 +153,16 @@ namespace wi::ecs other.Clear(); } + inline void Copy(const ComponentManager_Interface& other) + { + Copy((ComponentManager&)other); + } + + inline void Merge(ComponentManager_Interface& other) + { + Merge((ComponentManager&)other); + } + // Read/Write everything to an archive depending on the archive state inline void Serialize(wi::Archive& archive, EntitySerializer& seri) { @@ -161,6 +202,34 @@ namespace wi::ecs } } + //Read one single component onto an archive, make sure entity are serialized first + inline void Component_Serialize(Entity entity, wi::Archive& archive, EntitySerializer& seri) + { + if(archive.IsReadMode()) + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = this->Create(entity); + component.Serialize(archive, seri); + } + } + else + { + auto component = this->GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + } + // Create a new component and retrieve a reference to it inline Component& Create(Entity entity) { @@ -346,6 +415,120 @@ namespace wi::ecs // Disallow this to be copied by mistake ComponentManager(const ComponentManager&) = delete; }; + + // This is the class to store all component managers, + // this is useful for bulk operation of all attached components within an entity + class ComponentLibrary + { + public: + struct LibraryEntry + { + std::unique_ptr component_manager; + uint64_t version = 0; + }; + wi::unordered_map entries; + + // Create an instance of ComponentManager of a certain data type + // The name must be unique, it will be used in serialization + // version is optional, it will be propagated to ComponentManager::Serialize() inside the EntitySerializer parameter + template + inline ComponentManager& Register(std::string name, uint64_t version = 0) + { + entries[name].component_manager = std::make_unique>(); + entries[name].version = version; + return static_cast&>(*entries[name].component_manager); + } + + // Serialize all registered component managers + inline void Serialize(wi::Archive& archive, EntitySerializer& seri) + { + if(archive.IsReadMode()) + { + bool has_next = false; + do + { + archive >> has_next; + if(has_next) + { + std::string name; + archive >> name; + uint64_t jump_size = 0; + archive >> jump_size; + auto it = entries.find(name); + if(it != entries.end()) + { + archive >> seri.version; + it->second.component_manager->Serialize(archive, seri); + } + else + { + // component manager of this name was not registered, skip serialization by jumping over the data + archive.Jump(jump_size); + } + } + } + while(has_next); + } + else + { + for(auto& it : entries) + { + archive << true; + archive << it.first; // name + size_t offset = archive.WriteUnknownJumpPosition(); // we will be able to jump from here... + archive << it.second.version; + it.second.component_manager->Serialize(archive, seri); + archive.PatchUnknownJumpPosition(offset); // ...to here, if this component manager was not registered + } + archive << false; + } + } + + // Serialize all components for one entity + inline void Entity_Serialize(Entity entity, wi::Archive& archive, EntitySerializer& seri) + { + if(archive.IsReadMode()) + { + bool has_next = false; + do + { + archive >> has_next; + if(has_next) + { + std::string name; + archive >> name; + uint64_t jump_size = 0; + archive >> jump_size; + auto it = entries.find(name); + if (it != entries.end()) + { + archive >> seri.version; + it->second.component_manager->Component_Serialize(entity, archive, seri); + } + else + { + // component manager of this name was not registered, skip serialization by jumping over the data + archive.Jump(jump_size); + } + } + } + while(has_next); + } + else + { + for(auto& it : entries) + { + archive << true; + archive << it.first; // name + size_t offset = archive.WriteUnknownJumpPosition(); // we will be able to jump from here... + archive << it.second.version; + it.second.component_manager->Component_Serialize(entity, archive, seri); + archive.PatchUnknownJumpPosition(offset); // ...to here, if this component manager was not registered + } + archive << false; + } + } + }; } #endif // WI_ENTITY_COMPONENT_SYSTEM_H diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index d834d604c..7d8f1aa21 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -2025,34 +2025,10 @@ namespace wi::scene } void Scene::Clear() { - names.Clear(); - layers.Clear(); - transforms.Clear(); - hierarchy.Clear(); - materials.Clear(); - meshes.Clear(); - impostors.Clear(); - objects.Clear(); - aabb_objects.Clear(); - rigidbodies.Clear(); - softbodies.Clear(); - armatures.Clear(); - lights.Clear(); - aabb_lights.Clear(); - cameras.Clear(); - probes.Clear(); - aabb_probes.Clear(); - forces.Clear(); - decals.Clear(); - aabb_decals.Clear(); - animations.Clear(); - animation_datas.Clear(); - emitters.Clear(); - hairs.Clear(); - weathers.Clear(); - sounds.Clear(); - inverse_kinematics.Clear(); - springs.Clear(); + for(auto& entry : componentLibrary.entries) + { + entry.second.component_manager->Clear(); + } TLAS = RaytracingAccelerationStructure(); BVH.Clear(); @@ -2069,67 +2045,19 @@ namespace wi::scene } void Scene::Merge(Scene& other) { - names.Merge(other.names); - layers.Merge(other.layers); - transforms.Merge(other.transforms); - hierarchy.Merge(other.hierarchy); - materials.Merge(other.materials); - meshes.Merge(other.meshes); - impostors.Merge(other.impostors); - objects.Merge(other.objects); - aabb_objects.Merge(other.aabb_objects); - rigidbodies.Merge(other.rigidbodies); - softbodies.Merge(other.softbodies); - armatures.Merge(other.armatures); - lights.Merge(other.lights); - aabb_lights.Merge(other.aabb_lights); - cameras.Merge(other.cameras); - probes.Merge(other.probes); - aabb_probes.Merge(other.aabb_probes); - forces.Merge(other.forces); - decals.Merge(other.decals); - aabb_decals.Merge(other.aabb_decals); - animations.Merge(other.animations); - animation_datas.Merge(other.animation_datas); - emitters.Merge(other.emitters); - hairs.Merge(other.hairs); - weathers.Merge(other.weathers); - sounds.Merge(other.sounds); - inverse_kinematics.Merge(other.inverse_kinematics); - springs.Merge(other.springs); + for (auto& entry : componentLibrary.entries) + { + entry.second.component_manager->Merge(*other.componentLibrary.entries[entry.first].component_manager); + } bounds = AABB::Merge(bounds, other.bounds); } void Scene::FindAllEntities(wi::unordered_set& entities) const { - entities.insert(names.GetEntityArray().begin(), names.GetEntityArray().end()); - entities.insert(layers.GetEntityArray().begin(), layers.GetEntityArray().end()); - entities.insert(transforms.GetEntityArray().begin(), transforms.GetEntityArray().end()); - entities.insert(hierarchy.GetEntityArray().begin(), hierarchy.GetEntityArray().end()); - entities.insert(materials.GetEntityArray().begin(), materials.GetEntityArray().end()); - entities.insert(meshes.GetEntityArray().begin(), meshes.GetEntityArray().end()); - entities.insert(impostors.GetEntityArray().begin(), impostors.GetEntityArray().end()); - entities.insert(objects.GetEntityArray().begin(), objects.GetEntityArray().end()); - entities.insert(aabb_objects.GetEntityArray().begin(), aabb_objects.GetEntityArray().end()); - entities.insert(rigidbodies.GetEntityArray().begin(), rigidbodies.GetEntityArray().end()); - entities.insert(softbodies.GetEntityArray().begin(), softbodies.GetEntityArray().end()); - entities.insert(armatures.GetEntityArray().begin(), armatures.GetEntityArray().end()); - entities.insert(lights.GetEntityArray().begin(), lights.GetEntityArray().end()); - entities.insert(aabb_lights.GetEntityArray().begin(), aabb_lights.GetEntityArray().end()); - entities.insert(cameras.GetEntityArray().begin(), cameras.GetEntityArray().end()); - entities.insert(probes.GetEntityArray().begin(), probes.GetEntityArray().end()); - entities.insert(aabb_probes.GetEntityArray().begin(), aabb_probes.GetEntityArray().end()); - entities.insert(forces.GetEntityArray().begin(), forces.GetEntityArray().end()); - entities.insert(decals.GetEntityArray().begin(), decals.GetEntityArray().end()); - entities.insert(aabb_decals.GetEntityArray().begin(), aabb_decals.GetEntityArray().end()); - entities.insert(animations.GetEntityArray().begin(), animations.GetEntityArray().end()); - entities.insert(animation_datas.GetEntityArray().begin(), animation_datas.GetEntityArray().end()); - entities.insert(emitters.GetEntityArray().begin(), emitters.GetEntityArray().end()); - entities.insert(hairs.GetEntityArray().begin(), hairs.GetEntityArray().end()); - entities.insert(weathers.GetEntityArray().begin(), weathers.GetEntityArray().end()); - entities.insert(sounds.GetEntityArray().begin(), sounds.GetEntityArray().end()); - entities.insert(inverse_kinematics.GetEntityArray().begin(), inverse_kinematics.GetEntityArray().end()); - entities.insert(springs.GetEntityArray().begin(), springs.GetEntityArray().end()); + for (auto& entry : componentLibrary.entries) + { + entities.insert(entry.second.component_manager->GetEntityArray().begin(), entry.second.component_manager->GetEntityArray().end()); + } } void Scene::Entity_Remove(Entity entity, bool recursive) @@ -2152,34 +2080,10 @@ namespace wi::scene } } - names.Remove(entity); - layers.Remove(entity); - transforms.Remove(entity); - hierarchy.Remove(entity); - materials.Remove(entity); - meshes.Remove(entity); - impostors.Remove(entity); - objects.Remove(entity); - aabb_objects.Remove(entity); - rigidbodies.Remove(entity); - softbodies.Remove(entity); - armatures.Remove(entity); - lights.Remove(entity); - aabb_lights.Remove(entity); - cameras.Remove(entity); - probes.Remove(entity); - aabb_probes.Remove(entity); - forces.Remove(entity); - decals.Remove(entity); - aabb_decals.Remove(entity); - animations.Remove(entity); - animation_datas.Remove(entity); - emitters.Remove(entity); - hairs.Remove(entity); - weathers.Remove(entity); - sounds.Remove(entity); - inverse_kinematics.Remove(entity); - springs.Remove(entity); + for (auto& entry : componentLibrary.entries) + { + entry.second.component_manager->Remove(entity); + } } Entity Scene::Entity_FindByName(const std::string& name) { diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index d061df195..8848c4e50 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -1308,34 +1308,36 @@ namespace wi::scene struct Scene { - wi::ecs::ComponentManager names; - wi::ecs::ComponentManager layers; - wi::ecs::ComponentManager transforms; - wi::ecs::ComponentManager hierarchy; - wi::ecs::ComponentManager materials; - wi::ecs::ComponentManager meshes; - wi::ecs::ComponentManager impostors; - wi::ecs::ComponentManager objects; - wi::ecs::ComponentManager aabb_objects; - wi::ecs::ComponentManager rigidbodies; - wi::ecs::ComponentManager softbodies; - wi::ecs::ComponentManager armatures; - wi::ecs::ComponentManager lights; - wi::ecs::ComponentManager aabb_lights; - wi::ecs::ComponentManager cameras; - wi::ecs::ComponentManager probes; - wi::ecs::ComponentManager aabb_probes; - wi::ecs::ComponentManager forces; - wi::ecs::ComponentManager decals; - wi::ecs::ComponentManager aabb_decals; - wi::ecs::ComponentManager animations; - wi::ecs::ComponentManager animation_datas; - wi::ecs::ComponentManager emitters; - wi::ecs::ComponentManager hairs; - wi::ecs::ComponentManager weathers; - wi::ecs::ComponentManager sounds; - wi::ecs::ComponentManager inverse_kinematics; - wi::ecs::ComponentManager springs; + wi::ecs::ComponentLibrary componentLibrary; + + wi::ecs::ComponentManager& names = componentLibrary.Register("wi::scene::Scene::names"); + wi::ecs::ComponentManager& layers = componentLibrary.Register("wi::scene::Scene::layers"); + wi::ecs::ComponentManager& transforms = componentLibrary.Register("wi::scene::Scene::transforms"); + wi::ecs::ComponentManager& hierarchy = componentLibrary.Register("wi::scene::Scene::hierarchy"); + wi::ecs::ComponentManager& materials = componentLibrary.Register("wi::scene::Scene::materials"); + wi::ecs::ComponentManager& meshes = componentLibrary.Register("wi::scene::Scene::meshes"); + wi::ecs::ComponentManager& impostors = componentLibrary.Register("wi::scene::Scene::impostors"); + wi::ecs::ComponentManager& objects = componentLibrary.Register("wi::scene::Scene::objects"); + wi::ecs::ComponentManager& aabb_objects = componentLibrary.Register("wi::scene::Scene::aabb_objects"); + wi::ecs::ComponentManager& rigidbodies = componentLibrary.Register("wi::scene::Scene::rigidbodies"); + wi::ecs::ComponentManager& softbodies = componentLibrary.Register("wi::scene::Scene::softbodies"); + wi::ecs::ComponentManager& armatures = componentLibrary.Register("wi::scene::Scene::armatures"); + wi::ecs::ComponentManager& lights = componentLibrary.Register("wi::scene::Scene::lights"); + wi::ecs::ComponentManager& aabb_lights = componentLibrary.Register("wi::scene::Scene::aabb_lights"); + wi::ecs::ComponentManager& cameras = componentLibrary.Register("wi::scene::Scene::cameras"); + wi::ecs::ComponentManager& probes = componentLibrary.Register("wi::scene::Scene::probes"); + wi::ecs::ComponentManager& aabb_probes = componentLibrary.Register("wi::scene::Scene::aabb_probes"); + wi::ecs::ComponentManager& forces = componentLibrary.Register("wi::scene::Scene::forces"); + wi::ecs::ComponentManager& decals = componentLibrary.Register("wi::scene::Scene::decals"); + wi::ecs::ComponentManager& aabb_decals = componentLibrary.Register("wi::scene::Scene::aabb_decals"); + wi::ecs::ComponentManager& animations = componentLibrary.Register("wi::scene::Scene::animations"); + wi::ecs::ComponentManager& animation_datas = componentLibrary.Register("wi::scene::Scene::animation_datas"); + wi::ecs::ComponentManager& emitters = componentLibrary.Register("wi::scene::Scene::emitters"); + wi::ecs::ComponentManager& hairs = componentLibrary.Register("wi::scene::Scene::hairs"); + wi::ecs::ComponentManager& weathers = componentLibrary.Register("wi::scene::Scene::weathers"); + wi::ecs::ComponentManager& sounds = componentLibrary.Register("wi::scene::Scene::sounds"); + wi::ecs::ComponentManager& inverse_kinematics = componentLibrary.Register("wi::scene::Scene::inverse_kinematics"); + wi::ecs::ComponentManager& springs = componentLibrary.Register("wi::scene::Scene::springs"); // Non-serialized attributes: float dt = 0; diff --git a/WickedEngine/wiScene_Serializers.cpp b/WickedEngine/wiScene_Serializers.cpp index 495175e5f..2b9a66665 100644 --- a/WickedEngine/wiScene_Serializers.cpp +++ b/WickedEngine/wiScene_Serializers.cpp @@ -1406,69 +1406,78 @@ namespace wi::scene // With this we will ensure that serialized entities are unique and persistent across the scene: EntitySerializer seri; - names.Serialize(archive, seri); - layers.Serialize(archive, seri); - transforms.Serialize(archive, seri); - if (archive.GetVersion() < 75) + if(archive.GetVersion() >= 84) { - ComponentManager prev_transforms; - prev_transforms.Serialize(archive, seri); + // New scene serialization path with component library: + componentLibrary.Serialize(archive, seri); } - hierarchy.Serialize(archive, seri); - materials.Serialize(archive, seri); - meshes.Serialize(archive, seri); - impostors.Serialize(archive, seri); - objects.Serialize(archive, seri); - aabb_objects.Serialize(archive, seri); - rigidbodies.Serialize(archive, seri); - softbodies.Serialize(archive, seri); - armatures.Serialize(archive, seri); - lights.Serialize(archive, seri); - aabb_lights.Serialize(archive, seri); - cameras.Serialize(archive, seri); - probes.Serialize(archive, seri); - aabb_probes.Serialize(archive, seri); - forces.Serialize(archive, seri); - decals.Serialize(archive, seri); - aabb_decals.Serialize(archive, seri); - animations.Serialize(archive, seri); - emitters.Serialize(archive, seri); - hairs.Serialize(archive, seri); - weathers.Serialize(archive, seri); - if (archive.GetVersion() >= 30) + else { - sounds.Serialize(archive, seri); - } - if (archive.GetVersion() >= 37) - { - inverse_kinematics.Serialize(archive, seri); - } - if (archive.GetVersion() >= 38) - { - springs.Serialize(archive, seri); - } - if (archive.GetVersion() >= 46) - { - animation_datas.Serialize(archive, seri); - } - - if (archive.GetVersion() < 46) - { - // Fixing the animation import from archive that didn't have separate animation data components: - for (size_t i = 0; i < animations.GetCount(); ++i) + // Old serialization path with hard coded componentn types: + names.Serialize(archive, seri); + layers.Serialize(archive, seri); + transforms.Serialize(archive, seri); + if (archive.GetVersion() < 75) { - AnimationComponent& animation = animations[i]; - for (const AnimationComponent::AnimationChannel& channel : animation.channels) + ComponentManager prev_transforms; + prev_transforms.Serialize(archive, seri); + } + hierarchy.Serialize(archive, seri); + materials.Serialize(archive, seri); + meshes.Serialize(archive, seri); + impostors.Serialize(archive, seri); + objects.Serialize(archive, seri); + aabb_objects.Serialize(archive, seri); + rigidbodies.Serialize(archive, seri); + softbodies.Serialize(archive, seri); + armatures.Serialize(archive, seri); + lights.Serialize(archive, seri); + aabb_lights.Serialize(archive, seri); + cameras.Serialize(archive, seri); + probes.Serialize(archive, seri); + aabb_probes.Serialize(archive, seri); + forces.Serialize(archive, seri); + decals.Serialize(archive, seri); + aabb_decals.Serialize(archive, seri); + animations.Serialize(archive, seri); + emitters.Serialize(archive, seri); + hairs.Serialize(archive, seri); + weathers.Serialize(archive, seri); + if (archive.GetVersion() >= 30) + { + sounds.Serialize(archive, seri); + } + if (archive.GetVersion() >= 37) + { + inverse_kinematics.Serialize(archive, seri); + } + if (archive.GetVersion() >= 38) + { + springs.Serialize(archive, seri); + } + if (archive.GetVersion() >= 46) + { + animation_datas.Serialize(archive, seri); + } + + if (archive.GetVersion() < 46) + { + // Fixing the animation import from archive that didn't have separate animation data components: + for (size_t i = 0; i < animations.GetCount(); ++i) { - assert(channel.samplerIndex < (int)animation.samplers.size()); - AnimationComponent::AnimationSampler& sampler = animation.samplers[channel.samplerIndex]; - if (sampler.data == INVALID_ENTITY) + AnimationComponent& animation = animations[i]; + for (const AnimationComponent::AnimationChannel& channel : animation.channels) { - // backwards-compatibility mode - sampler.data = CreateEntity(); - animation_datas.Create(sampler.data) = sampler.backwards_compatibility_data; - sampler.backwards_compatibility_data.keyframe_times.clear(); - sampler.backwards_compatibility_data.keyframe_data.clear(); + assert(channel.samplerIndex < (int)animation.samplers.size()); + AnimationComponent::AnimationSampler& sampler = animation.samplers[channel.samplerIndex]; + if (sampler.data == INVALID_ENTITY) + { + // backwards-compatibility mode + sampler.data = CreateEntity(); + animation_datas.Create(sampler.data) = sampler.backwards_compatibility_data; + sampler.backwards_compatibility_data.keyframe_times.clear(); + sampler.backwards_compatibility_data.keyframe_data.clear(); + } } } } @@ -1491,670 +1500,736 @@ namespace wi::scene { seri.allow_remap = false; } - - if (archive.IsReadMode()) + + if (archive.GetVersion() >= 84) { - // Check for each components if it exists, and if yes, READ it: - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = names.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = layers.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = transforms.Create(entity); - component.Serialize(archive, seri); - } - } - if(archive.GetVersion() < 75) - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - ComponentManager prev_transforms; - auto& component = prev_transforms.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = hierarchy.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = materials.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = meshes.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = impostors.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = objects.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = aabb_objects.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = rigidbodies.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = softbodies.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = armatures.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = lights.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = aabb_lights.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = cameras.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = probes.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = aabb_probes.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = forces.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = decals.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = aabb_decals.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = animations.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = emitters.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = hairs.Create(entity); - component.Serialize(archive, seri); - } - } - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = weathers.Create(entity); - component.Serialize(archive, seri); - } - } - if (archive.GetVersion() >= 30) - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = sounds.Create(entity); - component.Serialize(archive, seri); - } - } - if (archive.GetVersion() >= 37) - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = inverse_kinematics.Create(entity); - component.Serialize(archive, seri); - } - } - if (archive.GetVersion() >= 38) - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = springs.Create(entity); - component.Serialize(archive, seri); - } - } - if (archive.GetVersion() >= 46) - { - bool component_exists; - archive >> component_exists; - if (component_exists) - { - auto& component = animation_datas.Create(entity); - component.Serialize(archive, seri); - } - } + // New entity serialization path with component library: + componentLibrary.Entity_Serialize(entity, archive, seri); - // Wait the job system, because from this point, component managers could be resized - // due to more serialization tasks in recursive operation - // The pointers must not be invalidated while serialization jobs are not finished - wi::jobsystem::Wait(seri.ctx); - - if (archive.GetVersion() >= 72 && has_flag(flags, EntitySerializeFlags::RECURSIVE)) + if (archive.IsReadMode()) { - // serialize children: - seri.allow_remap = restore_remap; - size_t childCount = 0; - archive >> childCount; - for (size_t i = 0; i < childCount; ++i) + // Wait the job system, because from this point, component managers could be resized + // due to more serialization tasks in recursive operation + // The pointers must not be invalidated while serialization jobs are not finished + wi::jobsystem::Wait(seri.ctx); + + if (archive.GetVersion() >= 72 && has_flag(flags, EntitySerializeFlags::RECURSIVE)) { - Entity child = Entity_Serialize(archive, seri, INVALID_ENTITY, flags); - if (child != INVALID_ENTITY) + // serialize children: + seri.allow_remap = restore_remap; + size_t childCount = 0; + archive >> childCount; + for (size_t i = 0; i < childCount; ++i) { - HierarchyComponent* hier = hierarchy.GetComponent(child); - if (hier != nullptr) + Entity child = Entity_Serialize(archive, seri, INVALID_ENTITY, flags); + if (child != INVALID_ENTITY) { - hier->parentID = entity; + HierarchyComponent* hier = hierarchy.GetComponent(child); + if (hier != nullptr) + { + hier->parentID = entity; + } } } } } + else + { + // Wait the job system, because from this point, component managers could be resized + // due to more serialization tasks in recursive operation + // The pointers must not be invalidated while serialization jobs are not finished + wi::jobsystem::Wait(seri.ctx); + + if (archive.GetVersion() >= 72 && has_flag(flags, EntitySerializeFlags::RECURSIVE)) + { + // Recursive serialization for all children: + seri.allow_remap = restore_remap; + wi::vector children; + for (size_t i = 0; i < hierarchy.GetCount(); ++i) + { + const HierarchyComponent& hier = hierarchy[i]; + if (hier.parentID == entity) + { + Entity child = hierarchy.GetEntity(i); + children.push_back(child); + } + } + archive << children.size(); + for (Entity child : children) + { + Entity_Serialize(archive, seri, child, flags); + } + } + } + } else { - // Find existing components one-by-one and WRITE them out: + // Old entity serialization path code for hard coded component types: + if (archive.IsReadMode()) { - auto component = names.GetComponent(entity); - if (component != nullptr) + // Check for each components if it exists, and if yes, READ it: { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = layers.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = transforms.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = hierarchy.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = materials.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = meshes.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = impostors.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = objects.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = aabb_objects.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = rigidbodies.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = softbodies.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = armatures.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = lights.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = aabb_lights.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = cameras.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = probes.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = aabb_probes.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = forces.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = decals.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = aabb_decals.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = animations.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = emitters.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = hairs.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - { - auto component = weathers.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - if(archive.GetVersion() >= 30) - { - auto component = sounds.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - if (archive.GetVersion() >= 37) - { - auto component = inverse_kinematics.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - if (archive.GetVersion() >= 38) - { - auto component = springs.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - if (archive.GetVersion() >= 46) - { - auto component = animation_datas.GetComponent(entity); - if (component != nullptr) - { - archive << true; - component->Serialize(archive, seri); - } - else - { - archive << false; - } - } - - // Wait the job system, because from this point, component managers could be resized - // due to more serialization tasks in recursive operation - // The pointers must not be invalidated while serialization jobs are not finished - wi::jobsystem::Wait(seri.ctx); - - if (archive.GetVersion() >= 72 && has_flag(flags, EntitySerializeFlags::RECURSIVE)) - { - // Recursive serialization for all children: - seri.allow_remap = restore_remap; - wi::vector children; - for (size_t i = 0; i < hierarchy.GetCount(); ++i) - { - const HierarchyComponent& hier = hierarchy[i]; - if (hier.parentID == entity) + bool component_exists; + archive >> component_exists; + if (component_exists) { - Entity child = hierarchy.GetEntity(i); - children.push_back(child); + auto& component = names.Create(entity); + component.Serialize(archive, seri); } } - archive << children.size(); - for (Entity child : children) { - Entity_Serialize(archive, seri, child, flags); + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = layers.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = transforms.Create(entity); + component.Serialize(archive, seri); + } + } + if(archive.GetVersion() < 75) + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + ComponentManager prev_transforms; + auto& component = prev_transforms.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = hierarchy.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = materials.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = meshes.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = impostors.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = objects.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = aabb_objects.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = rigidbodies.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = softbodies.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = armatures.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = lights.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = aabb_lights.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = cameras.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = probes.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = aabb_probes.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = forces.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = decals.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = aabb_decals.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = animations.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = emitters.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = hairs.Create(entity); + component.Serialize(archive, seri); + } + } + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = weathers.Create(entity); + component.Serialize(archive, seri); + } + } + if (archive.GetVersion() >= 30) + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = sounds.Create(entity); + component.Serialize(archive, seri); + } + } + if (archive.GetVersion() >= 37) + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = inverse_kinematics.Create(entity); + component.Serialize(archive, seri); + } + } + if (archive.GetVersion() >= 38) + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = springs.Create(entity); + component.Serialize(archive, seri); + } + } + if (archive.GetVersion() >= 46) + { + bool component_exists; + archive >> component_exists; + if (component_exists) + { + auto& component = animation_datas.Create(entity); + component.Serialize(archive, seri); + } + } + + // Wait the job system, because from this point, component managers could be resized + // due to more serialization tasks in recursive operation + // The pointers must not be invalidated while serialization jobs are not finished + wi::jobsystem::Wait(seri.ctx); + + if (archive.GetVersion() >= 72 && has_flag(flags, EntitySerializeFlags::RECURSIVE)) + { + // serialize children: + seri.allow_remap = restore_remap; + size_t childCount = 0; + archive >> childCount; + for (size_t i = 0; i < childCount; ++i) + { + Entity child = Entity_Serialize(archive, seri, INVALID_ENTITY, flags); + if (child != INVALID_ENTITY) + { + HierarchyComponent* hier = hierarchy.GetComponent(child); + if (hier != nullptr) + { + hier->parentID = entity; + } + } + } + } + } + else + { + // Find existing components one-by-one and WRITE them out: + { + auto component = names.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = layers.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = transforms.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = hierarchy.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = materials.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = meshes.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = impostors.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = objects.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = aabb_objects.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = rigidbodies.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = softbodies.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = armatures.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = lights.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = aabb_lights.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = cameras.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = probes.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = aabb_probes.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = forces.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = decals.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = aabb_decals.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = animations.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = emitters.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = hairs.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + { + auto component = weathers.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + if(archive.GetVersion() >= 30) + { + auto component = sounds.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + if (archive.GetVersion() >= 37) + { + auto component = inverse_kinematics.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + if (archive.GetVersion() >= 38) + { + auto component = springs.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + if (archive.GetVersion() >= 46) + { + auto component = animation_datas.GetComponent(entity); + if (component != nullptr) + { + archive << true; + component->Serialize(archive, seri); + } + else + { + archive << false; + } + } + + // Wait the job system, because from this point, component managers could be resized + // due to more serialization tasks in recursive operation + // The pointers must not be invalidated while serialization jobs are not finished + wi::jobsystem::Wait(seri.ctx); + + if (archive.GetVersion() >= 72 && has_flag(flags, EntitySerializeFlags::RECURSIVE)) + { + // Recursive serialization for all children: + seri.allow_remap = restore_remap; + wi::vector children; + for (size_t i = 0; i < hierarchy.GetCount(); ++i) + { + const HierarchyComponent& hier = hierarchy[i]; + if (hier.parentID == entity) + { + Entity child = hierarchy.GetEntity(i); + children.push_back(child); + } + } + archive << children.size(); + for (Entity child : children) + { + Entity_Serialize(archive, seri, child, flags); + } } } } diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index c27a3d207..2c7d485c0 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 12; + const int revision = 13; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);