Acessing CustomDataType parameters



  • 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.



  • 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



  • 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.


Log in to reply