Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Write to C4D console in real time

    Cinema 4D SDK
    python
    5
    14
    2.5k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • I
      ivodow
      last edited by ivodow

      Here is a contrived minimal working example that demonstrates the issue. This is only intended to force the issue to occur. My actual code involves loading multiple >2 GB databases and building particle systems.

      Thank you.

      
      import c4d
      
      
      def long_process():
      
          fullpath = c4d.storage.LoadDialog( type = c4d.FILESELECTTYPE_IMAGES, title = "Select File > 10MB:" )
          if not fullpath:
              return
      
          for n in xrange( 10 ):
      
              cnt = 0
              with open( fullpath, 'rb') as f:
                  while( True ):
                      ansi_byte = f.read(1)
                      if( ansi_byte == b'' ):
                          break
                      if( cnt % 100000 == 0 ):
                          print( "Scanned " + str(cnt) + " bytes..." )
                      cnt += 1
      
              print( "Pass: " + str(n) )
      
      
      if __name__ == "__main__":
      
          c4d.CallCommand( 13957 )
      
          print( "Start" )
      
          long_process()
      
          print( "End" )
      
          c4d.EventAdd()
      
      1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand
        last edited by

        Hi,

        I might be misunderstanding something here, but your script looks like it is intended for the script manager. A script manager script is blocking (at least when implemented like this). Which means Cinema will only interpret the sys.stdout file object after the script has ended.

        To circumvent this, you could either write some kind of plugin (CommandData would be a good choice), use a dangling asynchronous dialog (which is not recommended) or (ab)use one of the scripting nodes (which probably isn't recommended either). Or you could use c4dpy, which will give you a more traditional interpreter environment.

        Cheers,
        zipit

        MAXON SDK Specialist
        developers.maxon.net

        1 Reply Last reply Reply Quote 0
        • r_giganteR
          r_gigante
          last edited by r_gigante

          hi @ivodow, I've reported this behavior to our developers and we'll look into it in the future cause we think there's room for improving it.

          For the time being consider it as a limitation.

          As an alternative you can consider having a look here where taking advantage of existing loggers is explained.

          Cheers, R

          M 1 Reply Last reply Reply Quote 0
          • indexofrefractionI
            indexofrefraction
            last edited by indexofrefraction

            @zipit

            Hi, could you elaborate a bit on these suggestions?
            I'm tackling with the same problem here from inside my CommandData plugin.

            1. open async dialog
            2. start "long processing" with occasional prints
              --> normal stdout (to console) does not show until the the processing ended
              --> stdout redirected to dialog. the dialog does not show until the processing ended (!)

            after opening a TYPE_ASYNC GeDialog, isOpen() returns True even if the window is not open, yet.
            How could one halt the script / wait until the dialog is REALLY open?
            Is there a way to deal with output buffering and get the printing flushed immediately?

            best, index

            1 Reply Last reply Reply Quote 0
            • ferdinandF
              ferdinand
              last edited by

              Hi,

              uhh, that would be a lot of guess work on my end with that description. It sounds a bit like you have something in place which blocks the main thread, but to pinpoint what exactly is going wrong in your case, you should open a new thread and post some code.

              To be clear: Unless you are constantly blocking the main thread, you should be able to print to the console without any problems.

              Cheers,
              zipit

              MAXON SDK Specialist
              developers.maxon.net

              1 Reply Last reply Reply Quote 0
              • indexofrefractionI
                indexofrefraction
                last edited by indexofrefraction

                @zipit said in Write to C4D console in real time:

                To be clear: Unless you are constantly blocking the main thread, you should be able to print to the console without any problems.

                yes, all is happening in the main thread, no threading involved.
                the user should not be able to change the hierarchy while processing.

                i for example traverse the whole object hierarchy and center all axes of objects and nulls.
                after that i print "xxx axes centered" and continue with other stuff
                the whole process can take 2-3 minutes and it would be nice to see the output "live" not just at the end.

                is there no possibility to trigger the console to output the buffered lines?

                1 Reply Last reply Reply Quote 0
                • indexofrefractionI
                  indexofrefraction
                  last edited by indexofrefraction

                  btw, also with threading the prints show only collected after the thread is finished

                  t = ThreadedCode()
                  t.Start()
                  t.Wait(True)
                  
                  class ThreadedCode(c4d.threading.C4DThread):
                  	def __init__(self):
                  		print "thread init"
                  	def Main(self):
                  		print "thread start",
                  		for i in range(0,100000):
                  			print i
                  		print "thread done"
                  
                  1 Reply Last reply Reply Quote 0
                  • M
                    m_adam @r_gigante
                    last edited by m_adam

                    Hi @indexofrefraction this is unfortunately not possible, at least not in python, since Python is always using the main thread, even if you have multiple threads, keep in mind this is not true parallelism more information read Python Programming/Threading. Since internally Python is executed on the main thread, this means the main thread will be in any case busy all the time of the execution. Due to some optimization done in R20 see (Disable default Right-Click Menu)[https://developers.maxon.net/forum/topic/11987/disable-default-right-click-menu] for more information. The console UI is not refreshed all the time when something new is popping but only when Draw events are processed.

                    Except recreating your own console UI, there is no workaround for it.
                    Cheers,
                    Maxime.

                    MAXON SDK Specialist

                    Development Blog, MAXON Registered Developer

                    1 Reply Last reply Reply Quote 0
                    • indexofrefractionI
                      indexofrefraction
                      last edited by indexofrefraction

                      @m_adam

                      tx for those infos maxime!
                      i'm actually using my own "Console" GeDialog. and i redirect stdout to it.
                      but i have the same problem as with the real Console.

                      It would be very interesting to know what "recreating your own console UI" means O:-)

                      maybe some ConsoleDialog.flush() function would work,
                      but I don't even know how to wait until that ASYNC ConsoleDialog window is really visible.
                      Both GeDialog.isOpen() or isVisible() are returning false positives after Open()!

                      import sys
                      import time
                      
                      import c4d
                      from c4d import gui
                      
                      class ConsoleDialog(gui.GeDialog):
                      	ID_TEXTBOX = 1001
                      	ID_BUTTON = 1002
                      
                      	def __init__(self, pluginid=0):
                      		self.text = ""
                      		self.SetTimer(350)
                      		self.Open(c4d.DLG_TYPE_ASYNC, pluginid, -2, -2, 400, 300)
                      
                      	def CreateLayout(self):
                      		self.SetTitle("ConsoleDialog")
                      		self.GroupBorderNoTitle(c4d.BORDER_NONE)
                      		self.GroupBorderSpace(4, 2, 2, 4)
                      		self.AddMultiLineEditText(self.ID_TEXTBOX, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 0, 0, c4d.DR_MULTILINE_WORDWRAP | c4d.DR_MULTILINE_READONLY)
                      		self.AddButton(self.ID_BUTTON, c4d.BFH_RIGHT | c4d.BFV_CENTER, 100, 15, "OK")
                      		return True
                      
                      	def write(self, text=""):
                      		self.text += str(text)
                      		self.SetString(self.ID_TEXTBOX, self.text)
                      
                      	def Timer(self, msg):
                      		if self.text != self.GetString(self.ID_TEXTBOX):
                      			self.SetString(self.ID_TEXTBOX, self.text)
                      
                      	def Command(self, id, msg):
                      		if id == self.ID_BUTTON: self.Close()
                      		return True
                      
                      if __name__ == "__main__":
                      	cd = ConsoleDialog()
                      	stdout_bak = sys.stdout
                      	sys.stdout = cd
                      	print("Hello World!")
                      	for i in range(0, 5):
                      		print(i)
                      		time.sleep(1)
                      	sys.stdout = stdout_bak
                      
                      # Problem 1: ConsoleDialog window does not show until after processing
                      # Problem 2: Print output (probably) does not show until after processing
                      
                      1 Reply Last reply Reply Quote 0
                      • I
                        ivodow
                        last edited by ivodow

                        An answer to my initial question, for others who may encounter the same issue. This can be used in lieu of print()

                        import maxon
                        
                        def ConsolePrint( *args ):
                            # concatenate var args into a single, space separated string suitable for maxon.Loggers
                            txt = " ".join(str(i) for i in args)
                            maxon.Loggers.Python().Write( maxon.TARGETAUDIENCE.ALL, txt, maxon.MAXON_SOURCE_LOCATION(1), maxon.WRITEMETA.UI_SYNC_DRAW )
                        
                        if __name__ == "__main__":
                        
                           ConsolePrint( "Output" )
                        
                        1 Reply Last reply Reply Quote 1
                        • indexofrefractionI
                          indexofrefraction
                          last edited by

                          @ivodow
                          how is your ConsolePrint() different to a simple print() statement?
                          in my test i didn''t get a real time output with ConsolePrint()

                          best, index

                          1 Reply Last reply Reply Quote 0
                          • First post
                            Last post