Navigation

 ·   Wiki Home
 ·   Categories
 ·   Title List
 ·   Uncategorized Pages
 ·   Random Page
 ·   Recent Changes
 ·   RSS
 ·   Atom
 ·   What Links Here

Search:

 

Create or Find Page:

 

View Python: Creating objects and modifying parameters

First of all, in this article, I will distinguish between objects in Cinema 4D’s Object-manager, and instances that are objects in a programming-languages context.

Objects in the Object-Manager of Cinema 4D are represented by instances of the c4d.BaseObject class. It is a subclass of c4d.BaseList2D class which basically implements the hierarchial arranged structure you can find very often in Cinema 4D. (Object-Manager, Layer-Channel, Renderoptions, etc.) Subclassing allows us to use methods implemented in a parent-class in it’s subclass. Any method that c4d.BaseList2D implements can be used from an instance of c4d.BaseObject.

Modifying an object’s parameters

Every instance of c4d.BaseList2D owns a reference to an object of the c4d.BaseContainer class. It is basically is an associative array containg all the values of the parameters an object has in the Attribute-Manager.

1. Accessing the BaseContainer and using it’s methods

Modifieng an object’s parameter is simple in that case. First, we get the c4d.BaseContainer instance. Next, we take the ID of the parameter we want to change and change the value in the container. That’s all.

Make sure that a cube-object is selected in the Object-manager before running the script in the Script-manager.

import c4d
bc = op.GetDataInstance()
bc.SetVector(c4d.PRIM_CUBE_LEN, c4d.Vector(500, 100, 20))

Note, c4d.BaseContainer.GetDataInstance() returns the original container, NOT A COPY. Modifieng this container will directly modify the object’s parameters. If you want to get a copy, use c4d.BaseObject.GetData()

2. Accessing the BaseContainer and using subscripting

There is a more convenient way, an alternative of using methods like SetVector, SetReal, etc. The trick is called subscripting using the bracket [] syntax.

import c4d
bc = op.GetDataInstance()
bc[c4d.PRIM_CUBE_LEN] = c4d.Vector(500, 100, 20)



3. Using subscripting directly on the object

The third and last way to modify an object’s parameters is to use the subscripting syntax directly on the object itself, which you will most likely see in most of the Py4D codes available.

import c4d
op[c4d.PRIM_CUBE_LEN] = c4d.Vector(500, 100, 20)

 

But what’s better?

Basically, you can say: “The more inconvenient, the more efficient.” which is normal in computer-programming. Adding more and more easy-of-use to anything requires something being wrapped that will produce overhead in doing what it is supposed to do.
We can say that, method #1 is the fastest way, method #2 in between and method #3 the slowest. But why is this?

Imagine you are an automated glass-container that seperates different types of glass from each other. Method #1 wouldn’t you require to think about anything, you are being told where to put the incoming glass, and that’s fine. Method #2, in contrast, doesn’t tell you what type of glass is incoming, you have to check where to put it, which requires a little more time. Finally, method #3 would be like giving the glass to the attendant of the dump because someone’s in a hurry, who then gives the glass to you, and you are executing method #2.


Creating new objects in Python

Fine, now that we’ve discussed about how to modify and object’s parameters, we can go on on how to create an object from Python.
There are several way of doing so.

1. Create an all new object from scratch

As already said in the first section, every object in the Object-manager is an instance of the c4d.BaseObject<7span> class. Why not creating an instance of this class directly? It’s simple. The constructor takes a single argument that defines the type of object that should be constructed.

import c4d
op = c4d.BaseObject(c4d.Ocube)

Hm, got an object now. But what to do with it? There are different ways of inserting an object into a document. You can either use the current document or another object to do so.

import c4d
op = c4d.BaseObject(c4d.Ocube)
doc.InsertObject(op)
# .. or ..
op.InsertBefore(doc.GetFirstObject())

Both ways end in the same result, but using the first one has a big advantage. If doc.GetFirstObject() results in None, that is when no object is in the document, the call will boil down to op.InsertBefore(None) which will cause an exception.

2. Cloning an existing object

Test the following script only if you can accept Cinema 4D to crash!

op = doc.GetFirstObject()
op.InsertUnder(op)

Here you got one of the simplest examples of how to crash Cinema 4D. But can you imagine of why this would cause a crash?
It is simple, actually. With op you have the reference to the real internal instance of the first object in the OM. Inserting an object under it’s exactly same instance will cause an infinite loop.

  • MyUniqueCube
    • MyUniqueCube
      • MyUniqueCube
        • [and so on ... ]


What do we learn from this? DO NEVER INSERT AN OBJECT THAT IS ALREADY STORED SOMEWHERE ELSE.
You can avoid this by creating a copy of the object.

op = doc.GetFirstObject()
op.InsertUnder(op.GetClone())

Category:Scripting

Categories: