Wish / request: c4d.CallComand()

Dear SDK Team,

I would like to propose an idea for the c4d.CallComand()

I often call callcomand in my scripts on vast lists of objects in succession, which is not optimal. Therefore I would like to propose an optional Paramtere to pass a list to the callcomand to execute.

Similar to the utils.SendModelingCommand()

Why: Because the internal Callcomand is faster than any self programed solution in python only the overhead of reapeataly calling it hinders its full potential.

Things to be solved: What happens to a callcomand which already needs more than one object ... perhaps a list of lists ?

Hope I am not talking total nonsense here but I am as of right now already watching a 3 hour callcomand loop ... and it will probably take all day ... losing that overhead would shafe of more than minutes in my case ...

Yes I know I could learn C++ from zero and build a full solution but I think this is unrealistic in the short midterm. 😉

kind regards
mogh

Hello @mogh,

thank you for reaching out to us and for bringing your feature request forward. Unfortunately, it is very unlikely that we will ever implement something like this.

CallCommand() does nothing other than executing a CommandData plugin (internally we also use other interfaces, but that is the gist of it). It will also work with a plugin id of one of your own CommandData plugins for example. A CommandData plugin, or more specifically its Execute method, has no explicit inputs, only an implicit input, the argument doc which is passed to it by Cinema 4D upon execution. So, there is no meaningful way to pass an input, your list of objects, to a CallCommand() execution.

We could of course write a little wrapper which could for example change the object selection state of doc based on your list and the repeatedly pass that to Execute(). It is however unlikely that this would bring any significant execution speed improvements. In C++ you would just replace one overhead (the time it takes between CallCommand() and Execute() being invoked) with another one (doing all the document shuffling). And in Python it might yield very minor speed improvements, but the overhead of the Python bindings for 20,000 CallCommand() calls should be below one second (i.e, 50 µs per call). So, the performance which could be gained here is negligible. CallCommand() is also heavily being used internally, which further decreases the likelihood that we start shuffling things around there.

When I remember correctly, you were operating on some very heavy CAD data with tens of thousands of objects in a scene. Your proposed feature would not help you there, neither in Python nor in C++. Calling CallCommand() thousands of times in a row will take time, because that is not what the CommandData interface ever has been intended for. If you want these CAD-cleanup and merging operations on GBs of data to run fast, you will have to write the functions from the ground up in a multi-threaded manner in C++.

Cheers,
Ferdinand

Thanks @ferdinand for you explanation. I understand the problems and the unlikelihood of this idea.

On the topic anyway hence your recall my import data problem, Do you have an idea why huge imports are exponentially in behavior?
I have to log some statistics but my suspicion is that even tho the polycount per objects to connect is similar the more objects are in the doc the slower the callcomand is.

Could you take a peak at the code internally of Connect Objects + Delete ? or perhaps its the selection of objects ... anyway the behavior is from slow to fast as less objects to connect in the doc which feels weird ...

def select_children(mother, childrenlist):
    mother.SetBit(c4d.BIT_ACTIVE)
    for child in childrenlist:
        child.SetBit(c4d.BIT_ACTIVE)
c4d.CallCommand(16768, 16768) # Connect Objects + Delete

cheers mogh

Actually I wouldn't expect the actual CallCommand() to get slower itself. But C4D will get slower during such "import orgy". Not only, does the size of scene increase, but also the undo stack grows. And then you do a Connect and Delete (may I guess, you keep connecting to the same object over and over?), which if I remember correctly does also not behave too nicely with growing data sets (certainly not O(n), if remember correctly).
One would need to know your exact use case to say, if there are maybe faster ways to achieve the same. If you want, we can meet via Skype or so, to talk about your specific needs and maybe then I can suggest some improvements (or come to the conclusion that you are screwed...). Anyway, PM me, if you like.

I did some rudimentary logging of just my slection + callcomand and I cannot see a "slow" execution. So @a_block might have a hunch that its the doc passing / filesize / undo accumulation ...

and what makes the "exponetial" feeling even more is that the engineers put screws (small stuff) at the bottom of the tree

I only import one file at a time ... so my file size shrinks because I "connect" objects ....

Sorted by time logged to console (145 MB , 3.965.783 polys, 547 calls on Callcomand)
2022-03-03-Window_000064.png <- not all calls

anyway its late fresh mind tomorrow

cheers mogh

@a_block where is the PM system ? I can't find anything here in the forum ...

Sorry, my bad, different forum, different rules... I had forgotten, we do not have PMs in here.
Send me an email to "job AT andreasblock dot de".