MakeEditable in C++



  • On 08/05/2013 at 14:36, xxxxxxxx wrote:

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

    ---------
    The questions just won't stop....

    I created an Ocube primitive in my code. Now, how can I make it editable (as in Make Editable).

    I tried:
    doc->SetActiveObject(op, SELECTION_NEW);
    CallCommand(12236);

    But this crashed C4D.

    Then I experimented with this:
    op->ChangeNBit( NBIT_OM1_FOLD, NBITCONTROL_SET );

    but it didn't do anything.

    So what is the proper way to do this.
    This is in DescriptionToolData::Message.

    Peter



  • On 08/05/2013 at 15:06, xxxxxxxx wrote:

      
      ModelingCommandData cd;  
    cd.doc = doc;  
    cd.op = op;  
    if (!SendModelingCommand(MCOMMAND_MAKEEDITABLE, cd)) return FALSE;  
    


  • On 08/05/2013 at 20:03, xxxxxxxx wrote:

    Thanks for the reply.
    This kept crashing C4D:

    ModelingCommandData cd;  
    cd.doc = doc;  
    cd.op = op;  
    if (!SendModelingCommand(MCOMMAND_MAKEEDITABLE, cd)) return FALSE;
    

    But after I added cd.flags = MODELINGCOMMANDFLAGS_CREATEUNDO;

    So this code works.

    ModelingCommandData mcd;
    opMachine = BaseObject::Alloc(Ocube);
    doc->InsertObject(opMachine, NULL, NULL);
                                   
    mcd.doc = doc;
    mcd.op = opMachine;
    mcd.flags = MODELINGCOMMANDFLAGS_CREATEUNDO;
    if (!SendModelingCommand(MCOMMAND_MAKEEDITABLE, mcd)) return FALSE;



  • On 08/05/2013 at 20:14, xxxxxxxx wrote:

    Oops, another observation:
    In my code I create three individual primitives. If I call

    if (!SendModelingCommand(MCOMMAND_MAKEEDITABLE, mcd)) return FALSE;

    after InsertObject() but before creating the next object I get a crash. If I create all needed objects and then use

    if (!SendModelingCommand(MCOMMAND_MAKEEDITABLE, mcd)) return FALSE;

    for each of the objects it's good.

    Is that a threading issue where the next object gets created before the previous one is done?



  • On 08/05/2013 at 20:34, xxxxxxxx wrote:

    And there I lied. If I use

    if (!SendModelingCommand(MCOMMAND_MAKEEDITABLE, mcd)) return FALSE;

    once after all objects are inserted it works fine but when I try to do this three times in a row for all three objects I get a crash. Is that because it's a Threaded Function? Forbidden?



  • On 08/05/2013 at 21:00, xxxxxxxx wrote:

    After doing a little more testing:
    The three objects I insert are hierarchal (ob3 is child of ob2 is child of ob1). All this happens in the 'Message' method of DescriptionToolData after I hit the Apply button

    Here then the question:
    I can insert three objects into my document in the proper hierarchy.
    But when I now try to use SendModelingCommand to make them editable I get a crash.

    I can insert the same three objects all at the top level of the doc.
    Then using the SendModelingCommand will work fine.
    But when I then try to rearrange my hierarchy I get the crash again.

    So either hierarchy or make editable.

    Are there restrictions I need to know of or other conflicts?

    Thanks



  • On 09/05/2013 at 01:43, xxxxxxxx wrote:

    No, no, and more no.  Please post some code instead of making wild (and unfounded) guesses.  You are doing something wrong that leads to the crashes yet you haven't given us the required information to tell you what it is.

    You can insert, hierarchy, and make editable without crashing.  But you have to know what you are doing.  For instance, after Make Editable, the new object is not the same one you are pointing to in your code (!).



  • On 09/05/2013 at 05:53, xxxxxxxx wrote:

    Here is the code snippet:

    case MDATA_APPLY:

    // create the project object
        opProject = BaseObject::Alloc(Onull);
        opProject->SetName(data.GetString(GCHELPER_PROJECTNAME));
        doc->InsertObject(opProject, NULL, NULL);

    // create the machine object
        opMachine = BaseObject::Alloc(Ocube);
        opMachine->SetParameter(PRIM_CUBE_LEN, GeData(Vector(data.GetReal(GCHELPER_MACHINEWIDTH), DEFAULT_MACHINE_HEIGHT, data.GetReal(GCHELPER_MACHINEHEIGHT))), DESCFLAGS_SET_0);
        opMachine->SetName(data.GetString(GCHELPER_MACHINENAME));
        doc->InsertObject(opMachine, opProject, NULL);

    mcd.doc = doc;
        mcd.op = opMachine;
        mcd.flags = MODELINGCOMMANDFLAGS_CREATEUNDO;
        if (!SendModelingCommand(MCOMMAND_MAKEEDITABLE, mcd)) return FALSE;

    // create the material object
        opMaterial = BaseObject::Alloc(Oplane);
        opMaterial->SetParameter(PRIM_PLANE_WIDTH, GeData(data.GetReal(GCHELPER_MATERIALWIDTH)), DESCFLAGS_SET_0);
        opMaterial->SetParameter(PRIM_PLANE_HEIGHT, GeData(data.GetReal(GCHELPER_MATERIALHEIGHT)), DESCFLAGS_SET_0);
        opMaterial->SetParameter(PRIM_PLANE_SUBW, GeData(1), DESCFLAGS_SET_0);
        opMaterial->SetParameter(PRIM_PLANE_SUBH, GeData(1), DESCFLAGS_SET_0);
        opMaterial->SetName(DEFAULT_MATERIAL_NAME);
        opMaterial->SetAbsPos(Vector(opMaterial->GetAbsPos().x, (DEFAULT_MACHINE_HEIGHT/2)+2, opMaterial->GetAbsPos().y));
        doc->InsertObject(opMaterial, opMachine, NULL);

    mcd.doc = doc;
        mcd.op = opMaterial;
        mcd.flags = MODELINGCOMMANDFLAGS_CREATEUNDO;
        if (!SendModelingCommand(MCOMMAND_MAKEEDITABLE, mcd)) return FALSE;

    // create a default polygon with default name
        opCuttingPath = BaseObject::Alloc(Oplane);
        opCuttingPath->SetParameter(PRIM_PLANE_WIDTH, GeData(data.GetReal(GCHELPER_CUTTINGPATHWIDTH)), DESCFLAGS_SET_0);
        opCuttingPath->SetParameter(PRIM_PLANE_HEIGHT, GeData(data.GetReal(GCHELPER_CUTTINGPATHHEIGHT)), DESCFLAGS_SET_0);
        opCuttingPath->SetParameter(PRIM_PLANE_SUBW, GeData(1), DESCFLAGS_SET_0);
        opCuttingPath->SetParameter(PRIM_PLANE_SUBH, GeData(1), DESCFLAGS_SET_0);
        opCuttingPath->SetName(DEFAULT_CUTTINGPATH_NAME);
        opCuttingPath->SetAbsPos(Vector(opCuttingPath->GetAbsPos().x, 2, opCuttingPath->GetAbsPos().y));

    doc->InsertObject(opCuttingPath, opMaterial, NULL);

    mcd.doc = doc;
        mcd.op = opCuttingPath;
        mcd.flags = MODELINGCOMMANDFLAGS_CREATEUNDO;
        if (!SendModelingCommand(MCOMMAND_MAKEEDITABLE, mcd)) return FALSE;

    DrawViews(DRAWFLAGS_NO_THREAD);

    break;



  • On 09/05/2013 at 09:25, xxxxxxxx wrote:

    As I said, there is your problem.  You are 'making editable' the objects that you add to the document and then reusing them for parenting new objects as if the pointer points to the same object afterwards.
    _<_t_>_
    MCOMMAND_MAKEEDITABLE
    |
    Make editable (returns object)
    <_<_t_>_This command returns a 'new' object.  I do not remember if it replaces the document object directly or you have to insert it into the document, but you then proceed to create new objects that are dependent upon possibly non-existent objects (having been replaced by the SendModelingCommand(MCOMMANd_MAKEEDITABLE).  Your first course of action is to see if the original object is replaced in the document by the made-editable object (just do one MCOMMAND_MAKEEDITABLE and note the results in the document0.  If so, get the new object for parenting of the subsequent new objects you allocate.  The new object should be in AtomArray* arr or AtomArray* result in the ModelingCommandData structure.  Use that instead of the old object that you made editable to avoid the crashing.



  • On 09/05/2013 at 10:42, xxxxxxxx wrote:

      
    //-------------------------------------------------------------------------------------------------  
    // Caller owns returning object !!!  
    // Use PolygonObject::Free(poly); on the end !!!  
    // or better call it like this:  
    //  AutoFree<BaseObject> poly( GetEditableObject(op,doc) );  
    inline BaseObject *GetEditableObject(BaseObject *obj, BaseDocument *doc = NULL)  
    {  
      // Get polygon object  
      ModelingCommandData md1;   
      md1.op = obj;   
      if(doc) md1.doc = doc;  
      else md1.doc = obj->GetDocument();  
      if (!SendModelingCommand(MCOMMAND_MAKEEDITABLE, md1)){ return NULL; }  
      
      BaseObject *poly = static_cast<BaseObject*>(md1.result->GetIndex(0)); if (!poly) return NULL;  
      return poly;  
    }  
    


  • On 10/05/2013 at 16:42, xxxxxxxx wrote:

    Thanks for clearing that up. I suspected something like that. As a rookie it's sometimes not quite clear what to search for in the SDK docs.

    It works if I call 'GetEditableObject' like this:
    opMaterial = GetEditableObject(op,doc);

    If I try to use
    AutoFree<BaseObject> poly( GetEditableObject(op,doc) );
    it won't compile because of scope issues (it gets called in a Switch/Case block)
    can I use AutoAlloc() to create my objects in the first place?

    Thanks so much for your help.

    Peter


Log in to reply