fbxpropertypage.h

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