Parameters in predefined functions
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 02/02/2007 at 02:47, xxxxxxxx wrote:
User Information:
Cinema 4D Version: R9.507
Platform: Windows ;
Language(s) : C++ ;---------
I got a little problem understanding the parameter handling in functions. In some functions there are parameters like BaseDocument* doc, BaseObject* op or Description *description. It seems to me that Cinema4d "knows" that 'doc' is this document or 'op' is the object the function belongs to. But what how can i manually call functions with these standart parameters?
I want to create someting like the Mocca Pose Mixer Tag Interface. If you click on "Add Pose" a new line in the description file will be created.
I thought i have to combine a Message and a GetDDescription function like this:
There is my GetDDesctiption function which is able to create some entries in a descrtipion file:Bool TagCone::GetDDescription(GeListNode *node, Description *description, LONG &flags)
and there is my Message function which controls the buttons in the description file.
Bool TagCone::Message(GeListNode *node, LONG type, void *data) { switch (type) { case MSG_DESCRIPTION_COMMAND: { DescriptionCommand *dc = (DescriptionCommand* ) data; Bool TagCone::Message(GeListNode *node, LONG type, void *data) { GePrint("Yeah hit me again!!!"); GetDDescription(node,???,???); } ....
How you can see I want to call the GetDDescription Function out of my Message Function. The parameter node is used in both functions so i can pass it to the GetDDescription Function. But i don't know how i can pass the parameter "description" to the GetDDescription Function, cause the Message Function has no parameter "description". (And i don't know what i should do with this LONG &flags)
Can someone tell me what i should do or tell me if there is another maybe simpler way (with only one function) to get an interface like in the Mocca Pose Mixer Tag ... -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 02/02/2007 at 12:07, xxxxxxxx wrote:
GetDDescription() is called *fairly* often (sarcasm). If you add GePrint("GetDDescription"); to the top of your GetDDescription() function call and open C4D's Console, you'll see just how frequently is it indeed called.
That said, you should never have to call this function directly. A good way to 'kick' your plugin to call GetDDescription() is to send a Message(MSG_CHANGE) for the plugin - node->Message(MSG_CHANGE);. You may also try node->GetDescription(desc,0);. Description* desc will need to be allocated/freed each time.
For example, you add your dynamic description elements using GetD(ynamic)Description(). These are description elements not stored statically in the description .res file for the plugin. They need their own IDs that don't conflict with the static ones.
MSG_DESCRIPTION_COMMAND is sent when a description button is clicked. If you are wanting to add dynamic elements on a button click, then you are heading in the correct direction. But instead of trying to call GetDDescription from there, get the node and do node->Message(MSG_CHANGE). In the GetDDescription() function is where you are going to assemble the dynamic elements - that is its purpose.
// NodeData.GetDDescription - Descriptions and Parameters //*---------------------------------------------------------------------------* Bool IPPBase::GetDDescription(GeListNode* node, Description* description, LONG& flags) //*---------------------------------------------------------------------------* { if (!(node && description)) return FALSE; if (!description->LoadDescription(node->GetType())) return FALSE; // Get Object containing Dials BaseDocument* baseDoc = node->GetDocument(); if (!baseDoc) return FALSE; BaseObject* obj = static_cast<BaseObject*>(node); if (!obj) return FALSE; BaseContainer* opBC = obj->GetDataInstance(); if (!opBC) return FALSE; // Add dial tags BaseContainer* pbc; DescID descID; String dname; ULONG type; ULONG tsf; LONG index; BOOL hideZero = opBC->GetBool(IPP_HIDE_ZERODIALS); BOOL hide; Real value; // Initialize BaseContainer static values BaseContainer sliderBC = GetCustomDataTypeDefault(DTYPE_REAL); sliderBC.SetLong(DESC_ANIMATE, DESC_ANIMATE_ON); sliderBC.SetBool(DESC_REMOVEABLE, FALSE); sliderBC.SetLong(DESC_CUSTOMGUI, CUSTOMGUI_REALSLIDER); // _REAL, _REALSLIDERONLY sliderBC.SetReal(DESC_MIN, MINREAL); sliderBC.SetReal(DESC_MAX, MAXREAL); #ifdef C4D_R85 sliderBC.SetBool(DESC_SCALEH, TRUE); #endif BaseContainer editBC = GetCustomDataTypeDefault(DTYPE_BUTTON); editBC.SetString(DESC_SHORT_NAME, "Edit"); editBC.SetLong(DESC_CUSTOMGUI, CUSTOMGUI_BUTTON); editBC.SetLong(DESC_ANIMATE, DESC_ANIMATE_OFF); editBC.SetBool(DESC_REMOVEABLE, FALSE); // Filter visible body part dial groups for (BaseTag* pt = obj->GetFirstTag(); pt; pt = pt->GetNext()) { if (!pt->IsInstanceOf(ID_IPPDIALTAG)) continue; pbc = pt->GetDataInstance(); if (!pbc) continue; // Dial Index index = pbc->GetLong(IPPDIAL_INDEX); // Dial Slider dname = pbc->GetString(IPPDIAL_DIALNAME); sliderBC.SetString(DESC_NAME, dname); value = pbc->GetReal(IPPDIAL_CURRENTVALUE); tsf = (ULONG)pbc->GetLong(IPPDIAL_TYPESUBFLAGS); type = tsf & 0x000000FFL; hide = tsf & DIAL_FLAGS_HIDDEN; // Transforms if (tsf & DIAL_FLAGS_TRANSFORM) descID = DescID(DescLevel(GROUP_TRANSFORM)); // Morphs else if (type == CHAN_TYPE_TARGETGEOM) { if (hideZero && (value == 0.0f)) hide = TRUE; descID = DescID(DescLevel(GROUP_MORPH)); } // Other else { if ((type == CHAN_TYPE_VALUEPARM) && hideZero && (value == 0.0f)) hide = TRUE; descID = DescID(DescLevel(GROUP_OTHER)); } if (hide) { // - Set display state to hide sliderBC.SetBool(DESC_HIDE, TRUE); editBC.SetBool(DESC_HIDE, TRUE); } else { sliderBC.SetString(DESC_SHORT_NAME, pt->GetName()); sliderBC.SetLong(DESC_UNIT, chanTypeParams[type].unit); // - Set Min/Max/Step for Slider sliderBC.SetReal(DESC_MINSLIDER, pbc->GetReal(IPPDIAL_MIN)); sliderBC.SetReal(DESC_MAXSLIDER, pbc->GetReal(IPPDIAL_MAX)); sliderBC.SetReal(DESC_STEP, pbc->GetReal(IPPDIAL_STEP)); // - Set display state to show sliderBC.SetBool(DESC_HIDE, FALSE); editBC.SetBool(DESC_HIDE, FALSE); editBC.SetString(DESC_NAME, dname); // -- Set Master-Slave button to show whether dial is Master and/or Slave if (tsf & DIAL_FLAGS_SLAVES) { if (tsf & DIAL_FLAGS_VALUEOP) editBC.SetString(DESC_SHORT_NAME, "Edit M/S"); else editBC.SetString(DESC_SHORT_NAME, "Edit M/_"); } else { if (tsf & DIAL_FLAGS_VALUEOP) editBC.SetString(DESC_SHORT_NAME, "Edit _/S"); else editBC.SetString(DESC_SHORT_NAME, "Edit _/_"); } } // Dial Slider if (!description->SetParameter(DescLevel(index,DTYPE_REAL,0), sliderBC, descID)) return FALSE; // Edit Button if (!description->SetParameter(DescLevel(index+1,DTYPE_BUTTON,0), editBC, descID)) return FALSE; opBC->SetReal(index, value); } flags |= DESCFLAGS_DESC_LOADED|DESCFLAGS_DESC_RECURSIONLOCK; return SUPER::GetDDescription(node,description,flags); }
Note that a set of tags is being used to set up a set of dynamic sliders and buttons on this plugin object.
Your message would be something like:
// NodeData.Message //*---------------------------------------------------------------------------* Bool IPPBase::Message(GeListNode* node, LONG type, void* data) //*---------------------------------------------------------------------------* { if (!node) return FALSE; switch (type) { // One of the Buttons case MSG_DESCRIPTION_COMMAND: { if (!data) return TRUE; LONG id = ((DescriptionCommand* )data)->id[0].id; switch (id) { // Force update of Attributes Manager descriptions // This will also force a call to GetDDescription() case DIALGROUP_KICK: AutoAlloc<Description> desc; if (desc) node->GetDescription(desc,0); break; ... } break; } } return TRUE; }
If the AutoAlloc<> doesn't work with Description, you'll need to do it this way:
Description* desc = Description::Alloc(); if (desc) { node->GetDescription(desc,0); Description::Free(desc); }
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 02/02/2007 at 14:08, xxxxxxxx wrote:
GetDDescription will be called for every change of the description elements, except button clicks, you have to catch these within Message and change the description's container. Haven't looked through Robert's code but will do so after the weekend and will try to post another example.
cheers,
Matthias -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 06/02/2007 at 00:01, xxxxxxxx wrote:
Thx a lot for this partricularized answer. I will try to solve my problem with this. When i got the solution i will post it here ...