- Main Page
- Classes
- Files
- Directories

- File List
- File Members

# 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_ */