Many thanks for your help and thorough explanations, Ferdinand! Much appreciated!
I'll go create a temp document and clones, and don't expect much more resistance from this particular issue. Thanks again, and have a happy holiday season! :)
Many thanks for your help and thorough explanations, Ferdinand! Much appreciated!
I'll go create a temp document and clones, and don't expect much more resistance from this particular issue. Thanks again, and have a happy holiday season! :)
Hi Ferdinand,
Thank you very much for your reply! I tried marking the post as a question but I guess I messed up. Will do better next time, and include code. :)
You are right - I am using the Python Generator object in Cinema 4D as a starting point, and my work is being done in main() or in functions being called from main().
In my case, I am building quite a few text objects that I need to lay out - a common case would be in the order of 180 - 250 of them. I'm basically building this script/plugin because I don't want to have to do that manually. :)
I really appreciate your code example. I will adapt this to my case and use it, seems straightforward enough. But I do have a few questions that I hope you could answer, to help me understand this better.
First question: Efficiency
In your example, everything is fairly simple. A spline in an extrude in a new document, execute the passes, get the info. Simple as can be. However, as mentioned, I can have MANY text objects, and I need to collect things like max width and max height out of all of them. What would be most efficient?
A. For each of the original text objects, create a temp document, insert a clone, execute cache pass, GetRad.
B. Create temp document only once, loop through original text objects, inserting a clone of them, executing cahce pass, GetRad.
C. Create temp document only once, dump all text object clones at once, execute cahce pass only once, loop through and GetRad.
My normal understanding of programming would lead me to believe option C is the most efficient. Only one document would be created, and we would execute the cache pass only once, albeit with more clones populated into the document. Resource wise it seems like a no-brainer, but I have no idea how C4D is coded and optimized. Would it even make a difference? Could option C make things worse in certain situations?
And additionally: Do I need to dispose of the temporary BaseDocument created when I am done, or will it simply disappear when the main() method completes and it presumably goes out of scope?
Second question: Recreating objects
As mentioned, my script is right now inside a Python Generator C4D object. It has some user data that acts as parameters for the objects being created. Some of these are simple layout parameters, such as horizontal and vertical "padding" that will be added on the respective sides of the bounding box of each object as part of my layout pass.
Changing these values in theory should only move the objects, not recreate them. However, there is no way Cinema 4D can know that - the only thing it knows about is my main() function. Whenever anything changes, it is called, which causes the whole structure to be recreated from scratch. This works, of course, but it means that if I pull on a slider, for each mouse movement main() is called and I generate ~200 objects. The user experience of this is... sluggish.
Is this an inherent limitation of the Python Generator C4D object? Or is there a way to say "If THESE parameters change, rerun all of main, but if only THESE parameters run, call another function that will just adjust the layout"?
Would this be the same if I moved from the Python Generator C4D object to a "full" python plugin? Could I then split the plugin instance into "functionality that generates geometry" and "functionality that arranges and lays out the already created geometry"?
Thank you very much for taking the time to help a n00b get going with this!
And a happy holiday season to everyone reading this. :)
Hi all,
I am new to programming in C4D, but not programming in general. Trying to wrap my head around an issue.
I have a Python Generator (which may at some point be turned into a full plugin, if it turns out to have any value) with a scripts that generates some text objects (fully extruded text objects, not just splines), depending on user data settings that the user can play with.
The objects are generated as expected, and become visible in the scene after my script returns the root object. However, the several text objects are all right on top of each other. I can set their relative position easily, using user data values, or calculated values, but I want to go one step further; I want to lay them out in relation to each other.
Which means that once they are generated, I need to get the bounding box of each of the text elements.
I have understood that I can get the size in three dimensions using something like
text.GetRad() * 2
However, this always returns an empty vector to me ([0,0,0]).
If I make a text object in the Object Manager (without making it editable), and access it in the console using something like Text.GetRad()
I get a vector accurately reporting the extents of the object, which I could use with The Math to do the calculations I need to.
This tells me that I don't need to worry about making them editable.. So didn't they really get a bounding box yet, even if I added them to the scene? Do I need to let Cinema 4D perform a run loop or something in order to process my objects?
I did see a web page mentioning doing something like this:
doc.ExecutePasses(None, True, True, True, c4d.BUILDFLAGS_INTERNALRENDERER)
But the only result of running that command is that Cinema 4D freezes for several minutes, so that feels like the wrong thing to do. :)
I've also seen some bits about getting a cached version - GetCache() returns "None" for me it seems. The text object has no children.
Is there a surefire way to get the bounding box of a text object inside the generator function, before it returns?
Thanks for any insights!