Heavy function freezes Cinema



  • On 14/01/2013 at 07:40, xxxxxxxx wrote:

    Hi!
    I'm currently working on a script, that executes a function from a C++ Python extension inside a loop. I didn't write that extension and have no access to the sourcecode whatsoever.

    My script goes something like this:

      
    for i in xrange(10) :  
      print "Currently rendering superslow function nr. ",i  
      superslow.function(i) # Runs for a couple of seconds  
    

    The function involves some heavy rendering, so it is pretty slow. The problem I'm having, is that C4D freezes up after the first couple of iterations and not even the print statement is evaluated until the script is completely finished.
    This has a couple of bad side effects, namely Windows recognizing Cinema 4D as unresponsive (If I click somewhere it asks if I want to close the application) and a lack of feedback on the current progress of the script.
    While I understand the unresponsiveness of the application during the processing of the function, I don't really get, why the print statements are not evaluated after each function is finished.

    Is there something like a "wakeup call" for Cinema that basically tells it to first give the system a sign of life, before it plunges into the next heavy calculation or would calling the function from a thread solve my problem?

    Thanks for your help!



  • On 14/01/2013 at 07:47, xxxxxxxx wrote:

    I have a few intensive looping scripts/plugs as well that
    put Cinema into unresponsness (spining ball OSX).
    However Cinema -is- working, so in each for loop
    I listen to the ESC key, this way I can get out of the loop
    just by holding the ESC down for a bit.

    Cheers
    Lennart



  • On 14/01/2013 at 08:05, xxxxxxxx wrote:

    Yes, the script definitely works, but it would be still nice to have some information on the current progress. Also, having Cinema completely locked up and looking like it's on the brink of crashing is not as "elegant" as I'd like it to be. ;)



  • On 14/01/2013 at 08:15, xxxxxxxx wrote:

    I do put a progress bar and Text info (like frame or something) into the loop.
    There are some native functions that also do this lock up, so that's the way it is
    to the best of my knowledge.
    Lately some of them (baking stuff) have got a progress pop up to be able to bail out.



  • On 14/01/2013 at 08:36, xxxxxxxx wrote:

    Take a look at the c4d.threading or threading module and see i you can
    make your operations asynchronous. This, however, is not recommended
    from the script manager. You should go for a CommandData plugin then.

    Best,
    Niklas



  • On 14/01/2013 at 09:17, xxxxxxxx wrote:

    I already had a progress bar in the script, but it didn't help either. There doesn't seem to be anything that can get Cinema to snap back into normal mode until the script is finished.

    @ Niklas: I have just read your last thread on threading here in the forum (Unintentional pun ;)). The problem with this is, that I'd have to wait around for the thread to be finished before I can proceed to the next iteration of the loop. Wouldn't this make it pointless to start the thread in the first place? Have you ever achieved something similar in a CommandData plugin?



  • On 14/01/2013 at 15:14, xxxxxxxx wrote:

    Hi Sparkle,

    You don't have to run each iteration seperated asynchronously, but you can
    make the for-loop asynchronous. You just need to ensure that you will be
    able to stop the work that is being done asynchronous. The ideal would be
    a dialog that lets the user run and stop the work.

    The following is not 100% full functional code as some symbols are not
    declared. The dialog class only serves a purpose for demonstrating the
    theory behind starting and stopping the work.

    import c4d

    def Dialog(c4d.gui.GeDialog) :

    def __init__(self) :
              super(Dialog, self).__init__()
              self.thread = Worker()

    def Command(self, id, msg) :
              if id == BTN_STARTWORK:
                  if self.thread.IsRunning() :
                      c4d.gui.MessageDialog("Already running")
                  else:
                      self.thread.Start()
              elif id == BTN_ENDWORK:
                  if self.thread.IsRunning() :
                      self.thread.End()
                  else:
                      c4d.gui.MessageDialog("Not running")

    return True

    class Worker(c4d.threading.C4DThread) :

    def Main(self) :
              for i in xrange(30) :
                  if self.TestBreak() :
                      break

    superheavy.function()

    Best,
    Niklas



  • On 15/01/2013 at 00:53, xxxxxxxx wrote:

    Thanks Niklas! The updating of the console works a little better using your approach. Unfortunately I need to be able to successively skip trough all the frames in the timeline during the threaded loop, which obviously doesn't work, when you are not allowed to make changes to C4D from within the thread.
    In any case, using threads is probably the way to go, but there is still a lot to figure out for me.

    *update*

    I just tried my (non threaded) script  in R14 and now every output is evaluated. Of course Cinema is still locked up by the script, but Windows doesn't detect it as unresponsive anymore.
    Kudos to the Maxon people to make a stable software even more stable. :)


Log in to reply