Tool Plugins: Selecting Polygons?



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 13/06/2012 at 10:28, xxxxxxxx wrote:

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

    ---------
    Hi,
    I've managed to create a tool plugin that highlights the polygons when the mouse is hovering over them. But I don't know how to actually select the polygon when the mouse is clicked on it.

    I'm using the LiquidTool as the base for the plugin.
    Here's the code:

    #include "c4d.h"  
    #include "c4d_symbols.h"  
      
    #define ID_LIQUIDTOOL 1000973  
      
    class LiquidToolData : public ToolData  
    {  
      public:  
          virtual Bool        MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg);  
          virtual Bool        KeyboardInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg);  
          virtual LONG        GetState(BaseDocument *doc);  
          virtual Bool            GetCursorInfo(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, Real x, Real y, BaseContainer &bc);  
          virtual TOOLDRAW        Draw(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, BaseDrawHelp *bh, BaseThread *bt,TOOLDRAWFLAGS flags);  
      
          virtual SubDialog*    AllocSubDialog(BaseContainer* bc);  
      
      private:  
          LONG polygonid;  
          Bool highlight;  
      
    };  
      
    TOOLDRAW LiquidToolData::Draw(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, BaseDrawHelp *bh, BaseThread *bt,TOOLDRAWFLAGS flags)  
    {  
      if (!(flags & TOOLDRAWFLAGS_HIGHLIGHT))  
          return TOOLDRAW_0;  
      
      if (doc->GetMode() != Mpolygons)  
          return TOOLDRAW_0;  
      
      if (!highlight)  
          return TOOLDRAW_0;  
      
      BaseObject *op = doc->GetActiveObject();  
      if (op && op->GetType() == Opolygon)  
      {  
          const CPolygon *polys = ToPoly(op)->GetPolygonW();  
          const Vector *points = ToPoly(op)->GetPointW();  
          Vector *p = bNew Vector[4];  
          p[0] = points[polys[polygonid].a];  
          p[1] = points[polys[polygonid].b];  
          p[2] = points[polys[polygonid].c];  
          p[3] = points[polys[polygonid].d];  
      
          Vector *f = bNew Vector[4];  
          f[0] = 1.0;  
          f[1] = 1.0;       //The color of the selected polygon?  
          f[2] = 1.0;  
          f[3] = 1.0;  
      
          bd->SetMatrix_Matrix(NULL, op->GetMg(), 3);  
          bd->DrawPolygon(p,f,TRUE);  
      
          bd->LineZOffset(0);  
      
          bDelete(p);  
          bDelete(f);  
      }  
      
      highlight = FALSE;  
      
      return TOOLDRAW_0;  
    }  
      
      
    LONG LiquidToolData::GetState(BaseDocument *doc)  
    {  
      if (doc->GetMode()==Mpaint) return 0;  
      return CMD_ENABLED;  
    }  
      
    Bool LiquidToolData::KeyboardInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg)  
    {  
      LONG key = msg.GetData(BFM_INPUT_CHANNEL).GetLong();  
      String str = msg.GetData(BFM_INPUT_ASC).GetString();  
      if (key == KEY_ESC)  
      {  
          // do what you want  
      
          // return TRUE to signal that the key is processed!  
          return TRUE;  
      }  
      return FALSE;  
    }  
      
    Bool LiquidToolData::MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd,EditorWindow *win, const BaseContainer &msg)  
    {    
      Real mx = msg.GetReal(BFM_INPUT_X);  
      Real my = msg.GetReal(BFM_INPUT_Y);  
      LONG button;  
        
      switch (msg.GetLong(BFM_INPUT_CHANNEL))  
      {  
          case BFM_INPUT_MOUSELEFT : button=KEY_MLEFT; break;  
          case BFM_INPUT_MOUSERIGHT: button=KEY_MRIGHT; break;  
          default: return TRUE;  
      }  
        
      
      DrawViews(DRAWFLAGS_ONLY_ACTIVE_VIEW|DRAWFLAGS_NO_THREAD|DRAWFLAGS_NO_ANIMATION);  
      
      if (win->MouseDragEnd()==MOUSEDRAGRESULT_ESCAPE)  
      {  
          doc->DoUndo(TRUE);  
      }  
      
      
      EventAdd();  
      return TRUE;  
    }  
      
    Bool LiquidToolData::GetCursorInfo(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, Real x, Real y, BaseContainer &bc)  
    {  
      LONG left, top, right, bottom, width, height;  
      bd->GetFrame(&left,  &top, &right, &bottom);  
      width = right - left + 1;  
      height = bottom - top + 1;  
      
      LONG mode = doc->GetMode();  
      
      BaseObject *op = doc->GetActiveObject();  
      if (!op || op->GetType() != Opolygon) return TRUE;  
        
      AutoAlloc<ViewportSelect> vs;  
      if (!vs || !vs->Init(width,height,bd,op,mode,TRUE,VIEWPORTSELECTFLAGS_0)) return FALSE;  
      
      if (mode == Mpolygons)  
      {  
          highlight = TRUE;  
      
          ViewportPixel *vpp = NULL;  
      
          LONG mx = x;  
          LONG my = y;  
      
          vpp = vs->GetNearestPolygon(op, mx, my, MAXLONGl, FALSE, NULL, 0);  
      
          if (vpp)  
          {  
              polygonid = vpp->i;  
      
              DrawViews(DRAWFLAGS_ONLY_ACTIVE_VIEW|DRAWFLAGS_NO_THREAD|DRAWFLAGS_NO_ANIMATION, bd);  
          }  
      }  
      
      return TRUE;  
    }  
      
    class LiquidToolDialog: public SubDialog  
    {  
      public:  
          virtual Bool CreateLayout(void);  
          virtual Bool InitValues(void);  
      
          virtual Bool InitDialog(void);  
          virtual Bool Command(LONG id,const BaseContainer &msg);  
    };  
      
    Bool LiquidToolDialog::CreateLayout(void)  
    {  
      return TRUE;  
    }  
      
    Bool LiquidToolDialog::InitValues(void)  
    {  
      return InitDialog();  
    }  
      
    Bool LiquidToolDialog::InitDialog(void)  
    {  
      BaseContainer *bc=GetToolData(GetActiveDocument(),ID_LIQUIDTOOL);  
      if (!bc) return FALSE;  
      
      return TRUE;  
    }  
      
    Bool LiquidToolDialog::Command(LONG id,const BaseContainer &msg)  
    {  
      return TRUE;  
    }  
      
    SubDialog* LiquidToolData::AllocSubDialog(BaseContainer* bc)  
    {  
      return gNew LiquidToolDialog;   
    }  
      
    Bool RegisterPrimitiveTool(void)  
    {  
      return RegisterToolPlugin(ID_LIQUIDTOOL,GeLoadString(IDS_PRIMITIVETOOL),0,AutoBitmap("liquid.tif"),"C++ SDK Liquid Painting Tool",gNew LiquidToolData);  
    }
    

    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 14/06/2012 at 00:57, xxxxxxxx wrote:

    GetPolygonS() is what you are looking for..



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 14/06/2012 at 07:54, xxxxxxxx wrote:

    I'm afraid I don't understand.
    Currently the way the plugin works is if I hover the mouse over a polygon. That polygon will highlight. But if I LMB on it. That polygon does not become selected(turn red).

    GetPolygonS() returns the selected polygons. But I don't have any selected polygons yet.
    That's where I'm having trouble.

    Is it possible that in a tool plugin. When a polygon is highlighted like I'm doing it. It's also selected?
    If so. Then do I need to use GetPolygonS() and a loop using IsSelected() to test to see which polygon is selected?
    Where would I do this polygon searching? The MouseInput() method?

    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 14/06/2012 at 08:09, xxxxxxxx wrote:

    Yes, in MouseInput once the user clicks (LMB) you change the BaseSelect that you get with GetPolygonS() to select/deselect polygons the user is hovering over. Don't forget to update the object with the according message. You don't need to check if it is selected, you can use BaseSelect::Toggle() to deselect selected polygons and vice-versa.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 14/06/2012 at 12:01, xxxxxxxx wrote:

    Thanks Katachi,
    I've managed to get it working with your help.

    But there's one last thing that is bothering me that I would really like to change.
    I would like to be able to click anywhere in the scene to de-select any selected polygons.
    Right now whenever the mouse enters the editor window. It will select a polygon. Which is annoying.
    I need to somehow get better control of the highlighting so it doesn't execute as soon as it hits the edge of editor window(if that's possible) like that. So that I can click in the scene with no polygons highlighted. And be able to de-select any selected polygons.
    In other words...Like C4D normally works when not in a tool plugin.

    Any idea how I could do that?
    Here's the current version of the plugin that lets me select the highlighted polygon

    #include "c4d.h"  
    #include "c4d_symbols.h"  
      
    #define ID_LIQUIDTOOL 1000973  
      
    class LiquidToolData : public ToolData  
    {  
     public:  
         virtual Bool        MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg);  
         virtual Bool        KeyboardInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg);  
         virtual LONG        GetState(BaseDocument *doc);  
         virtual Bool            GetCursorInfo(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, Real x, Real y, BaseContainer &bc);  
         virtual TOOLDRAW        Draw(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, BaseDrawHelp *bh, BaseThread *bt,TOOLDRAWFLAGS flags);  
      
         virtual SubDialog*    AllocSubDialog(BaseContainer* bc);  
      
      private:  
          LONG polygonid;  //This will come in handy when we need to select the polygon that's being highlighted   
          Bool highlight;  
      
    };  
      
    TOOLDRAW LiquidToolData::Draw(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, BaseDrawHelp *bh, BaseThread *bt,TOOLDRAWFLAGS flags)  
    {  
      if (!(flags & TOOLDRAWFLAGS_HIGHLIGHT))  
          return TOOLDRAW_0;  
      
      if (doc->GetMode() != Mpolygons)  
          return TOOLDRAW_0;  
      
      if (!highlight)  
          return TOOLDRAW_0;  
      
      BaseObject *op = doc->GetActiveObject();  
      if (op && op->GetType() == Opolygon)  
      {  
          const CPolygon *polys = ToPoly(op)->GetPolygonW();  
          const Vector *points = ToPoly(op)->GetPointW();  
          Vector *p = bNew Vector[4];  
          p[0] = points[polys[polygonid].a];  
          p[1] = points[polys[polygonid].b];  
          p[2] = points[polys[polygonid].c];  
          p[3] = points[polys[polygonid].d];  
      
          Vector *f = bNew Vector[4];  
          f[0] = 1.0;  
          f[1] = 1.0;       //The color of the four corners of the selected polygon  
          f[2] = 1.0;  
          f[3] = 1.0;  
      
          bd->SetMatrix_Matrix(NULL, op->GetMg(), 3);  
         bd->DrawPolygon(p,f,TRUE);  
      
          bd->LineZOffset(0);  
      
          bDelete(p);  
          bDelete(f);  
      }  
      
      highlight = FALSE;  
      
      return TOOLDRAW_0;  
    }  
      
      
    LONG LiquidToolData::GetState(BaseDocument *doc)  
    {  
     if (doc->GetMode()==Mpaint) return 0;  
     return CMD_ENABLED;  
    }  
      
    Bool LiquidToolData::KeyboardInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg)  
    {  
     LONG key = msg.GetData(BFM_INPUT_CHANNEL).GetLong();  
     String str = msg.GetData(BFM_INPUT_ASC).GetString();  
     if (key == KEY_ESC)  
     {  
         // do what you want  
         // return TRUE to signal that the key is processed!  
         return TRUE;  
     }  
     return FALSE;  
    }  
      
    Bool LiquidToolData::MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd,EditorWindow *win, const BaseContainer &msg)  
    {    
      Real mx = msg.GetReal(BFM_INPUT_X);  
      Real my = msg.GetReal(BFM_INPUT_Y);  
      LONG button;  
       
      switch (msg.GetLong(BFM_INPUT_CHANNEL))  
      {  
          case BFM_INPUT_MOUSELEFT : button=KEY_MLEFT; break;  
          case BFM_INPUT_MOUSERIGHT: button=KEY_MRIGHT; break;  
          default: return TRUE;  
      }  
        
      
      BaseObject *obj = doc->GetActiveObject();  
      if (!obj) return FALSE;  
      
      PolygonObject *pobj = ToPoly(obj);        //Cast the active object to a polygon type   
      BaseSelect *bs = pobj->GetPolygonS();    //Create a new BaseSelect filled with the currently selected polygons(if any)  
      
      
      BaseContainer state;  
      while (GetInputState(BFM_INPUT_MOUSE, BFM_INPUT_MOUSELEFT, state)) //While the LMB is down   
      {  
        if (state.GetLong(BFM_INPUT_VALUE) == 0) break; //If the state value is 0. The LMB is no longer down..so don't enter the loop   
        
        LONG x = state.GetLong(BFM_INPUT_X); //Get the cursor's X screen coordinates  
        LONG y = state.GetLong(BFM_INPUT_Y); //Get the cursor's Y screen coordinates  
      
        GeShowMouse(MOUSE_POINT_HAND);       //Change the cursor's apperance when the mouse button is down  
        
        bs->Select(polygonid);               //Select the polygon that's currently highlighted  
      }  
      
      EventAdd();  
      return TRUE;  
    }  
      
    Bool LiquidToolData::GetCursorInfo(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, Real x, Real y, BaseContainer &bc)  
    {  
      LONG left, top, right, bottom, width, height;  
      bd->GetFrame(&left,  &top, &right, &bottom);  
      width = right - left + 1;  
      height = bottom - top + 1;  
      
      LONG mode = doc->GetMode();  
      
      BaseObject *op = doc->GetActiveObject();  
      if (!op || op->GetType() != Opolygon) return TRUE;  
        
      AutoAlloc<ViewportSelect> vs;  
      if (!vs || !vs->Init(width,height,bd,op,mode,TRUE,VIEWPORTSELECTFLAGS_0)) return FALSE;  
      
      if (mode == Mpolygons)  
      {  
          highlight = TRUE;  
      
          ViewportPixel *vpp = NULL;  
      
          LONG mx = x;  
          LONG my = y;  
      
          vpp = vs->GetNearestPolygon(op, mx, my, MAXLONGl, FALSE, NULL, 0);  
      
          if (vpp)  
          {  
              polygonid = vpp->i;  
              DrawViews(DRAWFLAGS_ONLY_ACTIVE_VIEW|DRAWFLAGS_NO_THREAD|DRAWFLAGS_NO_ANIMATION, bd);  
          }  
      }  
      
      return TRUE;  
    }  
      
    class LiquidToolDialog: public SubDialog  
    {  
      public:  
          virtual Bool CreateLayout(void);  
          virtual Bool InitValues(void);  
      
          virtual Bool InitDialog(void);  
          virtual Bool Command(LONG id,const BaseContainer &msg);  
    };  
      
    Bool LiquidToolDialog::CreateLayout(void)  
    {  
      return TRUE;  
    }  
      
    Bool LiquidToolDialog::InitValues(void)  
    {  
      return InitDialog();  
    }  
      
    Bool LiquidToolDialog::InitDialog(void)  
    {  
      BaseContainer *bc=GetToolData(GetActiveDocument(),ID_LIQUIDTOOL);  
      if (!bc) return FALSE;  
      
      return TRUE;  
    }  
      
    Bool LiquidToolDialog::Command(LONG id,const BaseContainer &msg)  
    {  
      return TRUE;  
    }  
      
    SubDialog* LiquidToolData::AllocSubDialog(BaseContainer* bc)  
    {  
      return gNew LiquidToolDialog;   
    }  
      
    Bool RegisterPrimitiveTool(void)  
    {  
      return RegisterToolPlugin(ID_LIQUIDTOOL,GeLoadString(IDS_PRIMITIVETOOL),0,AutoBitmap("liquid.tif"),"C++ SDK Liquid Painting Tool",gNew LiquidToolData);  
    }
    

    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 15/06/2012 at 01:04, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    I would like to be able to click anywhere in the scene to de-select any selected polygons.

    GetPolygonS()->DeselectAll();

    Right now whenever the mouse enters the editor window. It will select a polygon. Which is annoying.

    Hmm, I cannot see why this happens in your code. I don't see any selection action there, only when the LMB is clicked. So either you don't show the whole code or I don't understand what you mean.

    I need to somehow get better control of the highlighting so it doesn't execute as soon as it hits the edge of editor window(if that's possible) like that.

    Maybe in the above you mean highlight not select? There is a 'maxradius' option when you use "GetNearestPolygon" of the ViewportSelect call. You have set it to MAXLONGl. So it finds any polygon that is in the editor view. If you don't want that, change this to a more appropriate pixel value. I assume 2-4 would be enough and get rid of your issue. For example:

      
      
        
        
        vpp = vs->GetNearestPolygon(op, mx, my, 2, FALSE, NULL, 0);
    

    Make sure you reset your polygonid if the mouse is then not near a poly, so something like:

      
    if (vpp)  
        
        
                {  
                  polygonid = vpp->i;  
                  DrawViews(DRAWFLAGS_ONLY_ACTIVE_VIEW|DRAWFLAGS_NO_THREAD|DRAWFLAGS_NO_ANIMATION, bd);  
              }  
        else  
               polygonid = -1;  
        
    

    So that I can click in the scene with no polygons highlighted. And be able to de-select any selected polygons. In other words...Like C4D normally works when not in a tool plugin.

    With the above changes you would do in MouseInput sth like:

      
        
        
        if(polygonid > -1) bs->Select(polygonid);               //Select the polygon that's currently highlighted  
        else bs->DeselectAll(); //No polygon in the vicinity, so deselect all  
        
    

    Any idea how I could do that?

    yes... ;)



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 15/06/2012 at 08:10, xxxxxxxx wrote:

    Unfortunately the things you've suggested are crashing C4D.
    My plugin uses GetFrame(). So what's happening is that once the mouse pointer enters the scene view. It activates. And starts highlighting polygons.
    I need to figure out a way to stop that.

    I came up with this solution idea yesterday that sort of works. But it's very hackish.
    I used collision detection to trigger the ViewportSelect() code. So the polygons will no longer highlight unless the mouse is within a certain range of the object's axis.
    But of course this is a bad method. Because I'm then limited to the hard coded range value which will fail if the object is too big or too small.

    This is my latest collision version.
    You should be able to run it by going into the LiquidTool SDK plugin and comment everything out.
    Then paste this code above it:

    #include "c4d.h"  
    #include "c4d_symbols.h"  
    #include "lib_collider.h"  
      
    #define ID_LIQUIDTOOL 1000973  
      
    class LiquidToolData : public ToolData  
    {  
      public:  
          virtual Bool            MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg);  
          virtual Bool            KeyboardInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg);  
          virtual LONG            GetState(BaseDocument *doc);  
          virtual Bool            GetCursorInfo(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, Real x, Real y, BaseContainer &bc);  
          virtual TOOLDRAW        Draw(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, BaseDrawHelp *bh, BaseThread *bt,TOOLDRAWFLAGS flags);  
      
          virtual SubDialog*    AllocSubDialog(BaseContainer* bc);  
      
      private:  
          LONG polygonid;  //This will come in handy when we need to select the polygon that's being highlighted   
          Bool highlight;  
      
    };  
      
    TOOLDRAW LiquidToolData::Draw(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, BaseDrawHelp *bh, BaseThread *bt,TOOLDRAWFLAGS flags)  
    {  
      if (!(flags & TOOLDRAWFLAGS_HIGHLIGHT))  
          return TOOLDRAW_0;  
      
      if (doc->GetMode() != Mpolygons)  
          return TOOLDRAW_0;  
      
      if (!highlight)  
          return TOOLDRAW_0;  
      
      BaseObject *op = doc->GetActiveObject();  
      
      if (op && op->GetType() == Opolygon)  
      {  
          const CPolygon *polys = ToPoly(op)->GetPolygonW();  
          const Vector *points = ToPoly(op)->GetPointW();  
          Vector *p = bNew Vector[4];  
          p[0] = points[polys[polygonid].a];  
          p[1] = points[polys[polygonid].b];  
          p[2] = points[polys[polygonid].c];  
          p[3] = points[polys[polygonid].d];  
      
          Vector *f = bNew Vector[4];  
          f[0] = 1.0;  
          f[1] = 1.0;       //The color of the four corners of the selected polygon  
          f[2] = 1.0;  
          f[3] = 1.0;  
      
          bd->SetMatrix_Matrix(NULL, op->GetMg(), 3);  
          bd->DrawPolygon(p,f,TRUE);  
      
          bd->LineZOffset(0);  
      
          bDelete(p);  
          bDelete(f);  
      }  
      
      highlight = FALSE;  
      
      return TOOLDRAW_0;  
    }  
      
      
    LONG LiquidToolData::GetState(BaseDocument *doc)  
    {  
      if (doc->GetMode()==Mpaint) return 0;  
      return CMD_ENABLED;  
    }  
      
    Bool LiquidToolData::KeyboardInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg)  
    {  
      LONG key = msg.GetData(BFM_INPUT_CHANNEL).GetLong();  
      String str = msg.GetData(BFM_INPUT_ASC).GetString();  
      if (key == KEY_ESC)  
      {  
          // do what you want  
          // return TRUE to signal that the key is processed!  
          return TRUE;  
      }  
      return FALSE;  
    }  
      
    Bool LiquidToolData::MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd,EditorWindow *win, const BaseContainer &msg)  
    {    
      Real mx = msg.GetReal(BFM_INPUT_X);  
      Real my = msg.GetReal(BFM_INPUT_Y);  
      LONG button;  
        
      switch (msg.GetLong(BFM_INPUT_CHANNEL))  
      {  
          case BFM_INPUT_MOUSELEFT : button=KEY_MLEFT; break;  
          case BFM_INPUT_MOUSERIGHT: button=KEY_MRIGHT; break;  
          default: return TRUE;  
      }  
        
      
      BaseObject *obj = doc->GetActiveObject();  
      if (!obj) return FALSE;  
      
      PolygonObject *pobj = ToPoly(obj);        //Cast the active object to a polygon type   
      BaseSelect *bs = pobj->GetPolygonS();    //Create a new BaseSelect filled with the currently selected polygons(if any)  
      
      
      BaseContainer state;  
      while (GetInputState(BFM_INPUT_MOUSE, BFM_INPUT_MOUSELEFT, state)) //While the LMB is down   
      {  
        if (state.GetLong(BFM_INPUT_VALUE) == 0) break; //If the state value is 0. The LMB is no longer down..so don't enter the loop   
        
        LONG x = state.GetLong(BFM_INPUT_X);           //Get the cursor's X screen coordinates  
        LONG y = state.GetLong(BFM_INPUT_Y);           //Get the cursor's Y screen coordinates  
      
        GeShowMouse(MOUSE_POINT_HAND);                 //Change the cursor's apperance when the mouse button is down   
      
        if( polygonid >-1) bs->Select(polygonid);      //Select the polygon that's currently highlighted  
        else bs->DeselectAll();  
      }  
      
      EventAdd();  
      return TRUE;  
    }  
      
    Bool LiquidToolData::GetCursorInfo(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, Real x, Real y, BaseContainer &bc)  
    {  
      LONG mx = x;  
      LONG my = y;  
      
      LONG mode = doc->GetMode();  
      
      BaseObject *op = doc->GetActiveObject();  
      if (!op || op->GetType() != Opolygon) return TRUE;  
      
      AutoAlloc<GeRayCollider> cRay;  
      GeRayColResult res;  
        
      if (!cRay)  
      {  
          return TOOLDRAW_0;  
      }  
      
      Vector wtail =    bd->SW(Vector(mx, my, 0));  
      Vector whead =    bd->SW(Vector(mx, my, 100000));  
      Vector otail = (!op->GetMg()) * wtail;  
      Vector oray     = (whead - wtail) ^ (!op->GetMg());  
      
      cRay->Init(op, TRUE);  
      cRay->Intersect(otail, !oray, 10000.0);  
        
      Vector distance = PointLineDistance(wtail, whead, op->GetMg().off);  
      const Real threshold = 160.0; // The distance from the axis before detection is triggered  
      Real dist = distance.GetLength();  
        
      if(dist <= threshold)  //Only if the mouse is close enough to the object..do we do the highlighting stuff   
      {  
      
          if (mode == Mpolygons)  
          {  
            LONG left, top, right, bottom, width, height;  
            bd->GetFrame(&left,  &top, &right, &bottom);  
            width = right - left + 1;  
            height = bottom - top + 1;  
      
            AutoAlloc<ViewportSelect> vs;  
            if (!vs || !vs->Init(width,height,bd,op,mode,TRUE,VIEWPORTSELECTFLAGS_0)) return FALSE;  
            highlight = TRUE;  
            ViewportPixel *vpp = NULL;  
      
            vpp = vs->GetNearestPolygon(op, mx, my, MAXLONGl, FALSE, NULL, 0);  
      
            if (vpp)  
            {  
              polygonid = vpp->i;  
              DrawViews(DRAWFLAGS_ONLY_ACTIVE_VIEW|DRAWFLAGS_NO_THREAD|DRAWFLAGS_NO_ANIMATION, bd);  
            }  
        }  
      }  
      else   
      {  
          polygonid = -1;    //This will be used by the MouseInput loop to de-select all polygons  
      }  
      
      return TRUE;  
    }  
      
    class LiquidToolDialog: public SubDialog  
    {  
      public:  
          virtual Bool CreateLayout(void);  
          virtual Bool InitValues(void);  
      
          virtual Bool InitDialog(void);  
          virtual Bool Command(LONG id,const BaseContainer &msg);  
    };  
      
    Bool LiquidToolDialog::CreateLayout(void)  
    {  
      return TRUE;  
    }  
      
    Bool LiquidToolDialog::InitValues(void)  
    {  
      return InitDialog();  
    }  
      
    Bool LiquidToolDialog::InitDialog(void)  
    {  
      BaseContainer *bc=GetToolData(GetActiveDocument(),ID_LIQUIDTOOL);  
      if (!bc) return FALSE;  
      
      return TRUE;  
    }  
      
    Bool LiquidToolDialog::Command(LONG id,const BaseContainer &msg)  
    {  
      return TRUE;  
    }  
      
    SubDialog* LiquidToolData::AllocSubDialog(BaseContainer* bc)  
    {  
      return gNew LiquidToolDialog;   
    }  
      
    Bool RegisterPrimitiveTool(void)  
    {  
      return RegisterToolPlugin(ID_LIQUIDTOOL,GeLoadString(IDS_PRIMITIVETOOL),0,AutoBitmap("liquid.tif"),"C++ SDK Liquid Painting Tool",gNew LiquidToolData);  
    }
    

    I need to find a better way to do this that doesn't rely on the distance of the mouse to the objects axis.
    Selecting points&polys inside of a tool plugin seems pretty much like the first thing users would want to do. I'm a little baffled why Maxon doesn't have an example of that in their SDK.

    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 15/06/2012 at 08:53, xxxxxxxx wrote:

    What exactly is crashing? Sorry, I don't have time to debug or compile your code. If your code worked before (the above version not the latest you posted), I see no reason why the additions I suggested shall crash. At least it makes no sense except that GetNearestPolygon with an explicit radius crashes (which you should report to MAXON).

    However, I repost your previous code with the changes I suggested (and necessary changes resulting from it...I added a //**---- ADDED: comment ----** in changed areas). You say this crashes and before it didn't?

      
        
        
        #include "c4d.h"  
        #include "c4d_symbols.h"  
          
        #define ID_LIQUIDTOOL 1000973  
          
        class LiquidToolData : public ToolData  
        {  
          public:  
                LiquidToolData() : polygonid(-1) {} //**---- ADDED: initialise your tool with no polys selected ----**  
          
              virtual Bool        MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg);  
              virtual Bool        KeyboardInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg);  
              virtual LONG        GetState(BaseDocument *doc);  
              virtual Bool            GetCursorInfo(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, Real x, Real y, BaseContainer &bc);  
              virtual TOOLDRAW        Draw(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, BaseDrawHelp *bh, BaseThread *bt,TOOLDRAWFLAGS flags);  
          
              virtual SubDialog*    AllocSubDialog(BaseContainer* bc);  
          
          private:  
              LONG polygonid;  //This will come in handy when we need to select the polygon that's being highlighted   
              Bool highlight;  
          
        };  
          
        TOOLDRAW LiquidToolData::Draw(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, BaseDrawHelp *bh, BaseThread *bt,TOOLDRAWFLAGS flags)  
        {  
          if (!(flags & TOOLDRAWFLAGS_HIGHLIGHT))  
              return TOOLDRAW_0;  
          
          if (doc->GetMode() != Mpolygons)  
              return TOOLDRAW_0;  
          
          if (!highlight)  
              return TOOLDRAW_0;  
              
            if(polygonid==-1) return TOOLDRAW_0; //**---- ADDED: if there is no valid polygon id don't draw it highlighted ----**  
          
          BaseObject *op = doc->GetActiveObject();  
          if (op && op->GetType() == Opolygon)  
          {  
              const CPolygon *polys = ToPoly(op)->GetPolygonW();  
              const Vector *points = ToPoly(op)->GetPointW();  
              Vector *p = bNew Vector[4];  
              p[0] = points[polys[polygonid].a];  
              p[1] = points[polys[polygonid].b];  
              p[2] = points[polys[polygonid].c];  
              p[3] = points[polys[polygonid].d];  
          
              Vector *f = bNew Vector[4];  
              f[0] = 1.0;  
              f[1] = 1.0;       //The color of the four corners of the selected polygon  
              f[2] = 1.0;  
              f[3] = 1.0;  
          
              bd->SetMatrix_Matrix(NULL, op->GetMg(), 3);  
              bd->DrawPolygon(p,f,TRUE);  
          
              bd->LineZOffset(0);  
          
              bDelete(p);  
              bDelete(f);  
          }  
          
          highlight = FALSE;  
          
          return TOOLDRAW_0;  
        }  
          
          
        LONG LiquidToolData::GetState(BaseDocument *doc)  
        {  
          if (doc->GetMode()==Mpaint) return 0;  
          return CMD_ENABLED;  
        }  
          
        Bool LiquidToolData::KeyboardInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg)  
        {  
          LONG key = msg.GetData(BFM_INPUT_CHANNEL).GetLong();  
          String str = msg.GetData(BFM_INPUT_ASC).GetString();  
          if (key == KEY_ESC)  
          {  
              // do what you want  
              // return TRUE to signal that the key is processed!  
              return TRUE;  
          }  
          return FALSE;  
        }  
          
        Bool LiquidToolData::MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd,EditorWindow *win, const BaseContainer &msg)  
        {    
          Real mx = msg.GetReal(BFM_INPUT_X);  
          Real my = msg.GetReal(BFM_INPUT_Y);  
          LONG button;  
            
          switch (msg.GetLong(BFM_INPUT_CHANNEL))  
          {  
              case BFM_INPUT_MOUSELEFT : button=KEY_MLEFT; break;  
              case BFM_INPUT_MOUSERIGHT: button=KEY_MRIGHT; break;  
              default: return TRUE;  
          }  
            
          
          BaseObject *obj = doc->GetActiveObject();  
          if (!obj) return FALSE;  
          
          PolygonObject *pobj = ToPoly(obj);        //Cast the active object to a polygon type   
          BaseSelect *bs = pobj->GetPolygonS();    //Create a new BaseSelect filled with the currently selected polygons(if any)  
          
          
          BaseContainer state;  
          while (GetInputState(BFM_INPUT_MOUSE, BFM_INPUT_MOUSELEFT, state)) //While the LMB is down   
          {  
            if (state.GetLong(BFM_INPUT_VALUE) == 0) break; //If the state value is 0. The LMB is no longer down..so don't enter the loop   
            
            LONG x = state.GetLong(BFM_INPUT_X); //Get the cursor's X screen coordinates  
            LONG y = state.GetLong(BFM_INPUT_Y); //Get the cursor's Y screen coordinates  
          
            GeShowMouse(MOUSE_POINT_HAND);       //Change the cursor's apperance when the mouse button is down  
            
              //**---- ADDED: check if there is a valid poly id, otherwise deselect all polygons ----**  
            if(polygonid>-1) bs->Select(polygonid);               //Select the polygon that's currently highlighted  
              else bs->DeselectAll();  
          }  
          
          EventAdd();  
          return TRUE;  
        }  
          
        Bool LiquidToolData::GetCursorInfo(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, Real x, Real y, BaseContainer &bc)  
        {  
          LONG left, top, right, bottom, width, height;  
          bd->GetFrame(&left,  &top, &right, &bottom);  
          width = right - left + 1;  
          height = bottom - top + 1;  
          
          LONG mode = doc->GetMode();  
          
          BaseObject *op = doc->GetActiveObject();  
          if (!op || op->GetType() != Opolygon) return TRUE;  
            
          AutoAlloc<ViewportSelect> vs;  
          if (!vs || !vs->Init(width,height,bd,op,mode,TRUE,VIEWPORTSELECTFLAGS_0)) return FALSE;  
          
          if (mode == Mpolygons)  
          {  
              highlight = TRUE;  
          
              ViewportPixel *vpp = NULL;  
          
              LONG mx = x;  
              LONG my = y;  
          
                  
         //**---- ADDED: only use a small radius for checking a polygon vicinity (MAXLONGl replaced with e.g. 2) ----**  
              vpp = vs->GetNearestPolygon(op, mx, my, 2, FALSE, NULL, 0);  
          
              if (vpp)  
              {  
                  polygonid = vpp->i;  
                  DrawViews(DRAWFLAGS_ONLY_ACTIVE_VIEW|DRAWFLAGS_NO_THREAD|DRAWFLAGS_NO_ANIMATION, bd);  
              }  
                else polygonid = -1;   
         //**---- ADDED: no polygon found near the cursor, so set an invalid poly index (i.e. -1) ----**    }  
          
          return TRUE;  
        }  
          
        class LiquidToolDialog: public SubDialog  
        {  
          public:  
              virtual Bool CreateLayout(void);  
              virtual Bool InitValues(void);  
          
              virtual Bool InitDialog(void);  
              virtual Bool Command(LONG id,const BaseContainer &msg);  
        };  
          
        Bool LiquidToolDialog::CreateLayout(void)  
        {  
          return TRUE;  
        }  
          
        Bool LiquidToolDialog::InitValues(void)  
        {  
          return InitDialog();  
        }  
          
        Bool LiquidToolDialog::InitDialog(void)  
        {  
          BaseContainer *bc=GetToolData(GetActiveDocument(),ID_LIQUIDTOOL);  
          if (!bc) return FALSE;  
          
          return TRUE;  
        }  
          
        Bool LiquidToolDialog::Command(LONG id,const BaseContainer &msg)  
        {  
          return TRUE;  
        }  
          
        SubDialog* LiquidToolData::AllocSubDialog(BaseContainer* bc)  
        {  
          return gNew LiquidToolDialog;   
        }  
          
        Bool RegisterPrimitiveTool(void)  
        {  
          return RegisterToolPlugin(ID_LIQUIDTOOL,GeLoadString(IDS_PRIMITIVETOOL),0,AutoBitmap("liquid.tif"),"C++ SDK Liquid Painting Tool",gNew LiquidToolData);  
        }
      
    


  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 15/06/2012 at 09:23, xxxxxxxx wrote:

    Thanks.
    It's not crashing anymore.

    This code was crashing for me before:

            vpp = vs->GetNearestPolygon(op, mx, my, 2, FALSE, NULL, 0);  
          if (vpp)  
          {  
              polygonid = vpp->i;  
              DrawViews(DRAWFLAGS_ONLY_ACTIVE_VIEW|DRAWFLAGS_NO_THREAD|DRAWFLAGS_NO_ANIMATION, bd);  
          }  
          else polygonid = -1;
    

    I probably made a mistake when I used them before.

    Thanks a lot for taking the time to help me solve this.🍺
    This sort of thing should definitely be included in the SDK examples.

    -ScottA


Log in to reply