FieldList Enable Clamping
-
Hi.
I'm working on a plugin that utilizes a FieldList control that I am creating using custom data type CUSTOMDATATYPE_FIELDLIST. My issue comes in with the "Enable/Disable Value Clamping" control and not being able to change it using code.
I've looked through the sdk in relation to the FieldList entry and couldn't find anything that refrences it. The closest thing I could find was the FIELDLIST_FLAGS::CLAMPOUTPUT which not suprisingly had no effect on the control when used with SetFlags.
This is my code for creating my FieldList control.
DescID DescFieldGroup = DescLevel(idFieldGroup, DTYPE_GROUP, 0); if (!singleid || DescFieldGroup.IsPartOf(*singleid, NULL)) { BaseContainer bc; bc = GetCustomDataTypeDefault(DTYPE_GROUP); bc.SetInt32(DESC_COLUMNS, 1); bc.SetBool(DESC_SCALEH, TRUE); if (!description->SetParameter(DescFieldGroup, bc, idMainGroup)) return TRUE; } cid = DescLevel(idGrowField, CUSTOMDATATYPE_FIELDLIST, 0); if (!singleid || cid.IsPartOf(*singleid, NULL)) { BaseContainer bc; bc = GetCustomDataTypeDefault(CUSTOMDATATYPE_FIELDLIST); bc.SetBool(DESC_FIELDLIST_NOCOLOR, TRUE); bc.SetBool(DESC_FIELDLIST_NODIRECTION, TRUE); bc.SetBool(DESC_FIELDLIST_NOROTATION, TRUE); if (!description->SetParameter(cid, bc, DescFieldGroup)) return TRUE; }
Is it possible to change the control via code or can it only be changed manually by a user.
Any help would be greatly appreciated.
John Terenece
-
hi,
It is not clear what parameter you want to modify. The code you are sharing is inside GetDDescription i suppose.
You need to user SetParameter on your node itself. The tricky part is to build the DescID to target the right parameter.
You need the ID of your fieldList, the ID of the layer on that list and the parameter ID on that layer. All level must be defined as CUSTOMDATATYPE_FIELDLIST.You must search for the layer inside your field list and call GetUniqueID on it. This will return the correct ID you must use in your DescLevel. Below a script that will flip/flop the parameter "enable/value" for the first layer in the list.
I created a python script for r20 and for more recent version
R20 version
import c4d def main(): # Called when the plugin is selected by the user. Similar to CommandData.Execute. effector = op if effector is None: raise ValueError("there is no active objet") fieldList = effector[c4d.FIELDS] root = fieldList.GetLayersRoot() clampLayer = root.GetDown() # Retriving the unique ID allows to construct the DescID to target the right parameter. clampUniqueID = clampLayer.GetUniqueID() # Building the DescID # This ID is composed of three level: # the first one define the field list parameter, # the second define the layer, that is why we need its UniqueID, # the last level define the parameter in this layer. # Note that all DescLevel are of DataType CUSTOMDATATYPE_FIELDLIST enableID = c4d.DescID(c4d.DescLevel(c4d.FIELDS, c4d.CUSTOMDATATYPE_FIELDLIST), c4d.DescLevel(clampUniqueID, c4d.CUSTOMDATATYPE_FIELDLIST), c4d.DescLevel(c4d.ID_FIELDLAYER_ENABLE_VALUE, c4d.CUSTOMDATATYPE_FIELDLIST)) # Retreving the value using GetParameter on the effector itself. value = effector.GetParameter(enableID, c4d.DESCFLAGS_GET_NONE) # Define the oposite value effector.SetParameter(enableID, not value, c4d.DESCFLAGS_SET_NONE) c4d.EventAdd() if __name__ == '__main__': main()
Same example but for more recent version of c4d.
from typing import Optional import c4d doc: c4d.documents.BaseDocument # The active document op: Optional[c4d.BaseObject] # The active object, None if unselected def main() -> None: # Called when the plugin is selected by the user. Similar to CommandData.Execute. effector :c4d.BaseObject = op if effector is None: raise ValueError("there is no active objet") fieldList :c4d.FieldList = effector[c4d.FIELDS] root :c4d.GeListHead = fieldList.GetLayersRoot() clampLayer :c4d.modules.mograph.FieldLayer = root.GetDown() # Retriving the unique ID allows to construct the DescID to target the right parameter. clampUniqueID = clampLayer.GetUniqueID() # Building the DescID # This ID is composed of three level: # the first one define the field list parameter, # the second define the layer, that is why we need its UniqueID, # the last level define the parameter in this layer. # Note that all DescLevel are of DataType CUSTOMDATATYPE_FIELDLIST enableID :c4d.DescID = c4d.DescID(c4d.DescLevel(c4d.FIELDS, c4d.CUSTOMDATATYPE_FIELDLIST), c4d.DescLevel(clampUniqueID, c4d.CUSTOMDATATYPE_FIELDLIST), c4d.DescLevel(c4d.ID_FIELDLAYER_ENABLE_VALUE, c4d.CUSTOMDATATYPE_FIELDLIST)) # Retreving the value using GetParameter on the effector itself. value : bool = effector.GetParameter(enableID, c4d.DESCFLAGS_GET_NONE) # Define the oposite value effector.SetParameter(enableID, not value, c4d.DESCFLAGS_SET_NONE) c4d.EventAdd() if __name__ == '__main__': main()
Cheers,
Manuel -
-
hi,
for this, you must use the function SetFlags on the Field data and update the data on the object. The flag that must be set is
FIELDLIST_FLAGS::CLAMPOUTPUT
Unfortunately, the UI do not update, you must deselect and reselect the object. I did not find anything yet to address this issue.
I used c++ this time to be sure nothing was wrong with python.BaseObject* op = doc->GetActiveObject(); if (!op) return maxon::NullptrError(MAXON_SOURCE_LOCATION); GeData data; op->GetParameter(FIELDS, data, DESCFLAGS_GET::NONE); FieldList* fl = static_cast<FieldList*>(data.GetCustomDataType(CUSTOMDATATYPE_FIELDLIST)); fl->SetFlags(FIELDLIST_FLAGS::CLAMPOUTPUT, false); op->SetParameter(FIELDS, GeData(CUSTOMDATATYPE_FIELDLIST, *fl), DESCFLAGS_SET::NONE);
python code just in case
fl = op[c4d.FIELDS] toggle = fl.CheckFlag(c4d.FIELDLIST_FLAGS_CLAMPOUTPUT) fl.SetFlags(c4d.FIELDLIST_FLAGS_CLAMPOUTPUT, not toggle) op[c4d.FIELDS] = fl
Cheers,
Manuel -
Thanks, that was exactly what I was looking for.
John Terenece