Handles changed and no longer work!



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

    On 16/08/2012 at 11:28, xxxxxxxx wrote:

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

    ---------
    In my previous builds for Cinema 4D R12, handles were working.  Now that I have added some new features to the plugin and rebuilt, the handle no longer shows in Cinema 4D R12.048.  I've updated the Resource folder and used the Spherify.cpp as an example but nothing seems to make the handle appear anymore!  I am about to rebuild the api library and see if anything changes but this is VERY frustrating.  You guys must stop going back and forth on changes and solidify a path wherein updates to the SDK (esp. within the same version) do not break existing code.  I am currently working on updating FIVE C4D versions (15 builds!).  This could take me weeks - and I have days.  Stop already. ;(

    // ObjectData.Draw  
    //*---------------------------------------------------------------------------*  
    #ifdef    C4D_R13  
    DRAWRESULT UnfurlObj::Draw(BaseObject* op, DRAWPASS drawpass, BaseDraw* bd, BaseDrawHelp* bh)  
    #else  
    DRAWRESULT UnfurlObj::Draw(PluginObject* op, DRAWPASS drawpass, BaseDraw* bd, BaseDrawHelp* bh)  
    #endif  
    //*---------------------------------------------------------------------------*  
    {  
      if (!(op && bd && bh))                return DRAWRESULT_DRAWN;  
      
      if (drawpass == DRAWPASS_OBJECT)  
      {  
          BaseContainer*    bc =    op->GetDataInstance();  
          if (!bc)                return SUPER::Draw(op, drawpass, bd, bh);  
          PolygonObject*    dop =    GetPolygonObject(op);  
          if (!dop)                return SUPER::Draw(op, drawpass, bd, bh);  
          BaseTag*        tag =    dop->GetTag(ID_UNFURL_TAG);  
          if (!tag)                return SUPER::Draw(op, drawpass, bd, bh);  
          UnfurlTag*        uf =    static_cast<UnfurlTag*>(tag->GetNodeData());  
          if (!uf)                return SUPER::Draw(op, drawpass, bd, bh);  
          dop =                    GetCurrentStateToObject(dop);  
          if (!dop)                return SUPER::Draw(op, drawpass, bd, bh);  
          uf->MyDraw(tag, dop, bd, bh, bc->GetReal(UNFURL_UNFURL_AMOUNT));  
          PolygonObject::Free(dop);  
      }  
      else if (drawpass == DRAWPASS_HANDLES)  
      {  
    #ifdef    C4D_R13  
          LONG        hitid = op->GetHighlightHandle(bd);  
          HandleInfo    info;  
      
          bd->SetPen(GetViewColor(VIEWCOLOR_ACTIVEPOINT));  
          bd->SetMatrix_Matrix(op, bh->GetMg());  
          GetHandle(op, 0L, info);  
          if (hitid == 0L)    bd->SetPen(GetViewColor(VIEWCOLOR_SELECTION_PREVIEW));  
          else                bd->SetPen(GetViewColor(VIEWCOLOR_ACTIVEPOINT));  
          bd->DrawHandle(info.position, DRAWHANDLE_BIG, 0L);  
      
          GetHandle(op, 1L, info);  
          bd->SetPen(GetViewColor(VIEWCOLOR_ACTIVEPOINT));  
          bd->DrawLine(info.position, Vector(0.0), 0L);  
    #else  
          // Draw "Unfurl Amount" Handle  
          Matrix    m =        bh->GetMg();  
      
    #ifdef    C4D_R12  
          //bd->SetMatrix_Matrix(NULL, Matrix());  
          bd->SetMatrix_Matrix(op, m);  
    #endif  
          LONG    hit =    op->GetHighlightHandle(bd);  
          if (hit == 0L)    bd->SetPen(GetViewColor(VIEWCOLOR_SELECTION_PREVIEW));  
          else            bd->SetPen(GetViewColor(VIEWCOLOR_ACTIVEPOINT));  
    #ifdef    C4D_R12  
          //bd->DrawHandle(GetUnfurlHandle(op),DRAWHANDLE_BIG,0L);  
          bd->DrawHandle(GetUnfurlHandle(op)*m,DRAWHANDLE_BIG,0L);  
    #else  
          bd->Handle3D(GetUnfurlHandle(op)*m,DRAWHANDLE_BIG);  
    #endif  
          // Line from center to Handle  
          bd->SetPen(GetViewColor(VIEWCOLOR_ACTIVEPOINT));  
    #ifdef    C4D_R12  
          //bd->DrawLine(GetUnfurlHandle(op),Vector(0.0),0L);  
          bd->DrawLine(GetUnfurlHandle(op)*m,m.off,0L);  
    #else  
          bd->Line3D(GetUnfurlHandle(op)*m,m.off);  
    #endif  
    #endif  
          return DRAWRESULT_DRAWN;  
      }  
      return SUPER::Draw(op, drawpass, bd, bh);  
    }  
    #ifdef    C4D_R13  
    // ObjectData.GetHandle  
    //*---------------------------------------------------------------------------*  
    void UnfurlObj::GetHandle(BaseObject* op, LONG i, HandleInfo& info)  
    //*---------------------------------------------------------------------------*  
    {  
      BaseContainer* data =    op->GetDataInstance();  
      if (!data)                return;  
      
      info.position.x =        data->GetReal(UNFURL_UNFURL_AMOUNT)*125.0;  
      info.direction.x =        1.0;  
      info.type =                HANDLECONSTRAINTTYPE_LINEAR;  
    }  
    // ObjectData.DetectHandle  
    //*---------------------------------------------------------------------------*  
    LONG UnfurlObj::DetectHandle(BaseObject* op, BaseDraw* bd, LONG x, LONG y, QUALIFIER qualifier)  
    //*---------------------------------------------------------------------------*  
    {  
      HandleInfo    info;  
      GetHandle(op, 0L, info);  
      return (bd->PointInRange(info.position*op->GetMg(),x,y))?0L:NOTOK;  
    }  
    // ObjectData.MoveHandle  
    //*---------------------------------------------------------------------------*  
    Bool UnfurlObj::MoveHandle(BaseObject* op, BaseObject* undo, const Vector& mouse_pos, LONG hit_id, QUALIFIER qualifier, BaseDraw* bd)  
    //*---------------------------------------------------------------------------*  
    {  
      BaseContainer*    dst =    op->GetDataInstance();  
      if (!dst)                return TRUE;  
      HandleInfo        info;  
      Real            val =    mouse_pos.x;  
      GetHandle(op, hit_id, info);  
      
      if (bd)  
      {  
          Matrix mg =        op->GetUpMg() * undo->GetMl();  
          Vector pos =    bd->ProjectPointOnLine(info.position * mg, info.direction ^ mg, mouse_pos.x, mouse_pos.y);  
          val =            (pos * !mg) * info.direction;  
      }  
      
      if (hit_id != 0L)        return TRUE;  
      dst->SetReal(UNFURL_UNFURL_AMOUNT,FCut01(val*0.008));  
      return TRUE;  
    }  
    #else  
    // UnfurlObj.GetUnfurlHandle  
    //*---------------------------------------------------------------------------*  
    Vector UnfurlObj::GetUnfurlHandle(PluginObject* op)  
    //*---------------------------------------------------------------------------*  
    {  
      BaseContainer*    bc =        op->GetDataInstance();  
      if (!bc)                    return Vector(0.0);  
      return Vector(bc->GetReal(UNFURL_UNFURL_AMOUNT)*125.0,0.0,0.0);  
    }  
    // ObjectData.DetectHandle  
    //*---------------------------------------------------------------------------*  
    LONG UnfurlObj::DetectHandle(PluginObject* op, BaseDraw* bd, LONG x, LONG y, QUALIFIER qualifier)  
    //*---------------------------------------------------------------------------*  
    {  
      return (bd->PointInRange(GetUnfurlHandle(op)*op->GetMg(),x,y))?0L:NOTOK;  
    }  
    // ObjectData.MoveHandle  
    //*---------------------------------------------------------------------------*  
    Bool UnfurlObj::MoveHandle(PluginObject* op, PluginObject* undo, const Matrix& tm, LONG hit_id, QUALIFIER qualifier)  
    //*---------------------------------------------------------------------------*  
    {  
      BaseContainer*    src =    undo->GetDataInstance();  
      if (!src)                return TRUE;  
      BaseContainer*    dst =    op->GetDataInstance();  
      if (!dst)                return TRUE;  
      
      Real            val =    src->GetReal(UNFURL_UNFURL_AMOUNT)+(tm.off.x*0.008);  
      dst->SetReal(UNFURL_UNFURL_AMOUNT, FCut01(val));  
      
      return TRUE;  
    }  
    #endif
    


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

    On 16/08/2012 at 13:25, xxxxxxxx wrote:

    Hello Robert,

    Why are you distinguish that much code between R12 and R13 when you actually implement the drawing yourself? Instead of providing a GetHandle() and a GetUnfurlHandle() method, make only one method. You don't use functionality the HandleInfo class provides: Make your own structure that keeps the data, etc.

    I'm not planning to port my plugin to R12, but I do make the drawing and detecting myself. As I have a number of ObjectData plugins that need to implement handles, I wrote a BaseClass that makes it easy and implements a similar interface compared to the GetHandle()/SetHandle() convenience functions.

    Here's some code that could work for you (with adjustments). It is similar to the code I use for handle-detecting, -moving and -drawing.

    (Yes, I preferer underscore_seperated_names. It also makes it easier to distinguish between C4D API names and my owns.)

    #include <c4d.h>
    
    class HandleObjectData : ObjectData {
    
      public:
    
        //
        // HandleObjectData --------------------------------------------------------
        //
    
        // Return the number of handles for the object.
        virtual LONG get_handle_count(BaseObject\* op);
    
        // Fill in the handle's position, direction and type into the passed
        // HandleInfo object. Return TRUE on success, FALSE to prevent further
        // operations.
        virtual Bool get_handle(BaseObject\* op, LONG index, HandleInfo& info);
    
        // Set parameters based on the new position of the handle stored in
        // \*info.position\*.
        virtual void set_handle(BaseObject\* op, LONG index, const HandleInfo& info);
    
        //
        // ObjectData --------------------------------------------------------------
        //
    
        DRAWRESULT Draw(BaseObject\* op, DRAWPASS drawpass, BaseDraw\* bd, BaseDrawHelp\* bh);
    
        LONG DetectHandle(BaseObject\* op, BaseDraw\* bd, LONG x, LONG y, QUALIFIER qualifier);
    
    };
    
    //
    // HandleObjectData --------------------------------------------------------
    //
    
    LONG HandleObjectData::get_handle_count(BaseObject\* op) {
        /\* ... \*/
    }
    
    Bool HandleObjectData::get_handle(BaseObject\*, LONG index, HandleInfo& info) {
        /\* ... \*/
    }
    
    void HandleObjectData::set_handle(BaseObject\* op, LONG index, const HandleInfo& info) {
        /\* ... \*/
    }
    
    //
    // ObjectData ------------------------------------------------------------------
    //
    
    DRAWRESULT HandleObjectData::Draw(BaseObject\* op, DRAWPASS drawpass, BaseDraw\* bd, BaseDrawHelp\* bh) {
        if (drawpass != DRAWPASS_HANDLES) return DRAWRESULT_OK;
        bd->SetMatrix_Matrix(op, bh->GetMg());
    
        // Obtain the object's bounding-box information.
        Vector mp, rad;
        GetDimension(op, &mp, &rad);
    
        // Perform the drawing-operations onto the editor window.
        LONG hitid = op->GetHighlightHandle();
        for (LONG i=0; i < get_handle_count(op); i++) {
            HandleInfo info;
            if (!get_handle(op, i, info)) continue;
    
            // Offset by the object's BB-Center.
            info.position += mp;
    
            // Perform drawing operations.
            /\* ... \*/
        }
    
        return DRAWRESULT_OK;
    }
    
    LONG HandleObjectData::DetectHandle(BaseObject\* op, BaseDraw\* bd, LONG x, LONG y, QUALIFIER qualifier) {
        Matrix matrix = op->GetMg();
        LONG handle   = NOTOK;
        Bool shift    = qualifier & QUALIFIER_SHIFT;
    
        // Obtain the object's bounding-box information.
        Vector mp, rad;
        GetDimension(op, &mp, &rad);
    
        // Iterate over each hhandle and check which of them matches at the curent
        // mouse-position.
        for (LONG i=0; i < get_handle_count(op); i++) {
            HandleInfo info;
            if (!get_handle(op, i, info)) continue;
    
            // Offset by the object's BB-Center.
            info.position += mp;
    
            if (bd->PointInRange(info.position \* matrix, x, y)) {
                handle = i;
    
                // Use this handle when SHIFT is not pressed (which means
                // to use the first handle found). Otherwise, the last handle
                // will be used.
                if (shift) break;
            }
        }
    
        return handle;
    }
    
    Bool HandleObjectData::MoveHandle(BaseObject\* op, BaseObject\* undo, const Vector& mouse_pos, LONG hitid, QUALIFIER qualifier, BaseDraw\* bd) {
        if (not op) return FALSE;
    
        // Get the identified handle. Do not continue if get_handle() returned
        // False.
        HandleInfo info;
        if (not get_handle(op, hitid, info)) return TRUE;
    
        // Obtain the object's bounding-box information.
        Vector mp, size;
        GetDimension(op, &mp, &size);
        info.position += mp;
    
        // Compute the handles new position.
        Matrix matrix = op->GetUpMg() \* undo->GetMl();
        info.position = info.CalculateNewPosition(bd, matrix, mouse_pos);
    
        // Undo the handle-offset.
        info.position -= mp;
    
        // Invoke the procedure that implements the data-processing of the handle.
        set_handle(op, hitid, info);
        return TRUE;
    }
    

    I hope it will be useful for you.

    PS:
    - The DRAWRESULT_DRAWN constant is unknown to me.
    - From what version of the Cinema 4D API does PluginObject* come from?



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

    On 17/08/2012 at 04:47, xxxxxxxx wrote:

    Your code is using the C4D R13 version. HandleInfo doesn't exist in R12 and earlier.  Using my own GetHandle() method was the way to do it until it was added at some point in R12.0xx (you can see this in the cinema4dsdk example Spherify.cpp which I used as a template for my handle code).  My handle code for R13 works in R13 for the R13 build (but the R12 build handle never worked in R13) and my R12 build used to work in R12 but after rebuilding it and working with the last version of R12, it no longer works at all - the handle isn't even drawn anymore!

    DRAWRESULT_DRAWN is one of the changes in the R12 SDK that apparently was changed to DRAWRESULT_OK in the later R12 SDK.  Like I said, I wish they would stop fiddling with these things, especially with the same major version of the SDK.  Fixes and added functionality, I don't mind.  Changes that break working code, I do.



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

    On 17/08/2012 at 05:44, xxxxxxxx wrote:

    Your code is using the C4D R13 version. HandleInfo doesn't exist in R12 and earlier

    Yes, indeed. But what I wanted to say is, that you can instead just make your own HandleInfo class for R12 and include it in R12, but use the native HandleInfo class in R13 and higher. You could essentially just copy the code from the c4d-api as the HandleInfo class is open. This way, you could stick with the new API without struggling that much with conditional code for different versions of Cinema 4D.

    -Niklas



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

    On 17/08/2012 at 06:43, xxxxxxxx wrote:

    Well, that seems to have worked.  Sad that such a fundamental feature is so harassed and requires so much effort.  Maxon needs to use similar generic structures that change underneath so that we can leave our code alone and it still works just by fiat.  Oh well...


Log in to reply