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 ); } }
-
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?
-
CustomDataTypeClass does have GetParameter() and SetDParameter(), but is there a way get it instead of CustomDataType?
-
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.
-
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.