SplineData Callbacks

On 29/07/2013 at 15:55, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   13 
Platform:   Windows  ;   
Language(s) :     C++  ;

---------
Hi,
I'm trying to figure out how use the callbacks in the SDK. And I'm not getting very far.
I'd like to be able to execute the SplineDataCallbackCursorInfo callback to get the cursor's X&Y values when the mouse is inside of my splineGUI.
I'm using the PickSessionData code that Yannick posted as a guide. But I don't even know if the SplineData Callbacks works the same way?

At the top of my tag plugin. Which has a splineGUI in it. This is what I have so far:

#include "c4d.h"  
#include "c4d_symbols.h"  
#include "tsplinetag.h"  
  
// be sure to use a unique ID obtained from www.plugincafe.com  
#define ID_SPLINETAG    1000005  
  
static SplineDataCallbackCursorInfo *splInfo;  
  
Bool AllocSplineInfo()  
{  
  splInfo = gNew SplineDataCallbackCursorInfo;  
  return splInfo!=NULL;  
}    
void FreeSplineInfo()  
{  
  gDelete(splInfo);  
}  
  
void mySplineCallBack(LONG id, const void *d)  
{  
//How do I get the mouse's X & Y values in here?  
}

Then in my Execute method I try to call to mySplineCallBack() like this:

myspline->SetUserCallback(mySplineCallBack, NULL);

I think I'm not even close. Because I get this error when compiling it:
Error : 'SplineData::SetUserCallback' : cannot convert parameter 1 from 'void (__cdecl )(LONG,const void * )' to 'SplineDataCallback'

Has anyone successfully used the splineData callbacks?
I'm not getting very far with it.

-ScottA

On 30/07/2013 at 00:52, xxxxxxxx wrote:

The SplineDataCallback function type returns Bool not void. Also, you do not need to allocated a
SplineDataCallbackCursorInfo object, a pointer will be passed to the SplineDataCallback. It is just like the
Message system of Cinema 4D nodes.

Bool MySplineCallback(LONG type, void* p_data) {
    switch (type) {
        case SPLINE_CALLBACK_CURSORINFO: {
            auto data = (SplineDataCallbackCursorInfo* ) p_data;
            if (!data) return FALSE;
  
            GePrint("Mouse Pos: " + LongToString(data->x) + ", " LongToString(data->y));
            break;
        } 
    }
    return TRUE;
}

I've never used the Spline callbacks myself though and the code is not tested.

On 30/07/2013 at 08:09, xxxxxxxx wrote:

Thanks Nik,

I gave it a shot. But I'm getting a similar error.
Only this time it's this:
Error: cannot convert parameter 1 from 'Bool (__cdecl * )(LONG,void * )' to 'SplineDataCallback'

  
//The CallBack method  
Bool mySplineCallBack(LONG id, void *p_data)  
{  
  switch (id)  
  {  
      case SPLINE_CALLBACK_CURSORINFO:  
          {  
          auto data = (SplineDataCallbackCursorInfo* ) p_data;  
          if (!data) return FALSE;  
  
          GePrint("Mouse Pos: " + LongToString(data->x) + ", " + LongToString(data->y));  
          break;  
         }   
  }  
  return TRUE;  
}  
  
.........  
  
//Calling the callback method  
EXECUTIONRESULT SplineTag::Execute(BaseTag *tag, BaseDocument *doc, BaseObject *op, BaseThread *bt, LONG priority, EXECUTIONFLAGS flags)  
{  
  GeData d;                                                          //Create a variable to hold the data we will get using GetParameter() below  
  if (tag->GetParameter(DescLevel(MY_SPLINE), d, DESCFLAGS_GET_0))   //If the tag with the spline GUI exists  
  {  
      SplineData *myspline = (SplineData* )d.GetCustomDataType(CUSTOMDATATYPE_SPLINE); //Assign a variable to the spline's container so we can access & edit them later on  
      if(myspline)  
       {   
         CustomSplineKnot *knot1 = myspline->GetKnot(0);      //Get the first spline's knot in the spline GUI  
         CustomSplineKnot *knot2 = myspline->GetKnot(1);      //Get the second spline's knot in the spline GUI  
         if (knot2)  
          {  
           Vector knot1pos = knot1->vPos;                     //Get the position of the first spline's knot and assign it to a variable      
           Vector knot2pos = knot2->vPos;                     //Get the position of the second spline's knot and assign it to a variable  
  
           myspline->SetUserCallback(mySplineCallBack, NULL);   
          }  
   }  
    
  return EXECUTIONRESULT_OK;  
}

-ScottA

On 30/07/2013 at 08:27, xxxxxxxx wrote:

is MySplineCallback / mySplineCallback intentional ?

On 30/07/2013 at 08:32, xxxxxxxx wrote:

^LoL. You caught me before I could update my post. You guys are too quick. :joy:
I fixed it. But still I'm having problems getting it to work.

-ScottA

On 30/07/2013 at 08:52, xxxxxxxx wrote:

1. Why do you only test for knot2 but not knot1? It could be NULL too.
2. What are the new problems you are facing?
3. I think you should only call SetUserCallback() once in SplineTag::Init() where you initialize the Spline GUI

Cheers,
-Nik

On 30/07/2013 at 08:59, xxxxxxxx wrote:

My problem is getting the callback code to complie and work.
It doesn't work for me as  a Bool type either.

Error: cannot convert parameter 1 from 'Bool (__cdecl * )(LONG,void * )' to 'SplineDataCallback'

-ScottA

On 30/07/2013 at 09:37, xxxxxxxx wrote:

I overlooked this as well: The docs say that the second argument is const void* not void*.

On 30/07/2013 at 10:00, xxxxxxxx wrote:

Thanks. That fixed it.

It compiles now. However I'm not getting any results from it.
I wonder if we have to use GetUserCallback() in combination with this to get a result?

-ScottA

On 30/07/2013 at 10:52, xxxxxxxx wrote:

Never mind. I've got it working.

Apparently you have to call to your spline callback from within the Init() method.
In my mind that seem rather strange. Because it should make it run only once when the tag is created. Then not run anymore.
That's how using the Init() method usually works.

But in this case. I guess the callback uses the Init() method to start it up.
And then once it's been started, it will keep on running in the background. And feedback the mouse positions.

Thanks a lot for your help Niklas,
-ScottA

On 30/07/2013 at 11:23, xxxxxxxx wrote:

Originally posted by xxxxxxxx

Apparently you have to call to your spline callback from within the Init() method.
In my mind that seem rather strange. Because it should make it run only once when the tag is created. Then not run anymore.
That's how using the Init() method usually works.

By "call to your spline callback from within the Init() method", do you mean the following?

myspline->SetUserCallback(mySplineCallBack, NULL);

You do not call your function here. You only pass it as a parameter and the SplineGUI will call
this method at a later point. Calling your function would look like

SplineDataCallbackDraw data;
// fill the data
mySplineCallBack(SPLINE_CALLBACK_DRAW, &data);

but you should not do this. The SplineGUI is doing this, but doing this yourself makes no sense.

-Nik

On 30/07/2013 at 11:35, xxxxxxxx wrote:

Originally posted by xxxxxxxx

By "call to your spline callback from within the Init() method", do you mean the following?

myspline->SetUserCallback(mySplineCallBack, NULL);

Yes.

The other Callbacks I've used don't work this way.
I have to place them within an Execute, or Message method so that they will continuously update.
But this one acts more a like a windows service. Where once you start it. It will continue to run and update on it's own.

CallBacks in general always trip me up.
I'm not very good with them.

-ScottA