Hey @Madara,

in short, a Python generator object is not meant to generate splines. You can collapse the cache of your constructed spline and return its LineObject cache instead of the spline itself. For an example, see [1]. In your case that would be connect_obj. This will work in the sense that the generator cache will be then like a SplineObject cache and when you 'Current State to Object' your generator, it will behave like a spline and give you the interpolated editable linear spline and not a spline generator.

However, spline snapping not only inspects caches, but also checks if OBJECT_ISSPLINE is true. So, you cannot bamboozle it by faking a SplineObject cache. You will have to implement a proper spline plugin for what you want to do, as you can overwrite there GetContour

Cheers,
Ferdinand

PS: Your code contains multiple elements that can crash Cinema 4D and/or corrupt the loaded document. Specifically, these sections:

if link_clone: #Parametric object pobj = u.SendModelingCommand( command = c4d.MCOMMAND_CURRENTSTATETOOBJECT, list = [connect_obj], mode = c4d.MODELINGCOMMANDMODE_ALL, doc = op.GetMain()) connect_obj = pobj[0] ... offspline = u.SendModelingCommand( c4d.MCOMMAND_SPLINE_CREATEOUTLINE, [connect_obj], c4d.MODELINGCOMMANDMODE_ALL, bc=settings, doc=doc)

A Python generator's main() function is subject to the threading restrictions of Cinema 4D because it is just a wrapper for ObjectData.GetVirtualObjects. Executing SendModelingCommand in a threaded context is fine, but you cannot do it on the active document (both doc and op.GetDocument() are the active document). This is here even worsened by the fact that that the objects in list are not actually part of the document you pass as doc.

To circumvent that you must create your own document just as I have in [1] with temp. Find a more detailed example of that technique in smc_extrude_s26.py.

[1]

import c4d op: c4d.BaseObject # The Python generator object. def main() -> c4d.BaseObject: """ """ # A user data Boolean to toggle collapsing the cache of this generator. collapse: bool = op[c4d.ID_USERDATA, 1] spline: c4d.BaseObject = c4d.BaseObject(c4d.Osplinecircle) if not spline: return c4d.BaseObject(c4d.Onull) # Just return the circle spline itself when #collapse is false. if not collapse: return spline # Otherwise grab the LineObject cache of the spline and return a copy of it. temp: c4d.documents.BaseDocument = c4d.documents.BaseDocument() temp.InsertObject(spline) temp.ExecutePasses(c4d.threading.GeGetCurrentThread(), False, False, True, c4d.BUILDFLAGS_NONE) cache: c4d.LineObject | None = spline.GetCache() if not isinstance(cache, c4d.LineObject): return c4d.BaseObject(c4d.Onull) return cache.GetClone(c4d.COPYFLAGS_NONE)