This was a really quick JavaScript project that I made when I was a bit bored. I wrote it originally with Python, but I wanted to port it to JavaScript, so it is easy to use in browser or something.

It is render time estimator. Just type frames or frame range and average time how much it takes to render a single frame and then render time estimator calculates how long it takes to render whole sequence.

Time should be given in HH:mm:ss format.

Updated 17/11/2021
> Added support for multiple render times, separate values with comma and estimated render time is average of those values.
> Added history.

Render Time Estimator

Html, JavaScript

This is my first Python Field Object. With Selector Field, you can easily select items by typing their ID’s (e.g. 0, 10, 11, 25, 30 and so on). Selector Field supports also range selections which works by typing start ID and end ID e.g. 5-20, 49-99, 0-3 and so on.

Originally Selector Field is intended to use with MoGraph Effectors but it works also with polygon, edge and point selections and vertex maps.

There is three different ‘Input type’ systems: Single-Line, Multi-Line and Range Sliders. First two allows you to type ID’s and the last one allows you to select items with two sliders.

If you want to invert the selection, go to ‘Remapping’ tab and tick ‘Invert’ checkbox there.

Selector Field won’t update user interface if it does not have anything to process! You should first attach it to somewhere and then modify settings.

Updated 24/06/2020
> Updated – now it supports more than 400 items. N.B. large selections gets really slow! (Bad optimization)
Updated 17/09/2022
> Updated support for Cinema 4D R25 and newer (Python 3)

ar_field_selector_r21.c4d v2.0.0 (R21)
ar_field_selector_r25.c4d v2.1.1 (2023.1.2)

Cinema 4D, Field, MoGraph, Python

Lately I have worked a lot with alembic files that have point level animated geometry and once I had to attach objects to that PLA geometry. I figured out a couple different ways to do this (e.g. MoGraph Cloner or Contraint Tag) but my favorite solution is to use Xpresso and Python.

In this setup I’m taking three points from selected polygon. Then I’m creating vectors v1 and v2 from those points’ positions. Then vectors are used to generate orthogonal axes by using cross product.

import c4d
import math

def main():
    global Matrix

    v1 = Point1 - Point0
    v2 = Point2 - Point0

    m = c4d.Matrix()
    m.v1 = v1.GetNormalized()
    m.v3 = v1.Cross(v2).GetNormalized()
    m.v2 = m.v3.Cross(v1).GetNormalized() = Position

    Matrix = m


Cinema 4D, Python, Xpresso

This was a funny experiment. Sending MoGraph data from Cinema 4D to Novation Launchpad (the first version). I used Python Effector to send UDP packets to Processing and in Processing I used UDP library to read those packets and The MidiBus library to send MIDI messages to Launchpad.

Pads’ indexes starts from 0 and ends to 199. Every circle pad takes 8 indexes so in every row we add that amount to index value. Velocity value changes color and brightness of the pad but I did not have interest to find out what every single values from 0 to 127 did. In my setup I just mapped clone’s red color value (float 0.0-1.0) to MIDI velocity (integer 0-127). Mapping is done in Processing sketch.

Python Effector from this experiment can now be used as a template for different setups to send MoGraph data to other softwares. Data is transfered with UDP packets in strings. So Cinema 4D is sending constantly long strings and Processing sketch is listening those and unpacking those strings to something useful.

Python Effector code

import c4d
import socket
from c4d.modules import mograph as mo

def initSocket():
    global s
    global server
    host = '' # Host address
    port = 5001 # Port
    server = ('', 5006) # Server address and server port
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Initialize socket
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Re-use socket
    s.bind((host, port)) # Bind
    return s, server

initSocket() # Create a socket

def main():
    md = mo.GeGetMoData(op) # Get MoData
    if md is None: return False # If no MoData return false
    cnt = md.GetCount() # Get clone count
    carr = md.GetArray(c4d.MODATA_COLOR) # Get color array
    message = "" # Initialize message string
    row = 0 # Initialize row integer
    for i in xrange(0, cnt): # Loop through clones
        if i != 0: # If not the first index
            if i % 8 == 0:
                row = row + 8 # Launchpad pad numbering
        color = carr[i] # Get clone's color
        index = (i+row) # Calculate pitch
        message += str(index) + "-" + str(color.x) + "," # Write message
    s.sendto(message, server) # Send message
    return True # Everything is fine

Processing sketch

import themidibus.*;

MidiBus myBus;
UDP udp;

String HOST = ""; //ip address
int PORT = 5006; //port
String receivedFromUDP = "0-0.0,1-0.0,2-0.0,3-0.0,4-0.0,5-0.0,6-0.0,7-0.0,16-0.0,17-0.0,18-0.0,19-0.0,20-0.0,21-0.0,22-0.0,23-0.0,32-0.0,33-0.0,34-0.0,35-0.0,36-0.0,37-0.0,38-0.0,39-0.0,48-0.0,49-0.0,50-0.0,51-0.0,52-0.0,53-0.0,54-0.0,55-0.0,64-0.0,65-0.0,66-0.0,67-0.0,68-0.0,69-0.0,70-0.0,71-0.0,80-0.0,81-0.0,82-0.0,83-0.0,84-0.0,85-0.0,86-0.0,87-0.0,96-0.0,97-0.0,98-0.0,99-0.0,100-0.0,101-0.0,102-0.0,103-0.0,112-0.0,113-0.0,114-0.0,115-0.0,116-0.0,117-0.0,118-0.0,119-0.0,"; // Example message

void setup() {
  size(400, 400); // Document size
  background(0); // Background color
  udp = new UDP(this, PORT, HOST); // Create a new UDP
  udp.listen(true); // Listen UDP
  //MidiBus.list(); // List all available Midi devices
  myBus = new MidiBus(this, 1, "Launchpad"); // Create a new MidiBus

void draw() {
  String[] list = split(receivedFromUDP, ','); // Create a list from a string  
  int channel = 0; // MIDI channel
  int number = 0;
  int value = 90;
  for (int i = 0; i < (list.length-1); i+=1) {
    String[] values = split(list[i], '-');
    int pitch = int(values[0]); // Pitch (pad)
    float m = map(float(values[1]), 0, 1, 0, 127); // Map values from 0-1 to 0-127
    int velocity = int(m); // Velocity (color)
    myBus.sendNoteOn(channel, pitch, velocity); // Set note on
  myBus.sendControllerChange(channel, number, value); // Send a controller change  

void receive(byte[] data, String HOST, int PORT) {
  String value = new String(data); // Recieved UDP message
  receivedFromUDP = value; // Assign message to global string

That’s that.

Cinema 4D, Experimental, MoGraph, Processing, Python

This Python Tag automatically adds effectors to MoGraph generator. Add this Python Tag to MoGraph generator. Put effectors under Null object and link that hierarchy to Python Tag. Now you can quickly add and change order of effectors without opening generator’s “Effectors” tab.

This Python Tag detects if object in the hierarchy is an effector.

ar_auto_add_effectors.c4d v1.1.1 (2023.1.2)

Cinema 4D, MoGraph, Python, Tag

When you render with Cinema 4D’s render queue, you get a XML-file where C4D puts useful data, this file is called a render log. It’s not very pleasing to read the raw XML-file, so I made a simple log viewer with HTML and JavaScript that views render logs more readable way.

There is an input field where you can just drag and drop your log-file and when you press “View Log”-button, the site converts XML-file to nice looking HTML code.

The log viewer does not upload or collect any kind of data to my server. It opens file straight in the browser using HTML5’s FileReader, so your log files stays private.

Try log viewer here: Cinema 4D Log Viewer v0.2 Beta

The current version is in beta and I’ll keep developing this project and adding new features. All feedback is welcome.

Updated 18/08/2019
> Added support for multiple files
> Rebuild with Bootstrap

Cinema 4D, Html, JavaScript

This was a fun little friday experiment. Transfering MoGraph data to Spline Data with Python Tag. I don’t know how useful it is, but it is fun to play with.

import c4d
from c4d import utils as u
from c4d.modules import mograph as mo

def main():
    clamp = op[c4d.ID_USERDATA,2] # User Data: 'Clamp'
    intrp = op[c4d.ID_USERDATA,3] # User Data: 'Interpolation'
    obj = op.GetObject() # Get object
    md = mo.GeGetMoData(obj) # Get MoData
    if md is None: return False # If there is no MoData, stop processing
    cnt = md.GetCount() # Get clone count
    marr = md.GetArray(c4d.MODATA_MATRIX) # Get MoData matrix
    spline = c4d.SplineData() # Initialize Spline Data
    for i in range(0, cnt):
        x = u.RangeMap(marr[i].off.x, 0, 100, 0, 1, clamp) # Calculate X position
        y = u.RangeMap(marr[i].off.y, 0, 100, 0, 1, clamp) # Calculate Y position
        spline.InsertKnot(x, y) # Insert new knot
        leftTangent = c4d.Vector(0, 0, 0) # Left tangent values
        rightTangent = c4d.Vector(0, 0, 0) # Right tangent values
        spline.SetKnot(i, c4d.Vector(x,y,0), 0, False, leftTangent, rightTangent, intrp) # Edit knot
    spline.DeleteKnot(spline.GetKnotCount()-1) # Remove some leftovers
    spline.DeleteKnot(spline.GetKnotCount()-1) # Yes, do it twice
    op[c4d.ID_USERDATA,1] = spline # Set spline data to user data

mograph_to_splinedata.c4d v1.0.1 (2023.1.2)

Cinema 4D, Experimental, MoGraph, Python, Tag

This effector randomizes position, scale and rotation with given values (fixed). You can change seed separately for position, scale and rotation. There are also global seed that changes all seeds. There is additive mode (‘Add’-checkbox) that adds random values to current state, otherwise values are overwrited.

Scale group has also ‘Uniform’-checkbox that scales clones uniformly, there is own input field for this. If this checkbox is ticked, you cant use X, Y or Z checkboxes.

ar_effector_fixed_random_psr.c4d v1.1.0 (2023.1.2)

Cinema 4D, Effector, MoGraph, Python

Here are two old Python Tags of mine, that toggles object’s visibility based on different rules. I have find them very useful when you want maximise clarity in your viewport.

Show Only If Active
First tag shows the object only if object is selected (i.e. active). Sometimes this is very helpful, if you have for example bunch of deformers under one object and you want to focus to tweak just one. Just apply this tag to every deformers and then deformer is only visible when it is selected.

import c4d
def main():
    obj = op.GetObject() # Get object
    if obj == doc.GetActiveObject(): # If object is active
        obj[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = 0 # Set 'Visible in Editor' to 'On'
    else: # Otherwise
        obj[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = 1 # Set 'Visible in Editor' to 'Off'


Show Only If Correct Camera
Second tag shows the object only if correct camera is active. There are also different options to modify how the tag operates.

import c4d
def main():
    bd = doc.GetActiveBaseDraw() # Get active base draw
    activeCam = bd.GetSceneCamera(doc) # Get active camera
    targetCam = op[c4d.ID_USERDATA,2] # UD: Assigned camera
    activeMode = op[c4d.ID_USERDATA,6] # UD: Active mode
    deactiveMode = op[c4d.ID_USERDATA,7] # UD: 
    render = op[c4d.ID_USERDATA,3] # UD: Affect Render Visibility
    obj = op.GetObject() # Get object
    if invert == False: # If invert is not ticked
        if activeCam == targetCam: # If active camera is same as target camera
            obj[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = mode # Set 'Visible in Editor' to mode
            if render: # If render is ticked
                obj[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = mode # Set 'Visible in Renderer' to mode
            obj[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = 1 # Set 'Visible in Editor' to 'Off'
            if render: # If render is ticked
                obj[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = 1 # Set 'Visible in Renderer' to 'Off'
    else: # Otherwise (inverted)
        if activeCam == targetCam: # If active camera is same as target camera
            obj[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = mode # Set 'Visible in Editor' to mode
            if render: # If render is ticked
                obj[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = mode # Set 'Visible in Renderer' to mode
            obj[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = 2 # Set 'Visible in Editor' to 'Off'
            if render: # If render is ticked
                obj[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = 2 # Set 'Visible in Renderer' to 'Off'

Updated 30/10/2022
> Semantic versioning

ar_tag_show only_if_correct_camera.c4d v1.0.1 (2023.1.2)

Cinema 4D, Python, Tag

This effector quantizes clone’s position, scale and rotation with user given steps. For example, if clone moves from pos.x 0 to pos.x 500 and quantize step is set to 50, the clone moves only when it’s pos.x value reaches value 50, 100, 150, 200 and so on.

The quantization formula looks like this:

step * math.floor(value / step)

When you are quantizing scale your should modify clone only with uniform scaling, otherwise you’ll get funky results with this version of effector.

ar_effector_quantize_psr.c4d v.1.1.1 (2023.1.2)

Cinema 4D, Effector, MoGraph, Python