View Full Version : Py4D Tutorials

09-03-2011, 10:20 PM
This thread is some kind of workshop. I'll add tutorials written by myself, step-by-step.

For the I-don't-know-anything-about-programming - beginners:
The best place to start is the Python Tutorial (http://docs.python.org/tutorial/index.html).
Python for Cinema 4D is Python, it is definitely an advantage to have basic knowledge about Python before starting with Py4D. Otherwise it's even harder for you to understand the documentation and to get started diving into the Cinema 4D API.
Of course, you can start learning it in Cinema 4D, too, but don't mess up what part is Python and what part is Cinema 4D. ;)

The list of tutorials:

* Facts about the Py4D interpreter and the C4D API (http://forums.cgsociety.org/showpost.php?p=7102612&postcount=2)
* How to use the Py4D documentation - Part 1 (Overview and Functions) (http://forums.cgsociety.org/showpost.php?p=7102638&postcount=3)
* How to use the Py4D documentation - Part 2 (Classes) (http://forums.cgsociety.org/showpost.php?p=7104600&postcount=8)
* The BaseList2D class
* Interacting with a Cinema 4D Scene: Objects, Tags and Materials
* Splines and PolygonObjects
* Setting up an environment to work with asynchronous dialogs
* Creating Dialogs programmatically
* Creating Dialogs with ResEdit
* Using UserAreas
* Modifying particles
* Creating images programmatically
* Command plugins
* Object and Tag Plugins

Linked titles are already online, others aren't written yet.
Please leave comments. Cheers

09-03-2011, 10:21 PM
Facts about the Py4D interpreter and the C4D API

Cinema 4D R12 and higher comes with a normal Python distribution.
It's the CPython 2.6 interpreter and is located under Cinema 4D RXX\resource\modules\python\res\.

What is what ?
The Cinema 4D API is basically a module for Python written in C++ and is only available during run-time.
This means, you could start the Python interpreter that is within the C4D installation, but you weren't be able to import the C4D module.

When you want to interact with Cinema 4D, you almost always need to import the Cinema 4D module.
import c4d
You could also import only a sub module:

from c4d import gui
but the main c4d-module contains important constants and IDs needed in many method- and function-calls.

The Py4D documentation (http://www.maxon.net/index.php?id=157&L=0) gives you information about the contents of the module. However,
the documentation is often hard to understand and does also contain a lot of issues and wrong documented parts. The next tutorial will show you how the documentation is used, in general. If you don't understand something in the docs or have questions because there's something not working, go to the plugincafe (http://plugincafe). Me and other experienced Python developers are always there to help you out. :)

Keep in mind that the documentation does not have many examples and requires to have experience with the C4D C++ docs or at least COFFEE, to understand the basic principles of Cinema 4D. You will for sure have to look up stuff in the C++ documentation, so download it as well.

Installing Setuptools
Unfortunately it doesn't come with setuptools (which provides the easy_install/er to install 3rd-party packages easily). Depending on your system:

- OSX: Download the tarball and use the setup.py with the Cinema 4D Python installation of osx
- Win32: Use the executable installer and refer to the Cinema 4D Python installation of win32
- Win64: Download ez-setup.py and execute it using the Cinema 4D Python installation of win64

Downloadlink: http://pypi.python.org/pypi/setuptools


09-03-2011, 11:18 PM
How to use the Py4D documentation - Part 1 (Overview and Functions)


The documentation about the C4D API provided by Maxon isn't actually the one of the yellow.
It's sometimes hard to understand, wrong documented or even parts are missing.

On the index-site, we can find this screen:

http://www7.pic-upload.de/thumb/04.09.11/lsus6e3j5zh1.png (http://www.pic-upload.de/view-11270876/01.png.html)

1. Extra information. (Tutorials, examples, etc.)
2. The actual documentation about Py4D

The top link is about the main module, the others are submodules.
Let's just click on the c4d-module documentation. What we'll find is a list of all classes and functions that are in the module. The indentation of the class-names show their inheritance.

http://www7.pic-upload.de/thumb/04.09.11/5bkmu8gu1rw.png (http://www.pic-upload.de/view-11270911/02.png.html)

Check out the functions first. Click on GetObjectName() for example. You'll jump directly to it's documentation.

http://www7.pic-upload.de/thumb/04.09.11/gwnqzdv1wt8o.png (http://www.pic-upload.de/view-11270924/03.png.html)

You can find a short description about what the functions does, what parameters is needs and what type and what exactly it returns. In this case, we must give the function a parameter that is an ID from the c4d module that represents an object. In the example from the docs, it's Ocube.
But how to use this function ? Simple:

import c4d
print c4d.GetObjectName(c4d.Osphere)link to proper code (http://pastebin.com/HQcLwMes)

Will print "Sphere" (if your language is EN) to the console. (Open the console under Python > Open Console)

Let's make this even more interesting. Jump right to the c4d.gui module and take a look at it's functions. Search for one called "MessageDialog" and click on it.

http://www7.pic-upload.de/thumb/04.09.11/8ajyu4x5u.png (http://www.pic-upload.de/view-11270955/04.png.html)

The documentation tells us, this function displays a dialog that shows us text we give it.
Now, what you might notice are the brackets around "type = GEMB_OK". This is a default argument and you don't have to specify it if you don't want to.
Let us combine this one with the GetObjectName() function. Open the scriptmanager and copy-paste this code:

import c4d
name = c4d.GetObjectName(c4d.Osphere)
c4d.gui.MessageDialog("The name of a sphere object in your language is: " + name)link to proper code (http://pastebin.com/agg2NPvd)

A dialog as follows opens:


Not very interesting though. Taking a look into the documentation of the MessageDialog function again, we can see the "type" parameter can take one of the following IDs as value:


Copy-paste this code into your scriptmanager and execute it:

import c4d
name = c4d.GetObjectName(c4d.Osphere)
text = "The name of a sphere object in your language is: " + name
text = text + "\nIs this right ?"
c4d.gui.MessageDialog(text, c4d.GEMB_YESNO)link to proper code (http://pastebin.com/A2TJjQ8M)

You can see, we now have 2 Buttons what show "Yes" and "No" ("Ja" and "Nein" are the corresponding german words).


But clicking on Yes or No does nothing more than closing the dialog. Again, taking a look further in the documentation of MessageDialog() we can see what it returns:


It's an integer that tells us what button was pressed. This enables us to react on what the user does.

Again, copy-paste and execute. Test it for both buttons, click Yes and then No.

import c4d
name = c4d.GetObjectName(c4d.Osphere)
text = "The name of a sphere object in your language is: " + name
text = text + "\nIs this right ?"
result = c4d.gui.MessageDialog(text, c4d.GEMB_YESNO)

if result == c4d.GEMB_R_YES:
c4d.gui.MessageDialog("Test successful.")
c4d.gui.MessageDialog("You should report this to Maxon !")link to proper code (http://pastebin.com/QZehBH3G)

Now, when you click on Yes, which means that you say the name of the Sphere object is right in your language, another MessageDialog opens and tells you that the test was succesfull.
Clicking on No leads to another dialog that asks you to contact Maxon about this issue.

Any Questions ? Post below !

09-03-2011, 11:52 PM
hi niklas,

thanks, this should be very helpful, but i wouldn't place your tuts here. it would get pretty darn long and convoluted before you know it. could you put them up on your website? or perhaps a friend could host?


09-04-2011, 12:53 PM
Thanks for this, look forward to the rest of the series :thumbsup:

09-05-2011, 05:46 PM
Very useful! Thank you!
More please :)

09-06-2011, 07:33 AM
Thanks for your introduction :-)



09-06-2011, 08:00 AM
How to use the Py4D documentation - Part 2 (Classes)


In this part of the tutorial we're taking a look at how classes are documented in the Py4D documentation.
Let's say we want to write a script that centers the axis of a polygon object. We've never done anything before with polygon objects, so we gonna start from scratch.

Open the script manager, insert any polygon object into your scene and execute the following code:

print type(op)
op is the currently selected object in the OM.
The built-in function type will gives us the class of an instance.
It outputs "<type 'c4d.PolygonObject'>". Interesting. Take a look into the Py4D documentation an search for "PolygonObject".
After clicking the appropriate result (should be at the bottom: c4d.PolygonObject), we see the documentation of the PolygonObject class.
The first part is the Definition. It's a list of all public methods the class provides.

http://www7.pic-upload.de/thumb/06.09.11/cb6q3g9yv7.png (http://www.pic-upload.de/view-11296772/01.png.html)

To solve our task, we need to get the position of all points of the object in order to calculate the center. But there is nothing about points in this list !
Fortunately, PolygonObject inherits from PointObject ! This means, PolygonObject has got all methods from the PointObject class, but does also implement new methods and behaviours.
(Of course, a PointObject (a spline) isn't actually a polygon object, is it ? But a polygon object has points, just like a spline)

Take a look into the PointObject's class documentation. Here we can find our methods with "point" in their names, yippey !
PointObject.GetAllPoints() sounds very promising, doesn't it ?

Ok, let's start writing our script step by step.
In the documentation, we can see that PolygonObject.GetAllPoints() returns a list of points (vectors).


You can find documentation about the list class here (http://docs.python.org/tutorial/datastructures.html#more-on-lists).

import c4d

def main():
points = op.GetAllPoints()


Execute the script. Take a look into your console. Did something happen ? If yes, you forgot to select an object, you selected multiple objects or the selected object is not a polygon object and received a traceback message. Let's fix this issue.

import c4d
from c4d.gui import MessageDialog

def main():
if not op:
# op is None, no selected object or multiple ones
MessageDialog("You must select exactly one object.")
if not isinstance(op, c4d.PointObject):
# selected object is not a PointObject, we cannot center the axis
MessageDialog("You must select either a spline or polygon object")

points = op.GetAllPoints()


Now we're safe that the script will only run when the user selects an object we can work with, otherwise we'll tell the user about the problem.

We now have to find out the dimensions of the object in order to find it's center.
We'll create a function for this.

import c4d
from c4d.gui import MessageDialog
from copy import copy

def find_bounds(points):
Returns the center of the vectors 'points'.
min = copy(points[0])
max = copy(min)

for p in points:
if p.x < min.x: min.x = p.x
if p.x > max.x: max.x = p.x

if p.y < min.y: min.y = p.y
if p.y > max.y: max.y = p.y

if p.z < min.z: min.z = p.z
if p.z > max.z: max.z = p.z

return min, max

def main():
# ...

Now that we have the dimensions of our object, we can calculate the center. The vector class allows us to add, subtrate, multiply and even divide with vectors.

# ...
def main():
# ...
m1, m2 = find_bounds(points)
center = (m1 + m2) / 2

After we could find the center of the object, we need to substrate the "center" variable to every point-position. (this is what vector-maths defines. :P )
We also don't create a new list of points, we can use the old one. Just set the value back to the list.
Also, to keep the points' global position and only the axis moves to the center of the points, we add "center" to it.

# ...
pos = op.GetAbsPos() # the object's position
for i, p in enumerate(points):
points[i] = p - center

pos = pos + center # add the "center" to the position

"GetAbsPos()" is a method defined in the c4d.BaseObject class.

Now we only need to set the object's position and it's points. We also need to tell the object and cinema that something has changed. But first, we'll add undo-actions so you can press undo and what just happened will be made undone. ;)
# ...

# add an undo action to cinema, will apply for position and for the points
doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)

# set the data to the object
# update the object and cinema

Check out this link (http://pastebin.de/18659) to the full and proper code.
Any Questions ? Post below !

09-06-2011, 08:02 AM
Thanks for the feedback guys. :)
I hope I can fill the whole list as school starts in a week. Anyway, soccerrprp, good idea. I'll try to find a server were I can upload the tuts when I have finished them. (I think I'll post the tuts often enough so the thread will keep being alive until the tutorials have fnished.)


09-06-2011, 03:03 PM

how about creating your own blog at blogger or something?



10-25-2011, 07:24 PM
Unfortunately I am really busy with school at the moment. I will have holidays the next week and time to get a little bit further with those tutorials.


at²software (http://www.at2-software.com/) was as friendly and made me webspace and a domain available for those tutorials.
However, I must also first create a website. It will be located at http://www.niklasrosenstein.de/

Thanks for your understanding. Cheers, and have nice coding.

CGTalk Moderation
10-25-2011, 07:24 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.