- Main Page
- Classes
- Files
- Directories
- Examples

- File List
- File Members

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