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 fbxpropertypage.h
13#ifndef _FBXSDK_CORE_PROPERTY_PAGE_H_
14#define _FBXSDK_CORE_PROPERTY_PAGE_H_
15
16#include <fbxsdk/fbxsdk_def.h>
17
18#include <fbxsdk/core/base/fbxstringlist.h>
19#include <fbxsdk/core/fbxobject.h>
20#include <fbxsdk/core/fbxsymbol.h>
21#include <fbxsdk/core/fbxpropertydef.h>
22
23#include <fbxsdk/fbxsdk_nsbegin.h>
24
25typedef FbxPair<FbxInt, const char*> FbxNameMapKey;
26
27struct FbxNameMapCompare
28{
29 inline int operator()(const FbxNameMapKey& pKeyA, const FbxNameMapKey& pKeyB) const
30 {
31 if( pKeyA.mFirst < pKeyB.mFirst ) return -1;
32 else if( pKeyA.mFirst > pKeyB.mFirst ) return 1;
33 return strcmp(pKeyA.mSecond, pKeyB.mSecond);
34 }
35};
36
37class FBXSDK_DLL FbxPropertyInfo
38{
39public:
40 FBXSDK_FRIEND_NEW();
41 static FbxPropertyInfo* Create(const char* pName, FbxPropertyPage* pTypeInfo) { return FbxNew< FbxPropertyInfo >(pName,pTypeInfo); }
42 static FbxPropertyInfo* Create(const char* pName, EFbxType pType=eFbxUndefined) { return FbxNew< FbxPropertyInfo >(pName,pType); }
43 void Destroy() { FbxDelete(this); }
44 FbxPropertyInfo* Clone(FbxPropertyPage* /*pPage*/)
45 {
46 // @@@@@ Filter is missing
47 // @@@@@ Clone is incomplete
48 if (mTypeInfo)
49 {
50 return FbxNew< FbxPropertyInfo >(mName,mTypeInfo);
51 }
52 else
53 {
54 return FbxNew< FbxPropertyInfo >(mName,mType);
55 }
56 }
57
58 inline void IncRef() { mRef++; }
59 inline void DecRef() { mRef--; if (mRef==0) FbxDelete(this); }
60 inline int GetRef() { return mRef; }
61
62 // Labels and Types
63
64 inline FbxStringSymbol GetName() const { return mName; }
65 EFbxType GetType() const;
66 FbxPropertyPage* GetTypeInfo() const { return mTypeInfo; }
67
68 inline void SetLabel(const char* pLabel) { mLabel=pLabel; }
69 inline const char* GetLabel() const { return mLabel.IsEmpty() ? "" : ((const char*)mLabel); }
70
71 inline void SetUserTag(int pUserTag) { mUserTag=pUserTag; }
72 inline int GetUserTag() const { return mUserTag; }
73
74 inline void SetUserData(const void* pUserData) { mUserData=(void*)pUserData; }
75 inline void* GetUserData() const { return mUserData; }
76
77 // Enum list
78 int AddEnumValue(const char* pStringValue)
79 {
80 EFbxType lType = GetType();
81 if (lType == eFbxEnum || lType == eFbxEnumM)
82 {
83 if (!mEnumList)
84 mEnumList.Reset(FbxNew< FbxStringList >());
85
86 bool lCanAdd = (lType == eFbxEnumM || mEnumList->FindIndex( pStringValue ) == -1);
87 if( lCanAdd )
88 return mEnumList->Add((char*)pStringValue);
89 }
90 return -1;
91 }
92
93 void InsertEnumValue(int pIndex, const char* pStringValue)
94 {
95 EFbxType lType = GetType();
96 if (lType == eFbxEnum || lType == eFbxEnumM)
97 {
98 if (!mEnumList)
99 mEnumList.Reset(FbxNew< FbxStringList >());
100
101 bool lCanAdd = (lType == eFbxEnumM || mEnumList->FindIndex( pStringValue ) == -1);
102 if( lCanAdd )
103 mEnumList->InsertAt(pIndex,(char*)pStringValue);
104 }
105 }
106
107 int GetEnumCount()
108 {
109 return mEnumList ? mEnumList->GetCount() : 0;
110 }
111
112 void SetEnumValue(int pIndex, const char* pStringValue)
113 {
114 EFbxType lType = GetType();
115 if (lType == eFbxEnum || lType == eFbxEnumM)
116 {
117 if (!mEnumList)
118 mEnumList.Reset(FbxNew< FbxStringList >());
119
120 bool lCanAdd = (lType == eFbxEnumM || mEnumList->FindIndex( pStringValue ) == -1);
121 if (lCanAdd)
122 mEnumList->SetStringAt(pIndex,(char*)pStringValue);
123 }
124 }
125
126 void RemoveEnumValue(int pIndex)
127 {
128 EFbxType lType = GetType();
129 if (lType == eFbxEnum || lType == eFbxEnumM)
130 {
131 if (!mEnumList)
132 mEnumList.Reset(FbxNew< FbxStringList >());
133
134 mEnumList->RemoveAt(pIndex);
135 }
136 }
137
138 char* GetEnumValue(int pIndex)
139 {
140 char* lValue = NULL;
141 EFbxType lType = GetType();
142 if (lType == eFbxEnum || lType == eFbxEnumM)
143 {
144 lValue = mEnumList ? mEnumList->GetStringAt(pIndex) : 0;
145 }
146 return lValue;
147 }
148
149
150 // Min and Max values
151 enum EValueIndex {eValueMin, eValueSoftMin, eValueMax, eValueSoftMax, eValueCount};
152
153 bool HasMinMax(EValueIndex pId) const
154 {
155 return mMinMaxValue[pId] != NULL;
156 }
157
158 bool GetMinMax(EValueIndex pId, void* pValue, EFbxType pValueType) const
159 {
160 if (mMinMaxValue[pId]) {
161 return FbxTypeCopy(pValue, pValueType, mMinMaxValue[pId], GetType());
162 }
163 return false;
164 }
165
166 bool SetMinMax(EValueIndex pId, const void* pValue, EFbxType pValueType)
167 {
168 if (!mMinMaxValue[pId]) {
169 size_t lSize = FbxTypeSizeOf(GetType());
170 if (lSize) {
171 mMinMaxValue[pId] = FbxMalloc(lSize);
172 }
173 }
174 if (mMinMaxValue[pId]) {
175 return FbxTypeCopy(mMinMaxValue[pId], GetType(), pValue, pValueType);
176 }
177 return false;
178 }
179
180private:
181 FbxPropertyInfo(const char* pName, FbxPropertyPage* pTypeInfo)
182 : mRef(0)
183 , mName(pName)
184 , mType(eFbxUndefined)
185 , mTypeInfo(pTypeInfo)
186 , mUserTag(0)
187 , mUserData(0)
188 , mFilter(0)
189 {
190 for (int i=0; i<eValueCount; i++) {
191 mMinMaxValue[i] = 0;
192 }
193 }
194
195 FbxPropertyInfo(FbxStringSymbol pName,FbxPropertyPage *pTypeInfo)
196 : mRef(0)
197 , mName(pName)
198 , mType(eFbxUndefined)
199 , mTypeInfo(pTypeInfo)
200 , mUserTag(0)
201 , mUserData(0)
202 , mFilter(0)
203 {
204 for (int i=0; i<eValueCount; i++) {
205 mMinMaxValue[i] = 0;
206 }
207 }
208
209 FbxPropertyInfo(const char* pName, EFbxType pType)
210 : mRef(0)
211 , mName(pName)
212 , mType(pType)
213 , mTypeInfo(0)
214 , mUserTag(0)
215 , mUserData(0)
216 , mFilter(0)
217 {
218 for (int i=0; i<eValueCount; i++) {
219 mMinMaxValue[i] = 0;
220 }
221 }
222 ~FbxPropertyInfo()
223 {
224 for (int i=eValueMin; i<eValueCount; i++) {
225 FbxFree(mMinMaxValue[i]);
226 }
227 }
228
229 int mRef;
230 FbxStringSymbol mName;
231 FbxStringSymbol mLabel;
232 EFbxType mType;
233 FbxPropertyPage* mTypeInfo;
234 int mUserTag;
235 void* mMinMaxValue[eValueCount];
236 void* mUserData;
237 FbxConnectionPointFilter* mFilter;
238 FbxAutoDeletePtr<FbxStringList> mEnumList;
239};
240
241#if defined(FBXSDK_COMPILER_MSC)
242 #pragma warning (push)
243 #pragma warning (disable: 4355)
244#endif
245
246class FBXSDK_DLL FbxPropertyConnect
247{
248public:
249 FBXSDK_FRIEND_NEW();
250 static FbxPropertyConnect* Create(FbxPropertyPage* pPage,FbxInt pId) { return FbxNew< FbxPropertyConnect >(pPage,pId); }
251 void Destroy() { FbxDelete(this); }
252 FbxPropertyConnect* Clone(FbxPropertyPage* pPage)
253 {
254 return FbxNew< FbxPropertyConnect >(pPage,mId);
255 }
256
257 inline void IncRef() { mRef++; }
258 inline void DecRef() { mRef--; if (mRef==0) FbxDelete(this); }
259 inline int GetRef() { return mRef; }
260
261// Properties
262 FbxPropertyPage* GetPage() { return mPage; }
263 FbxInt GetPropertyId() { return mId; }
264
265// ClearConnectCache()
266// ------------------------------------------------------
267 inline void ClearConnectCache()
268 {
269 mConnectionPoint.SubConnectRemoveAll();
270 }
271
272 //! Clear all connect without sending any notification (Internal use ONLY)
273 inline void WipeAllConnections()
274 {
275 mConnectionPoint.WipeConnectionList();
276 }
277
278// Properties
279 inline bool ConnectSrc(FbxPropertyConnect* pSrc, FbxConnection::EType pType)
280 {
281 return mConnectionPoint.ConnectSrc(&pSrc->mConnectionPoint,pType);
282 }
283 inline bool DisconnectSrc(FbxPropertyConnect* pSrc)
284 {
285 return mConnectionPoint.DisconnectSrc(&pSrc->mConnectionPoint);
286 }
287 inline bool IsConnectedSrc(FbxPropertyConnect* pSrc)
288 {
289 return mConnectionPoint.IsConnectedSrc(&pSrc->mConnectionPoint);
290 }
291 inline int GetSrcCount(FbxConnectionPointFilter* pFilter)
292 {
293 return mConnectionPoint.GetSrcCount(pFilter);
294 }
295 inline FbxPropertyConnect* GetSrc(FbxConnectionPointFilter* pFilter, int pIndex)
296 {
297 FbxConnectionPoint *lCP = mConnectionPoint.GetSrc(pIndex,pFilter);
298 return lCP ? (FbxPropertyConnect * )lCP->GetData() : 0;
299 }
300 inline bool ConnectDst(FbxPropertyConnect* pDst, FbxConnection::EType pType)
301 {
302 return mConnectionPoint.ConnectDst(&pDst->mConnectionPoint,pType);
303 }
304 inline bool IsConnectedDst(FbxPropertyConnect* pSrc)
305 {
306 return mConnectionPoint.IsConnectedSrc(&pSrc->mConnectionPoint);
307 }
308 inline bool DisconnectDst(FbxPropertyConnect* pDst)
309 {
310 return mConnectionPoint.DisconnectDst(&pDst->mConnectionPoint);
311 }
312 inline int GetDstCount(FbxConnectionPointFilter* pFilter)
313 {
314 return mConnectionPoint.GetDstCount(pFilter);
315 }
316 inline FbxPropertyConnect* GetDst(FbxConnectionPointFilter* pFilter, int pIndex)
317 {
318 FbxConnectionPoint *lCP = mConnectionPoint.GetDst(pIndex,pFilter);
319 return lCP ? (FbxPropertyConnect * )lCP->GetData() : 0;
320 }
321
322 int mRef;
323 FbxConnectionPoint mConnectionPoint;
324 FbxPropertyPage* mPage;
325 FbxInt mId;
326
327private:
328 FbxPropertyConnect(FbxPropertyPage* pPage,FbxInt pId) :
329 mRef(0),
330 mConnectionPoint(this),
331 mPage(pPage),
332 mId(pId)
333 {
334 }
335
336 ~FbxPropertyConnect(){ if( FbxObject::GetWipeMode() ) mConnectionPoint.WipeConnectionList(); }
337};
338
339#if defined(FBXSDK_COMPILER_MSC)
340 #pragma warning (pop)
341#endif
342
343class FBXSDK_DLL FbxPropertyEntry
344{
345public:
346 static FbxPropertyEntry* Create(FbxInt pParentId, FbxPropertyInfo* pInfo, FbxPropertyValue* pValue, FbxPropertyConnect* pConnect){ return FbxNew<FbxPropertyEntry>(pParentId, pInfo, pValue, pConnect); }
347
348 void Destroy() { FbxDelete(this); }
349
350 inline FbxInt GetParentId(){ return mParentId; }
351 inline bool IsEmpty(){ return (mInfo || mValue || mConnect || mFlags.GetMask() != 0) ? false : true; }
352
353 inline FbxPropertyInfo* Get(const FbxPropertyInfo* /*pType*/){ return mInfo; }
354
355 void Set(FbxPropertyInfo* pInfo)
356 {
357 FbxPropertyInfo* lInfo = mInfo;
358 if( pInfo ) pInfo->IncRef();
359 mInfo = pInfo;
360 if( lInfo ) lInfo->DecRef();
361 }
362
363 inline FbxPropertyValue* Get(const FbxPropertyValue* /*pType*/){ return mValue; }
364
365 void Set(FbxPropertyValue* pValue)
366 {
367 FbxPropertyValue* lValue = mValue;
368 if( pValue ) pValue->IncRef();
369 mValue = pValue;
370 if( lValue ) lValue->DecRef();
371 }
372
373 inline FbxPropertyConnect* Get(const FbxPropertyConnect* /*pType*/){ return mConnect; }
374
375 void Set(FbxPropertyConnect* pConnect)
376 {
377 FbxPropertyConnect* lConnect = mConnect;
378 if( pConnect ) pConnect->IncRef();
379 mConnect = pConnect;
380 if( lConnect ) lConnect->DecRef();
381 }
382
383 inline FbxPropertyFlags* Get(const FbxPropertyFlags* /*pType*/){ return &mFlags; }
384 inline void Set(FbxPropertyFlags pType){ mFlags = pType; }
385 inline void Set(FbxPropertyFlags* pType){ mFlags = pType ? *pType : FbxPropertyFlags(FbxPropertyFlags::eNone); }
386
387private:
388 FbxPropertyEntry(FbxInt pParentId,FbxPropertyInfo *pInfo,FbxPropertyValue *pValue,FbxPropertyConnect *pConnect) :
389 mInfo(pInfo),
390 mValue(pValue),
391 mConnect(pConnect),
392 mParentId(pParentId),
393 mFlags(FbxPropertyFlags::eNone)
394 {
395 if( mInfo ) mInfo->IncRef();
396 if( mValue ) mValue->IncRef();
397 if( mConnect ) mConnect->IncRef();
398 }
399
400 ~FbxPropertyEntry()
401 {
402 if( mInfo ) mInfo->DecRef();
403 if( mValue ) mValue->DecRef();
404 if( mConnect ) mConnect->DecRef();
405 }
406
407 FbxPropertyInfo* mInfo;
408 FbxPropertyValue* mValue;
409 FbxPropertyConnect* mConnect;
410 FbxInt mParentId;
411 FbxPropertyFlags mFlags;
412
413 FBXSDK_FRIEND_NEW();
414 friend class FbxPropertyPage;
415};
416
417class FBXSDK_DLL FbxPropertyIdGenerator
418{
419public:
420 FbxPropertyIdGenerator() : mRef(0), mNextId(0) {}
421
422 inline FbxInt GetNextId() const { return mNextId; }
423 inline FbxInt GetNextIdAndInc() { return mNextId++; }
424
425 inline void IncRef() { mRef++; }
426 inline void DecRef() { mRef--; if( mRef == 0 ) FbxDelete(this); }
427
428private:
429 FbxInt mRef, mNextId;
430};
431
432class FBXSDK_DLL FbxPropertyPage
433{
434
435public:
436 FBXSDK_FRIEND_NEW();
437 static FbxPropertyPage* Create (FbxPropertyPage* pInstanceOf=0) { return FbxNew< FbxPropertyPage >(pInstanceOf); }
438 static FbxPropertyPage* Create (const char* pName, FbxPropertyPage* pTypeInfo) { return FbxNew< FbxPropertyPage >(pName,pTypeInfo); }
439 static FbxPropertyPage* Create (const char* pName, EFbxType pType=eFbxUndefined) { return FbxNew< FbxPropertyPage >(pName,pType); }
440 void Destroy() { FbxDelete(this); }
441
442 template<class T> inline T* GetPropertyItem(const T* pItemType,FbxInt pIndex,FbxPropertyPage **pFoundIn=0) const
443 {
444 FbxPropertyPage* lReferencePage = 0;
445 FbxPropertyEntry* lReferenceEntry = GetPropertyEntry(pIndex,&lReferencePage);
446 if (pFoundIn) *pFoundIn = 0;
447 if (lReferenceEntry) {
448 T* lItem = lReferenceEntry->Get( FBX_TYPE(T) );
449 if (lItem) {
450 if (pFoundIn) *pFoundIn = lReferencePage;
451 return lItem;
452 } else {
453 return lReferencePage->mInstanceOf ? lReferencePage->mInstanceOf->GetPropertyItem(pItemType,pIndex,pFoundIn) : 0 ;
454 }
455 }
456 return 0;
457 }
458
459 template<class T> inline T* ChangePropertyItemState(const T* pItemType, FbxInt pIndex, FbxPropertyFlags::EInheritType pInheritType)
460 {
461 FbxPropertyPage* lReferencePage = NULL;
462 T* lItem = GetPropertyItem(pItemType, pIndex, &lReferencePage);
463 if( pInheritType == FbxPropertyFlags::eOverride )
464 {
465 if( lReferencePage == this )
466 {
467 return lItem;
468 }
469 else if( lItem )
470 {
471 FbxPropertyEntry* lEntry = ChangePropertyEntryState(pIndex, FbxPropertyFlags::eOverride);
472 lEntry->Set(lItem->Clone(this));
473 return lEntry->Get(FBX_TYPE(T));
474 }
475 }
476 else
477 {
478 // can't inherit entries that were created on our page.
479 bool lOwnEntry = !mInstanceOf || (mInstanceOf->GetPropertyItem(pItemType, pIndex) == NULL);
480 if( lOwnEntry && FbxPropertyFlags::eInherit == pInheritType) return 0;
481
482 if( lItem && (lReferencePage == this) )
483 {
484 FbxPropertyEntry* lEntry = GetPropertyEntry(pIndex);
485 lEntry->Set((T*)0);
486 if( lEntry->IsEmpty() )
487 {
488 ChangePropertyEntryState(pIndex, FbxPropertyFlags::eInherit);
489 }
490 }
491 return 0;
492 }
493 return 0;
494 }
495
496 template<class T> FbxPropertyPage* GetFirstPropertyItem(FbxInt pId, const T* pItem) const
497 {
498 FbxPropertyPage* lReferencePage = NULL;
499 GetPropertyItem(FBX_TYPE(T), pId, &lReferencePage);
500 if( lReferencePage && lReferencePage->mInstanceOf )
501 {
502 FbxPropertyPage* lReferencePage2 = lReferencePage->mInstanceOf->GetFirstPropertyItem(pId, pItem);
503 return lReferencePage2 ? lReferencePage2 : lReferencePage;
504 }
505 return lReferencePage;
506 }
507
508 const char* GetName(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT)
509 {
510 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
511 return lPropertyInfo ? ((const char*)lPropertyInfo->GetName()) : "";
512 }
513
514 const char* GetLabel(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT)
515 {
516 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
517 return lPropertyInfo ? ((const char*)lPropertyInfo->GetLabel()) : "";
518 }
519
520 bool SetLabel(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT, const char* pLabel="")
521 {
522 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
523 // Don't make it writeable (Keep it shared)
524 if (lPropertyInfo) {
525 lPropertyInfo->SetLabel(pLabel);
526 return true;
527 } else {
528 return false;
529 }
530 }
531
532 void* GetUserData(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT)
533 {
534 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
535 return lPropertyInfo ? lPropertyInfo->GetUserData() : 0;
536 }
537
538 bool SetUserData(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT, const void* pUserData=0)
539 {
540 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
541 // Don't make it writeable (Keep it shared)
542 if (lPropertyInfo) {
543 lPropertyInfo->SetUserData(pUserData);
544 return true;
545 } else {
546 return false;
547 }
548 }
549
550 int GetUserTag(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT)
551 {
552 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
553 return lPropertyInfo ? lPropertyInfo->GetUserTag() : 0;
554 }
555
556 bool SetUserTag(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT,int pUserTag=0)
557 {
558 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
559 // Don't make it writeable (Keep it shared)
560 if (lPropertyInfo) {
561 lPropertyInfo->SetUserTag(pUserTag);
562 return true;
563 } else {
564 return false;
565 }
566 }
567
568 EFbxType GetType(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT) const
569 {
570 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
571 return lPropertyInfo ? lPropertyInfo->GetType() : eFbxUndefined;
572 }
573
574 FbxInt GetParent(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT) const
575 {
576 FbxPropertyEntry* lPropertyEntry = GetPropertyEntry( pId );
577 return lPropertyEntry ? lPropertyEntry->GetParentId() : FBXSDK_PROPERTY_ID_NULL;
578 }
579
580 FbxPropertyPage* GetTypeInfo(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT)
581 {
582 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
583 return lPropertyInfo ? lPropertyInfo->GetTypeInfo() : 0;
584 }
585 FbxInt Add(FbxInt pParentId, const char* pName, EFbxType pType)
586 {
587 return Add(pParentId,FbxPropertyInfo::Create(pName,pType),FbxPropertyValue::Create(0,pType),0);
588 }
589 FbxInt Add(FbxInt pParentId, const char* pName, FbxPropertyPage* pTypeInfo)
590 {
591 return Add(pParentId,FbxPropertyInfo::Create(pName,pTypeInfo),FbxPropertyValue::Create(0,pTypeInfo->GetType()),0);
592 }
593
594 inline bool Reparent( FbxInt /*pChildId*/, FbxInt /*pNewParentId*/ )
595 {
596 // Not implemented.
597 /*
598 if( GetParent(pChildId) != pNewParentId && pChildId < mEntries.GetCount() )
599 {
600 FbxPropertyEntry* lChildEntry = mEntries[pChildId];
601 lChildEntry->mParentId = pNewParentId;
602
603 //@@@@@ TODO: propagate to instances
604
605 return true;
606 }
607 */
608 return false;
609 }
610
611 inline bool IsChildOf(FbxInt pId,FbxInt pParentId) const
612 {
613 return GetParent(pId)==pParentId;
614
615 }
616
617 inline bool IsDescendentOf(FbxInt pId,FbxInt pAncestorId) const
618 {
619 if (pAncestorId>0) {
620 FbxInt lParentId = GetParent(pId);
621 while (lParentId != FBXSDK_PROPERTY_ID_NULL ) {
622 if (lParentId==pAncestorId) {
623 return true;
624 }
625 lParentId = GetParent(lParentId);
626 }
627 return false;
628 } else {
629 return true;
630 }
631
632 }
633
634 //#define PROPERTY_PAGE_SANITY_CHECK // Debug purpose only. Never enable it in a production release.
635
636 /** Retrieves the first child property id of a specified property id.
637 * \param pParentId The specified property id
638 * \return the first child property id
639 */
640 FbxInt GetChild(FbxInt pParentId=FBXSDK_PROPERTY_ID_ROOT) const
641 {
642 #ifdef PROPERTY_PAGE_SANITY_CHECK
643 FbxInt ret0 = FBXSDK_PROPERTY_ID_NULL;
644 if (pParentId!=FBXSDK_PROPERTY_ID_NULL) {
645 FbxInt lId = GetMinimumPropertyId(pParentId);
646 FbxInt lParentId = GetParent(lId);
647 const FbxInt lLastId = GetPropertyEntryCount();
648
649 while (lId<lLastId && lParentId!=pParentId) lParentId=GetParent(++lId);
650 ret0 = lId<lLastId ? lId : FBXSDK_PROPERTY_ID_NULL;
651 } else {
652 ret0 = FBXSDK_PROPERTY_ID_NULL;
653 }
654 #endif
655 FbxInt ret1 = FBXSDK_PROPERTY_ID_NULL;
656 if (pParentId != FBXSDK_PROPERTY_ID_NULL)
657 {
658 FbxPropertyEntry* lEntry;
659 FbxInt lId = pParentId;
660 do
661 {
662 lId = GetMinimumPropertyIdAndEntry(lId, &lEntry);
663 } while (lId != FBXSDK_PROPERTY_ID_NULL && lEntry->GetParentId() != pParentId);
664 ret1 = lId;
665 }
666 #ifdef PROPERTY_PAGE_SANITY_CHECK
667 FBX_ASSERT(ret0==ret1);
668 #endif
669 return ret1;
670 }
671
672 /** Retrieves the next sibling property id of a specified property id.
673 * \param pId The specified property id
674 * \return the next sibling property id
675 */
676 FbxInt GetSibling(FbxInt pId) const
677 {
678 #ifdef PROPERTY_PAGE_SANITY_CHECK
679 FbxInt pIdBackup = pId;
680 FbxInt ret0 = FBXSDK_PROPERTY_ID_NULL;
681 if (pId!=FBXSDK_PROPERTY_ID_NULL) {
682 FbxInt lReferenceParentId = GetParent(pId);
683 FbxInt lParentId = GetParent(++pId);
684 const FbxInt lLastId = GetPropertyEntryCount();
685
686 while (pId<lLastId && lReferenceParentId!=FBXSDK_PROPERTY_ID_NULL && lParentId!=lReferenceParentId)
687 lParentId=GetParent(++pId);
688 ret0 = pId<lLastId ? pId : FBXSDK_PROPERTY_ID_NULL;
689 } else {
690 ret0 = FBXSDK_PROPERTY_ID_NULL;
691 }
692 pId = pIdBackup;
693 #endif
694 FbxInt ret1 = FBXSDK_PROPERTY_ID_NULL;
695 if (pId != FBXSDK_PROPERTY_ID_NULL)
696 {
697 FbxInt lReferenceParentId = GetParent(pId);
698
699 if (lReferenceParentId != FBXSDK_PROPERTY_ID_NULL)
700 {
701 FbxPropertyEntry *lEntry;
702 do
703 {
704 pId = GetMinimumPropertyIdAndEntry(pId, &lEntry);
705 } while (pId != FBXSDK_PROPERTY_ID_NULL && lEntry->GetParentId() != lReferenceParentId);
706
707 ret1 = pId;
708 }
709 }
710
711 #ifdef PROPERTY_PAGE_SANITY_CHECK
712 FBX_ASSERT(ret0==ret1);
713 #endif
714 return ret1;
715 }
716
717 /** Retrieves the first descendent property id of a specified property id.
718 * \param pAnscestorId The specified property id
719 * \return the first descendent property id
720 */
721 FbxInt GetFirstDescendent(FbxInt pAnscestorId=FBXSDK_PROPERTY_ID_ROOT) const
722 {
723 #ifdef PROPERTY_PAGE_SANITY_CHECK
724 FbxInt ret0 = FBXSDK_PROPERTY_ID_NULL;
725 if (pAnscestorId!=FBXSDK_PROPERTY_ID_NULL) {
726 FbxInt lId = GetMinimumPropertyId(pAnscestorId);
727 FbxInt lParentId = GetParent(lId);
728 const FbxInt lLastId = GetPropertyEntryCount();
729
730 while (lId<lLastId) {
731 if( lParentId!=FBXSDK_PROPERTY_ID_NULL && IsDescendentOf(lId,pAnscestorId) )
732 {
733 ret0 = lId;
734 break;
735 }
736 lParentId = GetParent(++lId);
737 }
738 }
739 #endif
740 FbxInt ret1 = FBXSDK_PROPERTY_ID_NULL;
741 FbxInt lId = pAnscestorId;
742 FbxPropertyEntry* lEntry;
743 if (pAnscestorId != FBXSDK_PROPERTY_ID_NULL)
744 {
745 for(;;)
746 {
747 lId = GetMinimumPropertyIdAndEntry(lId, &lEntry);
748 if (lId == FBXSDK_PROPERTY_ID_NULL)
749 break;
750 if(lEntry->GetParentId() != FBXSDK_PROPERTY_ID_NULL && IsDescendentOf(lId, pAnscestorId))
751 {
752 ret1 = lId;
753 break;
754 }
755 }
756 }
757
758 #ifdef PROPERTY_PAGE_SANITY_CHECK
759 FBX_ASSERT(ret0==ret1);
760 #endif
761 return ret1;
762 }
763
764 /** Retrieves the next descendent property id of a specified property id, with given a descendent property id.
765 * \param pAnscestorId The specified property id
766 * \param pId The descendent property id
767 * \return the next descendent property id
768 */
769 FbxInt GetNextDescendent(FbxInt pAnscestorId, FbxInt pId) const
770 {
771 #ifdef PROPERTY_PAGE_SANITY_CHECK
772 FbxInt pIdBackup = pId;
773 FbxInt ret0 = FBXSDK_PROPERTY_ID_NULL;
774 if (pId!=FBXSDK_PROPERTY_ID_NULL) {
775 FbxInt lParentId = GetParent(++pId);
776 const FbxInt lLastId = GetPropertyEntryCount();
777
778 while (pId<lLastId) {
779 // GetParent returns null when the given id isn't in our page,
780 // or our ancestor's page.
781 if( lParentId != FBXSDK_PROPERTY_ID_NULL && IsDescendentOf(pId, pAnscestorId) )
782 {
783 ret0 = pId;
784 break;
785 }
786
787 lParentId = GetParent(++pId);
788 }
789 }
790
791 pId = pIdBackup;
792 #endif
793 FbxInt ret1 = FBXSDK_PROPERTY_ID_NULL;
794 if (pId != FBXSDK_PROPERTY_ID_NULL)
795 {
796 FbxPropertyEntry* lEntry;
797 for(;;)
798 {
799 pId = GetMinimumPropertyIdAndEntry(pId, &lEntry);
800 if (pId == FBXSDK_PROPERTY_ID_NULL)
801 break;
802 if(lEntry->GetParentId() != FBXSDK_PROPERTY_ID_NULL && IsDescendentOf(pId, pAnscestorId) )
803 {
804 ret1 = pId;
805 break;
806 }
807 }
808
809 }
810 #ifdef PROPERTY_PAGE_SANITY_CHECK
811 FBX_ASSERT(ret0==ret1);
812 #endif
813 return ret1;
814
815 }
816
817 FbxInt FastFind (FbxInt pId, const char* pName, FbxPropertyPage* pTypeInfo, bool pCaseSensitive)
818 {
819 FbxInt lId = FBXSDK_PROPERTY_ID_NULL;
820
821 bool lSlowQuery = true;
822 if( mNameMap.mSecond.GetSize() > 0 )
823 {
824 lSlowQuery = false;
825 // try to use the map if we've got it
826 NameMap::RecordType* lIterator = mNameMap.mSecond.Find( FbxNameMapKey( pId, pName ) );
827 if( !lIterator )
828 {
829 lId = FBXSDK_PROPERTY_ID_NULL;
830 }
831 else
832 {
833 lId = lIterator->GetValue();
834 if (lId != FBXSDK_PROPERTY_ID_NULL && pTypeInfo)
835 {
836 lSlowQuery = true;
837
838 // Try to match types.
839 // If they are mismatched, fall back to the slow query,
840 // since we might have multiple property with the same name but different types
841 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo), lId );
842 if (lPropertyInfo)
843 {
844 FbxPropertyPage* lTypeInfo2 = lPropertyInfo->GetTypeInfo();
845 if ( lTypeInfo2 && lTypeInfo2->Is(pTypeInfo) )
846 {
847 lSlowQuery = false;
848 }
849 }
850 }
851 }
852 }
853
854 if (!lSlowQuery)
855 return lId;
856
857 // fall back if there's no map or we got one with a different type
858
859 lId = GetChild(pId);
860 FbxStringSymbol lSearchSymbol( pName );
861 while( lId != FBXSDK_PROPERTY_ID_NULL ) {
862 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo), lId );
863 if ( (!pTypeInfo || lPropertyInfo->GetTypeInfo()->Is(pTypeInfo)) &&
864 ((!pCaseSensitive && FBXSDK_stricmp(lPropertyInfo->GetName(),pName)==0) ||
865 (pCaseSensitive && lPropertyInfo->GetName() == lSearchSymbol)) ) {
866 return lId;
867 }
868 lId = GetSibling(lId);
869 }
870
871 return FBXSDK_PROPERTY_ID_NULL;
872 }
873
874 FbxInt Find (FbxInt pId, const char* pName, FbxPropertyPage* pTypeInfo, bool pCaseSensitive, const char* pChildrenSeparators )
875 {
876 if (pChildrenSeparators)
877 {
878 FbxInt lId;
879 size_t lFoundIndex = strcspn(pName,pChildrenSeparators);
880
881 // Strip the first part of the name and search
882 if (lFoundIndex<strlen(pName))
883 {
884 FbxString pRootName;
885 pRootName.Append(pName,lFoundIndex);
886 lId = FastFind(pId,pRootName.Buffer(),NULL,pCaseSensitive);
887 return lId != FBXSDK_PROPERTY_ID_NULL ? Find(lId,pName+lFoundIndex+1,pTypeInfo,pCaseSensitive,pChildrenSeparators) : lId;
888 } else {
889 return FastFind(pId,pName,pTypeInfo,pCaseSensitive);
890 }
891 } else {
892 return FastFind(pId,pName,pTypeInfo,pCaseSensitive);
893 }
894 }
895
896// Enum list
897 int AddEnumValue(FbxInt pId, const char* pStringValue)
898 {
899 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
900 // Don't make it writeable (Keep it shared)
901 return lPropertyInfo ? lPropertyInfo->AddEnumValue(pStringValue) : - 1;
902 }
903
904 void InsertEnumValue(FbxInt pId, int pIndex, const char* pStringValue)
905 {
906 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
907 // Don't make it writeable (Keep it shared)
908 if (lPropertyInfo) lPropertyInfo->InsertEnumValue(pIndex,pStringValue);
909 }
910
911 int GetEnumCount(FbxInt pId)
912 {
913 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
914 // Don't make it writeable (Keep it shared)
915 return lPropertyInfo ? lPropertyInfo->GetEnumCount() : 0;
916 }
917
918 void SetEnumValue(FbxInt pId, int pIndex, const char* pStringValue)
919 {
920 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
921 // Don't make it writeable (Keep it shared)
922 if (lPropertyInfo) lPropertyInfo->SetEnumValue(pIndex,pStringValue);
923 }
924
925 void RemoveEnumValue(FbxInt pId, int pIndex)
926 {
927 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
928 // Don't make it writeable (Keep it shared)
929 if (lPropertyInfo) lPropertyInfo->RemoveEnumValue(pIndex);
930 }
931
932 char* GetEnumValue(FbxInt pId,int pIndex)
933 {
934 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
935 return lPropertyInfo ? lPropertyInfo->GetEnumValue(pIndex) : (char*)"";
936 }
937
938 // Connection
939 // ---------------------------------
940 void ClearConnectCache(FbxInt pId)
941 {
942 FbxPropertyPage* lReferencePage = 0;
943 FbxPropertyConnect* lPropertyConnect = GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pId,&lReferencePage );
944
945 // Connections are not considered propagated so
946 // make sure that we own the FbxPropertyConnect objects
947 if (lPropertyConnect) {
948 lPropertyConnect->ClearConnectCache();
949 }
950 }
951
952 void WipeAllConnections(FbxInt pId)
953 {
954 FbxPropertyPage* lReferencePage = 0;
955 FbxPropertyConnect* lPropertyConnect = GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pId,&lReferencePage );
956
957 if (lPropertyConnect) {
958 lPropertyConnect->WipeAllConnections();
959 }
960 }
961
962 bool ConnectSrc(FbxInt pDstId, FbxPropertyPage* pSrcPage, FbxInt pSrcId, FbxConnection::EType pType)
963 {
964 FbxPropertyEntry* lDstEntry = ChangePropertyEntryState(pDstId,FbxPropertyFlags::eOverride);
965 FbxPropertyEntry* lSrcEntry = pSrcPage->ChangePropertyEntryState(pSrcId,FbxPropertyFlags::eOverride);
966 FbxPropertyConnect* lDstConnect= lDstEntry->Get( FBX_TYPE(FbxPropertyConnect) );
967 FbxPropertyConnect* lSrcConnect= lSrcEntry->Get( FBX_TYPE(FbxPropertyConnect) );
968
969 // Make sure we have a connection point on both sides of the connection
970 if (!lDstConnect) {
971 lDstConnect = FbxPropertyConnect::Create( this,pDstId );
972 lDstEntry->Set( lDstConnect );
973 }
974 if (!lSrcConnect) {
975 lSrcConnect = FbxPropertyConnect::Create( pSrcPage,pSrcId );
976 lSrcEntry->Set( lSrcConnect );
977 }
978
979 // Must @@@@@@@ Propagate to inherited children
980 return lDstConnect->ConnectSrc(lSrcConnect,pType);
981
982 }
983
984 bool DisconnectSrc(FbxInt pDstId,FbxPropertyPage* pSrcPage,FbxInt pSrcId)
985 {
986 FbxPropertyPage* lDstReferencePage = 0;
987 FbxPropertyConnect* lDstConnect = GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pDstId,&lDstReferencePage );
988 FbxPropertyPage* lSrcReferencePage = 0;
989 FbxPropertyConnect* lSrcConnect = pSrcPage->GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pSrcId,&lSrcReferencePage );
990
991 // Make sure we have a connection point on both sides of the connection
992 if (lDstConnect && lSrcConnect && lDstReferencePage==this && lSrcReferencePage==pSrcPage) {
993 // Must @@@@@@@ Remove unused connections
994 return lDstConnect->DisconnectSrc(lSrcConnect);
995 }
996 return false;
997 }
998
999 bool IsConnectedSrc(FbxInt pDstId, FbxPropertyPage* pSrcPage, FbxInt pSrcId)
1000 {
1001 FbxPropertyPage* lDstReferencePage = 0;
1002 FbxPropertyConnect* lDstConnect = GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pDstId,&lDstReferencePage );
1003 FbxPropertyPage* lSrcReferencePage = 0;
1004 FbxPropertyConnect* lSrcConnect = pSrcPage->GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pSrcId,&lSrcReferencePage );
1005
1006 // Make sure we have a connection point on both sides of the connection
1007 if (lDstConnect && lSrcConnect && lDstReferencePage==this && lSrcReferencePage==pSrcPage) {
1008 // Must @@@@@@@ Remove unused connections
1009 return lDstConnect->IsConnectedSrc(lSrcConnect);
1010 }
1011 return false;
1012 }
1013
1014 int GetSrcCount(FbxInt pId, FbxConnectionPointFilter* pFilter)
1015 {
1016 FbxPropertyPage* lReferencePage = 0;
1017 FbxPropertyConnect* lPropertyConnect = GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pId,&lReferencePage );
1018
1019 // Connections are not considered propagated so
1020 // make sure that we own the FbxPropertyConnect objects
1021 return (lPropertyConnect && lReferencePage==this) ? lPropertyConnect->GetSrcCount(pFilter) : 0;
1022 }
1023
1024 bool GetSrc(FbxInt pId, int pIndex, FbxConnectionPointFilter* pFilter, FbxPropertyPage** pSrcPage, FbxInt* pSrcId)
1025 {
1026 FbxPropertyPage* lReferencePage = 0;
1027 FbxPropertyConnect* lPropertyConnect = GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pId,&lReferencePage );
1028
1029 // Connections are always overridden
1030 // make sure that we own the FbxPropertyConnect Item
1031 if (lPropertyConnect && lReferencePage==this)
1032 {
1033 FbxPropertyConnect* lSrc = lPropertyConnect->GetSrc(pFilter,pIndex);
1034 if (lSrc)
1035 {
1036 if (pSrcPage) *pSrcPage = lSrc->GetPage();
1037 if (pSrcId) *pSrcId = lSrc->GetPropertyId();
1038 return true;
1039 }
1040 }
1041 return false;
1042 }
1043
1044 bool ConnectDst(FbxInt pSrcId, FbxPropertyPage* pDstPage, FbxInt pDstId, FbxConnection::EType pType)
1045 {
1046 return pDstPage->ConnectSrc(pDstId,this,pSrcId,pType);
1047 }
1048
1049 bool DisconnectDst(FbxInt pSrcId, FbxPropertyPage* pDstPage, FbxInt pDstId)
1050 {
1051 return pDstPage->DisconnectSrc(pDstId,this,pSrcId);
1052 }
1053
1054 bool IsConnectedDst(FbxInt pSrcId, FbxPropertyPage* pDstPage, FbxInt pDstId)
1055 {
1056 return pDstPage->IsConnectedSrc(pDstId,this,pSrcId);
1057 }
1058
1059 int GetDstCount(FbxInt pId, FbxConnectionPointFilter* pFilter)
1060 {
1061 FbxPropertyPage* lReferencePage = 0;
1062 FbxPropertyConnect* lPropertyConnect = GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pId,&lReferencePage );
1063
1064 // Connections are not considered propagated so
1065 // make sure that we own the FbxPropertyConnect objects
1066 return (lPropertyConnect && lReferencePage==this) ? lPropertyConnect->GetDstCount(pFilter) : 0;
1067 }
1068
1069 bool GetDst(FbxInt pId, int pIndex, FbxConnectionPointFilter* pFilter, FbxPropertyPage** pDstPage, FbxInt* pDstId)
1070 {
1071 FbxPropertyPage* lReferencePage = 0;
1072 FbxPropertyConnect* lPropertyConnect = GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pId,&lReferencePage );
1073
1074 // Connections are always overridden
1075 // make sure that we own the FbxPropertyConnect Item
1076 if (lPropertyConnect && lReferencePage==this)
1077 {
1078 FbxPropertyConnect* lDst = lPropertyConnect->GetDst(pFilter,pIndex);
1079 if (lDst)
1080 {
1081 if (pDstPage) *pDstPage = lDst->GetPage();
1082 if (pDstId) *pDstId = lDst->GetPropertyId();
1083 return true;
1084 }
1085 }
1086 return false;
1087 }
1088
1089 // Min and Max
1090 // ---------------------------------
1091 enum EValueIndex { eValueMin,eValueSoftMin,eValueMax,eValueSoftMax,eValueCount };
1092
1093 bool HasMinMax(FbxInt pId, FbxPropertyInfo::EValueIndex pValueId) const
1094 {
1095 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
1096
1097 return lPropertyInfo ? lPropertyInfo->HasMinMax(pValueId) : false;
1098 }
1099
1100 bool GetMinMax(FbxInt pId, FbxPropertyInfo::EValueIndex pValueId, void* pValue, EFbxType pValueType)
1101 {
1102 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
1103 // Don't make it writeable (Keep it shared)
1104 return lPropertyInfo ? lPropertyInfo->GetMinMax(pValueId,pValue,pValueType) : false;
1105 }
1106
1107 bool SetMinMax(FbxInt pId, FbxPropertyInfo::EValueIndex pValueId, const void* pValue, EFbxType pValueType)
1108 {
1109 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
1110 // Don't make it writeable (Keep it shared)
1111 return lPropertyInfo ? lPropertyInfo->SetMinMax(pValueId,pValue,pValueType) : false;
1112 }
1113
1114 // Value
1115 // ---------------------------------
1116 bool Get(FbxInt pId, void* pValue, EFbxType pValueType)
1117 {
1118 FbxPropertyValue* lPropertyValue = GetPropertyItem( FBX_TYPE(FbxPropertyValue),pId );
1119 return lPropertyValue ? lPropertyValue->Get(pValue,pValueType) : 0;
1120 }
1121
1122 bool Set(FbxInt pId, const void* pValue, EFbxType pValueType, bool pCheckValueEquality)
1123 {
1124 if( pCheckValueEquality )
1125 {
1126 FbxPropertyPage* lReferencePage = NULL;
1127 FbxPropertyValue* lPropertyValue = GetPropertyItem( FBX_TYPE(FbxPropertyValue),pId,&lReferencePage );
1128 void* lCurrentValue = FbxTypeAllocate( pValueType );
1129 bool lValuesEqual = false;
1130 bool lValueChanged = false;
1131 if( lReferencePage && lReferencePage != this )
1132 {
1133 // this page inherits, so check if we have to override the value.
1134 if( lPropertyValue )
1135 {
1136 lPropertyValue->Get( lCurrentValue, pValueType );
1137 lValuesEqual = FbxTypeCompare( pValue, lCurrentValue, pValueType );
1138 }
1139 }
1140 else
1141 {
1142 FbxPropertyPage* lReferencePage2 = NULL;
1143 FbxPropertyValue* lPropertyValue2 = mInstanceOf ? mInstanceOf->GetPropertyItem( FBX_TYPE(FbxPropertyValue),pId,&lReferencePage2 ) : NULL;
1144 if( lReferencePage2 && lPropertyValue2 )
1145 {
1146 // this page is an override, but there is another page before us that overrides the value
1147 lPropertyValue2->Get( lCurrentValue, pValueType );
1148 lValuesEqual = FbxTypeCompare( pValue, lCurrentValue, pValueType );
1149
1150 if( lValuesEqual )
1151 {
1152 ChangePropertyItemState( FBX_TYPE(FbxPropertyValue), pId, FbxPropertyFlags::eInherit );
1153 lValueChanged = true;
1154 }
1155
1156 }
1157 // else this page is the originator of the property, so no need to check,
1158 }
1159
1160 FbxTypeDeallocate(pValueType, lCurrentValue);
1161 lCurrentValue = NULL;
1162
1163 if( lValuesEqual )
1164 return lValueChanged;
1165 }
1166
1167 FbxPropertyValue* lPropertyValue = ChangePropertyItemState( FBX_TYPE(FbxPropertyValue),pId,FbxPropertyFlags::eOverride );
1168 return lPropertyValue ? lPropertyValue->Set(pValue,pValueType) : false;
1169 }
1170
1171 inline FbxPropertyFlags::EInheritType GetValueInherit(FbxInt pId, bool pCheckInstanceOf) const
1172 {
1173 FbxPropertyPage* lReferencePage = NULL;
1174 GetPropertyItem(FBX_TYPE(FbxPropertyValue), pId, &lReferencePage);
1175
1176 // check one level
1177 if( !pCheckInstanceOf )
1178 {
1179 return lReferencePage == this ? FbxPropertyFlags::eOverride : FbxPropertyFlags::eInherit;
1180 }
1181 else
1182 {
1183 if( lReferencePage == this ) return FbxPropertyFlags::eOverride; // this page is either an override, or the originator
1184 else if( !lReferencePage->mInstanceOf ) return FbxPropertyFlags::eInherit; // the reference is the class root, so we must be inheriting
1185
1186 // The reference page is not the class root, might be another override, or the originator.
1187 FbxPropertyValue* lPropertyValue = lReferencePage->mInstanceOf->GetPropertyItem( FBX_TYPE(FbxPropertyValue), pId );
1188
1189 // if lReferencePage->mInstanceOf has the property value,
1190 // lReferencePage is an override
1191 // else
1192 // its the originator, so this page inherits from it.
1193 return lPropertyValue ? FbxPropertyFlags::eOverride : FbxPropertyFlags::eInherit;
1194 }
1195 }
1196
1197 inline bool SetValueInherit(FbxInt pId, FbxPropertyFlags::EInheritType pType)
1198 {
1199 // no support for this mode yet
1200 if( FbxPropertyFlags::eDeleted == pType )
1201 return false;
1202
1203 ChangePropertyItemState( FBX_TYPE(FbxPropertyValue), pId, pType );
1204
1205 // Above call doesn't return error codes, so just check that we match types.
1206 return GetValueInherit(pId, false) == pType;
1207 }
1208
1209 inline bool GetDefaultValue(FbxInt pId, void* pValue, EFbxType pValueType) const
1210 {
1211 FbxPropertyPage* lReferencePage = GetFirstPropertyItem( pId, FBX_TYPE(FbxPropertyValue) );
1212 FbxPropertyValue* lPropertyValue = lReferencePage ? lReferencePage->GetPropertyItem( FBX_TYPE(FbxPropertyValue), pId ) : NULL;
1213
1214 return lPropertyValue ? lPropertyValue->Get( pValue, pValueType ) : false;
1215 }
1216
1217
1218 // useful set and get functions
1219 template <class T> inline bool Set( FbxInt pId, const T& pValue ) { return Set( pId,&pValue,FbxTypeOf(pValue),true ); }
1220 template <class T> inline T Get( FbxInt pId, const T* pFBX_TYPE) { T lValue; Get( pId,&lValue,FbxTypeOf(lValue) ); return lValue; }
1221
1222
1223 void SetDataPtr(void* pDataPtr) { mDataPtr = pDataPtr; }
1224 void* GetDataPtr() const { return mDataPtr; }
1225
1226 // Instance and override management
1227 // ------------------------------------------
1228 void PushPropertiesToParentInstance()
1229 {
1230 if (mInstanceOf) {
1231 const int lCount = GetPropertyEntryCount();
1232 // push the existing properties into the parent
1233 // ----------------------------------------------
1234 for( int i = 0; i < lCount; ++i )
1235 {
1236 FbxPropertyEntry* lParentEntry = mInstanceOf->ChangePropertyEntryState( (FbxInt)i,FbxPropertyFlags::eOverride );
1237 FbxPropertyEntry* lEntry = GetPropertyEntry( (FbxInt)i );
1238
1239 if( !lParentEntry )
1240 {
1241 lParentEntry = FbxPropertyEntry::Create( lEntry->GetParentId(), 0, 0, 0 );
1242 mInstanceOf->mEntryMap.Insert( i, lParentEntry );
1243
1244 //mInstanceOf->AddChild(i);
1245
1246 }
1247
1248 FBX_ASSERT( lParentEntry );
1249
1250 // Add it to the parent
1251 // Don't touch the connections
1252 // -----------------------------------------
1253 if (lParentEntry) {
1254 lParentEntry->Set( lEntry->Get(FBX_TYPE(FbxPropertyInfo)) );
1255 lParentEntry->Set( lEntry->Get(FBX_TYPE(FbxPropertyValue)) );
1256 lParentEntry->Set( lEntry->Get(FBX_TYPE(FbxPropertyFlags)) );
1257 }
1258
1259 /*
1260 else {
1261 mInstanceOf->Add(
1262 lEntry->GetParentId(),
1263 lEntry->Get(FBX_TYPE(FbxPropertyInfo)), // The info
1264 lEntry->Get(FBX_TYPE(FbxPropertyValue)), // The Value
1265 0, // The connections
1266 false,
1267 false
1268 );
1269 }
1270 */
1271
1272 // Empty the current entry
1273 // Don't touch the connections
1274 // -----------------------------------------
1275 ChangePropertyItemState(FBX_TYPE(FbxPropertyInfo), i,FbxPropertyFlags::eInherit);
1276 ChangePropertyItemState(FBX_TYPE(FbxPropertyValue), i,FbxPropertyFlags::eInherit);
1277 ChangePropertyItemState(FBX_TYPE(FbxPropertyFlags), i,FbxPropertyFlags::eInherit);
1278 }
1279 }
1280 }
1281
1282 inline const FbxPropertyPage* GetInstanceOf() const { return mInstanceOf; }
1283 inline FbxPropertyPage* GetInstanceOf() { return mInstanceOf; }
1284
1285 inline const FbxArray<FbxPropertyPage*>& GetInstances() const { return mInstances; }
1286 inline FbxArray<FbxPropertyPage*>& GetInstances() { return mInstances; }
1287
1288
1289 // Flags
1290 // ------------------------------------------
1291 FbxPropertyFlags::EFlags GetFlags(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT) const
1292 {
1293 FbxPropertyPage* lFoundIn = NULL;
1294 FbxPropertyFlags* lPropertyFlags = GetPropertyItem( FBX_TYPE(FbxPropertyFlags), pId, &lFoundIn );
1295 FbxPropertyFlags::EFlags lFlags = FbxPropertyFlags::eNone;
1296
1297 if( lPropertyFlags )
1298 {
1299 if( !mInstanceOf ) // no inheritance.
1300 lFlags = lPropertyFlags->GetFlags();
1301 else
1302 {
1303 lFlags = mInstanceOf->GetFlags(pId);
1304 lFlags = lPropertyFlags->GetMergedFlags(lFlags);
1305 }
1306 }
1307 return lFlags;
1308 }
1309
1310 bool ModifyFlags(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT,FbxPropertyFlags::EFlags pFlags=FbxPropertyFlags::eNone,bool pValue=true,bool pCheckFlagEquality=true)
1311 {
1312 if( pCheckFlagEquality )
1313 {
1314 FbxPropertyPage* lFoundIn = NULL;
1315 FbxPropertyFlags* lFlag = GetPropertyItem( FBX_TYPE(FbxPropertyFlags), pId, &lFoundIn );
1316
1317 if( lFlag )
1318 {
1319 if( lFoundIn == this )
1320 {
1321 // set them in us.
1322 lFlag->ModifyFlags( pFlags, pValue );
1323
1324 // we override this entry, check if we need to revert
1325 FbxPropertyFlags* lInheritedFlags = mInstanceOf ? mInstanceOf->GetPropertyItem( FBX_TYPE(FbxPropertyFlags), pId ) : NULL;
1326 if( lInheritedFlags && lInheritedFlags->Equal( *lFlag, pFlags ) )
1327 {
1328 lFlag->UnsetMask( pFlags );
1329
1330 if( lFlag->GetMask() == 0 )
1331 ChangePropertyItemState( FBX_TYPE(FbxPropertyFlags), pId, FbxPropertyFlags::eInherit );
1332
1333 return true;
1334 }
1335 }
1336 else
1337 {
1338 // its not us. Just check if we need to set.
1339 FbxPropertyFlags lNewValues( pFlags );
1340 if( lFlag->Equal( lNewValues, pFlags ) )
1341 return true;
1342 }
1343 }
1344 }
1345
1346 FbxPropertyFlags* lPropertyFlags = ChangePropertyItemState(FBX_TYPE(FbxPropertyFlags), pId, FbxPropertyFlags::eOverride);
1347 return lPropertyFlags ? lPropertyFlags->ModifyFlags( pFlags, pValue ) : false;
1348 }
1349
1350 FbxPropertyFlags::EInheritType GetFlagsInheritType(FbxPropertyFlags::EFlags pFlags, bool pCheckInstanceOf, FbxInt pId=FBXSDK_PROPERTY_ID_ROOT) const
1351 {
1352 FbxPropertyPage* lFoundIn = NULL;
1353 FbxPropertyFlags* lPropertyFlags = GetPropertyItem( FBX_TYPE(FbxPropertyFlags), pId, &lFoundIn );
1354
1355 if( !pCheckInstanceOf )
1356 return lFoundIn != this ? FbxPropertyFlags::eInherit : ( lPropertyFlags ? lPropertyFlags->GetFlagsInheritType(pFlags) : FbxPropertyFlags::eInherit );
1357 else
1358 {
1359 // This code basically counts the number of overrides for the
1360 // given flags. The original entry is always considered an override.
1361 // so if we see more than one, something overrode the original.
1362 // and thus we are an override.
1363 FbxPropertyPage* lRefPage = lFoundIn;
1364 bool lFoundOverride = false;
1365 while( lRefPage )
1366 {
1367 lPropertyFlags = lRefPage->GetPropertyItem( FBX_TYPE(FbxPropertyFlags), pId );
1368
1369 if( !lPropertyFlags )
1370 break; // gone too far, break.
1371
1372 if( lPropertyFlags->GetFlagsInheritType( pFlags ) == FbxPropertyFlags::eOverride )
1373 {
1374 if( this == lRefPage || lFoundOverride )
1375 return FbxPropertyFlags::eOverride; // found two overrides or this page is the override.
1376 else
1377 lFoundOverride = true; // signal that we found the first override.
1378 }
1379 lRefPage = lRefPage->mInstanceOf;
1380 }
1381
1382 return FbxPropertyFlags::eInherit;
1383 }
1384 }
1385
1386 bool SetFlagsInheritType(FbxPropertyFlags::EInheritType pInheritType, FbxPropertyFlags::EFlags pFlags, FbxInt pId=FBXSDK_PROPERTY_ID_ROOT)
1387 {
1388 FbxPropertyPage* lFoundIn = NULL;
1389 FbxPropertyFlags* lPropertyFlags = NULL;
1390
1391 if( FbxPropertyFlags::eOverride == pInheritType )
1392 {
1393 lPropertyFlags = ChangePropertyItemState( FBX_TYPE(FbxPropertyFlags), pId, FbxPropertyFlags::eOverride );
1394
1395 // we should initialize our flag to the inherited value, if any.
1396 FbxPropertyFlags* lParentFlags = mInstanceOf ? mInstanceOf->GetPropertyItem( FBX_TYPE(FbxPropertyFlags), pId ) : NULL;
1397 if( lParentFlags && lPropertyFlags )
1398 {
1399 FbxPropertyFlags::EFlags lParentValues = lParentFlags->GetFlags();
1400 lPropertyFlags->SetFlags( pFlags, lParentValues );
1401 return lPropertyFlags->SetMask( pFlags );
1402 }
1403
1404 return false;
1405 }
1406 else if( FbxPropertyFlags::eInherit == pInheritType )
1407 {
1408 lPropertyFlags = GetPropertyItem(FBX_TYPE(FbxPropertyFlags), pId, &lFoundIn);
1409 if( !lPropertyFlags ) return false;
1410 if( lFoundIn != this ) return true; // not us
1411 lPropertyFlags->UnsetMask( pFlags );
1412 if( lPropertyFlags->GetMask() == 0 ) // revert
1413 ChangePropertyItemState( FBX_TYPE(FbxPropertyFlags), pId, FbxPropertyFlags::eInherit );
1414
1415 return true;
1416 }
1417 return false;
1418 }
1419
1420 inline void BeginCreateOrFindProperty()
1421 {
1422 if( 0 == mNameMap.mFirst )
1423 {
1424 mNameMap.mSecond.Reserve(20);
1425
1426 // push the existing properties into the map. Note: this includes the root property!
1427 FbxInt lFoundId = FBXSDK_PROPERTY_ID_ROOT;
1428 FbxPropertyEntry* lEntry = GetPropertyEntry(lFoundId);
1429 while(lFoundId != FBXSDK_PROPERTY_ID_NULL)
1430 {
1431 FbxPropertyInfo* lInfo = lEntry->Get(FBX_TYPE(FbxPropertyInfo));
1432 //FBX_ASSERT( lInfo );
1433 if (lInfo)
1434 {
1435 mNameMap.mSecond.Insert(FbxNameMapKey(lEntry->GetParentId(), lInfo->GetName()), lFoundId);
1436 }
1437 lFoundId = GetMinimumPropertyIdAndEntry(lFoundId, &lEntry);
1438 }
1439 mNameMap.mFirst++;
1440 }
1441 }
1442
1443 inline void EndCreateOrFindProperty()
1444 {
1445 if( mNameMap.mFirst > 0 )
1446 {
1447 if( --(mNameMap.mFirst) == 0 )
1448 mNameMap.mSecond.Clear();
1449 }
1450 }
1451
1452protected:
1453 FbxPropertyPage(FbxPropertyPage* pInstanceOf=0)
1454 : mInstanceOf(0)
1455 , mDataPtr(0)
1456 , mPropNextId(0)
1457 {
1458 mEntryMap.Reserve(32);
1459 mNameMap.mFirst = 0;
1460
1461 // instances don't need to create a root property
1462 if( !pInstanceOf )
1463 {
1464 mPropNextId = FbxNew< FbxPropertyIdGenerator >();
1465 mPropNextId->IncRef();
1466
1467 // First item is the root information
1468 Add(FBXSDK_PROPERTY_ID_NULL,"",eFbxUndefined);
1469 }
1470
1471 // Hook the instances
1472 // ------------------------
1473 mInstanceOf = pInstanceOf;
1474 if (mInstanceOf) {
1475 mInstanceOf->mInstances.Add(this);
1476
1477 mPropNextId = mInstanceOf->mPropNextId;
1478 mPropNextId->IncRef();
1479 }
1480 }
1481 FbxPropertyPage(const char* pName, EFbxType pType)
1482 : mInstanceOf(0)
1483 , mDataPtr(0)
1484 , mPropNextId(0)
1485 {
1486 mEntryMap.Reserve(32);
1487 mNameMap.mFirst = 0;
1488
1489 mPropNextId = FbxNew< FbxPropertyIdGenerator >();
1490 mPropNextId->IncRef();
1491
1492 // First item is the root information
1493 Add(FBXSDK_PROPERTY_ID_NULL,pName,pType);
1494 }
1495 FbxPropertyPage(const char* pName, FbxPropertyPage* pTypeInfo)
1496 : mInstanceOf(0)
1497 , mDataPtr(0)
1498 , mPropNextId(0)
1499 {
1500 mEntryMap.Reserve(32);
1501 mNameMap.mFirst = 0;
1502
1503 mPropNextId = FbxNew< FbxPropertyIdGenerator >();
1504 mPropNextId->IncRef();
1505
1506 // First item is the root information
1507 Add(FBXSDK_PROPERTY_ID_NULL,pName,pTypeInfo);
1508 }
1509 ~FbxPropertyPage()
1510 {
1511 // Propagate our property entries.
1512 int i = 0, j = 0;
1513 for( i = 0; i < mInstances.GetCount(); ++i )
1514 {
1515 for( j = 0; j < GetPropertyEntryCount(); ++j )
1516 {
1517 if( mInstances[i]->ChangePropertyEntryState((FbxInt)j, FbxPropertyFlags::eOverride) )
1518 {
1519 // Clone the info and values. Don't clone the connections,
1520 // since they aren't propagated.
1521 mInstances[i]->ChangePropertyItemState( FBX_TYPE(FbxPropertyInfo), (FbxInt)j, FbxPropertyFlags::eOverride );
1522 mInstances[i]->ChangePropertyItemState( FBX_TYPE(FbxPropertyValue), (FbxInt)j, FbxPropertyFlags::eOverride );
1523
1524 // Since all entries have their own flags, just override the ones in the instance.
1525 mInstances[i]->SetFlagsInheritType(FbxPropertyFlags::eOverride, FbxPropertyFlags::eAllFlags, (FbxInt)j );
1526 }
1527 }
1528
1529 // Instances become their own copies.
1530 mInstances[i]->mInstanceOf = NULL;
1531 }
1532
1533 FbxMapDestroy(mEntryMap);
1534
1535 if (mInstanceOf) {
1536 int lIndex = mInstanceOf->mInstances.Find(this);
1537 mInstanceOf->mInstances.SetAt(lIndex, mInstanceOf->mInstances[mInstanceOf->mInstances.GetCount()-1]);
1538 mInstanceOf->mInstances.RemoveAt(mInstanceOf->mInstances.GetCount()-1);
1539
1540 //mInstanceOf->mInstances.RemoveIt(this);
1541 }
1542
1543 mPropNextId->DecRef();
1544 mPropNextId = NULL;
1545
1546 mInstanceOf = NULL;
1547 mInstances.Clear();
1548 }
1549
1550 inline bool Is(FbxPropertyPage* pPage)
1551 {
1552 // @@@@@@@@@@@@@@@ Must complete for sub types
1553 return this==pPage;
1554 }
1555
1556// Internal entry management
1557private:
1558
1559 /** Retrieves the smallest property id of which are larger than a specified one.
1560 * \param pId The specified property id
1561 * \param pIncrementIfNone Whether it returns FBXSDK_PROPERTY_ID_NULL or pId+1, if not found.
1562 * \return The property id described above.
1563 */
1564 FbxInt GetMinimumPropertyId(FbxInt pId, bool pIncrementIfNone = true) const
1565 {
1566 if( pId == FBXSDK_PROPERTY_ID_NULL )
1567 pId = FBXSDK_PROPERTY_ID_ROOT;
1568
1569 FbxInt lMin = FBXSDK_PROPERTY_ID_NULL;
1570 const EntryMap::RecordType* lElement = mEntryMap.UpperBound(pId);
1571 if (NULL != lElement)
1572 {
1573 lMin = lElement->GetKey();
1574 }
1575
1576 FbxInt lParentMin = mInstanceOf ? mInstanceOf->GetMinimumPropertyId(pId,false) : FBXSDK_PROPERTY_ID_NULL;
1577
1578 bool lParentNull = lParentMin == FBXSDK_PROPERTY_ID_NULL;
1579 bool lMinNull = lMin == FBXSDK_PROPERTY_ID_NULL;
1580
1581 if( lParentNull && lMinNull ) return pIncrementIfNone ? pId+1 : FBXSDK_PROPERTY_ID_NULL;
1582 else if( lMinNull ) lMin = lParentMin;
1583 else if( !lParentNull ) lMin = lMin < lParentMin ? lMin : lParentMin;
1584
1585 return lMin;
1586 }
1587
1588 /** Retrieves the smallest property id of which are larger than a specified one, and retrieve its entry.
1589 * \param pId The specified property id
1590 * \param pEntry The returned property entry
1591 * \return The property id described above.
1592 */
1593 FbxInt GetMinimumPropertyIdAndEntry(FbxInt pId, FbxPropertyEntry** pEntry) const
1594 {
1595 FbxInt lFoundId = FBXSDK_PROPERTY_ID_NULL;
1596 FbxPropertyEntry* lFoundEntry = NULL;
1597 if( pId == FBXSDK_PROPERTY_ID_NULL )
1598 pId = FBXSDK_PROPERTY_ID_ROOT;
1599
1600 const EntryMap::RecordType* lElement = mEntryMap.UpperBound(pId);
1601 if (NULL != lElement)
1602 {
1603 lFoundId = lElement->GetKey();
1604 lFoundEntry = lElement->GetValue();
1605 }
1606
1607 FbxPropertyEntry* lParentEntry = NULL;
1608 FbxInt lParentMin = mInstanceOf ? mInstanceOf->GetMinimumPropertyIdAndEntry(pId, &lParentEntry) : FBXSDK_PROPERTY_ID_NULL;
1609
1610 bool lParentNull = lParentMin == FBXSDK_PROPERTY_ID_NULL;
1611 bool lMinNull = lFoundId == FBXSDK_PROPERTY_ID_NULL;
1612
1613 if( lMinNull && !lParentNull )
1614 {
1615 lFoundId = lParentMin;
1616 lFoundEntry = lParentEntry;
1617 }
1618 else if( !lMinNull && !lParentNull )
1619 {
1620 lFoundId = lFoundId < lParentMin ? lFoundId : lParentMin;
1621 lFoundEntry = lFoundId < lParentMin ? lFoundEntry : lParentEntry;
1622 }
1623
1624 if (pEntry)
1625 *pEntry = lFoundEntry;
1626 return lFoundId;
1627 }
1628
1629 int GetPropertyEntryCount() const
1630 {
1631 int lCount = 0;
1632 const EntryMap::RecordType* lElement = mEntryMap.Maximum();
1633
1634 if (NULL != lElement)
1635 {
1636 lCount = lElement->GetKey() + 1;
1637 }
1638
1639 int lParentCount = mInstanceOf ? mInstanceOf->GetPropertyEntryCount() : 0;
1640 return lParentCount > lCount ? lParentCount : lCount;
1641 }
1642
1643 FbxPropertyEntry* GetPropertyEntry(FbxInt pIndex,FbxPropertyPage **pFoundIn=0) const
1644 {
1645 const EntryMap::RecordType* lElement = mEntryMap.Find(pIndex);
1646 if (NULL != lElement)
1647 {
1648 if( pFoundIn )
1649 {
1650 *pFoundIn = const_cast<FbxPropertyPage*>(this);
1651 }
1652 return lElement->GetValue();
1653 }
1654
1655 if( pFoundIn )
1656 {
1657 *pFoundIn = 0;
1658 }
1659
1660 return mInstanceOf ? mInstanceOf->GetPropertyEntry(pIndex,pFoundIn) : 0;
1661 }
1662
1663 FbxPropertyEntry* ChangePropertyEntryState(FbxInt pIndex,FbxPropertyFlags::EInheritType pInheritType)
1664 {
1665 FbxPropertyPage* lReferencePage = 0;
1666 FbxPropertyEntry* lReferenceEntry = GetPropertyEntry(pIndex,&lReferencePage);
1667
1668 if (pInheritType==FbxPropertyFlags::eOverride) {
1669 if (lReferencePage==this) {
1670 return lReferenceEntry;
1671 } else if (lReferenceEntry) {
1672 // must create an entry
1673 FbxPropertyEntry* lEntry = FbxPropertyEntry::Create(lReferenceEntry->GetParentId(),0,0,0);
1674 mEntryMap.Insert( pIndex, lEntry );
1675
1676 return lEntry;
1677 }
1678 } else {
1679 if (lReferenceEntry && (lReferencePage==this)) {
1680 mEntryMap.Remove(pIndex);
1681 lReferenceEntry->Destroy();
1682 }
1683 }
1684 return 0;
1685 }
1686
1687 FbxInt Add(FbxInt pParentId,FbxPropertyInfo* pInfo,FbxPropertyValue* pValue,FbxPropertyConnect* pConnect,bool pRecursive=true)
1688 {
1689 FbxInt lId = mPropNextId->GetNextIdAndInc();
1690 FbxPropertyEntry* lEntry = FbxPropertyEntry::Create(pParentId,pInfo,pValue,pConnect);
1691
1692 // entries created through Add() are not overrides of another entry.
1693 // Thus, set all of their flags by default.
1694 FbxPropertyFlags* lFlags = lEntry->Get( FBX_TYPE(FbxPropertyFlags) );
1695 if( lFlags ) lFlags->ModifyFlags( FbxPropertyFlags::eAllFlags, false );
1696
1697 mEntryMap.Insert( lId, lEntry );
1698
1699 // We only add to the map if this Add is called after BeginCreateOrFindProperty()
1700 // in which case the size is always > 0 because it includes the root property
1701 if( mNameMap.mSecond.GetSize() > 0 )
1702 mNameMap.mSecond.Insert( FbxNameMapKey( pParentId, pInfo->GetName()), lId );
1703
1704 // If the entry has multiple children(Struct Datatype)
1705 // Recurse for the entries and create an entry in this structure
1706 if (pRecursive) {
1707 FbxPropertyPage* lTypeInfo = pInfo->GetTypeInfo();
1708 if (lTypeInfo) {
1709 FbxInt lChildId;
1710 lChildId = lTypeInfo->GetChild();
1711 while (lChildId!=FBXSDK_PROPERTY_ID_NULL) {
1712 FbxPropertyInfo* lPropertyInfo = lTypeInfo->GetPropertyItem( FBX_TYPE(FbxPropertyInfo),lChildId );
1713 FbxPropertyValue* lPropertyValue = lTypeInfo->GetPropertyItem( FBX_TYPE(FbxPropertyValue),lChildId );
1714 FbxPropertyConnect* lPropertyConnect = lTypeInfo->GetPropertyItem( FBX_TYPE(FbxPropertyConnect),lChildId );
1715
1716 Add ( lId, lPropertyInfo ? lPropertyInfo->Clone(this) : 0 , lPropertyValue ? lPropertyValue->Clone(this) : 0,
1717 lPropertyConnect ? lPropertyConnect->Clone(this) : 0 );
1718 lChildId = lTypeInfo->GetSibling(lChildId );
1719 }
1720 }
1721 }
1722 return lId;
1723 }
1724
1725 // Property management
1726 typedef FbxMap<FbxInt, FbxPropertyEntry*, FbxLessCompare<FbxInt>, FbxHungryAllocator> EntryMap;
1727 EntryMap mEntryMap;
1728
1729 // instance management
1730 FbxPropertyPage* mInstanceOf;
1731 FbxArray<FbxPropertyPage*> mInstances;
1732
1733 void* mDataPtr;
1734
1735 // speed up structure
1736 typedef FbxMap<FbxNameMapKey, FbxInt, FbxNameMapCompare > NameMap;
1737 typedef FbxPair<unsigned int, NameMap > NameLookupPair;
1738 NameLookupPair mNameMap;
1739
1740 FbxPropertyIdGenerator* mPropNextId;
1741
1742 friend class FbxPropertyHandle;
1743};
1744
1745#include <fbxsdk/fbxsdk_nsend.h>
1746
1747#endif /* _FBXSDK_CORE_PROPERTY_PAGE_H_ */
1748