// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
#pragma once
#include "SceneObject.h"
#include "Engine/Core/Collections/Dictionary.h"
///
/// Helper class for scene objects creation and deserialization utilities.
///
class FLAXENGINE_API SceneObjectsFactory
{
public:
struct PrefabInstance
{
Guid RootId;
Prefab* Prefab;
Dictionary IdsMapping;
};
struct Context
{
ISerializeModifier* Modifier;
int32 CurrentInstance = -1;
Array Instances;
Dictionary ObjectToInstance;
Context(ISerializeModifier* modifier);
void SetupIdsMapping(const SceneObject* obj);
};
///
/// Creates the scene object from the specified data value. Does not perform deserialization.
///
/// The serialization context.
/// The serialized data stream.
static SceneObject* Spawn(Context& context, ISerializable::DeserializeStream& stream);
///
/// Deserializes the scene object from the specified data value.
///
/// The serialization context.
/// The instance to deserialize.
/// The serialized data stream.
static void Deserialize(Context& context, SceneObject* obj, ISerializable::DeserializeStream& stream);
///
/// Handles the object deserialization error.
///
/// The value.
static void HandleObjectDeserializationError(const ISerializable::DeserializeStream& value);
///
/// Creates a new actor object of the given type identifier.
/// [Deprecated: 18.07.2019 expires 18.07.2020]
///
/// The type identifier.
/// The actor identifier.
/// The created actor, or null if failed.
static Actor* CreateActor(int32 typeId, const Guid& id);
public:
struct PrefabSyncData
{
friend SceneObjectsFactory;
// The created scene objects. Collection can be modified (eg. for spawning missing objects).
Array& SceneObjects;
// The scene objects data.
const ISerializable::DeserializeStream& Data;
// The objects deserialization modifier. Collection will be modified (eg. for spawned objects mapping).
ISerializeModifier* Modifier;
PrefabSyncData(Array& sceneObjects, const ISerializable::DeserializeStream& data, ISerializeModifier* modifier);
private:
struct NewObj
{
Prefab* Prefab;
const ISerializable::DeserializeStream* PrefabData;
Guid PrefabObjectId;
Guid Id;
};
int32 InitialCount;
Array NewObjects;
};
///
/// Initializes the prefab instances inside the scene objects for proper references deserialization.
///
///
/// Should be called after spawning scene objects but before scene objects deserialization.
///
/// The serialization context.
/// The sync data.
static void SetupPrefabInstances(Context& context, PrefabSyncData& data);
///
/// Synchronizes the new prefab instances by spawning missing objects that were added to prefab but were not saved with scene objects collection.
///
///
/// Should be called after spawning scene objects but before scene objects deserialization and PostLoad event when scene objects hierarchy is ready (parent-child relation exists). But call it before Init and BeginPlay events.
///
/// The serialization context.
/// The sync data.
static void SynchronizeNewPrefabInstances(Context& context, PrefabSyncData& data);
///
/// Synchronizes the prefab instances. Prefabs may have objects removed so deserialized instances need to synchronize with it. Handles also changing prefab object parent in the instance.
///
///
/// Should be called after scene objects deserialization and PostLoad event when scene objects hierarchy is ready (parent-child relation exists). But call it before Init and BeginPlay events.
///
/// The serialization context.
/// The sync data.
static void SynchronizePrefabInstances(Context& context, PrefabSyncData& data);
private:
static void SynchronizeNewPrefabInstance(Context& context, PrefabSyncData& data, Prefab* prefab, Actor* actor, const Guid& prefabObjectId);
};