Create Cloner with Effector inside InExcludeData



  • On 17/12/2017 at 21:01, xxxxxxxx wrote:

    Hello Plugincafe!
    I'm want to create OBJECT_GENERATOR plugin which generates an object with InExcludeData which will contain arbitrary elements created also by OBJECT_GENERATOR.
       
    In this example, I'm creating Cloner object with a cube as its child and also random effector that I want to insert into effectors list.

      1. import c4d
      2.   
      3. def main() :
      4.     cloner = c4d.BaseObject(1018544)         #Cloner Generator
      5.     cube = c4d.BaseObject(c4d.Ocube)         #Primitive Cube
      6.     cube.InsertUnder(cloner)
      7.     randomEffector = c4d.BaseObject(1018643) #Random Effector
      8.     
      9.     inexclude = c4d.InExcludeData()
      10.     inexclude.InsertObject(randomEffector,1)
      11.     cloner[c4d.ID_MG_MOTIONGENERATOR_EFFECTORLIST] = inexclude
      12.     
      13.     return cloner
    
    

    Seems like I can place there only existing objects from active document. 
    I wonder if it's possible to generate a virtual document that will contain desired objects and place them into InExcludeData?
    Or maybe there is another way.



  • On 18/12/2017 at 01:37, xxxxxxxx wrote:

    Hello,

    in your code you are creating a random effector. But this random effector is NOT inserted into any hierarchy. This means nobody takes ownership and Pythons garbage collection will delete it. InsertObject() defines only a reference, it defines NO ownership.

    You could try to create a null object and make both the cloner and random effector child of that null object. This way the random effector would be part of the cache and thus the scene.

    best wishes,
    Sebastian



  • On 18/12/2017 at 01:44, xxxxxxxx wrote:

    I thought Python generator or OBJECT_GENERATOR plugin is some sort of null object that creates its own hierarchy inside some invisible component.

    Now it's clear. Thanks for the answer!

    Cheers! :)



  • On 18/12/2017 at 02:41, xxxxxxxx wrote:

    I tried this with Tracer object but it's not working.



  • On 18/12/2017 at 09:31, xxxxxxxx wrote:

    Hello,

    the MoGraph system is highly complex and interconnected. In this case the tracer object expects a full initiated matrix object. But this matrix object cannot be fully set up in the cache of a generator, only in a BaseDocument. With this generator the matrix object is re-created all over again and in this case that's bad.

    The only solution I see right now is to create a virtual BaseDocument, copy all needed objects into that BaseDocument, execute it and get he objects in their final state from that document.

    best wishes,
    Sebastian



  • On 18/12/2017 at 12:11, xxxxxxxx wrote:

    How can I create virtual document? are there any examples in docs?



  • On 18/12/2017 at 12:59, xxxxxxxx wrote:

    virtualDoc = c4d.documents.BaseDocument()
    virtualDoc.InsertObject(finalResult)
    

    Then Execute pass and in your data simply return a clone of your object, since object will be owned by your virtual (tempory,buffer) document and it will be free at the end of your scope, so all objects will be deleted that belong to this document will be deleted (aka object not alive).

    Hope its help ;)



  • On 18/12/2017 at 13:17, xxxxxxxx wrote:

    Thank you again :)
    I'm getting this error. Am I doing something wrong?

    Traceback (most recent call last) :
      File "'Python Generator'", line 4, in main
    AttributeError: 'module' object has no attribute 'BaseDocument'



  • On 18/12/2017 at 14:01, xxxxxxxx wrote:

    Sorry I'm on phone. Use c4d.documents.BaseDocument()



  • On 18/12/2017 at 14:17, xxxxxxxx wrote:

    Thank buddy! you helped as always :) Now I'm a bit closer to the desired result.

    just getting this error.
    ReferenceError: the object 'c4d.BaseObject' is not alive

      
      1. import c4d
      2.   
      3.   
    
    


  • On 18/12/2017 at 14:30, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    Then Execute pass and in your data simply return a clone of your object, since object will be owned by your virtual (tempory,buffer) document and it will be free at the end of your scope, so all objects that belong to this document will be deleted (aka object not alive).

    tracer[c4d.MGTRACEROBJECT_OBJECTLIST] = inexclude
      
    virtualDoc.ExecutePasses(c4d.threading.GeGetCurrentThread(), True, True, True, c4d.BUILDFLAGS_INTERNALRENDERER)
    finalResult = finalResult.GetClone()
    return finalResult
    

    Still on phone so there may still have some issues. if yes I will fix them tomorow.



  • On 18/12/2017 at 15:12, xxxxxxxx wrote:

    It's not working but at least I learned something new from your code :D
    I appreciate your help!
    Cheers! :)



  • On 19/12/2017 at 05:55, xxxxxxxx wrote:

    For me everythings is working fine

    import c4d
      
    def CurrentStateToOBject(doc, objList) :
        if not doc:
            raise ValueError("Document is not valid")
        
        returnValue = c4d.utils.SendModelingCommand(
             command = c4d.MCOMMAND_CURRENTSTATETOOBJECT,
             list = objList,
             mode=c4d.MODELINGCOMMANDMODE_ALL,
             bc=c4d.BaseContainer(),
             doc = doc)
        
        if returnValue:
            return returnValue
        else:
            return None
      
    def main() :
        # Create object
        virtualDoc = c4d.documents.BaseDocument()
        nullMaster = c4d.BaseObject(c4d.Onull)
        matrix = c4d.BaseObject(1018545)
        tracer = c4d.BaseObject(1018655)
        downClone = op.GetDown().GetClone()
        
        # Insert all objects
        virtualDoc.InsertObject(nullMaster)
        virtualDoc.InsertObject(downClone)
        matrix.InsertUnder(nullMaster)
        tracer.InsertUnder(nullMaster)
        
        # Set options
        matrix[c4d.ID_MG_MOTIONGENERATOR_MODE] = 0
        matrix[c4d.MG_OBJECT_LINK] = downClone
        
        tracer[c4d.MGTRACEROBJECT_MODE] = 2
        inexclude = c4d.InExcludeData()
        inexclude.InsertObject(matrix,15)
        tracer[c4d.MGTRACEROBJECT_OBJECTLIST] = inexclude
        
        virtualDoc.ExecutePasses(c4d.threading.GeGetCurrentThread(), True, True, True, c4d.BUILDFLAGS_INTERNALRENDERER)
      
        # Convert the Tracer to spline
        finalResult = CurrentStateToOBject(virtualDoc, [tracer])
        if finalResult is None: return
      
        # Insert spline under a null and return it
        nullFinal = c4d.BaseObject(c4d.Onull)
        finalResult[0].InsertUnder(nullFinal)
      
        return nullFinal
    

    LinkField can work only if both objects (the one that got the linkField and the one that is pointed by this link) are on the same document. If they are on different doc, c4d will automaticly set them the LinkField to None.
    Matrix object is just some matrix, not an object, basicly you need a cloner in top of a matrix object if you want to see some geometry. And of course make editable doesn't have so much sense into a matrix.



  • On 20/12/2017 at 19:44, xxxxxxxx wrote:

    Thanks gr4ph0s!
    It's working :)
    I learned lots of new stuff from these codes.


Log in to reply