CSO from virtual objects



  • i only need the tracer object as a return value but if i do so the results are empty. so how do i get the cso from the tracer?
    a normal cso from the tracer itself is empty
    if i put all objects into a list the console told me that the object document don't match the document from the modeling command.

    import c4d
    #Welcome to the world of Python
    
    
    def createOutline(invert):
    	
    	bc = c4d.BaseContainer()
    	bc.SetData(c4d.MDATA_SPLINE_OUTLINE, op[c4d.ID_USERDATA,2] * invert)
    	bc.SetData(c4d.MDATA_SPLINE_OUTLINESEPARATE, True)
    	spline = op[c4d.ID_USERDATA,1]    
    	return c4d.utils.SendModelingCommand(command= c4d.MCOMMAND_SPLINE_CREATEOUTLINE,list= [spline],   mode= c4d.MODELINGCOMMANDMODE_ALL, bc = bc, doc        = doc)[0]
    
    
    
    
    def main():
    
    	ll = [] 
    	null = c4d.BaseObject(c4d.Onull)      
    	
    	spline = createOutline(-1)        
    	spline.InsertUnder(null) 
    	
    	
    	matrix = c4d.BaseObject(1018545)   
    	matrix.InsertUnder(spline)
    	matrix[c4d.ID_MG_MOTIONGENERATOR_MODE] = 0
    	matrix[c4d.MG_SPLINE_MODE] = 1
    	matrix[c4d.MG_SPLINE_STEP] = op[c4d.ID_USERDATA,3]
    	matrix [c4d.MG_OBJECT_LINK] = spline       
    	
    	
    	tracer = c4d.BaseObject(1018655)
    	tracer.InsertUnder(matrix)
    	inexclude = c4d.InExcludeData()
    	inexclude.InsertObject(matrix,1)    
    	tracer[c4d.MGTRACEROBJECT_OBJECTLIST] = inexclude
    	tracer[c4d.MGTRACEROBJECT_MODE] = 2
    	tracer[c4d.SPLINEOBJECT_TYPE] = 3
    	tracer[c4d.SPLINEOBJECT_SUB] = 6
    	tracer[c4d.SPLINEOBJECT_INTERPOLATION] = 1  
    	
    	return null


  • Hi @pyr I was not able to reproduce your issue. I attached my scene.

    On a side note, an this is important and maybe why I don't get any issue but I replaced spline = op[c4d.ID_USERDATA,1] by spline = op[c4d.ID_USERDATA,1].GetClone(c4d.COPYFLAGS_NONE). A Python Generator should never modify stuff outside of him. So When you Get the spline, you actually get the spline within the scene and you apply the modelingCommand to the object within the scene which is not correct and may crash Cinema 4D.

    0_1547459168000_cso-from-object.c4d

    If you have any question please, write explicitly in which context you are executing your python script and also in which Cinema 4D version.
    Cheers,
    Maxime



  • Hey,
    unfortunally this won't work in R18, and it gives me not the desired result.

    I updated my sourcecode a little bit and now i use a clone from my spline to create the outline

    import c4d
    #Welcome to the world of Python
    
    
    def createOutline(spline,invert):
    
    	bc = c4d.BaseContainer()
    	bc.SetData(c4d.MDATA_SPLINE_OUTLINE, op[c4d.ID_USERDATA,2] * invert)
    	bc.SetData(c4d.MDATA_SPLINE_OUTLINESEPARATE, True)
    	return c4d.utils.SendModelingCommand(command= c4d.MCOMMAND_SPLINE_CREATEOUTLINE,list= [spline],   mode= c4d.MODELINGCOMMANDMODE_ALL, bc = bc, doc        = doc)[0]
    
    def main():
    
    	spline = op[c4d.ID_USERDATA,1].GetClone()
    
    	null = c4d.BaseObject(c4d.Onull)
    
    	newSpline = createOutline(spline,-1)
    	newSpline.InsertUnder(null)
    
    	matrix = c4d.BaseObject(1018545)
    	matrix.InsertUnder(newSpline)
    	matrix[c4d.ID_MG_MOTIONGENERATOR_MODE] = 0
    	matrix[c4d.MG_SPLINE_MODE] = 1
    	matrix[c4d.MG_SPLINE_STEP] = op[c4d.ID_USERDATA,3]
    	matrix [c4d.MG_OBJECT_LINK] = newSpline
    
    	tracer = c4d.BaseObject(1018655)
    	tracer.InsertUnder(matrix)
    	inexclude = c4d.InExcludeData()
    	inexclude.InsertObject(matrix,1)
    	tracer[c4d.MGTRACEROBJECT_OBJECTLIST] = inexclude
    	tracer[c4d.MGTRACEROBJECT_MODE] = 2
    	tracer[c4d.SPLINEOBJECT_TYPE] = 3
    	tracer[c4d.SPLINEOBJECT_SUB] = 6
    	tracer[c4d.SPLINEOBJECT_INTERPOLATION] = 1
    
    	return tracer #not alive
    

    i also uploaded a scenefile:
    0_1547554705314_test.c4d

    my plan is to return only the tracer as an spline object to the scene all other objects are only helpers to get the correct shape from the source spline.



  • Ok, another try:

    i actually don't need the matrix and the tracer if i use a spline help and create a new spline object it works like a sharm.

    sampleSpline = c4d.SplineObject(samples,c4d.SPLINETYPE_BSPLINE)
    newPos = []
    for i in range(0,samples):
    	newPos.append(sh.GetPosition(sh.GetOffsetFromReal(i*step),0,realoffset = True,smooth =True))
    sampleSpline.SetAllPoints(newPos)
    sampleSpline.ResizeObject(samples,1)
    sampleSpline.SetSegment(0,samples,True)
    

    sh is a splinehelp from my spline offset, the only thing that bothers me is that the close segment seems to be ignored.

    also a solution for the tracer based solution would be great

    sampleSpline[c4d.SPLINEOBJECT_CLOSED] = True #close the spline



  • Hey @pyr, the tracer object is inserted, only under the null object, which is stored nowhere. That means at the end of the function, the Python Garbage collect actually free memory and all useless stuff it doesn't need anymore. And since the null which holds everything is stored nowhere else, the null is deleted and all its children even your tracer.
    That's lead to return a no-valid BaseObject.

    So the best way is to get a clone (aka object not inside any hierarchy) from a cache of the Tracer.

    With that's said there is no way to make the Python Generator returning a spline since it's not registered with OBJECT_ISSPLINE flag. So the only way will be to make a plugin. Here the code it's already looking very nice! Nice idea indead! 😄

    import c4d, os
    
    PYOUTLINE_ID  = 1000001  #Plugin ID
    
    class Ooutline(c4d.plugins.ObjectData):
    
        def createOutline(self, spline, invert):
    
            bc = c4d.BaseContainer()
            bc.SetData(c4d.MDATA_SPLINE_OUTLINE, invert)
            bc.SetData(c4d.MDATA_SPLINE_OUTLINESEPARATE, True)
            res = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_SPLINE_CREATEOUTLINE,
                                                list=[spline],
                                                mode=c4d.MODELINGCOMMANDMODE_ALL,
                                                bc=bc)
            if not res:
                return False
    
            return res[0]
    
        def GetContour(self, op, doc, lod, bt):
            # Get a clone of the spline
            spline = op[c4d.ID_USERDATA,1].GetClone()
    
            # Create a null used to define our hierarchy
            null = c4d.BaseObject(c4d.Onull)
    
            # Execute the CreateOutline Function in the created document.
            newSpline = self.createOutline(spline, op[c4d.ID_USERDATA,2] * -1)
            if not newSpline: return
    
            # Insert it into the Tracer and set up a hierarchy to get things done
            newSpline.InsertUnder(null)
    
            matrix = c4d.BaseObject(1018545)
            matrix.InsertUnder(newSpline)
            matrix[c4d.ID_MG_MOTIONGENERATOR_MODE] = 0
            matrix[c4d.MG_SPLINE_MODE] = 1
            matrix[c4d.MG_SPLINE_STEP] = op[c4d.ID_USERDATA,3]
            matrix [c4d.MG_OBJECT_LINK] = newSpline
    
            tracer = c4d.BaseObject(1018655)
            tracer.InsertUnder(matrix)
            inexclude = c4d.InExcludeData()
            inexclude.InsertObject(matrix,1)
            tracer[c4d.MGTRACEROBJECT_OBJECTLIST] = inexclude
            tracer[c4d.MGTRACEROBJECT_MODE] = 2
            tracer[c4d.SPLINEOBJECT_TYPE] = 3
            tracer[c4d.SPLINEOBJECT_SUB] = 6
            tracer[c4d.SPLINEOBJECT_INTERPOLATION] = 1
    
            # Create a temporary document to compute the cache of the tracer
            workDoc = c4d.documents.BaseDocument()
            workDoc.InsertObject(null)
            workDoc.ExecutePasses(bt, False, False, True, c4d.BUILDFLAGS_EXPORT)
    
            # Get the SplineObject from the tracer cache
            tracerSpline = tracer.GetCache()
            if not tracerSpline: return
            
            outSpline = tracerSpline.GetClone()
    
            # Close the spline
            outSpline[c4d.SPLINEOBJECT_CLOSED] = True
            
            return outSpline
    
    
    if __name__ == "__main__":
        bmp = c4d.bitmaps.BaseBitmap()
        dir, file = os.path.split(__file__)
        fn = os.path.join(dir, "res", "icon.tif")
        bmp.InitWith(fn)
        result          = c4d.plugins.RegisterObjectPlugin(
            id          = PYOUTLINE_ID, 
            str         = "Test", 
            g           = Ooutline, 
            description = "Ooutline", 
            info        = c4d.OBJECT_GENERATOR | c4d.OBJECT_ISSPLINE, 
            icon        = None)
    

    Very Cool
    Cheers,
    Maxime.


Log in to reply