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.