Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Acessing CustomDataType parameters

    SDK Help
    0
    3
    553
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      On 24/11/2017 at 19:42, xxxxxxxx wrote:

      User Information:
      Cinema 4D Version:   R9 
      Platform:   Windows  ; Mac  ;  Mac OSX  ; 
      Language(s) :     C++  ;

      ---------
      Hi,
      I'm using custom data types, but there are some things that I'm not working as I expected.
      Here's what I'm doing and what's missing. Please correct me if I'm doing anything wrong.

      I have a custom data class (MyData) derived from CustomDataType, that holds multiple arrays.
      Its defined by a CustomDataTypeClass (MyDataType), with a unique plugin ID (ID_MY_DATA).
      It declares a custom resource type (MYDATA , from GetResourceSym()) that I use on a tag (T_MY_DATA).

      To read and write MyData on the tag, I created 2 functions that work very fine:

      GeData holder;
      CustomDataType* customData = GetUserData( Get(), ID_MY_DATA, T_MY_DATA, holder );
      MyData* myData = static_cast< MyData*>( customData );
        
      	// holder will keep a valid pointer while in context
      	CustomDataType* GetUserData( GeListNode* node, const Int32 dataType, const Int32 refId, GeData& holder )
      	{
      		DescID desc( DescLevel( ID_USERDATA, DTYPE_SUBCONTAINER, 0 ), DescLevel(refId, dataType, 0 ) );
      		node->GetParameter( desc, holder, DESCFLAGS_GET_0 );
      		CustomDataType* customData = holder.GetCustomDataType(dataType);
      		return customData;
      	}
        
      SetUserData( Get(), ID_MY_DATA, T_MY_DATA, static_cast<CustomDataType*>( myData ) );
        
      	void SetUserData( GeListNode* node, const Int32 dataType, const Int32 refId, const CustomDataType* customData )
      	{
      		if (customData != nullptr)
      		{
      			GeData holder;
      			holder.SetCustomDataType( dataType, *customData );
      			DescID desc( DescLevel( ID_USERDATA, DTYPE_SUBCONTAINER, 0 ), DescLevel( refId, dataType, 0 ) );
      			node->SetParameter( desc, holder, DESCFLAGS_SET_FORCESET );
      		}
      	}
      
      1. My CustomDataTypeClass also defines some LONG parameters. How do I set and get them from outside the class? I tried many DescID configurations and no success. Since the CustomDataType I have access is an empty shell, not a NodeData or C4DAtom, I can't use SetParameter() and GetParameter(). Is this only exposed thru the Attributes Manager?

      2. CustomDataTypeClass does have GetParameter() and SetDParameter(), but is there a way get it instead of CustomDataType?

      3. I tried to set/set the LONGs from GetParameter() and SetDParameter(), but the data pointer points to an empty MyData. Is there a catch here? Compare() and CopyData() are implemented.

      4. GetEnabling() also seems to have no effect, even always returning false the attribute fields are always enabled.

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 27/11/2017 at 03:38, xxxxxxxx wrote:

        Hello,

        could you post the code of your custom data type? This would help to understand what you are doing.

        Please notice the the custom data stored in a custom data type is typically based on iCustomDataType. You find an example in customdata_customgui.cpp.

        A simple data type that defines a sub-parameters can look like this:

          
        class ExampleCustomDataClass;  
          
        class iExampleData : public iCustomDataType<iExampleData>  
        {  
         friend class ExampleCustomDataClass;  
          
        public:  
         String _string;  
         Int32     _int;  
          
         iExampleData()  
         {  
             _string = "";  
             _int = 0;  
         }  
        };  
          
        const Int g_customDataID = 1000001;  
          
        class ExampleCustomDataClass : public CustomDataTypeClass  
        {  
         INSTANCEOF(ExampleCustomData, CustomDataTypeClass)  
          
        public:  
         virtual Int32 GetId()  
         {  
             return g_customDataID;  
         }  
          
         virtual CustomDataType* AllocData()  
         {  
             iExampleData* data = NewObjClear(iExampleData);  
             return data;  
         };  
          
         virtual void FreeData(CustomDataType* data)  
         {  
             iExampleData* d = static_cast<iExampleData*>(data);  
             DeleteObj(d);  
         }  
          
         virtual Bool CopyData(const CustomDataType* src, CustomDataType* dst, AliasTrans* aliastrans)  
         {  
             const iExampleData* s = static_cast<const iExampleData*>(src);  
             iExampleData*                d = static_cast<iExampleData*>(dst);  
             if (!s || !d)  
                 return false;  
             d->_int = s->_int;  
             d->_string = d->_string;  
             return true;  
         }  
          
         virtual Int32 Compare(const CustomDataType* d1, const CustomDataType* d2)  
         {  
             const    iExampleData* const s = static_cast<const    iExampleData*>(d1);  
             const    iExampleData* const d = static_cast<const    iExampleData*>(d2);  
             if (!s || !d)  
                 return 0;  
             // just compare the int because I'm lazy  
             const maxon::Int countd1 = s->_int;  
             const maxon::Int countd2 = d->_int;  
          
             if (countd1 == countd2)  
                 return 0;  
             if (countd1 < countd2)  
                 return -1;  
             if (countd1 > countd2)  
                 return 1;  
          
             return 0;  
         }  
          
         virtual Bool _GetDescription(const CustomDataType* data, Description& res, DESCFLAGS_DESC& flags, const BaseContainer& parentdescription, DescID* singledescid)  
         {  
             BaseContainer stringSettings = GetCustomDataTypeDefault(DTYPE_STRING);  
             stringSettings.SetString(DESC_NAME, "String Data");  
             stringSettings.SetString(DESC_SHORT_NAME, "String Data");  
             stringSettings.SetFloat(DESC_MIN, 0.0f);  
             stringSettings.SetFloat(DESC_MAX, 1.0f);  
             stringSettings.SetFloat(DESC_STEP, 0.01f);  
             if (!res.SetParameter(DescLevel(1000, DTYPE_STRING, g_customDataID), stringSettings, DESCID_ROOT))  
                 return false;  
          
          
             BaseContainer intSettings = GetCustomDataTypeDefault(DTYPE_LONG);  
             intSettings.SetString(DESC_NAME, "Int data");  
             intSettings.SetString(DESC_SHORT_NAME, "Intdata");  
             if (!res.SetParameter(DescLevel(1001, DTYPE_LONG, g_customDataID), intSettings, DESCID_ROOT))  
                 return false;  
          
             flags |= DESCFLAGS_DESC_LOADED;  
             return CustomDataTypeClass::_GetDescription(data, res, flags, parentdescription, singledescid);  
         }  
          
         virtual Bool GetParameter(const CustomDataType* data, const DescID& id, GeData& t_data, DESCFLAGS_GET& flags)  
         {  
             iExampleData* s = (iExampleData* )data;  
             if (!s)  
                 return false;  
          
             const Int32 subID = id[0].id;  
          
             if (subID == 1000)  
                 t_data = GeData(s->_string);  
             else if (subID == 1001)  
                 t_data = GeData((Int32)s->_int);  
          
             flags |= DESCFLAGS_GET_PARAM_GET;  
             return CustomDataTypeClass::GetParameter(data, id, t_data, flags);  
         }  
          
         virtual Bool SetDParameter(CustomDataType* data, const DescID& id, const GeData& t_data, DESCFLAGS_SET& flags)  
         {  
             iExampleData* s = (iExampleData* )data;  
             if (!s)  
                 return false;  
          
             const Int32 subID = id[0].id;  
             if (subID == 1000)  
             {  
                 s->_string = t_data.GetString();  
             }  
             else if (subID == 1001)  
             {  
                 s->_int = t_data.GetInt32();  
             }  
             flags |= DESCFLAGS_SET_PARAM_SET;  
             return CustomDataTypeClass::SetDParameter(data, id, t_data, flags);  
         }  
          
         virtual Bool GetEnabling(const CustomDataType* data, const DescID& id, const GeData& t_data, DESCFLAGS_ENABLE& flags, const BaseContainer* itemdesc)  
         {  
             const iExampleData* s = static_cast<const iExampleData*>(data);  
             if (!s)  
                 return false;  
          
             const Int32 subID = id[0].id;;  
          
             if (subID == 1001)  
             {  
                 if (s->_string.Content())  
                     return true;  
                 else  
                     return false;  
             }  
          
             return SUPER::GetEnabling(data, id, t_data, flags, itemdesc);  
         }  
          
         virtual const Char* GetResourceSym()  
         {  
             return "EXAMPLE";  
         }  
          
         virtual void GetDefaultProperties(BaseContainer& data)  
         {  
             // the default values of this datatype  
             data.SetInt32(DESC_ANIMATE, DESC_ANIMATE_ON);  
         }  
          
         virtual Bool WriteData(const CustomDataType* t_d, HyperFile* hf)  
         {  
             // skip that to make this example easy  
             return true;  
         }  
          
         virtual Bool ReadData(CustomDataType* t_d, HyperFile* hf, Int32 level)  
         {  
             // skip that to make this example easy  
             return true;  
         }  
        };  
        

        The sub-parameter can then be accessed with a properly created DescID:

          
        GeData data;  
          
        DescID desc(DescLevel(ID_USERDATA, DTYPE_SUBCONTAINER, 0), DescLevel(1, g_customDataID, 0), DescLevel(1000, DTYPE_STRING, 0));  
          
        node->GetParameter(desc, data, DESCFLAGS_GET_0);  
          
        const String str = data.GetString();  
        GePrint(str);  
        

        To work with the CustomDataType returned by GetCustomDataType() you would have to define a public class based on CustomDataType that exposes internal functionality using the library system. But that's quite an advanced topic.

        From a quick look, it seems that GetEnabling() is not used at all.

        best wishes,
        Sebastian

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 11/12/2017 at 12:38, xxxxxxxx wrote:

          Hi Sebastian,

          I'm sure I wrote an answer to this topic, but probably never sent.

          The description to access user data works, thanks!

          Found out my problem in GetParameter and SetDParameter was because of my _GetDescription(). I copied it exactly like the datatype.cpp example, and just removing it allowed me to finally see the actual data in Get/Set. Seems like the UI was resetting it, but I could not find any mistake in my code. Now I'm using a _GetDescription() like yours and data is fine, I don't see the values in the attributes manager. I don't want the user to change the attributes, just show some chewed up data from the userdata.

          1 Reply Last reply Reply Quote 0
          • First post
            Last post