Select an inactive object



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

    On 21/07/2011 at 21:30, xxxxxxxx wrote:

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

    ---------
    Hello,

    How do I go about having my tool select an inactive object in the viewport.

    I think this could be done by walking the hierarchy and getting every object in the scene and checking collisions with the mouse for each one but that seems quite costly on memory and cpu.  Is there a function in the SDK that I am overlooking that will help me to select inactive objects in the viewport?

    I know that I will use SetActiveObject() to set the object as active but I am not sure how I will get the object that is located behind the mouse?

    Thanks,

    Shawn



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

    On 21/07/2011 at 22:19, xxxxxxxx wrote:

    This is from my InterPoser Pro Tool Draw method.  The mouseX and mouseY are stored in GetCursorInfo() for the tool.

        // Mouse outside of Editor view  
      if (mouseX < 0.0)                    return drawFlags;  
      
      // Add IPP objects under cursor to selection list  
      AutoAlloc<C4DObjectList>            objList;  
      if (!objList)                        return drawFlags;  
      if (!SelectionListCreate(doc, NULL, bd, mouseX, mouseY, NULL, objList))    return drawFlags;  
      LONG            cnt =                objList->GetCount();  
      if (!cnt)                            return drawFlags;  
      
      // Set level of object to highlight  
      LONG            i =                    0L;  
      LONG            a =                    0L;  
      // - lets us go back to level=0 if the level is beyond valid selections  
      LONG            seg =                -1L;  
      BaseTag*        ippTag =            NULL;  
      BaseObject*        obj =                NULL;  
      BaseContainer*    bc =                NULL;  
      BaseContainer*    fbc =                NULL;  
      // Skip objects in list that aren't conformant  
      for (a = 0; a < cnt; ++a)  
       {  
          obj =    objList->GetObject(a);  
          // Only check IPP objects  
          if (obj->IsInstanceOf(ID_IPPBASE))  
          {  
              if (!(bc = obj->GetDataInstance()))    continue;  
              hilitedBP =        obj;  
              obj =            bc->GetObjectLink(IPP_ROOT, doc);  
              if (!obj)        return drawFlags;  
          }  
          ippTag =    obj->GetTag(ID_IPPFIGURETAG);  
          if (!ippTag)  
          {  
              ippTag =        obj->GetTag(ID_IPPOBJECTTAG);  
              if (!ippTag)    continue;  
          }  
          if (ippTag->IsInstanceOf(ID_IPPFIGURETAG) && skipConformers)  
          {  
              fbc =    ippTag->GetDataInstance();  
              if (fbc && fbc->GetBool(IPPFIGURE_CONFORMED))    continue;  
          }  
          if (seg == -1L)    seg =    a;  
          if (i == level)    break;  
          ++i;  
      }  
      // - Invalid IPP object  
      if (!(ippTag && obj))    return drawFlags;  
      if (a == cnt)  
      {  
          if (seg != -1L)  
          {  
              level = 0L;  
              a =        seg;  
          }  
          else    return drawFlags;  
      }
    

    Basically, I am getting a list of objects under the cursor using a C4DObjectList instance and making determinations about the validity afterwards (probably not as important but included for thoroughness).  So, you could take the nearest object (using C4DObjectList::GetZ() to determine 'nearest') and then SetActiveObject() based on that criteria.



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

    On 21/07/2011 at 22:21, xxxxxxxx wrote:

    Note that you don't have to do this in the Draw() method.  You want to do this in the MouseInput() method.  But you should still store the cursor coordinates in GetCursorInfo() to use there. :)

    Also, don't forget to call EventAdd() after SetActiveObject()!



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

    On 21/07/2011 at 22:23, xxxxxxxx wrote:

    Perfect..  Thanks Robert.   I wish I could email you a beer or something.  You really ought to be paid for all the help you give.  :)

    Thanks again!

    ~Shawn



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

    On 22/07/2011 at 12:12, xxxxxxxx wrote:

    Hey Robert,  so your method works great.  I am able to select objects and use qualifiers to multi select or deselect.  One more question.   How would i deselect all if the user clicks an area where there is no object behind the cursor?

    Thanks,

    Shawn



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

    On 22/07/2011 at 12:37, xxxxxxxx wrote:

    Hey Shawn,

    Try it with a RayCollision. ;)



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

    On 22/07/2011 at 13:23, xxxxxxxx wrote:

    I would check the C4DObjectList for (cnt == 0) or (!cnt) as I do and if this is the case on a mouse click then you call:

    if (!cnt)
    {
    AutoAlloc<AtomArray>  atomArray;
    if (atomArray)
    {
      BaseObject* sobj = NULL;
      doc->GetActiveObjects(*atomArray, FALSE);
      LONG    cnt =            atomArray->GetCount();
      for (LONG i = 0L; i != cnt; ++i)
      {
      static_cast<BaseObject*>(atomArray->GetIndex(i))->DelBit(BIT_ACTIVE);
      }
      EventAdd();
    }
    }



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

    On 22/07/2011 at 13:57, xxxxxxxx wrote:

    Hmmm..

    Well I added what you mentioned and it still does nothing when I click off an object..   Here's my function..  This function is called directly from MouseInput()  :)

      
    //SELECT OBJECT  
    //==============================================//  
      
    Bool MyClass::SelectObject(BaseDraw *bd)  
    {  
      //Get the active document  
      BaseDocument *doc = GetActiveDocument();  
      if(!doc) return FALSE;  
      
      //Check to see if the cursor is in the editor window  
      if(mouseX < 0.0) return FALSE;  
      
      //Add all objects under the cursor to the Object List  
      AutoAlloc<C4DObjectList> objList;  
      if (!objList)return FALSE;  
      
      if (!SelectionListCreate(doc, NULL, bd, mouseX, mouseY, NULL, objList)) return FALSE;  
      LONG objectCount    = objList->GetCount();  
      if (!objectCount)    return FALSE;  
      
      BaseObject *obj = NULL;  
      
      if (!objectCount)  
      {  
          GePrint("NO OBJECT");  
          AutoAlloc<AtomArray>  atomArray;  
            
          if (atomArray)  
          {  
              BaseObject* sobj = NULL;  
              doc->GetActiveObjects(*atomArray, FALSE);  
              LONG cnt = atomArray->GetCount();  
      
              for (int i = 0; i != cnt; ++i)  
              {  
                  static_cast<BaseObject*>(atomArray->GetIndex(i))->DelBit(BIT_ACTIVE);  
              }  
      
              EventAdd();  
          }  
      }  
      
      //Loop through objects  
      for(int i = 0; i < objectCount; ++i)  
      {  
          obj = objList->GetObject(i);  
      
          BaseContainer state;  
      
          if (GetInputEvent(BFM_INPUT_KEYBOARD, state))  
          {  
              LONG key = state.GetLong(BFM_INPUT_QUALIFIER);  
                        
              if(key & QCTRL)  
              {  
                  doc->SetActiveObject(obj, SELECTION_SUB);  
                  EventAdd(EVENT_FORCEREDRAW);  
              }  
              else if(key & QSHIFT)  
              {  
                  doc->SetActiveObject(obj, SELECTION_ADD);  
                  EventAdd(EVENT_FORCEREDRAW);  
              }  
              else  
              {  
                  doc->SetActiveObject(obj, SELECTION_NEW);  
                  EventAdd(EVENT_FORCEREDRAW);  
              }  
          }  
      }  
    }  
    


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

    On 22/07/2011 at 13:59, xxxxxxxx wrote:

    Interestingly...  the GePrint() that I added never shows up which must mean that objectCount is never = 0.



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

    On 22/07/2011 at 14:02, xxxxxxxx wrote:

    DOH!  That was stupid..

    This line was the reason...

    if(!objectCount) return FALSE;

    LOL

    Oye..  Tired eyes.

    Thanks again Robert.

    ~Shawn



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

    On 22/07/2011 at 16:10, xxxxxxxx wrote:

    Get thee to bed. :)



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

    On 22/07/2011 at 16:12, xxxxxxxx wrote:

    And you can get rid of the "BaseObject* sobj = NULL;" since I made the DelBit() a one-liner into atomArray instead of getting the object and then calling DelBit().



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

    On 22/07/2011 at 16:16, xxxxxxxx wrote:

    Already done..  :) Thanks.  I got tired of looking at the "Initialized but not referenced "  warning  HAHAHA

    I'm about to call it a night.  :)  I've been at it for a while today.  Lots of good progress though.  Thanks a lot for your help.

    ~Shawn


Log in to reply