Generator and Cloner

On 31/01/2013 at 14:32, xxxxxxxx wrote:

Hy there,

I created a spline cacher, which is a Python Generator object. It uses the GetContour(..) overwrite to return a spline. The spline gets created by a cache, which is read dependent on the documents time. The document I use is the one given as an argument to the GetContour(..) callback.

Now, this all works fine, except it can't be used in a cloner:

File "AoB-SplineCacher.pyp", line 328, in GetContour
  frame = doc.GetTime().GetFrame(doc.GetFps())
ReferenceError: The object 'c4d.documents.BaseDocument' is not alive.

How do I need to handle the document, so the Spline Generator will also work within a cloner?

Thank you,

On 01/02/2013 at 01:54, xxxxxxxx wrote:

Hi maxx,

This may be an issue with GetContour() because the document passed should be always valid.
I'll ask the developers if there's a special case if a generator is used in a cloner.

But it seems some calls return a valid document and others no. You can filter the dead document with:

if doc() is not None:
    print doc
    print "Dead document"

doc() invokes doc.__call__() (see the documentation of C4DAtom.__call__()) to know if the document is alive or not.

On 01/02/2013 at 09:08, xxxxxxxx wrote:

Hy Yannick,

thank you for the hint about testing the doc. The problem seems to go away, if I use the same logic in the GetVirtualObjects method. But then the splines can't be rendered by hair.

The cloning is not working, if I just check if the doc is alive. Anything else I could try?


On 01/02/2013 at 11:50, xxxxxxxx wrote:

The passed BaseDocument is NULL sometimes in C++ when the object is cloned in a Cloner
object. It works eg. for the Array-Object. That the passed document can be NULL is not stated in
the C++ docs, nor I think this is intended?

The Python issue might be due to the fact that the Python wrapper assumes the document may
never be NULL and wraps a NULL pointer being passed to Python.

I reported this as a bug.

 \* Copyright (C) 2013, Niklas Rosenstein
 \* All rights reserved.

#include <c4d.h>

class SplineCacheData : public ObjectData {


    static NodeData\* Alloc() { return gNew SplineCacheData; }

    /\* Overrides: ObjectData \*/

    SplineObject\* GetContour(BaseObject\* op, BaseDocument\* doc, Real lod,
            BaseThread\* bt) {
        if (!doc) {
            GeDebugOut("WARNING: No document passed on GetContour()");
            return NULL;
        LONG frame = doc->GetTime().GetFrame(doc->GetFps());
        String name = doc->GetDocumentName().GetString();

        String message = "GetContour() Document name: " +
                         doc->GetDocumentName().GetString() + ", frame: " +
        return NULL;


Bool PluginStart() {
    return RegisterObjectPlugin(
        1000002, "Spline Cache Test", OBJECT_ISSPLINE, SplineCacheData::Alloc,
        "", NULL, 0);

Bool PluginMessage(LONG type, void\*pData) {
    return TRUE;

void PluginEnd() {


On 02/02/2013 at 05:18, xxxxxxxx wrote:

Thanks Niklas, for the C++ Test-Case...


On 05/02/2013 at 03:39, xxxxxxxx wrote:


For each clone no document is passed to GetContour() and op.GetDocument() gives None.
But yes there's an issue in Python that it gives a dead document instead of a None.

I think you better get the current frame overriding Execute() and caching it.

On 13/02/2013 at 17:34, xxxxxxxx wrote:

Ok, will do so...