Plugin Cafe Homepage
Forum Home Forum Home > Plugin Cafe > SDK Help
  New Posts New Posts
  FAQ FAQ  Forum Search   Register Register  Login Login

Update Attribute Manager after SetParameter

 Post Reply Post Reply
Author
Message
ripclaw View Drop Down
Member
Member
Avatar

Joined: 2010 Aug 05
Location: Berlin
Online Status: Offline
Posts: 73
Post Options Post Options   Quote ripclaw Quote  Post ReplyReply Direct Link To This Post Topic: Update Attribute Manager after SetParameter
    Posted: 2018 Jun 13 at 10:00am

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.


Back to Top
ripclaw View Drop Down
Member
Member
Avatar

Joined: 2010 Aug 05
Location: Berlin
Online Status: Offline
Posts: 73
Post Options Post Options   Quote ripclaw Quote  Post ReplyReply Direct Link To This Post Posted: 2018 Jun 14 at 3:58am
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!
Back to Top
Andreas Block View Drop Down
Forum Moderator
Forum Moderator
Avatar

Joined: 2014 Oct 01
Location: Hannover
Online Status: Offline
Posts: 1805
Post Options Post Options   Quote Andreas Block Quote  Post ReplyReply Direct Link To This Post Posted: 2018 Jun 14 at 9:50am
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.

Cheers,
Andreas
SDK Support Engineer
Back to Top
ripclaw View Drop Down
Member
Member
Avatar

Joined: 2010 Aug 05
Location: Berlin
Online Status: Offline
Posts: 73
Post Options Post Options   Quote ripclaw Quote  Post ReplyReply Direct Link To This Post Posted: 2018 Jun 15 at 2:32am
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;
}
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down

Bulletin Board Software by Web Wiz Forums® version 9.61 [Free Express Edition]
Copyright ©2001-2009 Web Wiz

This page was generated in 0.125 seconds.