How it was built
The bridge was built in one long session: tested live in both apps at every step, with plenty of dead ends. These are the main steps, including the ones that broke. Orange dots mark problems.
-
"Is a bridge even possible?"
Both apps can be scripted (Python in Cinema 4D, JavaScript in Cavalry), so the options were file exchange, a person in the loop, or a live socket. Cavalry's documentation showed a built-in
WebServerandWebClient, so the live route looked possible. -
Cavalry as the server: a freeze, then silence
A first test started Cavalry's
Lesson: the real cause turned out to be a security prompt (see below), but reversing the design made the bridge simpler and easier to test anyway.WebServerfrom an automation script. Cinema 4D could reach it in 1–4 ms, but only vialocalhost/IPv6 (127.0.0.1timed out), and Cavalry itself froze and had to be force-closed. From a proper script window,listen()then never opened the port at all. -
Reversed: Cinema 4D serves, Cavalry polls
A Python tag in Cinema 4D now runs a small HTTP server and publishes what the active camera sees. Cavalry polls it with a
TimerandWebClient, which Cavalry's docs recommend for polling web APIs. A fetch took 18 ms on the first try. -
Nothing arrived, but no errors either
The script window made no requests at all. The cause was Cavalry asking "…makes Web API calls. Do you trust this script?" when it opens: until you trust a script, its network calls quietly do nothing. Once trusted, cubes animated in C4D moved Cavalry layers to matching positions and rotations.
Lesson: the install guide now mentions the trust prompt first. -
Cavalry shapes to C4D splines
Any Cavalry shape (text, star, duplicator) can be turned into points by making a temporary editable copy and reading its path in world space. One catch: making that copy hides the original layer, so the bridge restores its visibility afterwards.
-
Ellipses looked boxy
Sampling showed C4D's curve bulging outwards. C4D's own Circle has tangents of 41.4 for radius 100, where a standard Bézier handle is 55.2: C4D tangents are ¾ as long. With that scaling the ellipse matched the true curve to within 0.01 units.
-
From Python Generator to a real spline object
The first receiver was a Python Generator, but Extrude and Sweep need a true spline. The bridge became a proper plugin with its own spline object. The first version drew everything 3× too large and eventually froze C4D: its two setting IDs (1000 and 1001) clashed with the IDs of C4D's built-in spline settings, so Scale was reading the Intermediate Points value. Moving them to 10000+ fixed both.
Lesson: when a plugin includes C4D's own spline settings, keep its setting IDs well away from theirs. -
One object per send, saved in the scene
At first every send replaced the same object, and the shapes only lived in memory. Now each send creates its own Cavalry Spline that stores its shapes inside the object, so they survive saving and reopening the scene. The object is created on C4D's main thread, which the server notifies when shapes arrive.
-
Position, rotation and scale animation
Cavalry's keyframes give values and easing names, but no handles. The bridge samples the motion and fits Bézier handles to it, length as well as height. With handle length fixed at a third, Slow In/Out fell back to keys on every frame; letting the length vary brought every ease back to its original two keys.
-
Phantom duplicates in Cavalry
During the C4D → Cavalry tests, each spline suddenly had two Cavalry layers. Viewport captures render a temporary copy of the document, and the tag had published that copy's objects, whose IDs differ. The tag now publishes only from the active document.
-
An installer that finds both apps
First a batch file, then, as requested, a real
.exe. It's compiled with the C# compiler that comes with Windows, and all the files travel inside it. It finds each Cinema 4D version that has been started and Cavalry, and installs into their user folders without admin rights. The first build's window overlapped on a high-DPI display, so the layout now scales with the screen's DPI. -
1.1: connecting by itself, without freezing
Auto-connect looked like a simple retry loop, until a test showed a refused connection blocks Cavalry for about 2 seconds on Windows. Retrying would have stuttered Cavalry every few seconds whenever Cinema 4D was closed. Instead the plugin keeps a small presence file (port, process) while C4D runs, and Cavalry checks it instantly before connecting.
-
1.1: why the Scale tool did nothing
Tried live: the Scale tool grew a native Circle but left a Cavalry Spline untouched. Logging what Cinema 4D sends showed why. In Model mode it resizes parametric objects through their length settings (like Circle's Radius), and the Cavalry Spline only had a plain Scale multiplier. It now has Width and Height in scene units, and the Scale tool resizes it like a primitive.
-
1.1: folders, both ways
Sending a Cavalry group now rebuilds it in C4D as Nulls with every level's position, rotation, scale and pivot (and keyframes). The test group, rotated and scaled with an animated child, landed within 1 px of Cavalry at every frame checked. From C4D, linking a Null streams its whole hierarchy into Cavalry groups, following renames, moves and hiding live; deleted objects are hidden, never deleted.
-
1.2: a panel instead of scripts
In real use, sending from Cinema 4D was hard to find: it meant selecting objects and running a script, and User Scripts had grown three bridge entries (one current, two old copies). Now Extensions › Cavalry Bridge opens a panel with the connection status, one Send button and what last arrived. A first version had a list and five buttons; testing showed that selecting objects and clicking Send is all anyone wants. The plugin became a single file, and the installer removes the old scripts.
-
1.2: a busy console, and a quiet one
Cavalry's console filled with a request every 33 ms, even when nothing moved. Now Cinema 4D writes a state file only when something changes, and Cavalry just checks its date. One slip on the way: Cavalry's
writeToFilewon't replace a file unless told to, so the first heartbeat logged an error every two seconds. -
1.2: a Plane arrived as a circle
3D objects had no spline to send, so Cavalry drew a placeholder circle. Tracing the edges where front faces meet back faces gave jagged blobs: seams, poles and faces seen edge-on broke the loops. What works is plainer: fill every projected face into a grid, trace the filled area, then snap its corners back onto the mesh. Plane, Cone, Torus, Sphere, a rotated Cube and a Landscape now match the C4D view, holes included.
-
1.2: shapes missing in the Front view
Some objects reached Cavalry's layer list but never drew. Flat views (Front, Top…) place their camera anywhere, so objects could sit "behind" it, and the bridge skipped them. Only a perspective camera has a behind now.
-
1.2.1: "we lost the animation"
Keys from Cavalry stopped arriving. Sending the same group by hand showed both ends still worked: the Animation (PSR) box simply started unticked each time the window opened. It now starts ticked and remembers your choice.
-
1.2.1: animation the other way
The first idea was a snapshot layer per frame: 250 layers per object. Cavalry can key a shape's path instead (its
inputPath), even with a different point count on each key. So Cinema 4D steps through the preview range, records each object's outline on every frame, and Cavalry keys one layer per object. A turning cube and a moving circle matched the C4D view frame for frame. -
1.2.2: a flood of "Point UIDs" errors
Cavalry's console filled with "Error re-syncing Point UIDs on Animating Path". Cavalry pairs points from one path key to the next, and a turning cube's outline has a different number of points (sometimes of contours) on each frame. Now every frame is padded to the same layout: extra points are copies of existing ones, and a contour missing on a frame shrinks to a single point, so the shape on each frame stays exactly the same.
-
1.3: a 3D mode, measured rather than guessed
Cavalry's camera has a Zoom but no field of view, and its docs don't say which way its axes turn. So coloured dots were placed at known 3D positions, rendered through a camera at a range of settings, and located in the pictures. Zoom turned out to be the focal length in pixels, the camera looks down −Z, and layers and the camera turn in slightly different orders. With that, a moving C4D camera and rotated Rectangle, Circle, Text, Plane and Cube matched the C4D render within a pixel or two on every frame tested.





