Update Attribute Manager after SetParameter
-
On 13/06/2018 at 10:00, xxxxxxxx wrote:
User Information:
Cinema 4D Version: 19
Platform: Windows ;
Language(s) : C++ ;---------
I'm sure I'm missing something obvious, but having not used the C++ SDK for quite a while...I'm updating a few parameters from a custom function. This is an ObjectData plugin with a few string and long fields. NR_FRAMEINDEX in this case is LONG.
// a static callback function void(__stdcall NeuronReader::BVHFrameDataReceived)(void* customObj, SOCKET_REF sender, BvhDataHeader* header, float* data) { NeuronReader* pthis = (NeuronReader* )customObj; BaseObject *op = (BaseObject* )(pthis->Get()); pthis->ReadNeuronBvhData(sender, header, data, op); } // this should update the parameters void NeuronReader::ReadNeuronBvhData(SOCKET_REF sender, BvhDataHeader* header, float* data, BaseObject* op) { if (sender) { Int32 frameIndex = (Int32)(header->FrameIndex); op->SetParameter(DescID(NR_FRAMEINDEX), GeData(frameIndex), DESCFLAGS_SET_0); //op->SetDirty(DIRTYFLAGS_DATA); //op->Message(MSG_CHANGE); //EventAdd(EVENT_ANIMATE); } }
This feels straightforward enough. Checking the NR_FRAMEINDEX parameter via GeConsoleOut shows me that it writes the correct values. However, the Attribute Manager attribute never gets updates.
Do I need to go through some SetDParameter magic or something? The various EventAdds and MSG_Change etc don't seem to do anything here.
-
On 14/06/2018 at 03:58, xxxxxxxx wrote:
I don't get it. I have now gone and implemented a (feeling somewhat convoluted) way to make sure that the SetParameter happens in the MainThread (by creating a MessageData plugin, sending a SpecialEventAdd() there containing a pointer to my object, sending a GePluginMessage() back (again containing the pointer) and then calling a function to apply the parameter.
I'm checking with GeIsMainThread() all along the way. Yet the UI will not update. Argh! -
On 14/06/2018 at 09:50, xxxxxxxx wrote:
Hi,
to be honest I don't immediately see the issue, either.
Normally a EventAdd() (and also your EventAdd(EVENT_ANIMATE)) should do the trick.
You seem to have had the same sus**cion as I had in your second post. Nevertheless I'd like to ask in which context the functions you posted are called/used? Maybe a rough description of the structure of your ObjectData could help as well.
In any case I will discuss this tomorrow with the team. -
On 15/06/2018 at 02:32, xxxxxxxx wrote:
This should be all the relevant code...
This is the output I get:
Registered the NeuronReader plugin Connected to Neuron server at 127.0.0.1:7001 Demo message IS MainThread ApplyNeuronData running in MainThread // Modifying:1004 Before: 0 MSG_DESCRIPTION_POSTSETPARAMETER: 1004 POSTSETPARAMETER_VALUE:40 After: 40
So the parameter is set correctly internally, but somehow it does not get reflected in the UI at all.
// This is a callback function, being called from a threaded context void(__stdcall ONeuronReader::BVHFrameDataReceived)(void* customObj, SOCKET_REF sender, BvhDataHeader* header, float* data) { ONeuronReader* pthis = (ONeuronReader* )customObj; BaseObject *op = (BaseObject* )(pthis->Get()); pthis->ReadNeuronBvhData(sender, header, data, op); } // This does nothing other than send a MessageData, which in turn sends a GePluginMessage() to this plugin void ONeuronReader::ReadNeuronBvhData(SOCKET_REF sender, BvhDataHeader* header, float* data, BaseObject* op) { if (sender) { SpecialEventAdd(MSG_NEURONMESSAGE, 0, (UInt)op); } } // Thanks to being called from PluginMessage, this is running in the MainThread (does it even have to?) // Attempting to set the LONG parameter to a test value of "40" // Value appears to be set correctly, however UI does not change void ONeuronReader::ApplyNeuronData(BaseObject *op) { if (GeIsMainThread()) { GeConsoleOut("ApplyNeuronData running in MainThread // Modifying:" \+ String::IntToString(NR_FRAMEINDEX)); GeData frameIndex; op->GetParameter(NR_FRAMEINDEX, frameIndex, DESCFLAGS_GET_0); GeConsoleOut("Before: " \+ String::IntToString(frameIndex.GetInt32())); op->SetParameter(DescID(NR_FRAMEINDEX), GeData(40), DESCFLAGS_SET_0); op->Message(MSG_CHANGE); EventAdd(); op->GetParameter(NR_FRAMEINDEX, frameIndex, DESCFLAGS_GET_0); GeConsoleOut("After: " \+ String::IntToString(frameIndex.GetInt32())); } else { GeConsoleOut("ApplyNeuronData NOT running in MainThread"); } } BaseObject* ONeuronReader::GetVirtualObjects(BaseObject* op, HierarchyHelp* hh) { return BaseObject::Alloc(Onull); } Bool ONeuronReader::Message(GeListNode* node, Int32 type, void* data) { BaseContainer* bc; ... else if (type == MSG_DESCRIPTION_POSTSETPARAMETER) { // Get message data DescriptionPostSetValue* dparm = (DescriptionPostSetValue* )data; Int32 parameterId = (*(dparm->descid))[0].id; bc = static_cast<BaseObject*>(node)->GetDataInstance(); GeConsoleOut("MSG_DESCRIPTION_POSTSETPARAMETER: " \+ String::IntToString(parameterId)); bc->SetInt32(NR_FRAMEINDEX, bc->GetInt32(NR_FRAMEINDEX)); switch (parameterId) { case NR_FRAMEINDEX: GeConsoleOut("POSTSETPARAMETER_VALUE:" \+ String::IntToString(bc->GetInt32(NR_FRAMEINDEX))); break; } } ... return SUPER::Message(node, type, data); } Bool NeuronMessage::CoreMessage(Int32 id, const BaseContainer& bc) { switch (id) { case MSG_NEURONMESSAGE: GeConsoleOut("Demo message"); BaseObject* pointer_op = (BaseObject* )bc.GetVoid(BFM_CORE_PAR2); //GeConsoleOut(pointer_op->GetName()); // Just checking... GePluginMessage(MSG_NEURONMESSAGE, (void * )pointer_op); } return true; } Bool RegisterNeuronReaderObject() { return RegisterObjectPlugin(ID_NEURONREADER, GeLoadString(IDS_NEURONREADER), OBJECT_GENERATOR, ONeuronReader::Alloc, "Oneuronreader", AutoBitmap("atom.tif"), 0); } Bool PluginMessage(Int32 id, void *data) { switch (id) { case C4DPL_INIT_SYS: if (!resource.Init()) return false; // don't start plugin without resource return true; case MSG_NEURONMESSAGE: if (GeIsMainThread()) { GeConsoleOut("IS MainThread"); ONeuronReader* op = (ONeuronReader* )data; //GeConsoleOut(op->GetName()); // just to confirm it is the correct pointer op->ApplyNeuronData((BaseObject* )op); } else { GeConsoleOut("NotMainThread"); } } return false; }
-