Files
WickedEngine/WickedEngine/wiScene_Serializers.cpp
T
2024-02-14 09:55:44 +01:00

3108 lines
81 KiB
C++

#include "wiScene.h"
#include "wiResourceManager.h"
#include "wiArchive.h"
#include "wiRandom.h"
#include "wiHelper.h"
#include "wiBacklog.h"
#include "wiTimer.h"
#include "wiVector.h"
#include "shaders/ShaderInterop_DDGI.h"
using namespace wi::ecs;
namespace wi::scene
{
struct DEPRECATED_PreviousFrameTransformComponent
{
void Serialize(wi::Archive& archive, wi::ecs::EntitySerializer& seri) { /*this never serialized any data*/ }
};
void NameComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> name;
}
else
{
archive << name;
}
}
void LayerComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> layerMask;
}
else
{
archive << layerMask;
}
}
void TransformComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> _flags;
archive >> scale_local;
archive >> rotation_local;
archive >> translation_local;
SetDirty();
UpdateTransform();
}
else
{
archive << _flags; // maybe not needed just for dirtiness, but later might come handy if we have more persistent flags
archive << scale_local;
archive << rotation_local;
archive << translation_local;
}
}
void HierarchyComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
SerializeEntity(archive, parentID, seri);
if (archive.IsReadMode())
{
archive >> layerMask_bind;
if (archive.GetVersion() < 36)
{
XMFLOAT4X4 world_parent_inverse_bind;
archive >> world_parent_inverse_bind;
}
}
else
{
archive << layerMask_bind;
}
}
void MaterialComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
const std::string& dir = archive.GetSourceDirectory();
if (archive.IsReadMode())
{
archive >> _flags;
archive >> (uint8_t&)engineStencilRef;
archive >> userStencilRef;
archive >> (uint8_t&)userBlendMode;
archive >> baseColor;
if (archive.GetVersion() >= 25)
{
archive >> emissiveColor;
}
archive >> texMulAdd;
archive >> roughness;
if (archive.GetVersion() < 35)
{
roughness = roughness == 0 ? 0 : std::sqrt(roughness);
}
archive >> reflectance;
archive >> metalness;
if (archive.GetVersion() < 25)
{
archive >> emissiveColor.w;
}
archive >> refraction;
if (archive.GetVersion() < 52)
{
archive >> subsurfaceScattering.w;
}
archive >> normalMapStrength;
archive >> parallaxOcclusionMapping;
archive >> alphaRef;
archive >> texAnimDirection;
archive >> texAnimFrameRate;
archive >> texAnimElapsedTime;
archive >> textures[BASECOLORMAP].name;
archive >> textures[SURFACEMAP].name;
archive >> textures[NORMALMAP].name;
archive >> textures[DISPLACEMENTMAP].name;
if (archive.GetVersion() >= 24)
{
archive >> textures[EMISSIVEMAP].name;
}
if (archive.GetVersion() >= 28)
{
archive >> textures[OCCLUSIONMAP].name;
archive >> textures[BASECOLORMAP].uvset;
archive >> textures[SURFACEMAP].uvset;
archive >> textures[NORMALMAP].uvset;
archive >> textures[DISPLACEMENTMAP].uvset;
archive >> textures[EMISSIVEMAP].uvset;
archive >> textures[OCCLUSIONMAP].uvset;
archive >> displacementMapping;
}
if (archive.GetVersion() >= 48)
{
archive >> (uint8_t&)shadingRate;
}
if (archive.GetVersion() >= 50)
{
archive >> (uint32_t&)shaderType;
archive >> customShaderID;
}
else
{
if (_flags & _DEPRECATED_WATER)
{
shaderType = SHADERTYPE_WATER;
}
if (_flags & _DEPRECATED_PLANAR_REFLECTION)
{
shaderType = SHADERTYPE_PBR_PLANARREFLECTION;
}
if (parallaxOcclusionMapping > 0)
{
shaderType = SHADERTYPE_PBR_PARALLAXOCCLUSIONMAPPING;
}
}
if (archive.GetVersion() >= 52 && archive.GetVersion() < 54)
{
uint32_t subsurfaceProfile;
archive >> subsurfaceProfile;
}
if (archive.GetVersion() >= 54)
{
archive >> subsurfaceScattering;
}
if (archive.GetVersion() >= 56)
{
archive >> specularColor;
}
if (archive.GetVersion() >= 59)
{
archive >> transmission;
archive >> textures[TRANSMISSIONMAP].name;
archive >> textures[TRANSMISSIONMAP].uvset;
}
if (archive.GetVersion() >= 61)
{
archive >> sheenColor;
archive >> sheenRoughness;
archive >> textures[SHEENCOLORMAP].name;
archive >> textures[SHEENROUGHNESSMAP].name;
archive >> textures[SHEENCOLORMAP].uvset;
archive >> textures[SHEENROUGHNESSMAP].uvset;
archive >> clearcoat;
archive >> clearcoatRoughness;
archive >> textures[CLEARCOATMAP].name;
archive >> textures[CLEARCOATROUGHNESSMAP].name;
archive >> textures[CLEARCOATNORMALMAP].name;
archive >> textures[CLEARCOATMAP].uvset;
archive >> textures[CLEARCOATROUGHNESSMAP].uvset;
archive >> textures[CLEARCOATNORMALMAP].uvset;
}
if (archive.GetVersion() >= 68)
{
archive >> textures[SPECULARMAP].name;
archive >> textures[SPECULARMAP].uvset;
}
if (seri.GetVersion() >= 1)
{
archive >> userdata;
}
if (seri.GetVersion() >= 2)
{
archive >> anisotropy_strength;
archive >> anisotropy_rotation;
archive >> textures[ANISOTROPYMAP].name;
archive >> textures[ANISOTROPYMAP].uvset;
}
else
{
anisotropy_strength = parallaxOcclusionMapping; // old version fix
}
if (seri.GetVersion() >= 3)
{
archive >> textures[TRANSPARENCYMAP].name;
archive >> textures[TRANSPARENCYMAP].uvset;
}
for (auto& x : textures)
{
if (!x.name.empty())
{
x.name = dir + x.name;
}
}
wi::jobsystem::Execute(seri.ctx, [&](wi::jobsystem::JobArgs args) {
CreateRenderData();
});
}
else
{
for (auto& x : textures)
{
seri.RegisterResource(x.name);
}
archive << _flags;
archive << (uint8_t)engineStencilRef;
archive << userStencilRef;
archive << (uint8_t)userBlendMode;
archive << baseColor;
if (archive.GetVersion() >= 25)
{
archive << emissiveColor;
}
archive << texMulAdd;
archive << roughness;
archive << reflectance;
archive << metalness;
if (archive.GetVersion() < 25)
{
archive << emissiveColor.w;
}
archive << refraction;
if (archive.GetVersion() < 52)
{
float subsurfaceScattering = 0;
archive << subsurfaceScattering;
}
archive << normalMapStrength;
archive << parallaxOcclusionMapping;
archive << alphaRef;
archive << texAnimDirection;
archive << texAnimFrameRate;
archive << texAnimElapsedTime;
archive << wi::helper::GetPathRelative(dir, textures[BASECOLORMAP].name);
archive << wi::helper::GetPathRelative(dir, textures[SURFACEMAP].name);
archive << wi::helper::GetPathRelative(dir, textures[NORMALMAP].name);
archive << wi::helper::GetPathRelative(dir, textures[DISPLACEMENTMAP].name);
if (archive.GetVersion() >= 24)
{
archive << wi::helper::GetPathRelative(dir, textures[EMISSIVEMAP].name);
}
if (archive.GetVersion() >= 28)
{
archive << wi::helper::GetPathRelative(dir, textures[OCCLUSIONMAP].name);
archive << textures[BASECOLORMAP].uvset;
archive << textures[SURFACEMAP].uvset;
archive << textures[NORMALMAP].uvset;
archive << textures[DISPLACEMENTMAP].uvset;
archive << textures[EMISSIVEMAP].uvset;
archive << textures[OCCLUSIONMAP].uvset;
archive << displacementMapping;
}
if (archive.GetVersion() >= 48)
{
archive << (uint8_t)shadingRate;
}
if (archive.GetVersion() >= 50)
{
archive << (uint32_t)shaderType;
archive << customShaderID;
}
if (archive.GetVersion() >= 54)
{
archive << subsurfaceScattering;
}
if (archive.GetVersion() >= 56)
{
archive << specularColor;
}
if (archive.GetVersion() >= 59)
{
archive << transmission;
archive << wi::helper::GetPathRelative(dir, textures[TRANSMISSIONMAP].name);
archive << textures[TRANSMISSIONMAP].uvset;
}
if (archive.GetVersion() >= 61)
{
archive << sheenColor;
archive << sheenRoughness;
archive << wi::helper::GetPathRelative(dir, textures[SHEENCOLORMAP].name);
archive << wi::helper::GetPathRelative(dir, textures[SHEENROUGHNESSMAP].name);
archive << textures[SHEENCOLORMAP].uvset;
archive << textures[SHEENROUGHNESSMAP].uvset;
archive << clearcoat;
archive << clearcoatRoughness;
archive << wi::helper::GetPathRelative(dir, textures[CLEARCOATMAP].name);
archive << wi::helper::GetPathRelative(dir, textures[CLEARCOATROUGHNESSMAP].name);
archive << wi::helper::GetPathRelative(dir, textures[CLEARCOATNORMALMAP].name);
archive << textures[CLEARCOATMAP].uvset;
archive << textures[CLEARCOATROUGHNESSMAP].uvset;
archive << textures[CLEARCOATNORMALMAP].uvset;
}
if (archive.GetVersion() >= 68)
{
archive << wi::helper::GetPathRelative(dir, textures[SPECULARMAP].name);
archive << textures[SPECULARMAP].uvset;
}
if (seri.GetVersion() >= 1)
{
archive << userdata;
}
if (seri.GetVersion() >= 2)
{
archive << anisotropy_strength;
archive << anisotropy_rotation;
archive << wi::helper::GetPathRelative(dir, textures[ANISOTROPYMAP].name);
archive << textures[ANISOTROPYMAP].uvset;
}
if (seri.GetVersion() >= 2)
{
archive << wi::helper::GetPathRelative(dir, textures[TRANSPARENCYMAP].name);
archive << textures[TRANSPARENCYMAP].uvset;
}
}
}
void MeshComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> _flags;
archive >> vertex_positions;
archive >> vertex_normals;
archive >> vertex_uvset_0;
archive >> vertex_boneindices;
archive >> vertex_boneweights;
archive >> vertex_atlas;
archive >> vertex_colors;
archive >> indices;
size_t subsetCount;
archive >> subsetCount;
subsets.resize(subsetCount);
for (size_t i = 0; i < subsetCount; ++i)
{
SerializeEntity(archive, subsets[i].materialID, seri);
archive >> subsets[i].indexOffset;
archive >> subsets[i].indexCount;
}
archive >> tessellationFactor;
SerializeEntity(archive, armatureID, seri);
if (archive.GetVersion() >= 28)
{
archive >> vertex_uvset_1;
}
if (archive.GetVersion() >= 41 && archive.GetVersion() < 79)
{
// These are no longer used:
Entity terrain_material1;
Entity terrain_material2;
Entity terrain_material3;
SerializeEntity(archive, terrain_material1, seri);
SerializeEntity(archive, terrain_material2, seri);
SerializeEntity(archive, terrain_material3, seri);
}
if (archive.GetVersion() >= 43)
{
archive >> vertex_windweights;
}
if (archive.GetVersion() >= 51)
{
archive >> vertex_tangents;
}
if (archive.GetVersion() >= 53)
{
size_t targetCount;
archive >> targetCount;
morph_targets.resize(targetCount);
for (size_t i = 0; i < targetCount; ++i)
{
archive >> morph_targets[i].vertex_positions;
archive >> morph_targets[i].vertex_normals;
archive >> morph_targets[i].weight;
if (seri.GetVersion() >= 1)
{
archive >> morph_targets[i].sparse_indices_positions;
}
if (seri.GetVersion() >= 2)
{
archive >> morph_targets[i].sparse_indices_normals;
}
}
}
if (archive.GetVersion() >= 76)
{
archive >> subsets_per_lod;
}
wi::jobsystem::Execute(seri.ctx, [&](wi::jobsystem::JobArgs args) {
CreateRenderData();
if (IsBVHEnabled())
{
BuildBVH();
}
});
}
else
{
archive << _flags;
archive << vertex_positions;
archive << vertex_normals;
archive << vertex_uvset_0;
archive << vertex_boneindices;
archive << vertex_boneweights;
archive << vertex_atlas;
archive << vertex_colors;
archive << indices;
archive << subsets.size();
for (size_t i = 0; i < subsets.size(); ++i)
{
SerializeEntity(archive, subsets[i].materialID, seri);
archive << subsets[i].indexOffset;
archive << subsets[i].indexCount;
}
archive << tessellationFactor;
SerializeEntity(archive, armatureID, seri);
if (archive.GetVersion() >= 28)
{
archive << vertex_uvset_1;
}
if (archive.GetVersion() >= 41 && archive.GetVersion() < 79)
{
// These are no longer used:
Entity terrain_material1;
Entity terrain_material2;
Entity terrain_material3;
SerializeEntity(archive, terrain_material1, seri);
SerializeEntity(archive, terrain_material2, seri);
SerializeEntity(archive, terrain_material3, seri);
}
if (archive.GetVersion() >= 43)
{
archive << vertex_windweights;
}
if (archive.GetVersion() >= 51)
{
archive << vertex_tangents;
}
if (archive.GetVersion() >= 53)
{
archive << morph_targets.size();
for (size_t i = 0; i < morph_targets.size(); ++i)
{
archive << morph_targets[i].vertex_positions;
archive << morph_targets[i].vertex_normals;
archive << morph_targets[i].weight;
if (seri.GetVersion() >= 1)
{
archive << morph_targets[i].sparse_indices_positions;
}
if (seri.GetVersion() >= 2)
{
archive << morph_targets[i].sparse_indices_normals;
}
}
}
if (archive.GetVersion() >= 76)
{
archive << subsets_per_lod;
}
}
}
void ImpostorComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> _flags;
archive >> swapInDistance;
SetDirty();
}
else
{
archive << _flags;
archive << swapInDistance;
}
}
void ObjectComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> _flags;
SerializeEntity(archive, meshID, seri);
archive >> cascadeMask;
if (seri.GetVersion() >= 1)
{
archive >> filterMask;
}
else
{
uint32_t tmp;
archive >> tmp;
}
archive >> color;
if (archive.GetVersion() >= 23)
{
archive >> lightmapWidth;
archive >> lightmapHeight;
archive >> lightmapTextureData;
}
if (archive.GetVersion() >= 31)
{
archive >> userStencilRef;
}
if (archive.GetVersion() >= 60)
{
archive >> emissiveColor;
}
if (archive.GetVersion() >= 76)
{
archive >> lod_distance_multiplier;
}
if (archive.GetVersion() >= 80)
{
archive >> draw_distance;
}
if (seri.GetVersion() >= 2)
{
archive >> sort_priority;
}
if (seri.GetVersion() >= 3)
{
archive >> vertex_ao;
}
wi::jobsystem::Execute(seri.ctx, [&](wi::jobsystem::JobArgs args) {
CreateRenderData();
});
}
else
{
archive << _flags;
SerializeEntity(archive, meshID, seri);
archive << cascadeMask;
if (seri.GetVersion() >= 1)
{
archive << filterMask;
}
archive << color;
if (archive.GetVersion() >= 23)
{
archive << lightmapWidth;
archive << lightmapHeight;
archive << lightmapTextureData;
}
if (archive.GetVersion() >= 31)
{
archive << userStencilRef;
}
if (archive.GetVersion() >= 60)
{
archive << emissiveColor;
}
if (archive.GetVersion() >= 76)
{
archive << lod_distance_multiplier;
}
if (archive.GetVersion() >= 80)
{
archive << draw_distance;
}
if (seri.GetVersion() >= 2)
{
archive << sort_priority;
}
if (seri.GetVersion() >= 3)
{
archive << vertex_ao;
}
}
}
void RigidBodyPhysicsComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> _flags;
archive >> (uint32_t&)shape;
archive >> mass;
archive >> friction;
archive >> restitution;
archive >> damping_linear;
if (archive.GetVersion() >= 57)
{
archive >> damping_angular;
}
else
{
// these were previously untested:
friction = 0.5f;
restitution = 0.0f;
damping_linear = 0;
}
if (archive.GetVersion() >= 58)
{
archive >> box.halfextents;
archive >> sphere.radius;
archive >> capsule.height;
archive >> capsule.radius;
}
if (seri.GetVersion() >= 1)
{
archive >> mesh_lod;
}
}
else
{
archive << _flags;
archive << (uint32_t&)shape;
archive << mass;
archive << friction;
archive << restitution;
archive << damping_linear;
if (archive.GetVersion() >= 57)
{
archive << damping_angular;
}
if (archive.GetVersion() >= 58)
{
archive << box.halfextents;
archive << sphere.radius;
archive << capsule.height;
archive << capsule.radius;
}
if (seri.GetVersion() >= 1)
{
archive << mesh_lod;
}
}
}
void SoftBodyPhysicsComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> _flags;
archive >> mass;
archive >> friction;
archive >> physicsToGraphicsVertexMapping;
archive >> graphicsToPhysicsVertexMapping;
archive >> weights;
if (archive.GetVersion() >= 29 && archive.GetVersion() < 34)
{
wi::vector<XMFLOAT3> temp;
archive >> temp;
}
if (archive.GetVersion() >= 57)
{
archive >> restitution;
}
else
{
// these were previously untested:
friction = 0.5f;
}
_flags &= ~SAFE_TO_REGISTER;
}
else
{
archive << _flags;
archive << mass;
archive << friction;
archive << physicsToGraphicsVertexMapping;
archive << graphicsToPhysicsVertexMapping;
archive << weights;
if (archive.GetVersion() >= 57)
{
archive << restitution;
}
}
}
void ArmatureComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> _flags;
size_t boneCount;
archive >> boneCount;
boneCollection.resize(boneCount);
for (size_t i = 0; i < boneCount; ++i)
{
Entity boneID;
SerializeEntity(archive, boneID, seri);
boneCollection[i] = boneID;
}
archive >> inverseBindMatrices;
if (archive.GetVersion() < 26)
{
XMFLOAT4X4 remapMatrix;
archive >> remapMatrix; // no longer used
}
if (archive.GetVersion() == 26)
{
Entity rootBoneID;
SerializeEntity(archive, rootBoneID, seri);
}
}
else
{
archive << _flags;
archive << boneCollection.size();
for (size_t i = 0; i < boneCollection.size(); ++i)
{
Entity boneID = boneCollection[i];
SerializeEntity(archive, boneID, seri);
}
archive << inverseBindMatrices;
if (archive.GetVersion() == 26)
{
Entity rootBoneID;
SerializeEntity(archive, rootBoneID, seri);
}
}
}
void LightComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
const std::string& dir = archive.GetSourceDirectory();
if (archive.IsReadMode())
{
archive >> _flags;
archive >> color;
archive >> (uint32_t&)type;
if (type > SPOT)
{
type = POINT; // fallback from old area light
}
archive >> intensity;
archive >> range;
archive >> outerConeAngle;
if (archive.GetVersion() < 55)
{
float shadowBias;
float radius;
float width;
float height;
archive >> shadowBias;
archive >> radius;
archive >> width;
archive >> height;
}
archive >> lensFlareNames;
if (archive.GetVersion() >= 81)
{
archive >> forced_shadow_resolution;
}
if (archive.GetVersion() >= 82)
{
archive >> innerConeAngle;
}
if (archive.GetVersion() < 83)
{
// Conversion from old light units to physical light units:
if (type != DIRECTIONAL)
{
BackCompatSetEnergy(intensity);
}
// Conversion from FOV to cone angle:
outerConeAngle *= 0.5f;
innerConeAngle *= 0.5f;
}
if (seri.GetVersion() >= 1)
{
archive >> cascade_distances;
}
if (seri.GetVersion() >= 2)
{
archive >> radius;
archive >> length;
}
wi::jobsystem::Execute(seri.ctx, [&](wi::jobsystem::JobArgs args) {
lensFlareRimTextures.resize(lensFlareNames.size());
for (size_t i = 0; i < lensFlareNames.size(); ++i)
{
if (!lensFlareNames[i].empty())
{
lensFlareNames[i] = dir + lensFlareNames[i];
lensFlareRimTextures[i] = wi::resourcemanager::Load(lensFlareNames[i], wi::resourcemanager::Flags::IMPORT_RETAIN_FILEDATA);
}
}
});
}
else
{
for (auto& x : lensFlareNames)
{
seri.RegisterResource(x);
}
archive << _flags;
archive << color;
archive << (uint32_t)type;
archive << intensity;
archive << range;
archive << outerConeAngle;
if (archive.GetVersion() < 55)
{
float shadowBias = 0;
float radius = 0;
float width = 0;
float height = 0;
archive << shadowBias;
archive << radius;
archive << width;
archive << height;
}
// If detecting an absolute path in textures, remove it and convert to relative:
wi::vector<std::string> lensFlareNamesRelative = lensFlareNames;
if (!dir.empty())
{
for (size_t i = 0; i < lensFlareNamesRelative.size(); ++i)
{
wi::helper::MakePathRelative(dir, lensFlareNamesRelative[i]);
}
}
archive << lensFlareNamesRelative;
if (archive.GetVersion() >= 81)
{
archive << forced_shadow_resolution;
}
if (archive.GetVersion() >= 82)
{
archive << innerConeAngle;
}
if (seri.GetVersion() >= 1)
{
archive << cascade_distances;
}
if (seri.GetVersion() >= 2)
{
archive << radius;
archive << length;
}
}
}
void CameraComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> _flags;
archive >> width;
archive >> height;
archive >> zNearP;
archive >> zFarP;
archive >> fov;
if (archive.GetVersion() >= 65)
{
archive >> focal_length;
archive >> aperture_size;
archive >> aperture_shape;
}
SetDirty();
}
else
{
archive << _flags;
archive << width;
archive << height;
archive << zNearP;
archive << zFarP;
archive << fov;
if (archive.GetVersion() >= 65)
{
archive << focal_length;
archive << aperture_size;
archive << aperture_shape;
}
}
}
void EnvironmentProbeComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
const std::string& dir = archive.GetSourceDirectory();
if (archive.IsReadMode())
{
archive >> _flags;
SetDirty();
if (seri.GetVersion() >= 1)
{
archive >> resolution;
archive >> textureName;
if (!textureName.empty())
{
textureName = dir + textureName;
CreateRenderData();
}
}
}
else
{
seri.RegisterResource(textureName);
archive << _flags;
if (seri.GetVersion() >= 1)
{
archive << resolution;
archive << wi::helper::GetPathRelative(dir, textureName);
}
}
}
void ForceFieldComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> _flags;
uint32_t value;
archive >> value;
if (seri.GetVersion() < 1)
{
if (value == 200)
value = 0;
if (value == 201)
value = 1;
}
type = (Type)value;
archive >> gravity;
archive >> range;
}
else
{
archive << _flags;
archive << (uint32_t)type;
archive << gravity;
archive << range;
}
}
void DecalComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> _flags;
if (seri.GetVersion() >= 1)
{
archive >> slopeBlendPower;
}
}
else
{
archive << _flags;
if (seri.GetVersion() >= 1)
{
archive << slopeBlendPower;
}
}
}
void AnimationComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> _flags;
archive >> start;
archive >> end;
archive >> timer;
if (archive.GetVersion() >= 44)
{
archive >> amount;
}
if (archive.GetVersion() >= 47)
{
archive >> speed;
}
size_t channelCount;
archive >> channelCount;
channels.resize(channelCount);
for (size_t i = 0; i < channelCount; ++i)
{
archive >> channels[i]._flags;
archive >> (uint32_t&)channels[i].path;
SerializeEntity(archive, channels[i].target, seri);
archive >> channels[i].samplerIndex;
if (seri.GetVersion() >= 1)
{
archive >> channels[i].retargetIndex;
}
}
size_t samplerCount;
archive >> samplerCount;
samplers.resize(samplerCount);
for (size_t i = 0; i < samplerCount; ++i)
{
archive >> samplers[i]._flags;
archive >> (uint32_t&)samplers[i].mode;
if (archive.GetVersion() < 46)
{
archive >> samplers[i].backwards_compatibility_data.keyframe_times;
archive >> samplers[i].backwards_compatibility_data.keyframe_data;
}
if (archive.GetVersion() >= 46)
{
SerializeEntity(archive, samplers[i].data, seri);
}
}
if (seri.GetVersion() >= 1)
{
size_t retargetCount;
archive >> retargetCount;
retargets.resize(retargetCount);
for (size_t i = 0; i < retargetCount; ++i)
{
SerializeEntity(archive, retargets[i].source, seri);
archive >> retargets[i].dstRelativeMatrix;
archive >> retargets[i].srcRelativeParentMatrix;
}
}
}
else
{
archive << _flags;
archive << start;
archive << end;
archive << timer;
if (archive.GetVersion() >= 44)
{
archive << amount;
}
if (archive.GetVersion() >= 47)
{
archive << speed;
}
archive << channels.size();
for (size_t i = 0; i < channels.size(); ++i)
{
archive << channels[i]._flags;
archive << (uint32_t&)channels[i].path;
SerializeEntity(archive, channels[i].target, seri);
archive << channels[i].samplerIndex;
if (seri.GetVersion() >= 1)
{
archive << channels[i].retargetIndex;
}
}
archive << samplers.size();
for (size_t i = 0; i < samplers.size(); ++i)
{
archive << samplers[i]._flags;
archive << samplers[i].mode;
SerializeEntity(archive, samplers[i].data, seri);
}
if (seri.GetVersion() >= 1)
{
archive << retargets.size();
for (size_t i = 0; i < retargets.size(); ++i)
{
SerializeEntity(archive, retargets[i].source, seri);
archive << retargets[i].dstRelativeMatrix;
archive << retargets[i].srcRelativeParentMatrix;
}
}
}
if (seri.GetVersion() >= 2)
{
// Root Bone Name
SerializeEntity(archive, rootMotionBone, seri);
}
}
void AnimationDataComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> _flags;
archive >> keyframe_times;
archive >> keyframe_data;
}
else
{
archive << _flags;
archive << keyframe_times;
archive << keyframe_data;
}
}
void WeatherComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
std::string dir = archive.GetSourceDirectory();
if (archive.IsReadMode())
{
archive >> _flags;
archive >> sunDirection;
archive >> sunColor;
archive >> horizon;
archive >> zenith;
archive >> ambient;
archive >> fogStart;
archive >> fogDensity;
if (seri.GetVersion() < 3)
{
fogDensity = (1.0f / fogDensity);
}
if (archive.GetVersion() < 86)
{
float fogHeightSky;
float cloudiness;
float cloudScale;
float cloudSpeed;
archive >> fogHeightSky;
archive >> cloudiness;
archive >> cloudScale;
archive >> cloudSpeed;
}
archive >> windDirection;
archive >> windRandomness;
archive >> windWaveSize;
archive >> oceanParameters.dmap_dim;
archive >> oceanParameters.patch_length;
archive >> oceanParameters.time_scale;
archive >> oceanParameters.wave_amplitude;
archive >> oceanParameters.wind_dir;
archive >> oceanParameters.wind_speed;
archive >> oceanParameters.wind_dependency;
archive >> oceanParameters.choppy_scale;
if (archive.GetVersion() < 67)
{
XMFLOAT3 waterColor;
archive >> waterColor;
oceanParameters.waterColor.x = waterColor.x;
oceanParameters.waterColor.y = waterColor.y;
oceanParameters.waterColor.z = waterColor.z;
}
else
{
archive >> oceanParameters.waterColor;
}
archive >> oceanParameters.waterHeight;
archive >> oceanParameters.surfaceDetail;
archive >> oceanParameters.surfaceDisplacementTolerance;
if (archive.GetVersion() >= 32)
{
archive >> skyMapName;
if (!skyMapName.empty())
{
skyMapName = dir + skyMapName;
skyMap = wi::resourcemanager::Load(skyMapName, wi::resourcemanager::Flags::IMPORT_RETAIN_FILEDATA);
}
}
if (archive.GetVersion() >= 40)
{
archive >> windSpeed;
}
if (archive.GetVersion() >= 62)
{
archive >> colorGradingMapName;
if (!colorGradingMapName.empty())
{
colorGradingMapName = dir + colorGradingMapName;
colorGradingMap = wi::resourcemanager::Load(colorGradingMapName, wi::resourcemanager::Flags::IMPORT_COLORGRADINGLUT | wi::resourcemanager::Flags::IMPORT_RETAIN_FILEDATA);
}
}
if (archive.GetVersion() >= 66)
{
archive >> skyExposure;
archive >> atmosphereParameters.bottomRadius;
archive >> atmosphereParameters.topRadius;
archive >> atmosphereParameters.planetCenter;
archive >> atmosphereParameters.rayleighDensityExpScale;
archive >> atmosphereParameters.rayleighScattering;
archive >> atmosphereParameters.mieDensityExpScale;
archive >> atmosphereParameters.mieScattering;
archive >> atmosphereParameters.mieExtinction;
archive >> atmosphereParameters.mieAbsorption;
archive >> atmosphereParameters.absorptionDensity0LayerWidth;
archive >> atmosphereParameters.absorptionDensity0ConstantTerm;
archive >> atmosphereParameters.absorptionDensity0LinearTerm;
archive >> atmosphereParameters.absorptionDensity1ConstantTerm;
archive >> atmosphereParameters.absorptionDensity1LinearTerm;
archive >> atmosphereParameters.absorptionExtinction;
archive >> atmosphereParameters.groundAlbedo;
}
if (archive.GetVersion() >= 70)
{
archive >> volumetricCloudParameters.layerFirst.albedo;
archive >> volumetricCloudParameters.ambientGroundMultiplier;
archive >> volumetricCloudParameters.layerFirst.extinctionCoefficient;
archive >> volumetricCloudParameters.beerPowder;
archive >> volumetricCloudParameters.beerPowderPower;
archive >> volumetricCloudParameters.phaseG;
archive >> volumetricCloudParameters.phaseG2;
archive >> volumetricCloudParameters.phaseBlend;
archive >> volumetricCloudParameters.multiScatteringScattering;
archive >> volumetricCloudParameters.multiScatteringExtinction;
archive >> volumetricCloudParameters.multiScatteringEccentricity;
archive >> volumetricCloudParameters.shadowStepLength;
archive >> volumetricCloudParameters.horizonBlendAmount;
archive >> volumetricCloudParameters.horizonBlendPower;
archive >> volumetricCloudParameters.layerFirst.rainAmount;
archive >> volumetricCloudParameters.cloudStartHeight;
archive >> volumetricCloudParameters.cloudThickness;
archive >> volumetricCloudParameters.layerFirst.skewAlongWindDirection;
archive >> volumetricCloudParameters.layerFirst.totalNoiseScale;
archive >> volumetricCloudParameters.layerFirst.detailScale;
archive >> volumetricCloudParameters.layerFirst.weatherScale;
archive >> volumetricCloudParameters.layerFirst.curlScale;
if (archive.GetVersion() < 86)
{
float ShapeNoiseHeightGradientAmount;
float ShapeNoiseMultiplier;
XMFLOAT2 ShapeNoiseMinMax;
float ShapeNoisePower;
archive >> ShapeNoiseHeightGradientAmount;
archive >> ShapeNoiseMultiplier;
archive >> ShapeNoiseMinMax;
archive >> ShapeNoisePower;
}
archive >> volumetricCloudParameters.layerFirst.detailNoiseModifier;
archive >> volumetricCloudParameters.layerFirst.detailNoiseHeightFraction;
archive >> volumetricCloudParameters.layerFirst.curlNoiseModifier;
archive >> volumetricCloudParameters.layerFirst.coverageAmount;
archive >> volumetricCloudParameters.layerFirst.coverageMinimum;
archive >> volumetricCloudParameters.layerFirst.typeAmount;
archive >> volumetricCloudParameters.layerFirst.typeMinimum;
if (archive.GetVersion() < 88)
{
float AnvilAmount;
float AnvilOverhangHeight;
archive >> AnvilAmount;
archive >> AnvilOverhangHeight;
}
archive >> volumetricCloudParameters.animationMultiplier;
archive >> volumetricCloudParameters.layerFirst.windSpeed;
archive >> volumetricCloudParameters.layerFirst.windAngle;
archive >> volumetricCloudParameters.layerFirst.windUpAmount;
archive >> volumetricCloudParameters.layerFirst.coverageWindSpeed;
archive >> volumetricCloudParameters.layerFirst.coverageWindAngle;
archive >> volumetricCloudParameters.layerFirst.gradientSmall;
archive >> volumetricCloudParameters.layerFirst.gradientMedium;
archive >> volumetricCloudParameters.layerFirst.gradientLarge;
archive >> volumetricCloudParameters.maxStepCount;
archive >> volumetricCloudParameters.maxMarchingDistance;
archive >> volumetricCloudParameters.inverseDistanceStepCount;
archive >> volumetricCloudParameters.renderDistance;
archive >> volumetricCloudParameters.LODDistance;
archive >> volumetricCloudParameters.LODMin;
archive >> volumetricCloudParameters.bigStepMarch;
archive >> volumetricCloudParameters.transmittanceThreshold;
archive >> volumetricCloudParameters.shadowSampleCount;
archive >> volumetricCloudParameters.groundContributionSampleCount;
if (archive.GetVersion() < 86)
{
volumetricCloudParameters.horizonBlendAmount *= 0.00001f;
volumetricCloudParameters.layerFirst.totalNoiseScale *= 0.0004f;
volumetricCloudParameters.layerFirst.weatherScale *= 0.0004f;
volumetricCloudParameters.layerFirst.coverageAmount /= 2.0f;
volumetricCloudParameters.layerFirst.coverageMinimum = std::max(0.0f, volumetricCloudParameters.layerFirst.coverageMinimum - 1.0f);
}
}
if (archive.GetVersion() >= 71)
{
archive >> fogHeightStart;
archive >> fogHeightEnd;
}
if (archive.GetVersion() >= 77 && archive.GetVersion() < 86)
{
float cloud_shadow_amount;
float cloud_shadow_scale;
float cloud_shadow_speed;
archive >> cloud_shadow_amount;
archive >> cloud_shadow_scale;
archive >> cloud_shadow_speed;
}
if (archive.GetVersion() >= 78)
{
archive >> stars;
}
if (archive.GetVersion() >= 86)
{
archive >> volumetricCloudsWeatherMapFirstName;
if (!volumetricCloudsWeatherMapFirstName.empty())
{
volumetricCloudsWeatherMapFirstName = dir + volumetricCloudsWeatherMapFirstName;
volumetricCloudsWeatherMapFirst = wi::resourcemanager::Load(volumetricCloudsWeatherMapFirstName, wi::resourcemanager::Flags::IMPORT_RETAIN_FILEDATA);
}
}
if (archive.GetVersion() >= 88)
{
archive >> volumetricCloudsWeatherMapSecondName;
if (!volumetricCloudsWeatherMapSecondName.empty())
{
volumetricCloudsWeatherMapSecondName = dir + volumetricCloudsWeatherMapSecondName;
volumetricCloudsWeatherMapSecond = wi::resourcemanager::Load(volumetricCloudsWeatherMapSecondName, wi::resourcemanager::Flags::IMPORT_RETAIN_FILEDATA);
}
archive >> volumetricCloudParameters.layerFirst.curlNoiseHeightFraction;
archive >> volumetricCloudParameters.layerFirst.skewAlongCoverageWindDirection;
archive >> volumetricCloudParameters.layerFirst.rainMinimum;
archive >> volumetricCloudParameters.layerFirst.anvilDeformationSmall;
archive >> volumetricCloudParameters.layerFirst.anvilDeformationMedium;
archive >> volumetricCloudParameters.layerFirst.anvilDeformationLarge;
archive >> volumetricCloudParameters.layerSecond.albedo;
archive >> volumetricCloudParameters.layerSecond.extinctionCoefficient;
archive >> volumetricCloudParameters.layerSecond.skewAlongWindDirection;
archive >> volumetricCloudParameters.layerSecond.totalNoiseScale;
archive >> volumetricCloudParameters.layerSecond.curlScale;
archive >> volumetricCloudParameters.layerSecond.curlNoiseHeightFraction;
archive >> volumetricCloudParameters.layerSecond.curlNoiseModifier;
archive >> volumetricCloudParameters.layerSecond.detailScale;
archive >> volumetricCloudParameters.layerSecond.detailNoiseHeightFraction;
archive >> volumetricCloudParameters.layerSecond.detailNoiseModifier;
archive >> volumetricCloudParameters.layerSecond.skewAlongCoverageWindDirection;
archive >> volumetricCloudParameters.layerSecond.weatherScale;
archive >> volumetricCloudParameters.layerSecond.coverageAmount;
archive >> volumetricCloudParameters.layerSecond.coverageMinimum;
archive >> volumetricCloudParameters.layerSecond.typeAmount;
archive >> volumetricCloudParameters.layerSecond.typeMinimum;
archive >> volumetricCloudParameters.layerSecond.rainAmount;
archive >> volumetricCloudParameters.layerSecond.rainMinimum;
archive >> volumetricCloudParameters.layerSecond.gradientSmall;
archive >> volumetricCloudParameters.layerSecond.gradientMedium;
archive >> volumetricCloudParameters.layerSecond.gradientLarge;
archive >> volumetricCloudParameters.layerSecond.anvilDeformationSmall;
archive >> volumetricCloudParameters.layerSecond.anvilDeformationMedium;
archive >> volumetricCloudParameters.layerSecond.anvilDeformationLarge;
archive >> volumetricCloudParameters.layerSecond.windSpeed;
archive >> volumetricCloudParameters.layerSecond.windAngle;
archive >> volumetricCloudParameters.layerSecond.windUpAmount;
archive >> volumetricCloudParameters.layerSecond.coverageWindSpeed;
archive >> volumetricCloudParameters.layerSecond.coverageWindAngle;
}
if (seri.GetVersion() >= 1)
{
archive >> gravity;
}
if (seri.GetVersion() >= 2)
{
archive >> atmosphereParameters.rayMarchMinMaxSPP;
archive >> atmosphereParameters.distanceSPPMaxInv;
archive >> atmosphereParameters.aerialPerspectiveScale;
}
if (seri.GetVersion() >= 4)
{
archive >> sky_rotation;
}
if (seri.GetVersion() >= 5)
{
archive >> rain_amount;
archive >> rain_length;
archive >> rain_speed;
archive >> rain_scale;
archive >> rain_splash_scale;
archive >> rain_color;
}
}
else
{
seri.RegisterResource(skyMapName);
seri.RegisterResource(colorGradingMapName);
seri.RegisterResource(volumetricCloudsWeatherMapFirstName);
seri.RegisterResource(volumetricCloudsWeatherMapSecondName);
archive << _flags;
archive << sunDirection;
archive << sunColor;
archive << horizon;
archive << zenith;
archive << ambient;
archive << fogStart;
archive << fogDensity;
archive << windDirection;
archive << windRandomness;
archive << windWaveSize;
archive << oceanParameters.dmap_dim;
archive << oceanParameters.patch_length;
archive << oceanParameters.time_scale;
archive << oceanParameters.wave_amplitude;
archive << oceanParameters.wind_dir;
archive << oceanParameters.wind_speed;
archive << oceanParameters.wind_dependency;
archive << oceanParameters.choppy_scale;
archive << oceanParameters.waterColor;
archive << oceanParameters.waterHeight;
archive << oceanParameters.surfaceDetail;
archive << oceanParameters.surfaceDisplacementTolerance;
if (archive.GetVersion() >= 32)
{
archive << wi::helper::GetPathRelative(dir, skyMapName);
}
if (archive.GetVersion() >= 40)
{
archive << windSpeed;
}
if (archive.GetVersion() >= 62)
{
archive << wi::helper::GetPathRelative(dir, colorGradingMapName);
}
if (archive.GetVersion() >= 66)
{
archive << skyExposure;
archive << atmosphereParameters.bottomRadius;
archive << atmosphereParameters.topRadius;
archive << atmosphereParameters.planetCenter;
archive << atmosphereParameters.rayleighDensityExpScale;
archive << atmosphereParameters.rayleighScattering;
archive << atmosphereParameters.mieDensityExpScale;
archive << atmosphereParameters.mieScattering;
archive << atmosphereParameters.mieExtinction;
archive << atmosphereParameters.mieAbsorption;
archive << atmosphereParameters.absorptionDensity0LayerWidth;
archive << atmosphereParameters.absorptionDensity0ConstantTerm;
archive << atmosphereParameters.absorptionDensity0LinearTerm;
archive << atmosphereParameters.absorptionDensity1ConstantTerm;
archive << atmosphereParameters.absorptionDensity1LinearTerm;
archive << atmosphereParameters.absorptionExtinction;
archive << atmosphereParameters.groundAlbedo;
}
if (archive.GetVersion() >= 70)
{
archive << volumetricCloudParameters.layerFirst.albedo;
archive << volumetricCloudParameters.ambientGroundMultiplier;
archive << volumetricCloudParameters.layerFirst.extinctionCoefficient;
archive << volumetricCloudParameters.beerPowder;
archive << volumetricCloudParameters.beerPowderPower;
archive << volumetricCloudParameters.phaseG;
archive << volumetricCloudParameters.phaseG2;
archive << volumetricCloudParameters.phaseBlend;
archive << volumetricCloudParameters.multiScatteringScattering;
archive << volumetricCloudParameters.multiScatteringExtinction;
archive << volumetricCloudParameters.multiScatteringEccentricity;
archive << volumetricCloudParameters.shadowStepLength;
archive << volumetricCloudParameters.horizonBlendAmount;
archive << volumetricCloudParameters.horizonBlendPower;
archive << volumetricCloudParameters.layerFirst.rainAmount;
archive << volumetricCloudParameters.cloudStartHeight;
archive << volumetricCloudParameters.cloudThickness;
archive << volumetricCloudParameters.layerFirst.skewAlongWindDirection;
archive << volumetricCloudParameters.layerFirst.totalNoiseScale;
archive << volumetricCloudParameters.layerFirst.detailScale;
archive << volumetricCloudParameters.layerFirst.weatherScale;
archive << volumetricCloudParameters.layerFirst.curlScale;
if (archive.GetVersion() < 86)
{
float ShapeNoiseHeightGradientAmount = 0.0f;
float ShapeNoiseMultiplier = 0.0f;
XMFLOAT2 ShapeNoiseMinMax = XMFLOAT2(0.0f, 0.0f);
float ShapeNoisePower = 0.0f;
archive << ShapeNoiseHeightGradientAmount;
archive << ShapeNoiseMultiplier;
archive << ShapeNoiseMinMax;
archive << ShapeNoisePower;
}
archive << volumetricCloudParameters.layerFirst.detailNoiseModifier;
archive << volumetricCloudParameters.layerFirst.detailNoiseHeightFraction;
archive << volumetricCloudParameters.layerFirst.curlNoiseModifier;
archive << volumetricCloudParameters.layerFirst.coverageAmount;
archive << volumetricCloudParameters.layerFirst.coverageMinimum;
archive << volumetricCloudParameters.layerFirst.typeAmount;
archive << volumetricCloudParameters.layerFirst.typeMinimum;
if (archive.GetVersion() < 88)
{
float AnvilAmount = 0.0f;
float AnvilOverhangHeight = 0.0f;
archive << AnvilAmount;
archive << AnvilOverhangHeight;
}
archive << volumetricCloudParameters.animationMultiplier;
archive << volumetricCloudParameters.layerFirst.windSpeed;
archive << volumetricCloudParameters.layerFirst.windAngle;
archive << volumetricCloudParameters.layerFirst.windUpAmount;
archive << volumetricCloudParameters.layerFirst.coverageWindSpeed;
archive << volumetricCloudParameters.layerFirst.coverageWindAngle;
archive << volumetricCloudParameters.layerFirst.gradientSmall;
archive << volumetricCloudParameters.layerFirst.gradientMedium;
archive << volumetricCloudParameters.layerFirst.gradientLarge;
archive << volumetricCloudParameters.maxStepCount;
archive << volumetricCloudParameters.maxMarchingDistance;
archive << volumetricCloudParameters.inverseDistanceStepCount;
archive << volumetricCloudParameters.renderDistance;
archive << volumetricCloudParameters.LODDistance;
archive << volumetricCloudParameters.LODMin;
archive << volumetricCloudParameters.bigStepMarch;
archive << volumetricCloudParameters.transmittanceThreshold;
archive << volumetricCloudParameters.shadowSampleCount;
archive << volumetricCloudParameters.groundContributionSampleCount;
}
if (archive.GetVersion() >= 71)
{
archive << fogHeightStart;
archive << fogHeightEnd;
}
if (archive.GetVersion() >= 78)
{
archive << stars;
}
if (archive.GetVersion() >= 86)
{
archive << wi::helper::GetPathRelative(dir, volumetricCloudsWeatherMapFirstName);
}
if (archive.GetVersion() >= 88)
{
archive << wi::helper::GetPathRelative(dir, volumetricCloudsWeatherMapSecondName);
archive << volumetricCloudParameters.layerFirst.curlNoiseHeightFraction;
archive << volumetricCloudParameters.layerFirst.skewAlongCoverageWindDirection;
archive << volumetricCloudParameters.layerFirst.rainMinimum;
archive << volumetricCloudParameters.layerFirst.anvilDeformationSmall;
archive << volumetricCloudParameters.layerFirst.anvilDeformationMedium;
archive << volumetricCloudParameters.layerFirst.anvilDeformationLarge;
archive << volumetricCloudParameters.layerSecond.albedo;
archive << volumetricCloudParameters.layerSecond.extinctionCoefficient;
archive << volumetricCloudParameters.layerSecond.skewAlongWindDirection;
archive << volumetricCloudParameters.layerSecond.totalNoiseScale;
archive << volumetricCloudParameters.layerSecond.curlScale;
archive << volumetricCloudParameters.layerSecond.curlNoiseHeightFraction;
archive << volumetricCloudParameters.layerSecond.curlNoiseModifier;
archive << volumetricCloudParameters.layerSecond.detailScale;
archive << volumetricCloudParameters.layerSecond.detailNoiseHeightFraction;
archive << volumetricCloudParameters.layerSecond.detailNoiseModifier;
archive << volumetricCloudParameters.layerSecond.skewAlongCoverageWindDirection;
archive << volumetricCloudParameters.layerSecond.weatherScale;
archive << volumetricCloudParameters.layerSecond.coverageAmount;
archive << volumetricCloudParameters.layerSecond.coverageMinimum;
archive << volumetricCloudParameters.layerSecond.typeAmount;
archive << volumetricCloudParameters.layerSecond.typeMinimum;
archive << volumetricCloudParameters.layerSecond.rainAmount;
archive << volumetricCloudParameters.layerSecond.rainMinimum;
archive << volumetricCloudParameters.layerSecond.gradientSmall;
archive << volumetricCloudParameters.layerSecond.gradientMedium;
archive << volumetricCloudParameters.layerSecond.gradientLarge;
archive << volumetricCloudParameters.layerSecond.anvilDeformationSmall;
archive << volumetricCloudParameters.layerSecond.anvilDeformationMedium;
archive << volumetricCloudParameters.layerSecond.anvilDeformationLarge;
archive << volumetricCloudParameters.layerSecond.windSpeed;
archive << volumetricCloudParameters.layerSecond.windAngle;
archive << volumetricCloudParameters.layerSecond.windUpAmount;
archive << volumetricCloudParameters.layerSecond.coverageWindSpeed;
archive << volumetricCloudParameters.layerSecond.coverageWindAngle;
}
if (seri.GetVersion() >= 1)
{
archive << gravity;
}
if (seri.GetVersion() >= 2)
{
archive << atmosphereParameters.rayMarchMinMaxSPP;
archive << atmosphereParameters.distanceSPPMaxInv;
archive << atmosphereParameters.aerialPerspectiveScale;
}
if (seri.GetVersion() >= 4)
{
archive << sky_rotation;
}
if (seri.GetVersion() >= 5)
{
archive << rain_amount;
archive << rain_length;
archive << rain_speed;
archive << rain_scale;
archive << rain_splash_scale;
archive << rain_color;
}
}
}
void SoundComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
const std::string& dir = archive.GetSourceDirectory();
if (archive.IsReadMode())
{
archive >> _flags;
archive >> filename;
archive >> volume;
archive >> (uint32_t&)soundinstance.type;
if (seri.GetVersion() >= 1)
{
archive >> soundinstance.begin;
archive >> soundinstance.length;
archive >> soundinstance.loop_begin;
archive >> soundinstance.loop_length;
}
wi::jobsystem::Execute(seri.ctx, [&](wi::jobsystem::JobArgs args) {
if (!filename.empty())
{
filename = dir + filename;
soundResource = wi::resourcemanager::Load(filename, wi::resourcemanager::Flags::IMPORT_RETAIN_FILEDATA);
soundinstance.SetLooped(IsLooped());
wi::audio::CreateSoundInstance(&soundResource.GetSound(), &soundinstance);
}
});
}
else
{
seri.RegisterResource(filename);
archive << _flags;
archive << wi::helper::GetPathRelative(dir, filename);
archive << volume;
archive << soundinstance.type;
if (seri.GetVersion() >= 1)
{
archive << soundinstance.begin;
archive << soundinstance.length;
archive << soundinstance.loop_begin;
archive << soundinstance.loop_length;
}
}
}
void VideoComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
const std::string& dir = archive.GetSourceDirectory();
if (archive.IsReadMode())
{
archive >> _flags;
archive >> filename;
wi::jobsystem::Execute(seri.ctx, [&](wi::jobsystem::JobArgs args) {
if (!filename.empty())
{
filename = dir + filename;
videoResource = wi::resourcemanager::Load(filename, wi::resourcemanager::Flags::IMPORT_RETAIN_FILEDATA);
wi::video::CreateVideoInstance(&videoResource.GetVideo(), &videoinstance);
}
});
}
else
{
seri.RegisterResource(filename);
archive << _flags;
archive << wi::helper::GetPathRelative(dir, filename);
}
}
void InverseKinematicsComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
SerializeEntity(archive, target, seri);
if (archive.IsReadMode())
{
archive >> _flags;
archive >> chain_length;
archive >> iteration_count;
}
else
{
archive << _flags;
archive << chain_length;
archive << iteration_count;
}
}
void SpringComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> _flags;
archive >> stiffnessForce;
archive >> dragForce;
archive >> windForce;
if (seri.GetVersion() >= 1)
{
archive >> hitRadius;
archive >> gravityPower;
archive >> gravityDir;
}
Reset();
}
else
{
archive << _flags;
archive << stiffnessForce;
archive << dragForce;
archive << windForce;
if (seri.GetVersion() >= 1)
{
archive << hitRadius;
archive << gravityPower;
archive << gravityDir;
}
}
}
void ColliderComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> _flags;
int ishape = 0;
archive >> ishape;
shape = (Shape)ishape;
if (seri.GetVersion() < 1)
{
Entity transformID;
SerializeEntity(archive, transformID, seri);
}
archive >> radius;
archive >> offset;
archive >> tail;
if (seri.GetVersion() < 2)
{
SetCPUEnabled(true);
SetGPUEnabled(true);
}
}
else
{
archive << _flags;
archive << (int)shape;
archive << radius;
archive << offset;
archive << tail;
}
}
void ScriptComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
const std::string& dir = archive.GetSourceDirectory();
if (archive.IsReadMode())
{
archive >> _flags;
archive >> filename;
if (IsPlayingOnlyOnce())
{
Play();
}
wi::jobsystem::Execute(seri.ctx, [&](wi::jobsystem::JobArgs args) {
CreateFromFile(dir + filename);
});
}
else
{
seri.RegisterResource(filename);
archive << _flags;
archive << wi::helper::GetPathRelative(dir, filename);
}
}
void ExpressionComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> _flags;
for (int& index : presets)
{
archive >> index;
}
archive >> blink_frequency;
archive >> blink_length;
archive >> blink_count;
archive >> look_frequency;
archive >> look_length;
size_t expression_count = 0;
archive >> expression_count;
expressions.resize(expression_count);
for (size_t expression_index = 0; expression_index < expression_count; ++expression_index)
{
Expression& expression = expressions[expression_index];
archive >> expression.name;
if (expression.preset == ExpressionComponent::Preset::Count && expression.name.compare("Surprised") == 0)
{
// Vroid was not exporting Suprised expression properly and it was not handled at import for some models:
expression.preset = ExpressionComponent::Preset::Surprised;
presets[size_t(ExpressionComponent::Preset::Surprised)] = int(expression_index);
}
archive >> expression.weight;
uint32_t value = 0;
archive >> value;
expression.preset = (Preset)value;
archive >> value;
expression.override_mouth = (Override)value;
archive >> value;
expression.override_blink = (Override)value;
archive >> value;
expression.override_look = (Override)value;
size_t count = 0;
archive >> count;
expression.morph_target_bindings.resize(count);
for (size_t i = 0; i < count; ++i)
{
SerializeEntity(archive, expression.morph_target_bindings[i].meshID, seri);
archive >> expression.morph_target_bindings[i].index;
archive >> expression.morph_target_bindings[i].weight;
}
expression.SetDirty();
}
}
else
{
archive << _flags;
for (int index : presets)
{
archive << index;
}
archive << blink_frequency;
archive << blink_length;
archive << blink_count;
archive << look_frequency;
archive << look_length;
archive << expressions.size();
for (size_t expression_index = 0; expression_index < expressions.size(); ++expression_index)
{
Expression& expression = expressions[expression_index];
archive << expression.name;
archive << expression.weight;
archive << (uint32_t)expression.preset;
archive << (uint32_t)expression.override_mouth;
archive << (uint32_t)expression.override_blink;
archive << (uint32_t)expression.override_look;
archive << expression.morph_target_bindings.size();
for (size_t i = 0; i < expression.morph_target_bindings.size(); ++i)
{
SerializeEntity(archive, expression.morph_target_bindings[i].meshID, seri);
archive << expression.morph_target_bindings[i].index;
archive << expression.morph_target_bindings[i].weight;
}
}
}
}
void HumanoidComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
{
if (archive.IsReadMode())
{
archive >> _flags;
archive >> default_look_direction;
archive >> head_rotation_max;
archive >> head_rotation_speed;
archive >> eye_rotation_max;
archive >> eye_rotation_speed;
for (auto& entity : bones)
{
SerializeEntity(archive, entity, seri);
}
}
else
{
archive << _flags;
archive << default_look_direction;
archive << head_rotation_max;
archive << head_rotation_speed;
archive << eye_rotation_max;
archive << eye_rotation_speed;
for (auto& entity : bones)
{
SerializeEntity(archive, entity, seri);
}
}
}
void Scene::Serialize(wi::Archive& archive)
{
wi::Timer timer;
if (archive.IsReadMode())
{
uint32_t reserved;
archive >> reserved;
}
else
{
uint32_t reserved = 0;
archive << reserved;
}
// Manage jump position to jump to resource serialization WRITE area:
size_t jump_before = 0;
size_t jump_after = 0;
size_t original_pos = 0;
if (archive.GetVersion() >= 90)
{
if (archive.IsReadMode())
{
archive >> jump_before;
archive >> jump_after;
original_pos = archive.GetPos();
archive.Jump(jump_before); // jump before resourcemanager::Serialize_WRITE
}
else
{
jump_before = archive.WriteUnknownJumpPosition();
jump_after = archive.WriteUnknownJumpPosition();
}
}
// Keeping this alive to keep serialized resources alive until entity serialization ends:
wi::resourcemanager::ResourceSerializer resource_seri;
if (archive.IsReadMode() && archive.GetVersion() >= 63)
{
wi::resourcemanager::Serialize_READ(archive, resource_seri);
if (archive.GetVersion() >= 90)
{
// After resource serialization, jump back to entity serialization area:
archive.Jump(original_pos);
}
}
// With this we will ensure that serialized entities are unique and persistent across the scene:
EntitySerializer seri;
if(archive.GetVersion() >= 84)
{
// New scene serialization path with component library:
componentLibrary.Serialize(archive, seri);
}
else
{
// Old serialization path with hard coded component types:
names.Serialize(archive, seri);
layers.Serialize(archive, seri);
transforms.Serialize(archive, seri);
if (archive.GetVersion() < 75)
{
ComponentManager<DEPRECATED_PreviousFrameTransformComponent> 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);
ComponentManager<wi::primitive::AABB> aabbs_tmp; // no longer needed from serializer
aabbs_tmp.Serialize(archive, seri);
rigidbodies.Serialize(archive, seri);
softbodies.Serialize(archive, seri);
armatures.Serialize(archive, seri);
lights.Serialize(archive, seri);
aabbs_tmp.Serialize(archive, seri);
cameras.Serialize(archive, seri);
probes.Serialize(archive, seri);
aabbs_tmp.Serialize(archive, seri);
forces.Serialize(archive, seri);
decals.Serialize(archive, seri);
aabbs_tmp.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)
{
AnimationComponent& animation = animations[i];
for (const AnimationComponent::AnimationChannel& channel : animation.channels)
{
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();
}
}
}
}
}
// Additional data serializations:
if (archive.GetVersion() >= 85)
{
ddgi.Serialize(archive);
}
wi::jobsystem::Wait(seri.ctx); // This is needed before emitter material fixup that is below, because material CreateRenderDatas might be pending!
// Fixup old emittedparticle distortion basecolor slot -> normalmap slot
if (archive.GetVersion() < 89)
{
for (size_t i = 0; i < emitters.GetCount(); ++i)
{
if (emitters[i].shaderType != EmittedParticleSystem::PARTICLESHADERTYPE::SOFT_DISTORTION)
continue;
Entity entity = emitters.GetEntity(i);
MaterialComponent* material = materials.GetComponent(entity);
if (material != nullptr)
{
material->textures[NORMALMAP] = std::move(material->textures[BASECOLORMAP]);
material->CreateRenderData(true);
}
}
}
if (archive.GetVersion() >= 90)
{
if (archive.IsReadMode())
{
archive.Jump(jump_after); // jump after resourcemanager::Serialize_WRITE
}
else
{
archive.PatchUnknownJumpPosition(jump_before);
wi::resourcemanager::Serialize_WRITE(archive, seri.resource_registration);
archive.PatchUnknownJumpPosition(jump_after);
}
}
wi::backlog::post("Scene serialize took " + std::to_string(timer.elapsed_seconds()) + " sec");
}
void Scene::DDGI::Serialize(wi::Archive& archive)
{
using namespace wi::graphics;
GraphicsDevice* device = GetDevice();
if (archive.IsReadMode())
{
archive >> frame_index;
archive >> grid_dimensions;
if (archive.GetVersion() >= 87)
{
archive >> grid_min;
archive >> grid_max;
archive >> smooth_backface;
}
wi::vector<uint8_t> data;
// color texture:
archive >> data;
if(!data.empty())
{
TextureDesc desc;
desc.width = DDGI_COLOR_TEXELS * grid_dimensions.x * grid_dimensions.y;
desc.height = DDGI_COLOR_TEXELS * grid_dimensions.z;
if (data.size() == desc.width * desc.height * GetFormatStride(Format::R9G9B9E5_SHAREDEXP))
{
desc.format = Format::R9G9B9E5_SHAREDEXP;
}
else
{
assert(data.size() == desc.width * desc.height * GetFormatStride(Format::R16G16B16A16_FLOAT));
desc.format = Format::R16G16B16A16_FLOAT;
}
desc.bind_flags = BindFlag::SHADER_RESOURCE;
SubresourceData initdata;
initdata.data_ptr = data.data();
initdata.row_pitch = desc.width * GetFormatStride(desc.format);
device->CreateTexture(&desc, &initdata, &color_texture[0]);
device->SetName(&color_texture[0], "ddgi.color_texture[serialized]");
}
// depth texture:
archive >> data;
if(!data.empty())
{
TextureDesc desc;
desc.width = DDGI_DEPTH_TEXELS * grid_dimensions.x * grid_dimensions.y;
desc.height = DDGI_DEPTH_TEXELS * grid_dimensions.z;
desc.format = Format::R16G16_FLOAT;
desc.bind_flags = BindFlag::UNORDERED_ACCESS | BindFlag::SHADER_RESOURCE;
SubresourceData initdata;
initdata.data_ptr = data.data();
initdata.row_pitch = desc.width * GetFormatStride(desc.format);
device->CreateTexture(&desc, &initdata, &depth_texture[0]);
device->SetName(&depth_texture[0], "ddgi.depth_texture[seriaized]");
}
// offset buffer:
archive >> data;
if(!data.empty())
{
GPUBufferDesc desc;
desc.stride = sizeof(DDGIProbeOffset);
desc.size = desc.stride * grid_dimensions.x * grid_dimensions.y * grid_dimensions.z;
desc.bind_flags = BindFlag::UNORDERED_ACCESS | BindFlag::SHADER_RESOURCE;
desc.misc_flags = ResourceMiscFlag::BUFFER_RAW;
device->CreateBuffer(&desc, data.data(), &offset_buffer);
device->SetName(&offset_buffer, "ddgi.offset_buffer[serialized]");
}
}
else
{
archive << frame_index;
archive << grid_dimensions;
if (archive.GetVersion() >= 87)
{
archive << grid_min;
archive << grid_max;
archive << smooth_backface;
}
wi::vector<uint8_t> data;
if (color_texture[0].IsValid())
{
bool success = wi::helper::saveTextureToMemory(color_texture[0], data);
assert(success);
}
archive << data;
data.clear();
if (depth_texture[0].IsValid())
{
bool success = wi::helper::saveTextureToMemory(depth_texture[0], data);
assert(success);
}
archive << data;
// Download and serialize offset buffer:
if(offset_buffer.IsValid())
{
GPUBufferDesc desc = offset_buffer.desc;
desc.usage = wi::graphics::Usage::READBACK;
desc.bind_flags = {};
desc.misc_flags = {};
GPUBuffer staging;
bool success = device->CreateBuffer(&desc, nullptr, &staging);
assert(success);
CommandList cmd = device->BeginCommandList();
{
GPUBarrier barriers[] = {
GPUBarrier::Buffer(&offset_buffer,ResourceState::SHADER_RESOURCE,ResourceState::COPY_SRC),
};
device->Barrier(barriers, arraysize(barriers), cmd);
}
device->CopyResource(&staging, &offset_buffer, cmd);
{
GPUBarrier barriers[] = {
GPUBarrier::Buffer(&offset_buffer,ResourceState::COPY_SRC,ResourceState::SHADER_RESOURCE),
};
device->Barrier(barriers, arraysize(barriers), cmd);
}
device->SubmitCommandLists();
device->WaitForGPU();
// serialize like vector<uint8_t>:
archive << staging.mapped_size;
for (size_t i = 0; i < staging.mapped_size; ++i)
{
archive << ((uint8_t*)staging.mapped_data)[i];
}
}
else
{
archive << size_t(0);
}
}
}
Entity Entity_Serialize_Internal(
Scene& scene,
wi::Archive& archive,
EntitySerializer& seri,
Entity entity,
Scene::EntitySerializeFlags flags
)
{
SerializeEntity(archive, entity, seri);
bool restore_remap = seri.allow_remap;
if (has_flag(flags, Scene::EntitySerializeFlags::KEEP_INTERNAL_ENTITY_REFERENCES))
{
seri.allow_remap = false;
}
if (archive.GetVersion() >= 84)
{
// New entity serialization path with component library:
scene.componentLibrary.Entity_Serialize(entity, archive, seri);
if (archive.IsReadMode())
{
// 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, Scene::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_Internal(scene, archive, seri, INVALID_ENTITY, flags);
if (child != INVALID_ENTITY)
{
HierarchyComponent* hier = scene.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, Scene::EntitySerializeFlags::RECURSIVE))
{
// Recursive serialization for all children:
seri.allow_remap = restore_remap;
wi::vector<Entity> children;
for (size_t i = 0; i < scene.hierarchy.GetCount(); ++i)
{
const HierarchyComponent& hier = scene.hierarchy[i];
if (hier.parentID == entity)
{
Entity child = scene.hierarchy.GetEntity(i);
children.push_back(child);
}
}
archive << children.size();
for (Entity child : children)
{
Entity_Serialize_Internal(scene, archive, seri, child, flags);
}
}
}
}
else
{
// Old entity serialization path code for hard coded component types:
if (archive.IsReadMode())
{
// Check for each components if it exists, and if yes, READ it:
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.names.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.layers.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.transforms.Create(entity);
component.Serialize(archive, seri);
}
}
if(archive.GetVersion() < 75)
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
ComponentManager<DEPRECATED_PreviousFrameTransformComponent> prev_transforms;
auto& component = prev_transforms.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.hierarchy.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.materials.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.meshes.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.impostors.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.objects.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto component = wi::primitive::AABB(); // no longer needed to be serialized
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.rigidbodies.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.softbodies.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.armatures.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.lights.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto component = wi::primitive::AABB(); // no longer needed to be serialized
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.cameras.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.probes.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto component = wi::primitive::AABB(); // no longer needed to be serialized
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.forces.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.decals.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto component = wi::primitive::AABB(); // no longer needed to be serialized
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.animations.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.emitters.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.hairs.Create(entity);
component.Serialize(archive, seri);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.weathers.Create(entity);
component.Serialize(archive, seri);
}
}
if (archive.GetVersion() >= 30)
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.sounds.Create(entity);
component.Serialize(archive, seri);
}
}
if (archive.GetVersion() >= 37)
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.inverse_kinematics.Create(entity);
component.Serialize(archive, seri);
}
}
if (archive.GetVersion() >= 38)
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.springs.Create(entity);
component.Serialize(archive, seri);
}
}
if (archive.GetVersion() >= 46)
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = scene.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, Scene::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_Internal(scene, archive, seri, INVALID_ENTITY, flags);
if (child != INVALID_ENTITY)
{
HierarchyComponent* hier = scene.hierarchy.GetComponent(child);
if (hier != nullptr)
{
hier->parentID = entity;
}
}
}
}
}
else
{
// Find existing components one-by-one and WRITE them out:
{
auto component = scene.names.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
auto component = scene.layers.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
auto component = scene.transforms.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
auto component = scene.hierarchy.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
auto component = scene.materials.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
auto component = scene.meshes.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
auto component = scene.impostors.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
auto component = scene.objects.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
archive << false; // aabb no longer needed to be serialized
}
{
auto component = scene.rigidbodies.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
auto component = scene.softbodies.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
auto component = scene.armatures.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
auto component = scene.lights.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
archive << false; // aabb no longer needed to be serialized
}
{
auto component = scene.cameras.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
auto component = scene.probes.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
archive << false; // aabb no longer needed to be serialized
}
{
auto component = scene.forces.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
auto component = scene.decals.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
archive << false; // aabb no longer needed to be serialized
}
{
auto component = scene.animations.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
auto component = scene.emitters.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
auto component = scene.hairs.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
{
auto component = scene.weathers.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
if(archive.GetVersion() >= 30)
{
auto component = scene.sounds.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
if (archive.GetVersion() >= 37)
{
auto component = scene.inverse_kinematics.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
if (archive.GetVersion() >= 38)
{
auto component = scene.springs.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seri);
}
else
{
archive << false;
}
}
if (archive.GetVersion() >= 46)
{
auto component = scene.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, Scene::EntitySerializeFlags::RECURSIVE))
{
// Recursive serialization for all children:
seri.allow_remap = restore_remap;
wi::vector<Entity> children;
for (size_t i = 0; i < scene.hierarchy.GetCount(); ++i)
{
const HierarchyComponent& hier = scene.hierarchy[i];
if (hier.parentID == entity)
{
Entity child = scene.hierarchy.GetEntity(i);
children.push_back(child);
}
}
archive << children.size();
for (Entity child : children)
{
Entity_Serialize_Internal(scene, archive, seri, child, flags);
}
}
}
}
seri.allow_remap = restore_remap;
return entity;
}
Entity Scene::Entity_Serialize(
wi::Archive& archive,
EntitySerializer& seri,
Entity entity,
EntitySerializeFlags flags
)
{
// Manage jump position to jump to resource serialization WRITE area:
size_t jump_before = 0;
size_t jump_after = 0;
size_t original_pos = 0;
if (archive.GetVersion() >= 90)
{
if (archive.IsReadMode())
{
archive >> jump_before;
archive >> jump_after;
original_pos = archive.GetPos();
archive.Jump(jump_before); // jump before resourcemanager::Serialize_WRITE
}
else
{
jump_before = archive.WriteUnknownJumpPosition();
jump_after = archive.WriteUnknownJumpPosition();
}
}
// Keeping this alive to keep serialized resources alive until entity serialization ends:
wi::resourcemanager::ResourceSerializer resource_seri;
if (archive.IsReadMode() && archive.GetVersion() >= 90)
{
wi::resourcemanager::Serialize_READ(archive, resource_seri);
// After resource serialization, jump back to entity serialization area:
archive.Jump(original_pos); // jump back to entity serialize
}
Entity ret = Entity_Serialize_Internal(
*this,
archive,
seri,
entity,
flags
);
if (archive.GetVersion() >= 90)
{
if (archive.IsReadMode())
{
archive.Jump(jump_after); // jump after resourcemanager::Serialize_WRITE
}
else
{
archive.PatchUnknownJumpPosition(jump_before);
wi::resourcemanager::Serialize_WRITE(archive, seri.resource_registration);
archive.PatchUnknownJumpPosition(jump_after);
}
}
return ret;
}
}