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 fbxusernotification.h |
13 | #ifndef _FBXSDK_UTILS_USER_NOTIFICATION_H_ |
14 | #define _FBXSDK_UTILS_USER_NOTIFICATION_H_ |
15 | |
16 | #include <fbxsdk/fbxsdk_def.h> |
17 | |
18 | #include <fbxsdk/core/base/fbxarray.h> |
19 | #include <fbxsdk/core/base/fbxstring.h> |
20 | #include <fbxsdk/core/base/fbxmultimap.h> |
21 | |
22 | #include <fbxsdk/fbxsdk_nsbegin.h> |
23 | |
24 | class FbxLogFile; |
25 | class FbxMessageEmitter; |
26 | class FbxUserNotificationFilteredIterator; |
27 | |
28 | /** This class defines one entry object held by the FbxUserNotification class. |
29 | * \nosubgrouping |
30 | * An entry object is a message to show error, warning or information. |
31 | * Direct manipulation of this object should not be required. At most, access to |
32 | * its members can be granted for querying purposes. |
33 | */ |
34 | class FBXSDK_DLL FbxAccumulatorEntry |
35 | { |
36 | public: |
37 | /** Category of the accumulator entry. |
38 | */ |
39 | enum EClass |
40 | { |
41 | eError=1, //!< Error message entry. |
42 | eWarning=2, //!< Warning message entry. |
43 | eInformation=4, //!< Information message entry. |
44 | eAny=7 //!< Entry that does not belong to above class. Cannot be used as a class ID |
45 | }; |
46 | |
47 | /** Constructor. |
48 | * \param pAEClass Specify the category for this entry. |
49 | * \param pName Identifies this entry (more than one object can have the same name). |
50 | * \param pDescr The description of the entry. This is the common message. The details |
51 | * are added separately by the FbxUserNotification classes. |
52 | * \param pDetail A list of detail string that will be copied into the local array. |
53 | * \param pMuteState Whether this entry is muted. |
54 | * \remarks By default the object is muted so it does not get processed by the low level |
55 | * output routines of the UserNotification accumulator. The entry gets activated |
56 | * (unmuted) by the calls to AddDetail() in the accumulator. |
57 | */ |
58 | FbxAccumulatorEntry(EClass pAEClass, const FbxString& pName, const FbxString& pDescr, |
59 | FbxString pDetail="" , bool pMuteState=true); |
60 | |
61 | /** Copy Constructor. |
62 | * \param pAE Another FbxAccumulatorEntry object to be copied. |
63 | * \param pSkipDetails Flag to skip details. |
64 | */ |
65 | FbxAccumulatorEntry(const FbxAccumulatorEntry& pAE, bool pSkipDetails); |
66 | |
67 | //! Destructor. |
68 | ~FbxAccumulatorEntry(); |
69 | |
70 | //! Returns the category class of this entry. |
71 | EClass GetClass() const; |
72 | |
73 | //! Returns the name of this entry. |
74 | FbxString GetName() const; |
75 | |
76 | //! Returns the description of this entry. |
77 | FbxString GetDescription() const; |
78 | |
79 | //! Returns the number of details stored. |
80 | int GetDetailsCount() const; |
81 | |
82 | /** Returns a pointer to one specific detail string (or NULL if the id is invalid). |
83 | * Detail string is dynamic. One entry can have multiple detail strings to hold extra information. |
84 | * For example, if one entry message is related to many FBX nodes, user can add these nodes' name as details. |
85 | * \param id The detail id. |
86 | * \return Pointer to the specific detail. |
87 | */ |
88 | const FbxString* GetDetail(int id) const; |
89 | |
90 | //! Returns True if this entry is muted. |
91 | bool IsMuted() const; |
92 | |
93 | private: |
94 | FbxArray<FbxString*>& GetDetails(); |
95 | void Mute(bool pState); |
96 | |
97 | bool mMute; |
98 | EClass mAEClass; |
99 | FbxString mName; |
100 | FbxString mDescr; |
101 | FbxArray<FbxString*> mDetails; |
102 | |
103 | friend class FbxUserNotification; |
104 | }; |
105 | |
106 | |
107 | /** This class accumulates user notifications and sends them to any device opened by the derived classes. |
108 | * If this class is not derived, the data can only be sent to a log file. To send data to a log file, |
109 | * it must be opened before attempting to send data, otherwise, the messages will be lost. |
110 | */ |
111 | class FBXSDK_DLL FbxUserNotification |
112 | { |
113 | public: |
114 | /** |
115 | * Create and initialize user notification object for the SDK manager. |
116 | * One SDK manager has one global user notification object. |
117 | * If the SDK manager already has global user notification object, the function will do nothing. |
118 | * |
119 | * \param pManager |
120 | * \param pLogFileName Name of the log file that will be open in the directory |
121 | * defined by the GetLogFilePath method. |
122 | * \param pSessionDescription This string is used to separate session logs in the file. |
123 | * \return the global user notification object owned by the SDK manager. |
124 | */ |
125 | static FbxUserNotification* Create(FbxManager* pManager, |
126 | const FbxString& pLogFileName, |
127 | const FbxString& pSessionDescription); |
128 | |
129 | /** |
130 | * Destroy the global user notification object owned by the SDK manager. |
131 | */ |
132 | static void Destroy(FbxManager* pManager); |
133 | |
134 | /** Instantiate a FbxUserNotification but leave it uninitialized. The caller must |
135 | * explicitly call InitAccumulator to initialize it and ClearAccumulator when finished |
136 | * using it. |
137 | * \param pManager |
138 | * \param pLogFileName Name of the log file that will be open in the directory |
139 | * defined by the GetLogFilePath method. |
140 | * \remarks If pLogFileName is an empty string the log file does not get created and any |
141 | * output sent to it is lost. |
142 | * \param pSessionDescription This string is used to separate session logs in the file. |
143 | * \remarks If the specified log file already exists, messages are appended to it. This |
144 | * class never deletes the log file. Derived classes may delete the log file |
145 | * before opening (it must be done in the constructor because the log file is |
146 | * opened in the InitAccumulator) or at the end of the processing in the |
147 | * PostTerminate method. |
148 | */ |
149 | FbxUserNotification(FbxManager* pManager, |
150 | FbxString const& pLogFileName, |
151 | FbxString const& pSessionDescription); |
152 | |
153 | //! Destructor. |
154 | virtual ~FbxUserNotification(); |
155 | |
156 | /** |
157 | * Accumulator is to hold the notification entries. User can add entries to it. |
158 | * This method must be called before using the Accumulator. It opens the log file and |
159 | * calls AccumulatorInit followed by OpenExtraDevices. Failing to call this method |
160 | * will prevent other actions except ClearAccumulator, GetLogFileName and GetLogFilePath. |
161 | */ |
162 | void InitAccumulator(); |
163 | |
164 | /** This method must be called when the Accumulator is no longer needed. It calls |
165 | * CloseExtraDevices, followed by the AccumulatorClear, and then closes the log file. |
166 | */ |
167 | void ClearAccumulator(); |
168 | |
169 | /** IDs for pre-defined message entries. |
170 | */ |
171 | enum EEntryID |
172 | { |
173 | eBindPoseInvalidObject, |
174 | eBindPoseInvalidRoot, |
175 | eBindPoseNotAllAncestorsNodes, |
176 | eBindPoseNotAllDeformingNodes, |
177 | eBindPoseNotAllAncestorsDefinitionNodes, |
178 | eBindPoseRelativeMatrix, |
179 | eEmbedMediaNotify, |
180 | eFileIONotify, //!< this is generic for reader and writer to log notifications. |
181 | eFileIONotifyMaterial, |
182 | eFileIONotifyDXFNotSupportNurbs, |
183 | eEntryStartID //!< Starting ID for any Accumulator entry added by derived classes. |
184 | }; |
185 | |
186 | /** |
187 | * \name Accumulator Management |
188 | */ |
189 | //@{ |
190 | /** Adds one entry into the accumulator. |
191 | * \param pID This entry unique ID. |
192 | * \param pName This entry name. |
193 | * \param pDescr The description of this entry. |
194 | * \param pClass The category of this entry. |
195 | * \return The ID of the newly allocated entry. This ID is pEntryId. |
196 | */ |
197 | int AddEntry(const int pID, const FbxString& pName, const FbxString& pDescr, FbxAccumulatorEntry::EClass pClass=FbxAccumulatorEntry::eWarning); |
198 | |
199 | /** Completes the accumulator entry (there can be more that one detail for each entry) and implicitly defines |
200 | * the sequence of events. Each call to this method is internally recorded, making it possible to output each |
201 | * notification in the order they have been defined. Also, when a detail is added to an entry, it is automatically unmuted |
202 | * so it can be sent to the devices (muted FbxAccumulatorEntry objects are not processed). |
203 | * \param pEntryId The entry index (as returned by AddEntry). |
204 | * \return The id of the detail in the recorded sequence of events. This Id should be used when the call to |
205 | * Output has the eSequencedDetails set as a source. If an error occurs, the returned value is -1 |
206 | */ |
207 | int AddDetail(int pEntryId); |
208 | |
209 | /** Completes the accumulator entry (there can be more that one detail for each entry) and implicitly defines |
210 | * the sequence of events. Each call to this method is internally recorded, making it possible to output each |
211 | * notification in the order they have been defined. Also, when a detail is added to an entry, it is automatically unmuted |
212 | * so it can be sent to the devices (muted FbxAccumulatorEntry objects are not processed). |
213 | * \param pEntryId The entry index (as returned by AddEntry). |
214 | * \param pString The detail string to add to the entry. |
215 | * \return The id of the detail in the recorded sequence of events. This Id should be used when the call to |
216 | * Output has the eSequencedDetails set as a source. If an error occurs, the returned value is -1 |
217 | */ |
218 | int AddDetail(int pEntryId, FbxString pString); |
219 | |
220 | /** Completes the accumulator entry (there can be more that one detail for each entry) and implicitly defines |
221 | * the sequence of events. Each call to this method is internally recorded, making it possible to output each |
222 | * notification in the order they have been defined. Also, when a detail is added to an entry, it is automatically unmuted |
223 | * so it can be sent to the devices (muted FbxAccumulatorEntry objects are not processed). |
224 | * \param pEntryId The entry index (as returned by AddEntry). |
225 | * \param pNode The node to add to the entry. |
226 | * \return The id of the detail in the recorded sequence of events. This Id should be used when the call to |
227 | * Output has the eSequencedDetails set as a source. If an error occurs, the returned value is -1 |
228 | */ |
229 | int AddDetail(int pEntryId, FbxNode* pNode); |
230 | |
231 | //! Returns the number of AccumulatorEntries currently stored in this accumulator. |
232 | int GetNbEntries() const; |
233 | |
234 | /** Get the specified FbxAccumulatorEntry. |
235 | * \param pEntryId ID of the entry to retrieve. |
236 | * \return Pointer to the specified entry, otherwise \c NULL if either the id is invalid or the Accumulator |
237 | * is not properly initialized. |
238 | */ |
239 | const FbxAccumulatorEntry* GetEntry(int pEntryId); |
240 | |
241 | /** Get the FbxAccumulatorEntry at the specified index. |
242 | * \param pEntryIndex index of the entry to retrieve. |
243 | * \return Pointer to the specified entry, otherwise \c NULL if either the index is invalid or the Accumulator |
244 | * is not properly initialized.. |
245 | */ |
246 | const FbxAccumulatorEntry* GetEntryAt(int pEntryIndex) const; |
247 | |
248 | //! Returns the number of Details recorded so far in this accumulator. |
249 | int GetNbDetails() const; |
250 | |
251 | /** Get the specified detail. |
252 | * \param pDetailId Index of the detail. This is the id-th detail of type pClass as inserted |
253 | * when the AddDetail |
254 | * \param pAE Pointer to the FbxAccumulatorEntry object that contains the requested detail. |
255 | * The returned valued can be NULL if an error occurred. |
256 | * \return The index of the detail to be used when calling the GetDetail of the FbxAccumulatorEntry. |
257 | * \remarks A value of -1 is acceptable and means that the FbxAccumulatorEntry has no details. However, |
258 | * if pAE is NULL, the return value is meaningless. |
259 | */ |
260 | int GetDetail(int pDetailId, const FbxAccumulatorEntry*& pAE) const; |
261 | |
262 | //@} |
263 | |
264 | /** |
265 | * \name Accumulator Output |
266 | */ |
267 | //@{ |
268 | /** Specify send what kind of data to output device. |
269 | */ |
270 | enum EOutputSource |
271 | { |
272 | eAccumulatorEntry, //!< Entry with its details. |
273 | eSequencedDetails //!< Details in the recorded order. |
274 | }; |
275 | |
276 | /** Send the accumulator entries to the output devices. |
277 | * This method needs to be explicitly called by the program that uses this |
278 | * class. |
279 | * \param pOutSrc Specify which data has to be sent to the output devices. Set to SEQUENCED_DETAILS |
280 | * to send the Details in the recorded order. Set to ACCUMULATOR_ENTRY to send |
281 | * each entry with its details regardless of the order in which the events occurred. |
282 | * \param pIndex If this parameter >= 0, only send the specified entry/detail index to the output devices. |
283 | * Otherwise send all of them. |
284 | * \param pExtraDevicesOnly If this parameter is True, the output is not sent to the log file. |
285 | * \remarks The pExtraDevicesOnly parameter is ignored if the log file has been disabled. |
286 | */ |
287 | bool Output(EOutputSource pOutSrc=eAccumulatorEntry, int pIndex = -1, bool = false); |
288 | |
289 | /** Send the accumulator entry to the output devices. |
290 | * \param pId Send the entry/detail that matching pIdx to the output devices, |
291 | * otherwise send all of them. |
292 | * \param pOutSrc Specify which data has to be sent to the output devices. Set to SEQUENCED_DETAILS |
293 | * to send the Details in the recorded order. Set to ACCUMULATOR_ENTRY to send |
294 | * each entry with its details regardless of the order in which the events occurred.. |
295 | * \param pExtraDevicesOnly If this parameter is True, the output is not sent to the log file. |
296 | */ |
297 | bool OutputById(EEntryID pId, EOutputSource pOutSrc=eAccumulatorEntry, bool = false); |
298 | |
299 | /** Send an immediate entry to the output devices. |
300 | * This method bypasses the accumulator by sending the entry directly to the output devices |
301 | * and discarding it right after. The internal accumulator lists are left unchanged by this call. |
302 | * \param pName This entry name. |
303 | * \param pDescr The description of this entry. |
304 | * \param pClass The category of this entry. |
305 | * \param pExtraDevicesOnly If this parameter is True, the output is not sent to the log file. |
306 | * \remarks The pExtraDevicesOnly parameter is ignored if the log file has been disabled. |
307 | */ |
308 | bool Output(const FbxString& pName, const FbxString& pDescr, FbxAccumulatorEntry::EClass pClass, bool = false); |
309 | |
310 | /** Sends the content of the iterator to the output devices. |
311 | * This method bypasses the accumulator by sending each entry in the iterator directly to |
312 | * the output devices. The internal accumulator lists are left unchanged by this call. |
313 | * \param pAEFIter The Filtered FbxAccumulatorEntry iterator object. |
314 | * \param pExtraDevicesOnly If this parameter is True, the output is not sent to the log file. |
315 | * \remarks The pExtraDevicesOnly parameter is ignored if the log file has been disabled. |
316 | */ |
317 | bool Output(FbxUserNotificationFilteredIterator& pAEFIter, bool = false); |
318 | |
319 | /** Set log message emitter. |
320 | * \param pLogMessageEmitter The new log message emitter. |
321 | */ |
322 | void SetLogMessageEmitter(FbxMessageEmitter * pLogMessageEmitter); |
323 | |
324 | /** |
325 | * \name Utilities |
326 | */ |
327 | //@{ |
328 | /** Returns the absolute path to the log file. If this method is not overridden in a derived class, it |
329 | * returns the TEMP directory. |
330 | * \param pPath The returned path. |
331 | */ |
332 | virtual void GetLogFilePath(FbxString& pPath); |
333 | |
334 | /** Returns the log file name. */ |
335 | inline FbxString GetLogFileName() { return mLogFileName; } |
336 | //@} |
337 | |
338 | protected: |
339 | /** |
340 | * Identify one detail in all accumulator entries by record the entry object and its detail id. |
341 | */ |
342 | class AESequence |
343 | { |
344 | public: |
345 | AESequence(FbxAccumulatorEntry* pAE, int pDetailId) : |
346 | mAE(pAE), |
347 | mDetailId(pDetailId) |
348 | { |
349 | }; |
350 | |
351 | //! Return the entry object the detail belongs to. |
352 | FbxAccumulatorEntry* AE() { return mAE; } |
353 | //! Return the detail id in the entry object |
354 | int DetailId() { return mDetailId; } |
355 | |
356 | private: |
357 | FbxAccumulatorEntry* mAE; |
358 | int mDetailId; |
359 | }; |
360 | |
361 | friend class FbxUserNotificationFilteredIterator; |
362 | |
363 | /** Allow a derived class to finalize processing AFTER the log file handle has been |
364 | * deleted. This may be required if the log file needs to be moved or shown. |
365 | * \returns True if the object is properly cleaned. |
366 | */ |
367 | virtual bool PostTerminate(); |
368 | |
369 | /** Allow the implementation class to perform accumulator initializations before |
370 | * the Extra devices are opened. By default this method does nothing. |
371 | */ |
372 | virtual void AccumulatorInit(); |
373 | |
374 | /** Allow the implementation class to perform accumulator clear after the Extra devices are |
375 | * closed. By default this method does nothing. |
376 | */ |
377 | virtual void AccumulatorClear(); |
378 | |
379 | /** Allow the implementation class to opens its output devices (called by InitAccumulator). |
380 | * By default this method does nothing. |
381 | */ |
382 | virtual void (); |
383 | |
384 | /** Allow the implementation class to send all the accumulator entries to the devices. |
385 | * By default this method loop trough all the elements of the received array and |
386 | * call the SendToExtraDevices method with the appropriate FbxAccumulatorEntry element and id. |
387 | * \param pOutputNow Flag indicates whether to output now. |
388 | * \param pEntries Accumulator entries to output. |
389 | * \return \c true if successful, \c false otherwise. |
390 | */ |
391 | virtual bool (bool pOutputNow, FbxArray<FbxAccumulatorEntry*>& pEntries); |
392 | |
393 | /** Allow the implementation class to send all the accumulator entries to the devices. |
394 | * By default this method loop trough all the elements of the received array and |
395 | * call the SendToExtraDevices method with the appropriate FbxAccumulatorEntry element and id. |
396 | * \param pOutputNow Flag indicates whether to output now. |
397 | * \param pAESequence Accumulator entries to output. |
398 | * \return \c true if successful, \c false otherwise. |
399 | */ |
400 | virtual bool (bool pOutputNow, FbxArray<AESequence*>& pAESequence); |
401 | |
402 | /** Allow the implementation class to send one accumulator entry to the devices. |
403 | * By default this method does nothing. |
404 | * \param pOutputNow Flag indicates whether to output now. |
405 | * \param pAccEntry Accumulator entry to output. |
406 | * \param pDetailId Detail id. |
407 | * \return \c true if successful, \c false otherwise. |
408 | * \remarks Derived methods should check for the IsMuted() state to decide if the accumulator |
409 | * entry should get through or get discarded. See AddDetail for more details. |
410 | */ |
411 | virtual bool (bool pOutputNow, const FbxAccumulatorEntry* pAccEntry, int pDetailId = -1); |
412 | |
413 | |
414 | /** Allow the implementation class to close it's output devices (called in the ClearAccumulator) |
415 | * By default this method does nothing. |
416 | */ |
417 | virtual void (); |
418 | |
419 | //! Clears the Accumulator list, remove all user notification entries.. |
420 | void ResetAccumulator(); |
421 | |
422 | //! Clears the Sequence list. |
423 | void ResetSequence(); |
424 | |
425 | /** Send the pIdth element of the accumulator or sequence list to the log file. |
426 | * \param pOutSrc The output source, accumulator or sequence list. |
427 | * \param pId Element id. |
428 | */ |
429 | void SendToLog(EOutputSource pOutSrc, int pId); |
430 | |
431 | /** Send the accumulator entry to the log file. |
432 | * \param pAccEntry The accumulator entry. |
433 | * \param pDetailId Detail id. |
434 | */ |
435 | void SendToLog(const FbxAccumulatorEntry* pAccEntry, int pDetailId = -1); |
436 | |
437 | private: |
438 | FbxString mLogFileName; |
439 | FbxString* mLog; |
440 | FbxLogFile* mLogFile; |
441 | FbxMessageEmitter* mLogMessageEmitter; |
442 | |
443 | bool mProperlyInitialized; |
444 | FbxString mSessionDescription; |
445 | bool mProperlyCleaned; |
446 | |
447 | FbxMultiMap mAccuHT; // The set establish a relationship between an FbxAccumulatorEntry and it's ID |
448 | FbxArray<FbxAccumulatorEntry*> mAccu; // The array defines the order the FbxAccumulatorEntry objects have been |
449 | // added to the accumulator (calls to AddEntry) |
450 | // Both structures share the same pointers. |
451 | FbxArray<AESequence*> mAESequence; |
452 | FbxManager* mSdkManager; |
453 | }; |
454 | |
455 | /** This class iterates through the accumulated messages depending on the configuration |
456 | * flags (filter). The iterator keeps a local copy of the data extracted from the |
457 | * accumulator. |
458 | */ |
459 | class FBXSDK_DLL FbxUserNotificationFilteredIterator |
460 | { |
461 | public: |
462 | /** Constructor. |
463 | * \param pAccumulator This reference is only used during construction for retrieving |
464 | * the data required to fill the iterator. |
465 | * \param pFilterClass The bitwise combination of the EClass identifiers. An FbxAccumulatorEntry |
466 | * element is copied from the accumulator if its Class matches one of the |
467 | * bits of this flag. |
468 | * \param pSrc Specify which data format is extracted from the accumulator. |
469 | * \param pNoDetail This parameter is used ONLY if pSrc == eAccumulatorEntry and, if set to |
470 | * false, the details of the FbxAccumulatorEntry are also sent to the output |
471 | * devices. If left to its default value, only the description of the |
472 | * FbxAccumulatorEntry is sent. |
473 | */ |
474 | FbxUserNotificationFilteredIterator(FbxUserNotification& pAccumulator, |
475 | int pFilterClass, |
476 | FbxUserNotification::EOutputSource pSrc = FbxUserNotification::eSequencedDetails, |
477 | bool pNoDetail = true); |
478 | |
479 | virtual ~FbxUserNotificationFilteredIterator(); |
480 | |
481 | //! Returns the number of elements contained in this iterator. |
482 | int GetNbItems() const; |
483 | |
484 | //! Put the iterator in its reset state. |
485 | void Reset(); |
486 | |
487 | /** Get this iterator's first item. |
488 | * \return NULL if the iterator is empty. |
489 | */ |
490 | FbxAccumulatorEntry* const First(); |
491 | |
492 | /** Get this iterator's previous item. |
493 | * \return NULL if the iterator reached the beginning (or is empty). |
494 | * \remarks This method will also return NULL if it is called before |
495 | * or immediately after a call to First() and reset the iterator to |
496 | * its reset state (meaning that a call to First() is mandatory |
497 | * to be able to iterate again). |
498 | */ |
499 | FbxAccumulatorEntry* const Previous(); |
500 | |
501 | /** Get this iterator's next item. |
502 | * \return NULL if the iterator reached the end (or is empty). |
503 | * \remarks This method will also return NULL if it is called while |
504 | * the iterator is in its reset state (called before |
505 | * First() or after a preceding call to Previous() reached |
506 | * beyond the beginning). |
507 | */ |
508 | FbxAccumulatorEntry* const Next(); |
509 | |
510 | protected: |
511 | // Called in the constructor. |
512 | virtual void BuildFilteredList(FbxUserNotification& pAccumulator); |
513 | |
514 | int mIterator; |
515 | int mFilterClass; |
516 | bool mNoDetail; |
517 | FbxUserNotification::EOutputSource mAccuSrcData; |
518 | FbxArray<FbxAccumulatorEntry*> mFilteredAE; |
519 | }; |
520 | |
521 | #include <fbxsdk/fbxsdk_nsend.h> |
522 | |
523 | #endif /* _FBXSDK_UTILS_USER_NOTIFICATION_H_ */ |
524 | |