fbxsdk/core/fbxpropertypage.h Source File
 
 
 
fbxsdk/core/fbxpropertypage.h
Go to the documentation of this file.
00001 /****************************************************************************************
00002  
00003    Copyright (C) 2013 Autodesk, Inc.
00004    All rights reserved.
00005  
00006    Use of this software is subject to the terms of the Autodesk license agreement
00007    provided at the time of installation or download, or which otherwise accompanies
00008    this software in either electronic or hard copy form.
00009  
00010 ****************************************************************************************/
00011 
00013 #ifndef _FBXSDK_CORE_PROPERTY_PAGE_H_
00014 #define _FBXSDK_CORE_PROPERTY_PAGE_H_
00015 
00016 #include <fbxsdk/fbxsdk_def.h>
00017 
00018 #include <fbxsdk/core/base/fbxstringlist.h>
00019 #include <fbxsdk/core/fbxobject.h>
00020 #include <fbxsdk/core/fbxsymbol.h>
00021 #include <fbxsdk/core/fbxpropertydef.h>
00022 #include <fbxsdk/core/fbxpropertytypes.h>
00023 
00024 #include <fbxsdk/fbxsdk_nsbegin.h>
00025 
00026 typedef FbxPair<FbxInt, const char*> FbxNameMapKey;
00027 
00028 class FbxNameMapCompare
00029 {
00030 public:
00031     inline int operator()(const FbxNameMapKey& pKeyA, const FbxNameMapKey& pKeyB) const
00032     {
00033         if( pKeyA.mFirst < pKeyB.mFirst )
00034             return -1;
00035         else if( pKeyA.mFirst > pKeyB.mFirst )
00036             return 1;
00037 
00038         return strcmp( pKeyA.mSecond, pKeyB.mSecond );
00039     }
00040 };
00041 
00042 /***********************************************
00043 FbxPropertyFlagsExt
00044 ************************************************/
00045 class FBXSDK_DLL FbxPropertyFlagsExt {
00046 public:
00047     typedef FbxUInt32 kFlagType;
00048     // Make sure type is large enough to hold the flags.
00049     FBX_ASSERT_STATIC( sizeof( kFlagType ) * 8 >= FbxPropertyAttr::eFlagCount );
00050 
00051     explicit FbxPropertyFlagsExt( FbxPropertyAttr::EFlags pFlags )
00052         :
00053     mFlagData(0), mMaskData(0)
00054     {
00055         ModifyFlags( pFlags, true );
00056     }
00057 
00058     FbxPropertyFlagsExt(): 
00059                 mFlagData(0), mMaskData(0)
00060     {
00061     }
00062 
00063     //This is just to get FbxPropertyPage::ChangeEntryItemState to work.
00064     inline FbxPropertyFlagsExt Clone(FbxPropertyPage* /*pPage*/)
00065     {
00066         return FbxPropertyFlagsExt();
00067     }
00068 
00069     inline bool SetMask( FbxPropertyAttr::EFlags pFlags )
00070     {
00071         mMaskData |= pFlags;
00072         return true;
00073     }
00074 
00075     inline bool UnsetMask( FbxPropertyAttr::EFlags pFlags )
00076     {
00077         mMaskData &= ~pFlags;
00078         return true;
00079     }
00080 
00081     inline FbxPropertyAttr::EFlags GetMask() const { return (FbxPropertyAttr::EFlags) (mMaskData); }
00082 
00083     inline FbxPropertyAttr::EFlags GetFlags() const { return (FbxPropertyAttr::EFlags) (mFlagData); }
00084 
00085     inline bool ModifyFlags( FbxPropertyAttr::EFlags pFlags, bool pValue )
00086     {
00087         SetMask( pFlags );
00088         mFlagData = pValue ? mFlagData | pFlags : mFlagData & ~pFlags;
00089         return true;
00090     }
00091 
00092     inline FbxPropertyAttr::EFlags GetMergedFlags( FbxPropertyAttr::EFlags pFlags ) const
00093     {
00094         kFlagType lTemp = (kFlagType)pFlags & ~(GetMask());     // zero out flags that we override
00095         return (FbxPropertyAttr::EFlags) (lTemp | GetFlags());                   // fill those flags with our values.
00096     }
00097 
00104     inline FbxPropertyAttr::EInheritType GetFlagsInheritType( FbxPropertyAttr::EFlags pFlags ) const
00105     {
00106         // If some, but not all, of the flags are overridden this returns FbxPropertyAttr::eOverride
00107         return (GetMask() & pFlags) != 0 ? FbxPropertyAttr::eOverride : FbxPropertyAttr::eInherit;
00108     }
00109 
00115     inline bool SetFlags( FbxPropertyAttr::EFlags pMask, FbxPropertyAttr::EFlags pFlags )
00116     {
00117         kFlagType lFlags = GetFlags() & ~pMask;     // zero out flags we are going to overwrite
00118         lFlags |= pFlags;                           // overwrite them
00119         mFlagData = lFlags;                         // set them
00120         return SetMask( pMask );                    // update the mask
00121     }
00122 
00123     inline bool Equal( const FbxPropertyFlagsExt& pOther, FbxPropertyAttr::EFlags pFlags ) const
00124     {
00125         kFlagType lMyFlags = GetFlags() & pFlags;
00126         kFlagType lOthersFlags = pOther.GetFlags() & pFlags;
00127         return lMyFlags == lOthersFlags;
00128     }
00129 
00130 private:
00131 
00132     kFlagType mFlagData;
00133     kFlagType mMaskData;
00134 };
00135 
00136 
00137 /***********************************************
00138 FbxPropertyInfo
00139 ************************************************/
00140 class FBXSDK_DLL FbxPropertyInfo {
00141 public:
00142     FBXSDK_FRIEND_NEW();
00143     static FbxPropertyInfo* Create(const char* pName, FbxPropertyPage* pTypeInfo)         { return FbxNew< FbxPropertyInfo >(pName,pTypeInfo); }
00144     static FbxPropertyInfo* Create(const char* pName, EFbxType   pType=eFbxUndefined)  { return FbxNew< FbxPropertyInfo >(pName,pType); }
00145     void                     Destroy()  { FbxDelete(this); }
00146     FbxPropertyInfo*        Clone(FbxPropertyPage* /*pPage*/)
00147     {
00148         // @@@@@ Filter is missing
00149         // @@@@@ Clone is incomplete
00150         if (mTypeInfo) 
00151                 {
00152             return FbxNew< FbxPropertyInfo >(mName,mTypeInfo);
00153         } 
00154                 else 
00155                 {
00156             return FbxNew< FbxPropertyInfo >(mName,mType);
00157         }
00158     }
00159 
00160     inline void IncRef() { mRef++; }
00161     inline void DecRef() { mRef--; if (mRef==0) FbxDelete(this); }
00162     inline int  GetRef() { return mRef; }
00163 
00164         // Labels and Types
00165 
00166     inline FbxStringSymbol GetName() const             { return mName; }
00167     EFbxType            GetType() const;
00168     FbxPropertyPage*       GetTypeInfo() const             { return mTypeInfo; }
00169 
00170     inline void         SetLabel(const char* pLabel)    { mLabel=pLabel;          }
00171     inline const char*  GetLabel() const                { return mLabel.IsEmpty() ? "" : ((const char*)mLabel); }
00172 
00173     inline void     SetUserTag(int pUserTag)            { mUserTag=pUserTag;      }
00174     inline int      GetUserTag() const                  { return mUserTag;        }
00175 
00176     inline void     SetUserData(const void* pUserData)  { mUserData=(void*)pUserData;    }
00177     inline void*   GetUserData() const                 { return mUserData;       }
00178 
00179         // Enum list       
00180     int AddEnumValue(const char* pStringValue)
00181     {
00182         if (GetType() == eFbxEnum)
00183         {
00184             if (!mEnumList)
00185                 mEnumList.Reset(FbxNew< FbxStringList >());
00186 
00187             if( mEnumList->FindIndex( pStringValue ) == -1 )
00188                 return mEnumList->Add((char*)pStringValue);
00189         }
00190         return -1;
00191     }
00192 
00193     void InsertEnumValue(int pIndex, const char* pStringValue)
00194     {
00195         if (GetType() == eFbxEnum)
00196         {
00197             if (!mEnumList)
00198                 mEnumList.Reset(FbxNew< FbxStringList >());
00199 
00200             mEnumList->InsertAt(pIndex,(char*)pStringValue);
00201         }
00202     }
00203 
00204     int GetEnumCount()
00205     {
00206         return mEnumList ? mEnumList->GetCount() : 0;
00207     }
00208 
00209     void SetEnumValue(int pIndex, const char* pStringValue)
00210     {
00211         if (GetType() == eFbxEnum)
00212         {
00213             if (!mEnumList)
00214                 mEnumList.Reset(FbxNew< FbxStringList >());
00215 
00216             mEnumList->SetStringAt(pIndex,(char*)pStringValue);
00217         }
00218     }
00219 
00220     void RemoveEnumValue(int pIndex)
00221     {
00222         if (GetType() == eFbxEnum)
00223         {
00224             if (!mEnumList)
00225                 mEnumList.Reset(FbxNew< FbxStringList >());
00226 
00227             mEnumList->RemoveAt(pIndex);
00228         }
00229     }
00230 
00231     char* GetEnumValue(int pIndex)
00232     {
00233       char* lValue = NULL;
00234         if (GetType() == eFbxEnum) {
00235             lValue = mEnumList ? mEnumList->GetStringAt(pIndex) : 0;
00236         }
00237         return lValue;
00238     }
00239 
00240 
00241         // Min and Max values       
00242     enum EValueIndex {eValueMin, eValueSoftMin, eValueMax, eValueSoftMax, eValueCount};
00243 
00244         bool HasMinMax(EValueIndex pId) const
00245         {
00246                 return mMinMaxValue[pId] != NULL;
00247         }
00248 
00249         bool GetMinMax(EValueIndex pId, void* pValue, EFbxType pValueType) const
00250         {
00251                 if (mMinMaxValue[pId]) {
00252                         return FbxTypeCopy(pValue, pValueType, mMinMaxValue[pId], GetType());
00253                 }
00254                 return false;
00255         }
00256 
00257         bool SetMinMax(EValueIndex pId, const void* pValue, EFbxType pValueType)
00258         {
00259                 if (!mMinMaxValue[pId]) {
00260                   size_t lSize = FbxTypeSizeOf(GetType());
00261                         if (lSize) {
00262                                 mMinMaxValue[pId] = FbxMalloc(lSize);
00263                         }
00264                 }
00265                 if (mMinMaxValue[pId]) {
00266                         return FbxTypeCopy(mMinMaxValue[pId], GetType(), pValue, pValueType);
00267                 }
00268                 return false;
00269         }
00270 
00271 private:
00272          FbxPropertyInfo(const char* pName, FbxPropertyPage* pTypeInfo)
00273         : mRef(0)
00274         , mName(pName)
00275         , mType(eFbxUndefined)
00276         , mTypeInfo(pTypeInfo)
00277         , mUserTag(0)
00278         , mUserData(0)
00279         , mFilter(0)
00280     {
00281         for (int i=0; i<eValueCount; i++) {
00282             mMinMaxValue[i] = 0;
00283         }
00284     }
00285 
00286     FbxPropertyInfo(FbxStringSymbol pName,FbxPropertyPage *pTypeInfo)
00287         : mRef(0)
00288         , mName(pName)
00289         , mType(eFbxUndefined)
00290         , mTypeInfo(pTypeInfo)
00291         , mUserTag(0)
00292         , mUserData(0)
00293         , mFilter(0)
00294     {
00295         for (int i=0; i<eValueCount; i++) {
00296             mMinMaxValue[i] = 0;
00297         }
00298     }
00299 
00300     FbxPropertyInfo(const char* pName, EFbxType pType)
00301         : mRef(0)
00302         , mName(pName)
00303         , mType(pType)
00304         , mTypeInfo(0)
00305         , mUserTag(0)
00306         , mUserData(0)
00307         , mFilter(0)
00308     {
00309         for (int i=0; i<eValueCount; i++) {
00310             mMinMaxValue[i] = 0;
00311         }
00312     }
00313     ~FbxPropertyInfo()
00314     {
00315         for (int i=eValueMin; i<eValueCount; i++) {
00316             FbxFree(mMinMaxValue[i]);
00317         }
00318     }
00319 
00320     int                         mRef;
00321     FbxStringSymbol            mName;
00322     FbxStringSymbol            mLabel;
00323     EFbxType                    mType;
00324     FbxPropertyPage*               mTypeInfo;      // Sub property
00325     int                         mUserTag;
00326     void*                       mMinMaxValue[eValueCount];  
00327     void*                       mUserData;
00328     FbxConnectionPointFilter*  mFilter;
00329     FbxAutoDeletePtr<FbxStringList>     mEnumList;
00330 };
00331 
00332 /***********************************************
00333 FbxPropertyValue
00334 ************************************************/
00335 class FBXSDK_DLL FbxPropertyValue {
00336 public:
00337     FBXSDK_FRIEND_NEW();
00338     static FbxPropertyValue*   Create(void* pData,EFbxType pType)  { return FbxNew< FbxPropertyValue >(pData,pType); }
00339     void                        Destroy()                           { FbxDelete(this); }
00340     FbxPropertyValue*          Clone(FbxPropertyPage* )           { return FbxNew< FbxPropertyValue >(mValue,mType); }
00341 
00342     inline void IncRef() { mRef++; }
00343     inline void DecRef() { mRef--; if (mRef==0) FbxDelete(this); }
00344     inline int  GetRef() { return mRef; }
00345 
00346     bool Get(void* pValue, EFbxType pValueType)
00347     {
00348         return mValue ? FbxTypeCopy(pValue,pValueType,mValue,mType) : false;
00349     }
00350     bool Set(const void* pValue, EFbxType pValueType)
00351     {
00352         return mValue ? FbxTypeCopy(mValue,mType,pValue,pValueType) : false;
00353     }
00354 private:
00355         FbxPropertyValue(void* pValue,EFbxType pType)
00356         : mRef(0)
00357         , mType(pType)
00358         , mValue(0)
00359     {
00360       size_t lSize = FbxTypeSizeOf(mType);
00361         if (lSize) {
00362             mValue = FbxTypeAllocate(mType);
00363             if (pValue && mType != eFbxReference ) {
00364                 FbxTypeCopy(mValue,mType,pValue,mType);
00365             }
00366         }
00367     }
00368     ~FbxPropertyValue()
00369     {
00370         FbxTypeDeallocate( mType, mValue );
00371     }
00372 
00373     int                 mRef;
00374     EFbxType    mType;
00375     void*               mValue;
00376 };
00377 
00378 /***********************************************
00379 FbxPropertyConnect
00380 ************************************************/
00381 #if defined(FBXSDK_COMPILER_MSC)
00382 #pragma warning (push)
00383 #pragma warning (disable: 4355)
00384 #endif
00385 
00386 class FBXSDK_DLL FbxPropertyConnect
00387 {
00388 public:
00389     FBXSDK_FRIEND_NEW();
00390     static FbxPropertyConnect* Create(FbxPropertyPage* pPage,FbxInt pId)  { return FbxNew< FbxPropertyConnect >(pPage,pId); }
00391     void                        Destroy() { FbxDelete(this); }
00392     FbxPropertyConnect*        Clone(FbxPropertyPage* pPage)
00393     {
00394         return FbxNew< FbxPropertyConnect >(pPage,mId);
00395     }
00396        
00397     inline void IncRef() { mRef++; }
00398     inline void DecRef() { mRef--; if (mRef==0) FbxDelete(this); }
00399     inline int  GetRef() { return mRef; }
00400 
00401 // Properties       
00402     FbxPropertyPage*   GetPage()       { return mPage; }
00403     FbxInt      GetPropertyId() { return mId; }
00404 
00405 // ClearConnectCache()
00406 // ------------------------------------------------------
00407     inline void ClearConnectCache()
00408     {
00409         mConnectionPoint.SubConnectRemoveAll();
00410     }
00411 
00413         inline void WipeAllConnections()
00414         {
00415                 mConnectionPoint.WipeConnectionList();
00416         }
00417 
00418 // Properties        
00419     inline bool ConnectSrc(FbxPropertyConnect* pSrc, FbxConnection::EType pType)
00420     {
00421         return mConnectionPoint.ConnectSrc(&pSrc->mConnectionPoint,pType);
00422     }
00423     inline bool DisconnectSrc(FbxPropertyConnect* pSrc)
00424     {
00425         return mConnectionPoint.DisconnectSrc(&pSrc->mConnectionPoint);
00426     }
00427     inline bool IsConnectedSrc(FbxPropertyConnect* pSrc)
00428     {
00429         return mConnectionPoint.IsConnectedSrc(&pSrc->mConnectionPoint);
00430     }
00431     inline int GetSrcCount(FbxConnectionPointFilter* pFilter)
00432     {
00433         return mConnectionPoint.GetSrcCount(pFilter);
00434     }
00435     inline FbxPropertyConnect* GetSrc(FbxConnectionPointFilter* pFilter, int pIndex)
00436     {
00437                 FbxConnectionPoint *lCP = mConnectionPoint.GetSrc(pIndex,pFilter);
00438         return lCP ? (FbxPropertyConnect * )lCP->GetData() : 0;
00439     }
00440     inline bool ConnectDst(FbxPropertyConnect* pDst, FbxConnection::EType pType)
00441     {
00442         return mConnectionPoint.ConnectDst(&pDst->mConnectionPoint,pType);
00443     }
00444     inline bool IsConnectedDst(FbxPropertyConnect* pSrc)
00445     {
00446         return mConnectionPoint.IsConnectedSrc(&pSrc->mConnectionPoint);
00447     }
00448     inline bool DisconnectDst(FbxPropertyConnect* pDst)
00449     {
00450         return mConnectionPoint.DisconnectDst(&pDst->mConnectionPoint);
00451     }
00452     inline int GetDstCount(FbxConnectionPointFilter* pFilter)
00453     {
00454         return mConnectionPoint.GetDstCount(pFilter);
00455     }
00456     inline FbxPropertyConnect* GetDst(FbxConnectionPointFilter* pFilter, int pIndex)
00457     {
00458                 FbxConnectionPoint *lCP = mConnectionPoint.GetDst(pIndex,pFilter);
00459         return lCP ? (FbxPropertyConnect * )lCP->GetData() : 0;
00460     }
00461 
00462     int                 mRef;
00463     FbxConnectionPoint mConnectionPoint;
00464     FbxPropertyPage*   mPage;
00465     FbxInt      mId;
00466 
00467 private:
00468     FbxPropertyConnect(FbxPropertyPage* pPage,FbxInt pId)
00469         : mRef(0)
00470         , mConnectionPoint(this)
00471         , mPage(pPage)
00472         , mId(pId)
00473     {
00474     }
00475     ~FbxPropertyConnect()
00476     {
00477                 if( FbxObject::GetWipeMode() ) mConnectionPoint.WipeConnectionList();
00478     }
00479 };
00480 #if defined(FBXSDK_COMPILER_MSC)
00481 #pragma warning (pop)
00482 #endif
00483 
00484 /***********************************************
00485 FbxPropertyEntry
00486 ************************************************/
00487 class FBXSDK_DLL FbxPropertyEntry {
00488 public:
00489     FBXSDK_FRIEND_NEW();
00490     static FbxPropertyEntry* Create(FbxInt pParentId, FbxPropertyInfo* pInfo, FbxPropertyValue* pValue, FbxPropertyConnect* pConnect)
00491     {
00492         return FbxNew< FbxPropertyEntry >(pParentId,pInfo,pValue,pConnect);
00493     }
00494     void                     Destroy() { FbxDelete(this); }
00495         
00496     inline FbxInt   GetParentId() { return mParentId; }
00497     inline bool             IsEmpty()     { return (mInfo || mValue || mConnect || mFlags.GetMask() != 0) ? false : true; }
00498 
00499     inline FbxPropertyInfo*    Get(const FbxPropertyInfo* /*pType*/) { return mInfo; }
00500     void                        Set(FbxPropertyInfo* pInfo)
00501     {
00502         FbxPropertyInfo* lInfo = mInfo;
00503         if (pInfo) pInfo->IncRef();
00504         mInfo=pInfo;
00505         if (lInfo) lInfo->DecRef();
00506     }
00507 
00508     inline FbxPropertyValue*   Get(const FbxPropertyValue* /*pType*/) { return mValue; }
00509     void                        Set(FbxPropertyValue* pValue)
00510     {
00511         FbxPropertyValue* lValue = mValue;
00512         if (pValue) pValue->IncRef();
00513         mValue=pValue;
00514         if (lValue) lValue->DecRef();
00515     }
00516 
00517     inline FbxPropertyConnect* Get(const FbxPropertyConnect* /*pType*/) { return mConnect; }
00518     void                        Set(FbxPropertyConnect* pConnect)
00519     {
00520         FbxPropertyConnect* lConnect = mConnect;
00521         if (pConnect) pConnect->IncRef();
00522         mConnect=pConnect;
00523         if (lConnect) lConnect->DecRef();
00524     }
00525 
00526     inline FbxPropertyFlagsExt* Get(const FbxPropertyFlagsExt* /*pType*/)
00527     {
00528         return &mFlags;
00529     }
00530 
00531     inline void Set( FbxPropertyFlagsExt pType )
00532     {
00533         mFlags = pType;
00534     }
00535 
00536     inline void Set( FbxPropertyFlagsExt* pType )
00537     {
00538         mFlags = pType ? *pType : FbxPropertyFlagsExt( FbxPropertyAttr::eNone );
00539     }
00540 
00541 private:
00542         FbxPropertyEntry(FbxInt pParentId,FbxPropertyInfo *pInfo,FbxPropertyValue *pValue,FbxPropertyConnect *pConnect)
00543         : mInfo(pInfo)
00544         , mValue(pValue)
00545         , mConnect(pConnect)
00546         , mParentId(pParentId)
00547         , mFlags(FbxPropertyAttr::eNone)
00548     {
00549         if (mInfo)  mInfo->IncRef();
00550         if (mValue) mValue->IncRef();
00551         if (mConnect) mConnect->IncRef();
00552     }
00553     ~FbxPropertyEntry()
00554     {
00555         if (mInfo)  mInfo->DecRef();
00556         if (mValue) mValue->DecRef();
00557         if (mConnect) mConnect->DecRef();
00558     }
00559 
00560     FbxPropertyInfo*       mInfo;
00561     FbxPropertyValue*      mValue;
00562     FbxPropertyConnect*    mConnect;
00563     FbxInt          mParentId;
00564 
00565     // Since mFlags is only a 32bit int, don't bother storing a pointer to it.
00566     FbxPropertyFlagsExt       mFlags;
00567 
00568     friend class FbxPropertyPage;
00569 };
00570 
00571 /***********************************************
00572 FbxPropertyIdGenerator
00573 ************************************************/
00574 class FBXSDK_DLL FbxPropertyIdGenerator
00575 {
00576 public:
00577 FbxPropertyIdGenerator() :  mRef(0), mNextId(0) { }
00578 
00579 inline FbxInt GetNextId() const { return mNextId; }
00580 inline FbxInt GetNextIdAndInc() { return mNextId++; }
00581 
00582 inline void IncRef() { mRef++; }
00583 inline void DecRef() { mRef--;  if( mRef == 0 ) FbxDelete(this); }
00584 
00585 private:
00586 int mRef;
00587 FbxInt mNextId;
00588 };
00589 
00590 /***********************************************
00591 FbxPropertyPage
00592 ************************************************/
00593 class FBXSDK_DLL FbxPropertyPage
00594 {
00595 
00596 public:
00597     FBXSDK_FRIEND_NEW();
00598     static FbxPropertyPage* Create (FbxPropertyPage* pInstanceOf=0)       { return FbxNew< FbxPropertyPage >(pInstanceOf);     }
00599     static FbxPropertyPage*     Create (const char* pName, FbxPropertyPage* pTypeInfo)    { return FbxNew< FbxPropertyPage >(pName,pTypeInfo); }
00600     static FbxPropertyPage*     Create (const char* pName, EFbxType    pType=eFbxUndefined)     { return FbxNew< FbxPropertyPage >(pName,pType);     }
00601     void                     Destroy() { FbxDelete(this); }
00602 
00603         template<class T> inline T* GetPropertyItem(const T* pItemType,FbxInt pIndex,FbxPropertyPage **pFoundIn=0) const
00604     {
00605       FbxPropertyPage*     lReferencePage = 0;
00606       FbxPropertyEntry*    lReferenceEntry = GetPropertyEntry(pIndex,&lReferencePage);
00607         if (pFoundIn) *pFoundIn = 0;
00608         if (lReferenceEntry) {
00609           T* lItem = lReferenceEntry->Get( FBX_TYPE(T) );
00610             if (lItem) {
00611                 if (pFoundIn) *pFoundIn = lReferencePage;
00612                 return lItem;
00613             } else {
00614                 return lReferencePage->mInstanceOf ? lReferencePage->mInstanceOf->GetPropertyItem(pItemType,pIndex,pFoundIn) : 0 ;
00615             }
00616         }
00617         return 0;
00618     }
00619 
00620         template<class T> inline T* ChangePropertyItemState(const T* pItemType, FbxInt pIndex, FbxPropertyAttr::EInheritType pInheritType)
00621         {
00622                 FbxPropertyPage*        lReferencePage = NULL;
00623                 T*                                      lItem = GetPropertyItem(pItemType, pIndex, &lReferencePage);
00624                 if( pInheritType == FbxPropertyAttr::eOverride )
00625                 {
00626                         if( lReferencePage == this )
00627                         {
00628                                 return lItem;
00629                         }
00630                         else if( lItem )
00631                         {
00632                                 FbxPropertyEntry* lEntry = ChangePropertyEntryState(pIndex, FbxPropertyAttr::eOverride);
00633                                 lEntry->Set(lItem->Clone(this));
00634                                 return lEntry->Get(FBX_TYPE(T));
00635                         }
00636                 }
00637                 else
00638                 {
00639                         // can't inherit entries that were created on our page.
00640                         bool lOwnEntry = !mInstanceOf || (mInstanceOf->GetPropertyItem(pItemType, pIndex) == NULL);
00641                         if( lOwnEntry && FbxPropertyAttr::eInherit == pInheritType) return 0;
00642 
00643                         if( lItem && (lReferencePage == this) )
00644                         {
00645                                 FbxPropertyEntry* lEntry = GetPropertyEntry(pIndex);
00646                                 lEntry->Set((T*)0);
00647                                 if( lEntry->IsEmpty() )
00648                                 {
00649                                         ChangePropertyEntryState(pIndex, FbxPropertyAttr::eInherit);
00650                                 }
00651                         }
00652                         return 0;
00653                 }
00654                 return 0;
00655         }
00656 
00657         template<class T> FbxPropertyPage* GetFirstPropertyItem(FbxInt pId, const T* pItem) const
00658         {
00659                 FbxPropertyPage* lReferencePage = NULL;
00660                 GetPropertyItem(FBX_TYPE(T), pId, &lReferencePage);
00661                 if( lReferencePage && lReferencePage->mInstanceOf )
00662                 {
00663                         FbxPropertyPage* lReferencePage2 = lReferencePage->mInstanceOf->GetFirstPropertyItem(pId, pItem);
00664                         return lReferencePage2 ? lReferencePage2 : lReferencePage;
00665                 }
00666                 return lReferencePage;
00667         }
00668 
00669     const char* GetName(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT)
00670     {
00671                 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
00672         return lPropertyInfo ? ((const char*)lPropertyInfo->GetName()) : "";
00673     }
00674 
00675     const char* GetLabel(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT)
00676     {
00677                 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
00678         return lPropertyInfo ? ((const char*)lPropertyInfo->GetLabel()) : "";
00679     }
00680 
00681     bool SetLabel(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT, const char* pLabel="")
00682     {
00683                 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
00684         // Don't make it writeable (Keep it shared)
00685                 if (lPropertyInfo) {
00686                         lPropertyInfo->SetLabel(pLabel);
00687                         return true;
00688                 } else {
00689                         return false;
00690         }
00691     }
00692 
00693     void* GetUserData(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT)
00694     {
00695                 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
00696         return lPropertyInfo ? lPropertyInfo->GetUserData() : 0;
00697     }
00698 
00699     bool SetUserData(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT, const void* pUserData=0)
00700     {
00701       FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
00702           // Don't make it writeable (Keep it shared)
00703           if (lPropertyInfo) {
00704               lPropertyInfo->SetUserData(pUserData);
00705               return true;
00706           } else {
00707               return false;
00708           }
00709     }
00710 
00711     int GetUserTag(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT)
00712     {
00713       FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
00714         return lPropertyInfo ? lPropertyInfo->GetUserTag() : 0;
00715     }
00716 
00717     bool SetUserTag(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT,int pUserTag=0)
00718     {
00719                 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
00720           // Don't make it writeable (Keep it shared)
00721                 if (lPropertyInfo) {
00722                         lPropertyInfo->SetUserTag(pUserTag);
00723                         return true;
00724                 } else {
00725                         return false;
00726                 }
00727     }
00728 
00729     EFbxType GetType(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT) const
00730     {
00731                 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
00732         return lPropertyInfo ? lPropertyInfo->GetType() : eFbxUndefined;
00733     }
00734 
00735     FbxInt GetParent(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT) const
00736     {
00737                 FbxPropertyEntry* lPropertyEntry = GetPropertyEntry( pId );
00738         return lPropertyEntry ? lPropertyEntry->GetParentId() : FBXSDK_PROPERTY_ID_NULL;
00739     }
00740 
00741     FbxPropertyPage* GetTypeInfo(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT)
00742     {
00743                 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
00744         return lPropertyInfo ? lPropertyInfo->GetTypeInfo() : 0;
00745     }
00746     FbxInt Add(FbxInt pParentId, const char* pName, EFbxType pType)
00747     {
00748         return Add(pParentId,FbxPropertyInfo::Create(pName,pType),FbxPropertyValue::Create(0,pType),0);
00749     }
00750     FbxInt Add(FbxInt pParentId, const char* pName, FbxPropertyPage* pTypeInfo)
00751     {
00752         return Add(pParentId,FbxPropertyInfo::Create(pName,pTypeInfo),FbxPropertyValue::Create(0,pTypeInfo->GetType()),0);
00753     }
00754 
00755     inline bool Reparent( FbxInt /*pChildId*/, FbxInt /*pNewParentId*/ )
00756     {
00757         // Not implemented.
00758         /*
00759         if( GetParent(pChildId) != pNewParentId  && pChildId < mEntries.GetCount() )
00760         {
00761             FbxPropertyEntry* lChildEntry = mEntries[pChildId];
00762             lChildEntry->mParentId = pNewParentId;
00763 
00764             //@@@@@ TODO: propagate to instances
00765 
00766             return true;
00767         }
00768         */
00769         return false;
00770     }
00771 
00772     inline bool IsChildOf(FbxInt pId,FbxInt pParentId) const
00773     {
00774         return GetParent(pId)==pParentId;
00775 
00776     }
00777 
00778     inline bool IsDescendentOf(FbxInt pId,FbxInt pAncestorId) const
00779     {
00780                 if (pAncestorId>0) {
00781             FbxInt lParentId = GetParent(pId);
00782             while (lParentId != FBXSDK_PROPERTY_ID_NULL ) {
00783                 if (lParentId==pAncestorId) {
00784                     return true;
00785                 }
00786                 lParentId = GetParent(lParentId);
00787             }
00788             return false;
00789         } else {
00790             return true;
00791         }
00792 
00793     }
00794 
00795     //#define PROPERTY_PAGE_SANITY_CHECK  // Debug purpose only. Never enable it in a production release.
00796 
00801     FbxInt GetChild(FbxInt pParentId=FBXSDK_PROPERTY_ID_ROOT) const
00802     {
00803     #ifdef PROPERTY_PAGE_SANITY_CHECK
00804         FbxInt ret0 = FBXSDK_PROPERTY_ID_NULL;
00805             if (pParentId!=FBXSDK_PROPERTY_ID_NULL) {
00806             FbxInt       lId        = GetMinimumPropertyId(pParentId);
00807             FbxInt       lParentId  = GetParent(lId);
00808             const FbxInt lLastId    = GetPropertyEntryCount();
00809 
00810             while (lId<lLastId && lParentId!=pParentId) lParentId=GetParent(++lId);
00811             ret0 = lId<lLastId ? lId : FBXSDK_PROPERTY_ID_NULL;
00812         } else {
00813             ret0 = FBXSDK_PROPERTY_ID_NULL;
00814         }
00815     #endif
00816         FbxInt ret1 = FBXSDK_PROPERTY_ID_NULL;
00817         if (pParentId != FBXSDK_PROPERTY_ID_NULL)
00818         {
00819             FbxPropertyEntry* lEntry;
00820             FbxInt lId = pParentId;
00821             do 
00822             {
00823                 lId = GetMinimumPropertyIdAndEntry(lId, &lEntry);
00824             } while (lId != FBXSDK_PROPERTY_ID_NULL && lEntry->GetParentId() != pParentId);
00825             ret1 = lId;
00826         }
00827     #ifdef PROPERTY_PAGE_SANITY_CHECK
00828         FBX_ASSERT(ret0==ret1);
00829     #endif
00830         return ret1;
00831     }
00832 
00837     FbxInt GetSibling(FbxInt pId) const
00838     {
00839     #ifdef PROPERTY_PAGE_SANITY_CHECK
00840         FbxInt pIdBackup = pId;
00841         FbxInt ret0 = FBXSDK_PROPERTY_ID_NULL;
00842         if (pId!=FBXSDK_PROPERTY_ID_NULL) {
00843             FbxInt       lReferenceParentId = GetParent(pId);
00844             FbxInt       lParentId          = GetParent(++pId);
00845             const FbxInt lLastId            = GetPropertyEntryCount();
00846 
00847             while (pId<lLastId && lReferenceParentId!=FBXSDK_PROPERTY_ID_NULL && lParentId!=lReferenceParentId)
00848                 lParentId=GetParent(++pId);
00849             ret0 = pId<lLastId ? pId : FBXSDK_PROPERTY_ID_NULL;
00850         } else {
00851             ret0 = FBXSDK_PROPERTY_ID_NULL;
00852         }
00853         pId = pIdBackup;
00854     #endif
00855         FbxInt ret1 = FBXSDK_PROPERTY_ID_NULL;
00856         if (pId != FBXSDK_PROPERTY_ID_NULL)
00857         {
00858             FbxInt lReferenceParentId = GetParent(pId);
00859 
00860             if (lReferenceParentId != FBXSDK_PROPERTY_ID_NULL)
00861             {
00862                 FbxPropertyEntry *lEntry;
00863                 do 
00864                 {
00865                     pId = GetMinimumPropertyIdAndEntry(pId, &lEntry);
00866                 } while (pId != FBXSDK_PROPERTY_ID_NULL && lEntry->GetParentId() != lReferenceParentId);
00867 
00868                 ret1 = pId;
00869             }
00870         }
00871 
00872     #ifdef PROPERTY_PAGE_SANITY_CHECK
00873         FBX_ASSERT(ret0==ret1);
00874     #endif
00875         return ret1;
00876     }
00877 
00882     FbxInt GetFirstDescendent(FbxInt pAnscestorId=FBXSDK_PROPERTY_ID_ROOT) const
00883     {
00884     #ifdef PROPERTY_PAGE_SANITY_CHECK
00885         FbxInt ret0 = FBXSDK_PROPERTY_ID_NULL;
00886         if (pAnscestorId!=FBXSDK_PROPERTY_ID_NULL) {
00887             FbxInt       lId        = GetMinimumPropertyId(pAnscestorId);
00888             FbxInt       lParentId  = GetParent(lId);
00889             const FbxInt lLastId    = GetPropertyEntryCount();
00890 
00891             while (lId<lLastId) {
00892                 if( lParentId!=FBXSDK_PROPERTY_ID_NULL && IsDescendentOf(lId,pAnscestorId) )
00893                 {
00894                     ret0 = lId;
00895                     break;
00896                 }
00897                 lParentId = GetParent(++lId);
00898             }
00899         }
00900     #endif
00901         FbxInt ret1 = FBXSDK_PROPERTY_ID_NULL;
00902         FbxInt lId = pAnscestorId;
00903         FbxPropertyEntry* lEntry;
00904         if (pAnscestorId != FBXSDK_PROPERTY_ID_NULL)
00905         {
00906             for(;;)
00907             {
00908                 lId  = GetMinimumPropertyIdAndEntry(lId, &lEntry);
00909                 if (lId == FBXSDK_PROPERTY_ID_NULL)
00910                     break;
00911                 if(lEntry->GetParentId() != FBXSDK_PROPERTY_ID_NULL && IsDescendentOf(lId, pAnscestorId))
00912                 {
00913                     ret1 = lId;
00914                     break;
00915                 }
00916             }
00917         }
00918 
00919     #ifdef PROPERTY_PAGE_SANITY_CHECK
00920         FBX_ASSERT(ret0==ret1);
00921     #endif
00922         return ret1;
00923     }
00924 
00930     FbxInt GetNextDescendent(FbxInt pAnscestorId, FbxInt pId) const
00931     {
00932     #ifdef PROPERTY_PAGE_SANITY_CHECK
00933         FbxInt pIdBackup = pId;
00934         FbxInt ret0 = FBXSDK_PROPERTY_ID_NULL;
00935         if (pId!=FBXSDK_PROPERTY_ID_NULL) {
00936             FbxInt       lParentId  = GetParent(++pId);
00937             const FbxInt lLastId    = GetPropertyEntryCount();
00938 
00939             while (pId<lLastId) {
00940                 // GetParent returns null when the given id isn't in our page,
00941                 // or our ancestor's page.
00942                 if( lParentId != FBXSDK_PROPERTY_ID_NULL && IsDescendentOf(pId, pAnscestorId) )
00943                 {
00944                     ret0 = pId;
00945                     break;
00946                 }
00947 
00948                 lParentId = GetParent(++pId);
00949             }
00950         }
00951         
00952         pId = pIdBackup;
00953     #endif
00954         FbxInt ret1 = FBXSDK_PROPERTY_ID_NULL;
00955         if (pId != FBXSDK_PROPERTY_ID_NULL)
00956         {
00957             FbxPropertyEntry* lEntry;
00958             for(;;)
00959             {
00960                 pId = GetMinimumPropertyIdAndEntry(pId, &lEntry);
00961                 if (pId == FBXSDK_PROPERTY_ID_NULL)
00962                     break;
00963                 if(lEntry->GetParentId() != FBXSDK_PROPERTY_ID_NULL && IsDescendentOf(pId, pAnscestorId) )
00964                 {
00965                     ret1 = pId;
00966                     break;
00967                 }
00968             }
00969 
00970         }
00971     #ifdef PROPERTY_PAGE_SANITY_CHECK
00972         FBX_ASSERT(ret0==ret1);
00973     #endif
00974         return ret1;
00975 
00976     }
00977 
00978     FbxInt FastFind (FbxInt pId, const char* pName, FbxPropertyPage* pTypeInfo, bool pCaseSensitive)
00979     {
00980         FbxInt lId = FBXSDK_PROPERTY_ID_NULL;
00981 
00982         bool lSlowQuery = true;
00983         if( mNameMap.mSecond.GetSize() > 0 )
00984         {
00985             lSlowQuery = false;
00986             // try to use the map if we've got it
00987             NameMap::RecordType* lIterator = mNameMap.mSecond.Find( FbxNameMapKey( pId, pName ) );
00988             if( !lIterator )
00989             {
00990                 lId = FBXSDK_PROPERTY_ID_NULL;
00991             }
00992             else
00993             {
00994                 lId = lIterator->GetValue();
00995                 if (lId != FBXSDK_PROPERTY_ID_NULL && pTypeInfo)
00996                 {
00997                     lSlowQuery = true;
00998 
00999                     // Try to match types.
01000                     // If they are mismatched, fall back to the slow query,
01001                     // since we might have multiple property with the same name but different types
01002                     FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo), lId );
01003                     if (lPropertyInfo)
01004                     {
01005                         FbxPropertyPage* lTypeInfo2 = lPropertyInfo->GetTypeInfo();
01006                         if ( lTypeInfo2 && lTypeInfo2->Is(pTypeInfo) )
01007                         {
01008                             lSlowQuery = false;
01009                         }
01010                     }
01011                 }
01012             }
01013         }
01014 
01015         if (!lSlowQuery)
01016             return lId;
01017 
01018         // fall back if there's no map or we got one with a different type
01019 
01020         lId = GetChild(pId);
01021         FbxStringSymbol lSearchSymbol( pName );
01022         while( lId != FBXSDK_PROPERTY_ID_NULL ) {
01023                         FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo), lId );
01024             if  ( (!pTypeInfo || lPropertyInfo->GetTypeInfo()->Is(pTypeInfo)) &&
01025                 ((!pCaseSensitive && FBXSDK_stricmp(lPropertyInfo->GetName(),pName)==0) ||
01026                 (pCaseSensitive && lPropertyInfo->GetName() == lSearchSymbol)) ) {
01027                 return lId;
01028             }
01029             lId = GetSibling(lId);
01030         }
01031 
01032         return FBXSDK_PROPERTY_ID_NULL;
01033     }
01034 
01035     FbxInt Find (FbxInt pId, const char* pName, FbxPropertyPage* pTypeInfo, bool pCaseSensitive, const char* pChildrenSeparators )
01036     {
01037                 if (pChildrenSeparators) 
01038                 {
01039                         FbxInt  lId;
01040                         size_t  lFoundIndex = strcspn(pName,pChildrenSeparators);
01041 
01042             // Strip the first part of the name and search
01043             if (lFoundIndex<strlen(pName)) 
01044                         {
01045                                 FbxString       pRootName;
01046                 pRootName.Append(pName,lFoundIndex);
01047                 lId = FastFind(pId,pRootName.Buffer(),NULL,pCaseSensitive);
01048                 return lId != FBXSDK_PROPERTY_ID_NULL ? Find(lId,pName+lFoundIndex+1,pTypeInfo,pCaseSensitive,pChildrenSeparators) : lId;
01049             } else {
01050                 return FastFind(pId,pName,pTypeInfo,pCaseSensitive);
01051             }
01052         } else {
01053             return FastFind(pId,pName,pTypeInfo,pCaseSensitive);
01054         }
01055     }
01056 
01057 // Enum list        
01058     int AddEnumValue(FbxInt pId, const char* pStringValue)
01059     {
01060                 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
01061         // Don't make it writeable (Keep it shared)
01062         return lPropertyInfo ? lPropertyInfo->AddEnumValue(pStringValue) : - 1;
01063     }
01064 
01065     void InsertEnumValue(FbxInt pId, int pIndex, const char* pStringValue)
01066     {
01067                 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
01068         // Don't make it writeable (Keep it shared)
01069         if (lPropertyInfo) lPropertyInfo->InsertEnumValue(pIndex,pStringValue);
01070     }
01071 
01072     int GetEnumCount(FbxInt pId)
01073     {
01074                 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
01075         // Don't make it writeable (Keep it shared)
01076         return lPropertyInfo ? lPropertyInfo->GetEnumCount() : 0;
01077     }
01078 
01079     void SetEnumValue(FbxInt pId, int pIndex, const char* pStringValue)
01080     {
01081                 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
01082         // Don't make it writeable (Keep it shared)
01083         if (lPropertyInfo) lPropertyInfo->SetEnumValue(pIndex,pStringValue);
01084     }
01085 
01086     void RemoveEnumValue(FbxInt pId, int pIndex)
01087     {
01088                  FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
01089         // Don't make it writeable (Keep it shared)
01090         if (lPropertyInfo) lPropertyInfo->RemoveEnumValue(pIndex);
01091     }
01092 
01093     char* GetEnumValue(FbxInt pId,int pIndex)
01094     {
01095                 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
01096         return lPropertyInfo ? lPropertyInfo->GetEnumValue(pIndex) : (char*)"";
01097     }
01098 
01099     // Connection
01100     // ---------------------------------
01101     void ClearConnectCache(FbxInt pId)
01102     {
01103                 FbxPropertyPage*     lReferencePage = 0;
01104                 FbxPropertyConnect*     lPropertyConnect = GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pId,&lReferencePage );
01105 
01106         // Connections are not considered propagated so
01107         // make sure that we own the FbxPropertyConnect objects
01108         if (lPropertyConnect) {
01109             lPropertyConnect->ClearConnectCache();
01110         }
01111     }
01112 
01113         void WipeAllConnections(FbxInt pId)
01114         {
01115         FbxPropertyPage*                lReferencePage = 0;
01116         FbxPropertyConnect*     lPropertyConnect = GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pId,&lReferencePage );
01117 
01118         if (lPropertyConnect) {
01119             lPropertyConnect->WipeAllConnections();
01120         }
01121         }
01122 
01123     bool ConnectSrc(FbxInt pDstId, FbxPropertyPage* pSrcPage, FbxInt pSrcId, FbxConnection::EType pType)
01124     {
01125                 FbxPropertyEntry*    lDstEntry = ChangePropertyEntryState(pDstId,FbxPropertyAttr::eOverride);
01126                 FbxPropertyEntry*    lSrcEntry = pSrcPage->ChangePropertyEntryState(pSrcId,FbxPropertyAttr::eOverride);
01127                 FbxPropertyConnect*  lDstConnect= lDstEntry->Get( FBX_TYPE(FbxPropertyConnect) );
01128                 FbxPropertyConnect*  lSrcConnect= lSrcEntry->Get( FBX_TYPE(FbxPropertyConnect) );
01129 
01130         // Make sure we have a connection point on both sides of the connection
01131         if (!lDstConnect) {
01132             lDstConnect = FbxPropertyConnect::Create( this,pDstId );
01133             lDstEntry->Set( lDstConnect );
01134         }
01135         if (!lSrcConnect) {
01136             lSrcConnect = FbxPropertyConnect::Create( pSrcPage,pSrcId );
01137             lSrcEntry->Set( lSrcConnect );
01138         }
01139 
01140         // Must @@@@@@@ Propagate to inherited children
01141         return lDstConnect->ConnectSrc(lSrcConnect,pType);
01142 
01143     }
01144 
01145     bool DisconnectSrc(FbxInt pDstId,FbxPropertyPage* pSrcPage,FbxInt pSrcId)
01146     {
01147                 FbxPropertyPage*                lDstReferencePage       = 0;
01148                 FbxPropertyConnect*     lDstConnect                     = GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pDstId,&lDstReferencePage );
01149                 FbxPropertyPage*                lSrcReferencePage       = 0;
01150                 FbxPropertyConnect*     lSrcConnect                     = pSrcPage->GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pSrcId,&lSrcReferencePage );
01151 
01152         // Make sure we have a connection point on both sides of the connection
01153         if (lDstConnect && lSrcConnect && lDstReferencePage==this && lSrcReferencePage==pSrcPage) {
01154             // Must @@@@@@@ Remove unused connections
01155             return lDstConnect->DisconnectSrc(lSrcConnect);
01156         }
01157         return false;
01158     }
01159 
01160     bool IsConnectedSrc(FbxInt pDstId, FbxPropertyPage* pSrcPage, FbxInt pSrcId)
01161     {
01162                 FbxPropertyPage*                lDstReferencePage       = 0;
01163                 FbxPropertyConnect*     lDstConnect                     = GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pDstId,&lDstReferencePage );
01164                 FbxPropertyPage*                lSrcReferencePage       = 0;
01165                 FbxPropertyConnect*     lSrcConnect                     = pSrcPage->GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pSrcId,&lSrcReferencePage );
01166 
01167         // Make sure we have a connection point on both sides of the connection
01168         if (lDstConnect && lSrcConnect && lDstReferencePage==this && lSrcReferencePage==pSrcPage) {
01169             // Must @@@@@@@ Remove unused connections
01170             return lDstConnect->IsConnectedSrc(lSrcConnect);
01171         }
01172         return false;
01173     }
01174 
01175     int GetSrcCount(FbxInt pId, FbxConnectionPointFilter* pFilter)
01176     {
01177                 FbxPropertyPage*                lReferencePage          = 0;
01178                 FbxPropertyConnect*     lPropertyConnect        = GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pId,&lReferencePage );
01179 
01180         // Connections are not considered propagated so
01181         // make sure that we own the FbxPropertyConnect objects
01182         return (lPropertyConnect && lReferencePage==this) ? lPropertyConnect->GetSrcCount(pFilter) : 0;
01183     }
01184 
01185     bool GetSrc(FbxInt pId, int pIndex, FbxConnectionPointFilter* pFilter, FbxPropertyPage** pSrcPage, FbxInt* pSrcId)
01186     {
01187                 FbxPropertyPage*                lReferencePage          = 0;
01188                 FbxPropertyConnect*     lPropertyConnect        = GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pId,&lReferencePage );
01189 
01190         // Connections are always overridden
01191         // make sure that we own the FbxPropertyConnect Item
01192         if (lPropertyConnect && lReferencePage==this) 
01193                 {
01194                         FbxPropertyConnect* lSrc = lPropertyConnect->GetSrc(pFilter,pIndex);
01195             if (lSrc) 
01196                         {
01197                 if (pSrcPage)   *pSrcPage = lSrc->GetPage();
01198                 if (pSrcId)     *pSrcId   = lSrc->GetPropertyId();
01199                 return true;
01200             }
01201         }
01202         return false;
01203     }
01204 
01205     bool ConnectDst(FbxInt pSrcId, FbxPropertyPage* pDstPage, FbxInt pDstId, FbxConnection::EType pType)
01206     {
01207         return pDstPage->ConnectSrc(pDstId,this,pSrcId,pType);
01208     }
01209 
01210     bool DisconnectDst(FbxInt pSrcId, FbxPropertyPage* pDstPage, FbxInt pDstId)
01211     {
01212         return pDstPage->DisconnectSrc(pDstId,this,pSrcId);
01213     }
01214 
01215     bool IsConnectedDst(FbxInt pSrcId, FbxPropertyPage* pDstPage, FbxInt pDstId)
01216     {
01217         return pDstPage->IsConnectedSrc(pDstId,this,pSrcId);
01218     }
01219 
01220     int GetDstCount(FbxInt pId, FbxConnectionPointFilter* pFilter)
01221     {
01222                 FbxPropertyPage*                lReferencePage   = 0;
01223                 FbxPropertyConnect*     lPropertyConnect = GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pId,&lReferencePage );
01224 
01225         // Connections are not considered propagated so
01226         // make sure that we own the FbxPropertyConnect objects
01227         return (lPropertyConnect && lReferencePage==this) ? lPropertyConnect->GetDstCount(pFilter) : 0;
01228     }
01229 
01230     bool GetDst(FbxInt pId, int pIndex, FbxConnectionPointFilter* pFilter, FbxPropertyPage** pDstPage, FbxInt* pDstId)
01231     {
01232                 FbxPropertyPage*                lReferencePage   = 0;
01233                 FbxPropertyConnect*     lPropertyConnect = GetPropertyItem( FBX_TYPE(FbxPropertyConnect),pId,&lReferencePage );
01234 
01235         // Connections are always overridden
01236         // make sure that we own the FbxPropertyConnect Item
01237         if (lPropertyConnect && lReferencePage==this)
01238                 {
01239                         FbxPropertyConnect* lDst = lPropertyConnect->GetDst(pFilter,pIndex);
01240             if (lDst) 
01241                         {
01242                 if (pDstPage)   *pDstPage = lDst->GetPage();
01243                 if (pDstId)     *pDstId   = lDst->GetPropertyId();
01244                 return true;
01245             }
01246         }
01247         return false;
01248     }
01249 
01250     // Min and Max
01251     // ---------------------------------
01252     enum EValueIndex { eValueMin,eValueSoftMin,eValueMax,eValueSoftMax,eValueCount };
01253 
01254         bool HasMinMax(FbxInt pId, FbxPropertyInfo::EValueIndex pValueId) const
01255         {
01256                 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
01257         
01258                 return lPropertyInfo ? lPropertyInfo->HasMinMax(pValueId) : false;
01259         }
01260 
01261     bool GetMinMax(FbxInt pId, FbxPropertyInfo::EValueIndex pValueId, void* pValue, EFbxType pValueType)
01262     {
01263                 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
01264         // Don't make it writeable (Keep it shared)
01265         return lPropertyInfo ? lPropertyInfo->GetMinMax(pValueId,pValue,pValueType) : false;
01266     }
01267 
01268     bool SetMinMax(FbxInt pId, FbxPropertyInfo::EValueIndex pValueId, const void* pValue, EFbxType pValueType)
01269     {
01270                 FbxPropertyInfo* lPropertyInfo = GetPropertyItem( FBX_TYPE(FbxPropertyInfo),pId );
01271         // Don't make it writeable (Keep it shared)
01272         return lPropertyInfo ? lPropertyInfo->SetMinMax(pValueId,pValue,pValueType) : false;
01273     }
01274 
01275     // Value
01276     // ---------------------------------
01277     bool Get(FbxInt pId, void* pValue, EFbxType pValueType)
01278     {
01279                 FbxPropertyValue* lPropertyValue = GetPropertyItem( FBX_TYPE(FbxPropertyValue),pId );
01280         return lPropertyValue ? lPropertyValue->Get(pValue,pValueType) : 0;
01281     }
01282 
01283     bool Set(FbxInt pId, const void* pValue, EFbxType pValueType, bool pCheckValueEquality)
01284     {
01285         if( pCheckValueEquality )
01286         {
01287             FbxPropertyPage*   lReferencePage  = NULL;
01288             FbxPropertyValue*  lPropertyValue  = GetPropertyItem( FBX_TYPE(FbxPropertyValue),pId,&lReferencePage );
01289             void* lCurrentValue = FbxTypeAllocate( pValueType );
01290             bool lValuesEqual = false;
01291             bool lValueChanged = false;
01292             if( lReferencePage && lReferencePage != this )
01293             {
01294                 // this page inherits, so check if we have to override the value.
01295                 if( lPropertyValue )
01296                 {
01297                     lPropertyValue->Get( lCurrentValue, pValueType );
01298                     lValuesEqual = FbxTypeCompare( pValue, lCurrentValue, pValueType );
01299                 }
01300             }
01301             else
01302             {
01303                 FbxPropertyPage* lReferencePage2 = NULL;
01304                 FbxPropertyValue*  lPropertyValue2 = mInstanceOf ? mInstanceOf->GetPropertyItem( FBX_TYPE(FbxPropertyValue),pId,&lReferencePage2 ) : NULL;
01305                 if( lReferencePage2 && lPropertyValue2 )
01306                 {
01307                     // this page is an override, but there is another page before us that overrides the value
01308                     lPropertyValue2->Get( lCurrentValue, pValueType );
01309                     lValuesEqual = FbxTypeCompare( pValue, lCurrentValue, pValueType );
01310 
01311                     if( lValuesEqual )
01312                     {
01313                         ChangePropertyItemState( FBX_TYPE(FbxPropertyValue), pId, FbxPropertyAttr::eInherit );
01314                         lValueChanged = true;
01315                     }
01316 
01317                 }
01318                 // else this page is the originator of the property, so no need to check,
01319             }
01320 
01321             FbxTypeDeallocate(pValueType, lCurrentValue);
01322             lCurrentValue = NULL;
01323 
01324             if( lValuesEqual )
01325                 return lValueChanged;
01326         }
01327 
01328         FbxPropertyValue* lPropertyValue = ChangePropertyItemState( FBX_TYPE(FbxPropertyValue),pId,FbxPropertyAttr::eOverride );
01329         return lPropertyValue ? lPropertyValue->Set(pValue,pValueType) : false;
01330     }
01331 
01332     inline FbxPropertyAttr::EInheritType GetValueInherit(FbxInt pId, bool pCheckInstanceOf) const
01333     {
01334                 FbxPropertyPage*     lReferencePage = 0;
01335                 FbxPropertyValue*    lPropertyValue = GetPropertyItem( FBX_TYPE(FbxPropertyValue),pId,&lReferencePage );
01336 
01337         // check one level
01338         if( !pCheckInstanceOf )
01339             return lReferencePage==this ? FbxPropertyAttr::eOverride : FbxPropertyAttr::eInherit;
01340         else
01341         {
01342             if( lReferencePage==this )                  return FbxPropertyAttr::eOverride;    // this page is either an override, or the originator
01343             else if( !lReferencePage->mInstanceOf )     return FbxPropertyAttr::eInherit;     // the reference is the class root, so we must be inheriting
01344 
01345             // The reference page is not the class root, might be another override, or the originator.
01346             lPropertyValue = lReferencePage->mInstanceOf->GetPropertyItem( FBX_TYPE(FbxPropertyValue), pId );
01347 
01348             // if lReferencePage->mInstanceOf has the property value,
01349             //      lReferencePage is an override
01350             //  else
01351             //      its the originator, so this page inherits from it.
01352             return lPropertyValue ? FbxPropertyAttr::eOverride : FbxPropertyAttr::eInherit;
01353         }
01354 
01355     }
01356 
01357     inline bool SetValueInherit(FbxInt pId, FbxPropertyAttr::EInheritType pType)
01358     {
01359         // no support for this mode yet
01360         if( FbxPropertyAttr::eDeleted == pType )
01361             return false;
01362 
01363         ChangePropertyItemState( FBX_TYPE(FbxPropertyValue), pId, pType );
01364 
01365         // Above call doesn't return error codes, so just check that we match types.
01366         return GetValueInherit(pId, false) == pType;
01367     }
01368 
01369     inline bool GetDefaultValue(FbxInt pId, void* pValue, EFbxType pValueType) const
01370     {
01371         FbxPropertyPage*        lReferencePage = GetFirstPropertyItem( pId, FBX_TYPE(FbxPropertyValue) );
01372         FbxPropertyValue*       lPropertyValue = lReferencePage ? lReferencePage->GetPropertyItem( FBX_TYPE(FbxPropertyValue), pId ) : NULL;
01373 
01374         return lPropertyValue ? lPropertyValue->Get( pValue, pValueType ) : false;
01375     }
01376 
01377 
01378     // useful set and get functions
01379     template <class T> inline bool  Set( FbxInt pId, const T& pValue )    { return Set( pId,&pValue,FbxTypeOf(pValue),true ); }
01380     template <class T> inline T     Get( FbxInt pId, const T* pFBX_TYPE)  { T lValue; Get( pId,&lValue,FbxTypeOf(lValue) ); return lValue; }
01381 
01382 
01383         void    SetDataPtr(void* pDataPtr)  { mDataPtr = pDataPtr; }
01384         void*   GetDataPtr() const          { return mDataPtr; }
01385 
01386         // Instance and override management
01387         // ------------------------------------------
01388         void    PushPropertiesToParentInstance()
01389         {
01390                 if (mInstanceOf) {
01391                         const int lCount = GetPropertyEntryCount();
01392                         // push the existing properties into the parent
01393                         // ----------------------------------------------
01394                         for( int i = 0; i < lCount; ++i )
01395                         {
01396                           FbxPropertyEntry* lParentEntry = mInstanceOf->ChangePropertyEntryState( (FbxInt)i,FbxPropertyAttr::eOverride );
01397                           FbxPropertyEntry* lEntry       = GetPropertyEntry( (FbxInt)i );
01398 
01399                                 if( !lParentEntry )
01400                                 {
01401                                         lParentEntry = FbxPropertyEntry::Create( lEntry->GetParentId(), 0, 0, 0 );
01402                                         mInstanceOf->mEntryMap.Insert( i, lParentEntry );
01403 
01404                                         //mInstanceOf->AddChild(i);
01405 
01406                                 }
01407 
01408                                 FBX_ASSERT( lParentEntry );
01409 
01410                                 // Add it to the parent
01411                                 // Don't touch the connections
01412                                 // -----------------------------------------
01413                                 if (lParentEntry) {
01414                                         lParentEntry->Set( lEntry->Get(FBX_TYPE(FbxPropertyInfo))  );
01415                                         lParentEntry->Set( lEntry->Get(FBX_TYPE(FbxPropertyValue)) );
01416                                         lParentEntry->Set( lEntry->Get(FBX_TYPE(FbxPropertyFlagsExt)) );
01417                                 }
01418 
01419                                 /*
01420                                 else {
01421                                         mInstanceOf->Add(
01422                                                 lEntry->GetParentId(),
01423                                                 lEntry->Get(FBX_TYPE(FbxPropertyInfo)),        // The info
01424                                                 lEntry->Get(FBX_TYPE(FbxPropertyValue)),       // The Value
01425                                                 0,                                              // The connections
01426                                                 false,
01427                                                 false
01428                                         );
01429                                 }
01430                                 */
01431 
01432                                 // Empty the current entry
01433                                 // Don't touch the connections
01434                                 // -----------------------------------------
01435                                 ChangePropertyItemState(FBX_TYPE(FbxPropertyInfo),  i,FbxPropertyAttr::eInherit);
01436                                 ChangePropertyItemState(FBX_TYPE(FbxPropertyValue), i,FbxPropertyAttr::eInherit);
01437                                 ChangePropertyItemState(FBX_TYPE(FbxPropertyFlagsExt), i,FbxPropertyAttr::eInherit);
01438                         }
01439                 }
01440         }
01441 
01442         inline const FbxPropertyPage*  GetInstanceOf() const   { return mInstanceOf; }
01443         inline FbxPropertyPage*        GetInstanceOf()         { return mInstanceOf; }
01444 
01445         inline const FbxArray<FbxPropertyPage*>&     GetInstances() const    { return mInstances; }
01446         inline FbxArray<FbxPropertyPage*>&           GetInstances()          { return mInstances; }
01447 
01448 
01449         // Flags
01450         // ------------------------------------------
01451         FbxPropertyAttr::EFlags GetFlags(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT) const
01452         {
01453                 FbxPropertyPage* lFoundIn = NULL;
01454                 FbxPropertyFlagsExt*  lPropertyFlags = GetPropertyItem( FBX_TYPE(FbxPropertyFlagsExt), pId, &lFoundIn );
01455                 FbxPropertyAttr::EFlags lFlags = FbxPropertyAttr::eNone;
01456 
01457                 if( lPropertyFlags )
01458                 {
01459                         if( !mInstanceOf ) // no inheritance.
01460                                 lFlags = lPropertyFlags->GetFlags();
01461                         else
01462                         {
01463                                 lFlags = mInstanceOf->GetFlags(pId);
01464                                 lFlags = lPropertyFlags->GetMergedFlags(lFlags);
01465                         }
01466                 }
01467                 return lFlags;
01468         }
01469 
01470         bool ModifyFlags(FbxInt pId=FBXSDK_PROPERTY_ID_ROOT,FbxPropertyAttr::EFlags pFlags=FbxPropertyAttr::eNone,bool pValue=true,bool pCheckFlagEquality=true)
01471         {
01472                 if( pCheckFlagEquality )
01473                 {
01474                         FbxPropertyPage* lFoundIn = NULL;
01475                         FbxPropertyFlagsExt* lFlag = GetPropertyItem( FBX_TYPE(FbxPropertyFlagsExt), pId, &lFoundIn );
01476 
01477                         if( lFlag )
01478                         {
01479                                 if( lFoundIn == this )
01480                                 {
01481                                         // set them in us.
01482                                         lFlag->ModifyFlags( pFlags, pValue );
01483 
01484                                          // we override this entry, check if we need to revert
01485                                         FbxPropertyFlagsExt* lInheritedFlags = mInstanceOf ? mInstanceOf->GetPropertyItem( FBX_TYPE(FbxPropertyFlagsExt), pId ) : NULL;
01486                                         if( lInheritedFlags && lInheritedFlags->Equal( *lFlag, pFlags ) )
01487                                         {
01488                                                 lFlag->UnsetMask( pFlags );
01489 
01490                                                 if( lFlag->GetMask() == 0 )
01491                                                         ChangePropertyItemState( FBX_TYPE(FbxPropertyFlagsExt), pId, FbxPropertyAttr::eInherit );
01492 
01493                                                 return true;
01494                                         }
01495                                 }
01496                                 else
01497                                 {
01498                                         // its not us. Just check if we need to set.
01499                                         FbxPropertyFlagsExt lNewValues( pFlags );
01500                                         if( lFlag->Equal( lNewValues, pFlags ) )
01501                                                 return true;
01502                                 }
01503                         }
01504                 }
01505 
01506                 FbxPropertyFlagsExt* lPropertyFlags = ChangePropertyItemState(FBX_TYPE(FbxPropertyFlagsExt), pId, FbxPropertyAttr::eOverride);
01507                 return lPropertyFlags ? lPropertyFlags->ModifyFlags( pFlags, pValue ) : false;
01508         }
01509 
01510         FbxPropertyAttr::EInheritType GetFlagsInheritType(FbxPropertyAttr::EFlags pFlags, bool pCheckInstanceOf, FbxInt pId=FBXSDK_PROPERTY_ID_ROOT) const
01511         {
01512                 FbxPropertyPage* lFoundIn = NULL;
01513                 FbxPropertyFlagsExt*  lPropertyFlags = GetPropertyItem( FBX_TYPE(FbxPropertyFlagsExt), pId, &lFoundIn );
01514 
01515                 if( !pCheckInstanceOf )
01516                         return lFoundIn != this ? FbxPropertyAttr::eInherit : ( lPropertyFlags ? lPropertyFlags->GetFlagsInheritType(pFlags) : FbxPropertyAttr::eInherit );
01517                 else
01518                 {
01519                         // This code basically counts the number of overrides for the
01520                         // given flags. The original entry is always considered an override.
01521                         // so if we see more than one, something overrode the original.
01522                         // and thus we are an override.
01523                         FbxPropertyPage* lRefPage = lFoundIn;
01524                         bool lFoundOverride = false;
01525                         while( lRefPage )
01526                         {
01527                                 lPropertyFlags = lRefPage->GetPropertyItem( FBX_TYPE(FbxPropertyFlagsExt), pId );
01528 
01529                                 if( !lPropertyFlags )
01530                                         break;  // gone too far, break.
01531 
01532                                 if( lPropertyFlags->GetFlagsInheritType( pFlags ) == FbxPropertyAttr::eOverride )
01533                                 {
01534                                         if( this == lRefPage || lFoundOverride )
01535                                                 return FbxPropertyAttr::eOverride;    // found two overrides or this page is the override.
01536                                         else
01537                                                 lFoundOverride = true;  // signal that we found the first override.
01538                                 }
01539                                 lRefPage = lRefPage->mInstanceOf;
01540                         }
01541 
01542                         return FbxPropertyAttr::eInherit;
01543                 }
01544         }
01545 
01546         bool SetFlagsInheritType(FbxPropertyAttr::EInheritType pInheritType, FbxPropertyAttr::EFlags pFlags, FbxInt pId=FBXSDK_PROPERTY_ID_ROOT)
01547         {
01548                 FbxPropertyPage* lFoundIn = NULL;
01549                 FbxPropertyFlagsExt* lPropertyFlags = NULL;
01550 
01551                 if( FbxPropertyAttr::eOverride == pInheritType )
01552                 {
01553                         lPropertyFlags = ChangePropertyItemState( FBX_TYPE(FbxPropertyFlagsExt), pId, FbxPropertyAttr::eOverride );
01554 
01555                         // we should initialize our flag to the inherited value, if any.
01556                         FbxPropertyFlagsExt* lParentFlags = mInstanceOf ? mInstanceOf->GetPropertyItem( FBX_TYPE(FbxPropertyFlagsExt), pId ) : NULL;
01557                         if( lParentFlags && lPropertyFlags )
01558                         {
01559                                 FbxPropertyAttr::EFlags lParentValues = lParentFlags->GetFlags();
01560                                 lPropertyFlags->SetFlags( pFlags, lParentValues );
01561                                 return lPropertyFlags->SetMask( pFlags );
01562                         }
01563 
01564                         return false;
01565                 }
01566                 else if( FbxPropertyAttr::eInherit == pInheritType )
01567                 {
01568                         lPropertyFlags = GetPropertyItem(FBX_TYPE(FbxPropertyFlagsExt), pId, &lFoundIn);
01569                         if( !lPropertyFlags ) return false;
01570                         if( lFoundIn != this ) return true; // not us
01571                         lPropertyFlags->UnsetMask( pFlags );
01572                         if( lPropertyFlags->GetMask() == 0 )    // revert
01573                                 ChangePropertyItemState( FBX_TYPE(FbxPropertyFlagsExt), pId, FbxPropertyAttr::eInherit );
01574 
01575                         return true;
01576                 }
01577                 return false;
01578         }
01579 
01580         inline void BeginCreateOrFindProperty()
01581         {
01582                 if( 0 == mNameMap.mFirst )
01583                 {
01584                         mNameMap.mSecond.Reserve(20);
01585 
01586                         // push the existing properties into the map. Note: this includes the root property!
01587                         FbxInt lFoundId = FBXSDK_PROPERTY_ID_ROOT;
01588                         FbxPropertyEntry* lEntry = GetPropertyEntry(lFoundId);
01589                         while(lFoundId != FBXSDK_PROPERTY_ID_NULL)
01590                         {
01591                                 FbxPropertyInfo* lInfo = lEntry->Get(FBX_TYPE(FbxPropertyInfo));
01592                                 //FBX_ASSERT( lInfo );
01593                                 if (lInfo)
01594                                 {
01595                                         mNameMap.mSecond.Insert(FbxNameMapKey(lEntry->GetParentId(), lInfo->GetName()), lFoundId);
01596                                 }
01597                                 lFoundId = GetMinimumPropertyIdAndEntry(lFoundId, &lEntry);
01598                         }
01599                         mNameMap.mFirst++;
01600                 }
01601         }
01602 
01603         inline void EndCreateOrFindProperty()
01604         {
01605                 if( mNameMap.mFirst > 0 )
01606                 {
01607                         if( --(mNameMap.mFirst) == 0 )
01608                                 mNameMap.mSecond.Clear();
01609                 }
01610         }
01611 
01612 protected:
01613     FbxPropertyPage(FbxPropertyPage* pInstanceOf=0)
01614         : mInstanceOf(0)
01615         , mDataPtr(0)
01616         , mPropNextId(0)
01617     {
01618         mEntryMap.Reserve(32);
01619         mNameMap.mFirst = 0;
01620 
01621         // instances don't need to create a root property
01622         if( !pInstanceOf )
01623         {
01624             mPropNextId = FbxNew< FbxPropertyIdGenerator >();
01625             mPropNextId->IncRef();
01626 
01627             // First item is the root information
01628             Add(FBXSDK_PROPERTY_ID_NULL,"",eFbxUndefined);
01629         }
01630 
01631         // Hook the instances
01632         // ------------------------
01633         mInstanceOf = pInstanceOf;
01634         if (mInstanceOf) {
01635             mInstanceOf->mInstances.Add(this);
01636 
01637             mPropNextId = mInstanceOf->mPropNextId;
01638             mPropNextId->IncRef();
01639         }
01640     }
01641     FbxPropertyPage(const char* pName, EFbxType pType)
01642         : mInstanceOf(0)
01643         , mDataPtr(0)
01644         , mPropNextId(0)
01645     {
01646         mEntryMap.Reserve(32);
01647         mNameMap.mFirst = 0;
01648 
01649         mPropNextId = FbxNew< FbxPropertyIdGenerator >();
01650         mPropNextId->IncRef();
01651 
01652         // First item is the root information
01653         Add(FBXSDK_PROPERTY_ID_NULL,pName,pType);
01654     }
01655     FbxPropertyPage(const char* pName, FbxPropertyPage* pTypeInfo)
01656         : mInstanceOf(0)
01657         , mDataPtr(0)
01658         , mPropNextId(0)
01659     {
01660         mEntryMap.Reserve(32);
01661         mNameMap.mFirst = 0;
01662 
01663         mPropNextId = FbxNew< FbxPropertyIdGenerator >();
01664         mPropNextId->IncRef();
01665 
01666         // First item is the root information
01667         Add(FBXSDK_PROPERTY_ID_NULL,pName,pTypeInfo);
01668     }
01669     ~FbxPropertyPage()
01670     {
01671         // Propagate our property entries.
01672         int i = 0, j = 0;
01673         for( i = 0; i < mInstances.GetCount(); ++i )
01674         {
01675             for( j = 0; j < GetPropertyEntryCount(); ++j )
01676             {
01677                 if( mInstances[i]->ChangePropertyEntryState((FbxInt)j, FbxPropertyAttr::eOverride) )
01678                 {
01679                     // Clone the info and values. Don't clone the connections,
01680                     // since they aren't propagated.
01681                     mInstances[i]->ChangePropertyItemState( FBX_TYPE(FbxPropertyInfo), (FbxInt)j, FbxPropertyAttr::eOverride );
01682                     mInstances[i]->ChangePropertyItemState( FBX_TYPE(FbxPropertyValue), (FbxInt)j, FbxPropertyAttr::eOverride );
01683 
01684                     // Since all entries have their own flags, just override the ones in the instance.
01685                     mInstances[i]->SetFlagsInheritType(FbxPropertyAttr::eOverride, FbxPropertyAttr::eAllFlags, (FbxInt)j );
01686                 }
01687             }
01688 
01689             // Instances become their own copies.
01690             mInstances[i]->mInstanceOf = NULL;
01691         }
01692 
01693         // Not a very efficient way of traversing the map
01694         EntryMap::Iterator lElement = mEntryMap.Begin();
01695         while (lElement != mEntryMap.End())
01696         {
01697             lElement->GetValue()->Destroy();
01698             lElement++;
01699         }
01700 
01701         if (mInstanceOf) {
01702             int lIndex = mInstanceOf->mInstances.Find(this);
01703             mInstanceOf->mInstances.SetAt(lIndex, mInstanceOf->mInstances[mInstanceOf->mInstances.GetCount()-1]);
01704             mInstanceOf->mInstances.RemoveAt(mInstanceOf->mInstances.GetCount()-1);
01705 
01706             //mInstanceOf->mInstances.RemoveIt(this);
01707         }
01708 
01709         mPropNextId->DecRef();
01710         mPropNextId = NULL;
01711 
01712         mInstanceOf = NULL;
01713         mInstances.Clear();
01714     }
01715 
01716     inline bool Is(FbxPropertyPage* pPage)
01717     {
01718         // @@@@@@@@@@@@@@@ Must complete for sub types
01719         return this==pPage;
01720     }
01721 
01722 // Internal entry management
01723 private:
01724 
01730     FbxInt GetMinimumPropertyId(FbxInt pId, bool pIncrementIfNone = true) const
01731     {
01732         if( pId == FBXSDK_PROPERTY_ID_NULL )
01733             pId = FBXSDK_PROPERTY_ID_ROOT;
01734        
01735         FbxInt lMin = FBXSDK_PROPERTY_ID_NULL;
01736         const EntryMap::RecordType* lElement = mEntryMap.UpperBound(pId);
01737         if (NULL != lElement)
01738         {
01739             lMin = lElement->GetKey();
01740         }
01741 
01742         FbxInt lParentMin = mInstanceOf ? mInstanceOf->GetMinimumPropertyId(pId,false) : FBXSDK_PROPERTY_ID_NULL;
01743 
01744         bool lParentNull = lParentMin == FBXSDK_PROPERTY_ID_NULL;
01745         bool lMinNull = lMin == FBXSDK_PROPERTY_ID_NULL;
01746 
01747         if( lParentNull && lMinNull )   return pIncrementIfNone ? pId+1 : FBXSDK_PROPERTY_ID_NULL;
01748         else if( lMinNull )             lMin = lParentMin;
01749         else if( !lParentNull )         lMin = lMin < lParentMin ? lMin : lParentMin;
01750 
01751         return lMin;
01752     }
01753 
01759     FbxInt GetMinimumPropertyIdAndEntry(FbxInt pId, FbxPropertyEntry** pEntry) const
01760     {
01761         FbxInt lFoundId = FBXSDK_PROPERTY_ID_NULL;
01762         FbxPropertyEntry* lFoundEntry = NULL;
01763         if( pId == FBXSDK_PROPERTY_ID_NULL )
01764             pId = FBXSDK_PROPERTY_ID_ROOT;
01765 
01766         const EntryMap::RecordType* lElement = mEntryMap.UpperBound(pId);
01767         if (NULL != lElement)
01768         {
01769             lFoundId = lElement->GetKey();
01770             lFoundEntry = lElement->GetValue();
01771         }
01772 
01773         FbxPropertyEntry* lParentEntry = NULL;
01774         FbxInt lParentMin = mInstanceOf ? mInstanceOf->GetMinimumPropertyIdAndEntry(pId, &lParentEntry) : FBXSDK_PROPERTY_ID_NULL;
01775 
01776         bool lParentNull = lParentMin == FBXSDK_PROPERTY_ID_NULL;
01777         bool lMinNull = lFoundId == FBXSDK_PROPERTY_ID_NULL;
01778 
01779         if( lMinNull && !lParentNull )
01780         {
01781             lFoundId = lParentMin;
01782             lFoundEntry = lParentEntry;
01783         }
01784         else if( !lMinNull && !lParentNull )
01785         {
01786             lFoundId = lFoundId < lParentMin ? lFoundId : lParentMin;
01787             lFoundEntry = lFoundId < lParentMin ? lFoundEntry : lParentEntry;
01788         }
01789 
01790         if (pEntry)
01791             *pEntry = lFoundEntry;
01792         return lFoundId;
01793     }
01794 
01795     int GetPropertyEntryCount() const
01796     {
01797         int lCount = 0;
01798         const EntryMap::RecordType* lElement = mEntryMap.Maximum();
01799 
01800         if (NULL != lElement)
01801         {
01802             lCount = lElement->GetKey() + 1;
01803         }
01804 
01805         int lParentCount = mInstanceOf ? mInstanceOf->GetPropertyEntryCount() : 0;
01806         return lParentCount > lCount ? lParentCount : lCount;
01807     }
01808 
01809     FbxPropertyEntry* GetPropertyEntry(FbxInt pIndex,FbxPropertyPage **pFoundIn=0) const
01810     {
01811         const EntryMap::RecordType* lElement = mEntryMap.Find(pIndex);
01812         if (NULL != lElement)
01813         {
01814             if( pFoundIn )
01815             {
01816                 *pFoundIn = const_cast<FbxPropertyPage*>(this);
01817             }
01818             return lElement->GetValue();
01819         }
01820         
01821         if( pFoundIn )
01822         {
01823             *pFoundIn = 0;
01824         }
01825 
01826         return mInstanceOf ? mInstanceOf->GetPropertyEntry(pIndex,pFoundIn) : 0;
01827     }
01828 
01829     FbxPropertyEntry* ChangePropertyEntryState(FbxInt pIndex,FbxPropertyAttr::EInheritType pInheritType)
01830     {
01831                 FbxPropertyPage*     lReferencePage      = 0;
01832                 FbxPropertyEntry*    lReferenceEntry     = GetPropertyEntry(pIndex,&lReferencePage);
01833 
01834         if (pInheritType==FbxPropertyAttr::eOverride) {
01835             if (lReferencePage==this) {
01836                 return lReferenceEntry;
01837             } else if (lReferenceEntry) {
01838                 // must create an entry
01839                 FbxPropertyEntry* lEntry = FbxPropertyEntry::Create(lReferenceEntry->GetParentId(),0,0,0);
01840                 mEntryMap.Insert( pIndex, lEntry );
01841 
01842                 return lEntry;
01843             }
01844         } else {
01845             if (lReferenceEntry && (lReferencePage==this)) {
01846                 mEntryMap.Remove(pIndex);
01847                 lReferenceEntry->Destroy();
01848             }
01849         }
01850         return 0;
01851     }
01852 
01853     FbxInt Add(FbxInt pParentId,FbxPropertyInfo* pInfo,FbxPropertyValue* pValue,FbxPropertyConnect* pConnect,bool pRecursive=true)
01854     {
01855         FbxInt lId = mPropNextId->GetNextIdAndInc();
01856         FbxPropertyEntry* lEntry = FbxPropertyEntry::Create(pParentId,pInfo,pValue,pConnect);
01857         
01858         // entries created through Add() are not overrides of another entry.
01859         // Thus, set all of their flags by default.
01860         FbxPropertyFlagsExt* lFlags = lEntry->Get( FBX_TYPE(FbxPropertyFlagsExt) );
01861         if( lFlags ) lFlags->ModifyFlags( FbxPropertyAttr::eAllFlags, false );
01862 
01863         mEntryMap.Insert( lId, lEntry );
01864 
01865         // We only add to the map if this Add is called after BeginCreateOrFindProperty()
01866         // in which case the size is always > 0 because it includes the root property
01867         if( mNameMap.mSecond.GetSize() > 0 )
01868             mNameMap.mSecond.Insert( FbxNameMapKey( pParentId, pInfo->GetName()), lId );
01869 
01870         // If the entry has multiple children(Struct Datatype)
01871         // Recurse for the entries and create an entry in this structure
01872         if (pRecursive) {
01873             FbxPropertyPage* lTypeInfo = pInfo->GetTypeInfo();
01874             if (lTypeInfo) {
01875                                 FbxInt lChildId;
01876                 lChildId = lTypeInfo->GetChild();
01877                 while (lChildId!=FBXSDK_PROPERTY_ID_NULL) {
01878                                         FbxPropertyInfo*                lPropertyInfo    = lTypeInfo->GetPropertyItem( FBX_TYPE(FbxPropertyInfo),lChildId );
01879                                         FbxPropertyValue*       lPropertyValue   = lTypeInfo->GetPropertyItem( FBX_TYPE(FbxPropertyValue),lChildId );
01880                                         FbxPropertyConnect*     lPropertyConnect = lTypeInfo->GetPropertyItem( FBX_TYPE(FbxPropertyConnect),lChildId );
01881 
01882                     Add ( lId, lPropertyInfo ? lPropertyInfo->Clone(this) : 0 , lPropertyValue ? lPropertyValue->Clone(this) : 0,
01883                                                            lPropertyConnect ? lPropertyConnect->Clone(this) : 0 );
01884                     lChildId = lTypeInfo->GetSibling(lChildId );
01885                 }
01886             }
01887         }
01888         return lId;
01889     }       
01890 
01891     // Property management
01892     typedef FbxMap<FbxInt, FbxPropertyEntry*, FbxLessCompare<FbxInt>, FbxHungryAllocator> EntryMap;
01893     EntryMap mEntryMap;
01894 
01895     // instance management
01896     FbxPropertyPage*                            mInstanceOf;
01897     FbxArray<FbxPropertyPage*>          mInstances;
01898 
01899     void*                                                       mDataPtr;
01900 
01901     // speed up structure
01902     typedef FbxMap<FbxNameMapKey, FbxInt, FbxNameMapCompare > NameMap;
01903     typedef FbxPair<unsigned int, NameMap > NameLookupPair;
01904     NameLookupPair     mNameMap;
01905 
01906     FbxPropertyIdGenerator* mPropNextId;
01907 
01908     friend class FbxPropertyHandle;
01909 };
01910 
01911 #include <fbxsdk/fbxsdk_nsend.h>
01912 
01913 #endif /* _FBXSDK_CORE_PROPERTY_PAGE_H_ */