SceneHook... how to?



  • On 08/06/2014 at 17:48, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   14 
    Platform:      Mac OSX  ; 
    Language(s) :     C++  ;

    ---------
    I have a tag that displays stuff on the editor using DrawPoly.
    But I found out that DisplayControl from SceneHook would be perfect for what I need.
    How can I create a modified SceneHook for displaying a single object (the one that has my tag attached).
    In simpler terms... I found this snippet of code:

    Bool LiquidToolData::InitDisplayControl(BaseDocument *doc, BaseContainer &data;, BaseDraw *bd, const AtomArray *active)
    {
        return TRUE;
    }

    void LiquidToolData::FreeDisplayControl()
    {
    }

    Bool LiquidToolData::DisplayControl(BaseDocument *doc, BaseObject *op, BaseObject *chainstart, BaseDraw *bd, BaseDrawHelp *bh, ControlDisplayStruct &cds;)
    {
        if (chainstart && op)    // FIX[46030]
        {
            if (chainstart->IsInstanceOf(Opoint) && op->IsInstanceOf(Opoint) && ToPoint(chainstart)->GetPointCount()==ToPoint(op)->GetPointCount()) op=chainstart;
            else return TRUE;
        }
        if (!op || !op->IsInstanceOf(Opoint)) return TRUE;

    LONG pcnt = ToPoint(op)->GetPointCount();

    cds.vertex_color = GeAllocTypeNC(SVector,pcnt);
        if (!cds.vertex_color) return FALSE;

    Random rnd;
        rnd.Init(45346);

    LONG i;

    for (i=0; i<pcnt; i++)
        {
            cds.vertex_color _= SVector(rnd.Get01(), rnd.Get01(), rnd.Get01());
        }

    return TRUE;
    }

    So, let us say that I want the object that has my tag attached, is displayed with random colored faces, using this code.
    How can I make it work with only the objects that have my tag?



  • On 08/06/2014 at 18:53, xxxxxxxx wrote:

    Ok, here is my code:

    #include "c4d.h"
    #include "c4d_symbols.h"

    #define ID_POLYPAINTEDITOR 1234567

    class polypainteditor : public NodeData
    {
         public:
         
              virtual Bool DisplayControl(BaseDocument* doc, BaseObject* op, BaseObject* chainstart, BaseDraw* bd, BaseDrawHelp* bh, ControlDisplayStruct& cds);
         
              virtual Bool InitDisplayControl(BaseDocument *doc, BaseContainer &data;, BaseDraw *bd, const AtomArray *active);

    virtual void FreeDisplayControl();
         
              static NodeData * Alloc(void) { return gNew polypainteditor; }
    };

    Bool polypainteditor::InitDisplayControl(BaseDocument *doc, BaseContainer &data;, BaseDraw *bd, const AtomArray *active)
    {
        return true;
    }

    void polypainteditor::FreeDisplayControl()
    {
    }

    Bool polypainteditor::DisplayControl(BaseDocument *doc, BaseObject *op, BaseObject *chainstart, BaseDraw *bd, BaseDrawHelp *bh, ControlDisplayStruct &cds;)
    {
         return true;
    }

    // ***************************************************************
    // register the plugin
    // be sure to use a unique ID obtained from www.plugincafe.com

    Bool Registerpolypainteditor(void)
    {     
         return RegisterSceneHookPlugin(ID_POLYPAINTEDITOR, "PolyPaintEditor",PLUGINFLAG_HIDE|PLUGINFLAG_HIDEPLUGINMENU|PLUGINFLAG_SCENEHOOK_NOTDRAGGABLE,polypainteditor::Alloc,EXECUTIONPRIORITY_EXPRESSION,0);
    }

    Even this simple code (that does nothing), crashes my Cinema4D as soon as it finishes loading.
    What could be wrong?



  • On 08/06/2014 at 19:32, xxxxxxxx wrote:

    Now I have this:

    #include "c4d.h"
    #include "c4d_symbols.h"

    #define ID_POLYPAINTEDITOR 1234567

    class polypainteditor : public SceneHookData
    {
         public:
         
              virtual Bool DisplayControl(BaseDocument* doc, BaseObject* op, BaseObject* chainstart, BaseDraw* bd, BaseDrawHelp* bh, ControlDisplayStruct& cds);
         
              virtual Bool InitDisplayControl(BaseDocument *doc, BaseContainer &data;, BaseDraw *bd, const AtomArray *active);

    virtual void FreeDisplayControl();
         
              static NodeData* Alloc(void) { return gNew polypainteditor; }
    };

    Bool polypainteditor::InitDisplayControl(BaseDocument *doc, BaseContainer &data;, BaseDraw *bd, const AtomArray *active)
    {
        return true;
    }

    void polypainteditor::FreeDisplayControl()
    {
    }

    Bool polypainteditor::DisplayControl(BaseDocument *doc, BaseObject *op, BaseObject *chainstart, BaseDraw *bd, BaseDrawHelp *bh, ControlDisplayStruct &cds;)
    {

    if (!op || !op->IsInstanceOf(Opolygon)) return true;

    LONG pcnt = ToPoint(op)->GetPointCount();
         
        cds.vertex_color = GeAllocTypeNC(SVector,pcnt);
        if (!cds.vertex_color) return false;
         
        LONG i;
        Random rnd;
        rnd.Init(45346);
         
        for (i=0; i<pcnt; i++)
        {
    cds.vertex_color _= SVector(rnd.Get01(), rnd.Get01(), rnd.Get01());
        }
         
        return true;
    }

    // ***************************************************************
    // register the plugin
    // be sure to use a unique ID obtained from www.plugincafe.com

    Bool Registerpolypainteditor(void)
    {     
         return RegisterSceneHookPlugin(ID_POLYPAINTEDITOR, "PolyPaintEditor",PLUGINFLAG_SCENEHOOK_NOTDRAGGABLE,polypainteditor::Alloc,EXECUTIONPRIORITY_EXPRESSION,0,NULL);
    }

    It builds fine and loads in Cinema4D (I know it loads... the main.cpp is calling the registration and prints a message if a true value is returned)
    But nothing is happening.
    Shouldn't it paint with random colors all the faces of polygonal objects?



  • On 09/06/2014 at 03:59, xxxxxxxx wrote:

    I placed some drawing code in the Draw method of the ScenHook to test if it was working. And it is.
    But I wanted to make it work like, for example, when we select a Vertex Map tag or a HyperNURBS Weight tool, changing the whole colors of how faces are drawn.
    That is made with DisplayControl, right?
    Can anyone tell me how? How do these two tags change the way faces are displayed?



  • On 09/06/2014 at 06:10, xxxxxxxx wrote:

    Howdy,

    It looks like none of the display control functions are being called.

    I added GePrint() functions to each of your scene hook's functions like this:

    Bool polypainteditor::InitDisplayControl(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, const AtomArray *active) 
    { 
    	GePrint("polypainteditor::InitDisplayControl()");
    	
    	return true; 
    } 
    

    ... and nothing was ever printed to the console. 

    Adios,
    Cactus Dan



  • On 09/06/2014 at 06:17, xxxxxxxx wrote:

    Exactly. I also did that and nothing is happening.
    Could it be broken? Or maybe, more probable, I'm missing something.
    Anyone from Maxon could explain how to do this?



  • On 09/06/2014 at 09:12, xxxxxxxx wrote:

    It all works fine, but no faces are colored with random colors.
    I mean, the triangles do appear but the object is still displayed the same.
    The DisplayControl method is simple ignored.



  • On 09/06/2014 at 09:37, xxxxxxxx wrote:

    Yeah. I realized that right after I posted it. That's why I deleted my reply Rui.
    But I still don't know why you're doing it that way?

    All of the drawing of lines, objects, polygons can be done in the Draw() method of your Tag plugin.
    Using a SceenHook for this seems like an unnecessary extra plugin that you don't really need.
    But even if for some reason you just wanted to use a SH. The object can be drawn using the Draw() method in there too.

    However...That being said.
    I would also like to know how to use the DisplayControl() method. Because the SDK does not explain properly how to use it.
    That's a documentation problem that needs to be addressed and clarified much better.
    Perhaps the InitDisplayControl() method needs to also be used in combo with it?

    -ScottA



  • On 09/06/2014 at 09:45, xxxxxxxx wrote:

    I already have it working inside the Draw method of the tag itself.
    But the problem is that I want the faces to be drawn in some specific colors, just like how it happens when one selects the Vertex Map tag. When we select a Vertex Map tag, the faces of the polygonal object show up in the red/yellow mapping of the weights.
    The way I have it now, it draws faces that are coplanar with the faces. Besides being slower, since I have to draw the polygons, the result is far from what I intend because I see the original faces and a bit of my drawn polygons, flickering a lot as I move the camera in the editor.
    Since I already have a list of RGB values that correspond to each point of the polygonal object, being able to provide that list to be used for display would be exactly what I want.
    And it seems to be exactly what the ControlDisplayStruct &cds; is meant for.
    If it worked, I would just need to fill the cds.vertex_color list with my list and Cinema4D would simply display the object like I wanted, without me having to manually draw all the faces.
    So, I really need to know how this works.
    The documentation is really not helping :-(



  • On 09/06/2014 at 11:01, xxxxxxxx wrote:

    I've sort of got it working...But I can't control it yet.
    The way I'm guessing it works is that the InitDisplayControl() method's TRUE/FALSE return value controls whether or not to use the DisplayControl() method.
    The active scene objects are stored in an Atom array called "active".

    But I can't seem to figure out how to shut it off when the objects are not selected or if they are not polygon type objects.
    Right now. All the objects get their vertices colored with random colors. And I can't seem to control it yet.

    Bool MySceneHook::InitDisplayControl(BaseSceneHook *node, BaseDocument *doc, BaseDraw *bd, const AtomArray *active)  
    {  
      for(LONG i=0; i != active->GetCount(); i++)  
      {  
          String name = static_cast<BaseObject*>(active->GetIndex(i))->GetName();  
          GePrint(name);  
      }  
      
      return TRUE;  
    }
    

    -ScottA



  • On 09/06/2014 at 11:27, xxxxxxxx wrote:

    I tried to include your code in my InitDisplayControl method and I don't even get anything printed in the Console :-(



  • On 09/06/2014 at 11:33, xxxxxxxx wrote:

    Even something as simple as:

    Bool polypainteditor::InitDisplayControl(BaseDocument *doc, BaseContainer &data;, BaseDraw *bd, const AtomArray *active)
    {
         GePrint("Inside InitDisplayControl");
         return TRUE;
    }

    Prints nothing!! :-(



  • On 09/06/2014 at 11:33, xxxxxxxx wrote:

    Howdy,

    At this point, we may need Maxon to supply an example. 

    Adios,
    Cactus Dan



  • On 09/06/2014 at 11:34, xxxxxxxx wrote:

    Maxon!!! Hey, MAXON!!! Are you there?!?
    Please, come helps us figure this out.



  • On 09/06/2014 at 11:54, xxxxxxxx wrote:

    But, are your polygonal objects displayed with random colors, Scott?
    If they are, can you show us all your code?



  • On 09/06/2014 at 12:01, xxxxxxxx wrote:

    Yes. They are random colors. But I can't control the stupid thing.
    When I select a polygon type object, all of the other objects in the scene(even primitives) have their vertices set to random colors too!
    It's really bizarre. Wacko

    Here's my entire code:

    #include "c4d.h"  
    #include "c4d_symbols.h"  
      
    #define PLUGIN_ID  1000009  
      
    class MySceneHook : public SceneHookData  
    {  
      public:  
          virtual    Bool Init(GeListNode *node);  
          virtual    Bool DisplayControl(BaseDocument* doc, BaseObject* op, BaseObject* chainstart, BaseDraw* bd, BaseDrawHelp* bh, ControlDisplayStruct& cds);  
          virtual    Bool InitDisplayControl(BaseSceneHook* node, BaseDocument* doc, BaseDraw* bd, const AtomArray* active);  
          virtual    Bool Draw(BaseSceneHook *node, BaseDocument *doc, BaseDraw *bd, BaseDrawHelp *bh, BaseThread *bt, SCENEHOOKDRAW flags);  
          virtual    Bool Message(GeListNode *node, LONG type, void *data);  
          virtual    EXECUTIONRESULT Execute(BaseSceneHook* node, BaseDocument* doc, BaseThread* bt, LONG priority, EXECUTIONFLAGS flags);  
          virtual    void FreeDisplayControl(void);  
          static     NodeData *Alloc(void) { return gNew MySceneHook; }   
    };  
      
      
    Bool MySceneHook::Init(GeListNode *node)  
    {  
      return TRUE;  
    }  
      
    Bool MySceneHook::InitDisplayControl(BaseSceneHook *node, BaseDocument *doc, BaseDraw *bd, const AtomArray *active)  
    {  
      
      for(LONG i=0; i != active->GetCount(); i++)  
      {  
          String name = static_cast<BaseObject*>(active->GetIndex(i))->GetName();  
          GePrint(name);  
          if(active->GetIndex(i)->IsInstanceOf(Opolygon))  
          {  
              GePrint("poly object");  
              return TRUE;    //Use the DisplayControl() method      
          }  
      
          else return FALSE;  //Don't use the DisplayControl() method  
      }  
    }  
      
    Bool MySceneHook::DisplayControl(BaseDocument *doc, BaseObject *op, BaseObject *chainstart, BaseDraw *bd, BaseDrawHelp *bh, ControlDisplayStruct &cds)  
    {  
    //What should happen here is that if a polygon type object is selected. The vertices get a random color applied to them  
    //And any non-polygon type objects in the scene should not get changed....But they do!!?  
    //Why are all of the non polygon objects in the scene getting their vector colors replaced too?  
      
      //Only run this code if the selected object is a polygon type object  
      if(op->IsInstanceOf(Opolygon))  
      {  
          PolygonObject *pobj = ToPoly(op);  
          LONG pcnt = pobj->GetPointCount();       
          cds.vertex_color = GeAllocTypeNC(SVector, pcnt);  
          if(!cds.vertex_color) return FALSE;  
         
          LONG i;  
          Random rnd;  
          rnd.Init(45346);  
      
          for(i=0; i<pcnt; i++)  
          {  
              cds.vertex_color[i] = SVector(rnd.Get01(), rnd.Get01(), rnd.Get01());  
          }  
          return TRUE;  
      }  
      
      else return FALSE;  
    }  
      
      
      
    Bool MySceneHook::Draw(BaseSceneHook *node, BaseDocument *doc, BaseDraw *bd, BaseDrawHelp *bh, BaseThread *bt, SCENEHOOKDRAW flags)  
    {   
      return TOOLDRAW_HANDLES|TOOLDRAW_AXIS;  
    }  
      
    Bool MySceneHook::Message(GeListNode *node, LONG type, void *data)  
    {  
      return TRUE;  
    }  
      
    EXECUTIONRESULT MySceneHook::Execute(BaseSceneHook* node, BaseDocument* doc, BaseThread* bt, LONG priority, EXECUTIONFLAGS flags)  
    {  
       return EXECUTIONRESULT_OK;  
    }  
      
    void MySceneHook::FreeDisplayControl(void)  
    {  
      //..Not sure what to do here...If anything????  
    }  
      
    Bool RegisterMySceneHook(void)  
    {      
      return RegisterSceneHookPlugin(PLUGIN_ID, "My SceneHook", 0, MySceneHook::Alloc, EXECUTIONPRIORITY_GENERATOR, 0, NULL);      
    }
    

    -ScottA



  • On 09/06/2014 at 12:02, xxxxxxxx wrote:

    Howdy,

    Hmmmmm, "polypainteditor"? Is this an editor tool, that could possibly be better off being a ToolData plugin?

    Adios,
    Cactus Dan



  • On 09/06/2014 at 12:06, xxxxxxxx wrote:

    Not, it is not a tool. I called editor because it is supposed to show the "shading" in the editor :-)
    I already have a shader that works just fine. But I would like it to show in the editor also.



  • On 09/06/2014 at 12:53, xxxxxxxx wrote:

    I made it work!!! :-)
    But in my case it is simpler to check what object needs to be painted because only objects with my specific tag need to be painted.
    However, this only works when the object is selected.
    I guess it is a limitation, right?
    Or is it possible to make it paint in the editor with the set of colors I define, even when the object is not selected?



  • On 09/06/2014 at 13:13, xxxxxxxx wrote:

    Howdy,

    OK, I see what's wrong with the code you posted.

    You have this function:

    virtual Bool InitDisplayControl(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, const AtomArray *active);
    

    ... when it should be this:

    virtual Bool InitDisplayControl(BaseSceneHook* node, BaseDocument* doc, BaseDraw* bd, const AtomArray* active);
    

    That's why your InitDisplayControl() function wasn't being called. The parameters were not correct, so in essence you were defining your own new virtual function that was never called. 😵

    Adios,
    Cactus Dan


Log in to reply