1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "BsCorePrerequisites.h"
6#include "Reflection/BsIReflectable.h"
7#include "Scene/BsGameObject.h"
8#include "Math/BsVector3.h"
9#include "Math/BsQuaternion.h"
10
11namespace bs
12{
13 struct SerializationContext;
14
15 /** @addtogroup Scene-Internal
16 * @{
17 */
18
19 /**
20 * Contains differences between two components of the same type.
21 *
22 * @see PrefabDiff
23 */
24 struct BS_CORE_EXPORT PrefabComponentDiff : public IReflectable
25 {
26 INT32 id;
27 SPtr<SerializedObject> data;
28
29 /************************************************************************/
30 /* RTTI */
31 /************************************************************************/
32
33 public:
34 friend class PrefabComponentDiffRTTI;
35 static RTTITypeBase* getRTTIStatic();
36 RTTITypeBase* getRTTI() const override;
37 };
38
39 /** Flags that mark which portion of a scene-object is modified. */
40 enum class BS_SCRIPT_EXPORT(api:bed,m:Utility-Editor) SceneObjectDiffFlags
41 {
42 Name = 0x01,
43 Position = 0x02,
44 Rotation = 0x04,
45 Scale = 0x08,
46 Active = 0x10
47 };
48
49 /**
50 * Contains a set of prefab differences for a single scene object.
51 *
52 * @see PrefabDiff
53 */
54 struct BS_CORE_EXPORT PrefabObjectDiff : public IReflectable
55 {
56 PrefabObjectDiff() { }
57
58 UINT32 id = 0;
59
60 String name;
61 Vector3 position = Vector3::ZERO;
62 Quaternion rotation = Quaternion::IDENTITY;
63 Vector3 scale = Vector3::ZERO;
64 bool isActive = false;
65 UINT32 soFlags = 0;
66
67 Vector<SPtr<PrefabComponentDiff>> componentDiffs;
68 Vector<UINT32> removedComponents;
69 Vector<SPtr<SerializedObject>> addedComponents;
70
71 Vector<SPtr<PrefabObjectDiff>> childDiffs;
72 Vector<UINT32> removedChildren;
73 Vector<SPtr<SerializedObject>> addedChildren;
74
75 /************************************************************************/
76 /* RTTI */
77 /************************************************************************/
78
79 public:
80 friend class PrefabObjectDiffRTTI;
81 static RTTITypeBase* getRTTIStatic();
82 RTTITypeBase* getRTTI() const override;
83 };
84
85 /**
86 * Contains modifications between an prefab and its instance. The modifications are a set of added/removed children or
87 * components and per-field "diffs" of their components.
88 */
89 class BS_CORE_EXPORT PrefabDiff : public IReflectable
90 {
91 public:
92 /**
93 * Creates a new prefab diff by comparing the provided instanced scene object hierarchy with the prefab scene
94 * object hierarchy.
95 */
96 static SPtr<PrefabDiff> create(const HSceneObject& prefab, const HSceneObject& instance);
97
98 /**
99 * Applies the internal prefab diff to the provided object. The object should have similar hierarchy as the prefab
100 * the diff was created for, otherwise the results are undefined.
101 *
102 * @note Be aware that this method will not instantiate newly added components or scene objects. It's expected
103 * that this method will be called on a fresh copy of a scene object hierarchy, and everything to be
104 * instantiated at once after diff is applied.
105 */
106 void apply(const HSceneObject& object);
107
108 private:
109 /** A reference to a renamed game object instance data, and its original ID so it may be restored later. */
110 struct RenamedGameObject
111 {
112 GameObjectInstanceDataPtr instanceData;
113 UINT64 originalId;
114 };
115
116 /**
117 * Recurses over every scene object in the prefab a generates differences between itself and the instanced version.
118 *
119 * @see create
120 */
121 static SPtr<PrefabObjectDiff> generateDiff(const HSceneObject& prefab, const HSceneObject& instance);
122
123 /**
124 * Recursively applies a per-object set of prefab differences to a specific object.
125 *
126 * @see apply
127 */
128 static void applyDiff(const SPtr<PrefabObjectDiff>& diff, const HSceneObject& object, SerializationContext* context);
129
130 /**
131 * Renames all game objects in the provided instance so that IDs of the objects will match the IDs of their
132 * counterparts in the prefab.
133 *
134 * @note
135 * This is a temporary action and should be undone by calling restoreInstanceIds() and providing it with the
136 * output of this method.
137 * @note
138 * By doing this before calling generateDiff() we ensure that any game object handles pointing to objects within
139 * the prefab instance hierarchy aren't recorded by the diff system, since we want those to remain as they are
140 * after applying the diff.
141 */
142 static void renameInstanceIds(const HSceneObject& prefab, const HSceneObject& instance, Vector<RenamedGameObject>& output);
143
144 /**
145 * Restores any instance IDs that were modified by the renameInstanceIds() method.
146 *
147 * @see renameInstanceIds
148 */
149 static void restoreInstanceIds(const Vector<RenamedGameObject>& renamedObjects);
150
151 SPtr<PrefabObjectDiff> mRoot;
152
153 /************************************************************************/
154 /* RTTI */
155 /************************************************************************/
156
157 Any mRTTIData;
158 public:
159 friend class PrefabDiffRTTI;
160 static RTTITypeBase* getRTTIStatic();
161 RTTITypeBase* getRTTI() const override;
162 };
163
164 /** @} */
165}