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 */
50class FBXSDK_DLL FbxCloneManager
51{
52public:
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
264private:
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