1 | /**************************************************************************************** |
2 | |
3 | Copyright (C) 2015 Autodesk, Inc. |
4 | All rights reserved. |
5 | |
6 | Use of this software is subject to the terms of the Autodesk license agreement |
7 | provided at the time of installation or download, or which otherwise accompanies |
8 | this software in either electronic or hard copy form. |
9 | |
10 | ****************************************************************************************/ |
11 | |
12 | //! \file fbxclonemanager.h |
13 | #ifndef _FBXSDK_UTILS_CLONE_MANAGER_H_ |
14 | #define _FBXSDK_UTILS_CLONE_MANAGER_H_ |
15 | |
16 | #include <fbxsdk/fbxsdk_def.h> |
17 | |
18 | #include <fbxsdk/core/fbxobject.h> |
19 | #include <fbxsdk/core/fbxquery.h> |
20 | |
21 | #include <fbxsdk/fbxsdk_nsbegin.h> |
22 | |
23 | /** The clone manager is a utility for cloning entire networks of FbxObject. |
24 | * Options are available for specifying how the clones inherit the connections |
25 | * of the original. |
26 | * |
27 | * Networks of FbxObject (inter-connected objects by OO, OP, PO or PP connections) |
28 | * can be cloned. How the connections of clones are handled depends on mSrcPolicy and mExternalDstPolicy. |
29 | * |
30 | * To clone FbxObject instances and their dependents, put them into a CloneSet |
31 | * and pass the CloneSet to this class: |
32 | * \code |
33 | * FbxCloneManager cloneManager; |
34 | * FbxCloneManager::CloneSet cloneSet; |
35 | * FbxCloneManager::CloneSetElement defaultCloneOptions(FbxCloneManager::sConnectToClone, |
36 | * FbxCloneManager::sConnectToOriginal, |
37 | * FbxObject::eDeepClone); |
38 | * cloneSet.Insert(someObject, defaultCloneOptions); |
39 | * cloneManager.AddDependents(cloneSet, someObject, defaultCloneOptions); |
40 | * cloneManager.Clone(cloneSet, scene) |
41 | * \endcode |
42 | * |
43 | * \remark If cloning occurs on the same scene as the original objects, the system will contain duplicated names. Although this is acceptable in FBX, |
44 | * some applications may not behave correctly with duplicated names. It is the responsability of the caller to resolve any conflicts. |
45 | * |
46 | * \see FbxCloneManager::CloneSetElement |
47 | * \see FbxCloneManager::CloneSet |
48 | * \nosubgrouping |
49 | */ |
50 | class FBXSDK_DLL FbxCloneManager |
51 | { |
52 | public: |
53 | |
54 | //! Maximum depth to clone dependents. |
55 | static const int sMaximumCloneDepth; |
56 | |
57 | /** Connect to objects that are connected to original object. |
58 | * This is a flag to mSrcPolicy or mExternalDstPolicy. |
59 | */ |
60 | static const int sConnectToOriginal; |
61 | |
62 | /** Connect to clones of objects that are connected to original object. |
63 | * (only if those original objects are also in the clone set) |
64 | * This is a flag to mSrcPolicy. |
65 | */ |
66 | static const int sConnectToClone; |
67 | |
68 | /** This represents an element in FbxCloneManager::CloneSet to be cloned. |
69 | * This class contains the option for specifying how connections are cloned and the |
70 | * cloned object. |
71 | * \see FbxCloneManager |
72 | * \see FbxCloneManager::CloneSet |
73 | */ |
74 | struct FBXSDK_DLL CloneSetElement |
75 | { |
76 | public: |
77 | /** Constructor. |
78 | * \param pSrcPolicy Specify how to handle source connections. Valid values are 0, sConnectToOriginal, |
79 | * sConnectToClone or sConnectToOriginal|sConnectToClone. |
80 | * \param pExternalDstPolicy Specify how to handle destination connections to objects NOT in |
81 | * the clone set. Valid values are 0 or sConnectToOriginal. |
82 | * \param pCloneType Specify the type of cloning. FbxObject::Clone uses the same parameter. |
83 | */ |
84 | CloneSetElement( int pSrcPolicy = 0, |
85 | int pExternalDstPolicy = 0, |
86 | FbxObject::ECloneType pCloneType = FbxObject::eReferenceClone ); |
87 | |
88 | //! the type of cloning to perform |
89 | FbxObject::ECloneType mType; |
90 | |
91 | /** Policy on how to handle source connections on the original object. Valid values are 0 |
92 | * or any bitwise OR'd combination of sConnectToOriginal, and sConnectToClone. |
93 | */ |
94 | int mSrcPolicy; |
95 | |
96 | /** policy on how to handle destination connections on the original object to |
97 | * objects NOT in the clone set. (Destination connections to objects in the set |
98 | * are handled by that object's source policy) Valid values are 0 or sConnectToOriginal. |
99 | */ |
100 | int mExternalDstPolicy; |
101 | |
102 | /** This is a pointer to the newly created clone. |
103 | * It is set after the call to FbxCloneManager::Clone() |
104 | */ |
105 | FbxObject* mObjectClone; |
106 | |
107 | /** Internal use. |
108 | */ |
109 | bool mLayerElementProcessed; |
110 | bool mConnectionsProcessed; |
111 | }; |
112 | |
113 | /** The CloneSet is a collection of pointers to objects that will be cloned in Clone() |
114 | * Attached to each object is a CloneSetElement. Its member variables dictate how |
115 | * the corresponding object will be cloned, and how it will inherit connections |
116 | * on the original object. |
117 | */ |
118 | typedef FbxMap<FbxObject*,CloneSetElement> CloneSet; |
119 | |
120 | /** Constructor |
121 | */ |
122 | FbxCloneManager(); |
123 | |
124 | /** Destructor |
125 | */ |
126 | virtual ~FbxCloneManager(); |
127 | |
128 | /** This function simplifies the process of cloning one object and all its depedency graph by automatically preparing |
129 | * the CloneSet and calling the Clone method using the code below. |
130 | * |
131 | * \code |
132 | * FbxCloneManager cloneManager; |
133 | * FbxCloneManager::CloneSet cloneSet; |
134 | * FbxCloneManager::CloneSetElement defaultCloneOptions(FbxCloneManager::sConnectToClone, |
135 | * FbxCloneManager::sConnectToOriginal, |
136 | * FbxObject::eDeepClone); |
137 | * FbxObject* lReturnObj = (FbxObject*)pObject; |
138 | * |
139 | * cloneManager.AddDependents(cloneSet, pObject, defaultCloneOptions, FbxCriteria::ObjectType(FbxObject::ClassId)); |
140 | * cloneSet.Insert((FbxObject*)pObject, defaultCloneOptions); |
141 | * |
142 | * // collect all the FbxCharacters, if any (these are indirect dependencies not visible by the AddDependents recursion) |
143 | * FbxArray<FbxObject*> lExtras; |
144 | * FbxCloneManager::CloneSet::RecordType* lIterator = cloneSet.Minimum(); |
145 | * while( lIterator ) |
146 | * { |
147 | * FbxObject* lObj = lIterator->GetKey(); |
148 | * cloneManager.LookForIndirectDependent(lObj, cloneSet, lExtras); |
149 | * lIterator = lIterator->Successor(); |
150 | * } |
151 | * |
152 | * // and add them to cloneSet |
153 | * for (int i = 0, c = lExtras.GetCount(); i < c; i++) |
154 | * { |
155 | * FbxObject* lObj = lExtras[i]; |
156 | * cloneManager.AddDependents(cloneSet, lObj, defaultCloneOptions); |
157 | * cloneSet.Insert(lObj, defaultCloneOptions); |
158 | * } |
159 | * |
160 | * // clone everything |
161 | * if (cloneManager.Clone(cloneSet, pContainer)) |
162 | * { |
163 | * // get the clone of pObject |
164 | * CloneSet::RecordType* lIterator = cloneSet.Find((FbxObject* const)pObject); |
165 | * if( lIterator ) |
166 | * { |
167 | * lReturnObj = lIterator->GetValue().mObjectClone; |
168 | * } |
169 | * } |
170 | * return lReturnObj; |
171 | * \endcode |
172 | * |
173 | * \param pObject Object to clone. |
174 | * \param pContainer This object (typically a scene or document) will contain the new clones. |
175 | * \return The clone of \e pObject if all its depedency graph have been cloned successfully, NULL otherwise. |
176 | * \remark It is advised not to use an FbxNode object for \e pContainer to group the cloned dependency graph. |
177 | * Some objects of the FBX SDK are not meant to be connected to FbxNode objects and if they are, the final scene |
178 | * will not comply to the FBX standard and its behavior cannot be guaranteed. |
179 | * \remark If \e pContainer is left \c NULL the cloned objects only exists in the FbxSdkManager and need to be |
180 | * manually connected to the scene in order to be saved to disk. |
181 | * |
182 | * Example: |
183 | * \code |
184 | * FbxObject* lObj2BCloned = ... |
185 | * FbxNode* myNewParent = FbxNode::Create(lNewScene, "Clone"); |
186 | * lNewScene->GetRootNode()->AddChild(lN); |
187 | * |
188 | * FbxCloneManager cloneManager; |
189 | * FbxNode *lClone = (FbxNode*)cloneManager.Clone(lObj2BCloned); |
190 | * |
191 | * // make sure the cloned object is connected to the scene |
192 | * lClone->ConnectDstObject(lNewScene); |
193 | * \endcode |
194 | */ |
195 | static FbxObject* Clone(const FbxObject* pObject, FbxObject* pContainer = NULL); |
196 | |
197 | /** Clone all objects in the set using the given policies for duplication |
198 | * of connections. Each CloneSetElement in the set will have its mObjectClone |
199 | * pointer set to the newly created clone. The following code shows how to access the cloned objects: |
200 | * |
201 | * \code |
202 | * if (cloneManager.Clone(cloneSet, pContainer)) |
203 | * { |
204 | * // access the clones |
205 | * FbxCloneManager::CloneSet::RecordType* lIterator = cloneSet.Minimum(); |
206 | * while( lIterator ) |
207 | * { |
208 | * FbxObject* lOriginalObject = lIterator->GetKey(); |
209 | * FbxObject* lClonedObject = lIterator->GetValue().mObjectClone; |
210 | * lIterator = lIterator->Successor(); |
211 | * } |
212 | * } |
213 | * \endcode |
214 | * |
215 | * \param pSet Set of objects to clone |
216 | * \param pContainer This object (typically a scene or document) will contain the new clones |
217 | * \return true if all objects were cloned, false otherwise. |
218 | * \remark It is advised not to use an FbxNode object for \e pContainer to group the cloned dependency graph. |
219 | * Some objects of the FBX SDK are not meant to be connected to FbxNode objects and if they are, the final scene |
220 | * will not comply to the FBX standard and its behavior cannot be guaranteed. |
221 | * \remark If \e pContainer is left \c NULL the cloned objects only exists in the FbxSdkManager and need to be |
222 | * manually connected to the scene in order to be saved to disk. |
223 | */ |
224 | virtual bool Clone( CloneSet& pSet, FbxObject* pContainer = NULL ) const; |
225 | |
226 | /** Add all dependents of the given object to the CloneSet. |
227 | * Dependents of items already in the set are ignored to prevent |
228 | * infinite recursion on cyclic dependencies. |
229 | * \param pSet The set to add items. |
230 | * \param pObject Object to add dependents to |
231 | * \param pCloneOptions |
232 | * \param pTypes Types of dependent objects to consider |
233 | * \param pDepth Maximum recursive depth. Valid range is [0,sMaximumCloneDepth] |
234 | * |
235 | * The following example shows how to perform multiple calls to AddDependents() to collect several |
236 | * subgraphs to be cloned: |
237 | * \code |
238 | * FbxObject* lRoot = ... // initialized with the root of the graph to be cloned |
239 | * FbxCharacter* lCharacter = ... // points to the FbxCharacter driving the character defined by "lRoot" graph |
240 | * |
241 | * FbxCloneManager cloneManager; |
242 | * FbxCloneManager::CloneSet cloneSet; |
243 | * |
244 | * cloneManager.AddDependents(cloneSet, lRoot); |
245 | * cloneSet.Insert(lRoot, defaultCloneOptions); |
246 | * |
247 | * cloneManager.AddDependents(cloneSet, lCharacter); |
248 | * cloneSet.Insert(lCharacter, defaultCloneOptions); |
249 | * |
250 | * \endcode |
251 | */ |
252 | virtual void AddDependents( CloneSet& pSet, |
253 | const FbxObject* pObject, |
254 | const CloneSetElement& pCloneOptions = CloneSetElement(), |
255 | FbxCriteria pTypes = FbxCriteria::ObjectType(FbxObject::ClassId), |
256 | int pDepth = sMaximumCloneDepth ) const; |
257 | |
258 | /***************************************************************************************************************************** |
259 | ** WARNING! Anything beyond these lines is for internal use, may not be documented and is subject to change without notice! ** |
260 | *****************************************************************************************************************************/ |
261 | #ifndef DOXYGEN_SHOULD_SKIP_THIS |
262 | static FbxObject* Clone(const FbxObject* pObject, CloneSet* pSet, FbxObject* pContainer = NULL); |
263 | |
264 | private: |
265 | friend class FbxScene; |
266 | |
267 | bool ReAssignLayerElements( FbxCloneManager::CloneSet::RecordType* pIterator, const FbxCloneManager::CloneSet& pSet) const; |
268 | bool CloneConnections( CloneSet::RecordType* pIterator, const CloneSet& pSet) const; |
269 | bool CheckIfCloneOnSameScene(const FbxObject* pObject, FbxObject* pContainer) const; |
270 | |
271 | virtual void LookForIndirectDependent(const FbxObject* pObject, CloneSet& pSet, FbxArray<FbxObject*>& lIndirectDepend); |
272 | virtual bool NeedToBeExcluded(FbxObject* lObj) const; |
273 | |
274 | bool mCloneOnSameScene; |
275 | |
276 | #endif /* !DOXYGEN_SHOULD_SKIP_THIS *****************************************************************************************/ |
277 | }; |
278 | |
279 | #include <fbxsdk/fbxsdk_nsend.h> |
280 | |
281 | #define CloneSetCast(x) ((FbxCloneManager::CloneSet*)(x)) |
282 | #define CloneSetElementCast(x) ((FbxCloneManager::CloneSetElement*)((x!=NULL)?&(x->GetValue()):NULL)) |
283 | |
284 | #endif /* _FBXSDK_UTILS_CLONE_MANAGER_H_ */ |
285 | |