Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python 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
    • Recent
    • Tags
    • Users
    • Login

    UDP data to C4d via Python

    Scheduled Pinned Locked Moved PYTHON Development
    15 Posts 0 Posters 1.6k Views
    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.
    • H Offline
      Helper
      last edited by

      On 05/03/2013 at 03:29, xxxxxxxx wrote:

      Because the code is run from the main thread and you never leave the while loop. Do
      you have programming experience? If you don't already know threads and (fake) parallel processing, you should inform yourself,
      learn about it and then implement your code in a thread. There is enough online ressource to get started.

      Be told that the script manager is not the optimal place to start threads, you'll be better off in a CommandData plugin.

      Best,
      -Niklas

      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

        On 05/03/2013 at 03:48, xxxxxxxx wrote:

        OK, i have some experience with java, javascript and python. 
        I don't have much experience with thread programming. So i will check CommandData(is this controlling from the command line?)
        But one short question, if i disable the while loop and check each running frame the input, this should  work?

        1 Reply Last reply Reply Quote 0
        • H Offline
          Helper
          last edited by

          On 05/03/2013 at 04:10, xxxxxxxx wrote:

          No, the CommandData plugin is an interface to run your custom code when the user starts your
          command via the plugin-menu. All available commands can be found in the Command Manager. An
          example command would be "Save" or "Open", "Optimize" or "Untriangulate".

          You could, for example, create a Python Tag that starts the socket once and checks for input data
          on each frame, depending on what you want to achieve. You also have to think about the case
          when the timeline is not running: Still check for input data from clients, and if so, what to do
          with this data?

          When implementing threading, you should also include the ability to stop the thread when the user
          does not want to use your plugin anymore. You should also ensure you don't hit any cross-thread
          barriers (like modifieng the scene from a thread is not allowed).

          Here's an example:

          import socket
          import threading
            
          class ServerThread(threading.Thread) :
            
              def __init__(self, host='192.168.178.21', port=20000, bufsize=1024) :
                  super(ClientThread, self).__init__()
                  self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                  self.sock.bind((host, port))
                  self.bufsize = int(bufsize)
                  self.running = False
            
              def on_data_recv(self, data, addr) :
                  # Do some stuff with your data. Remember you're still running
                  # in a thread!
                  pass
            
              # Overrides: threading.Thread
            
              def run(self) :
                  self.running = True
                  while self.running:
                      data, addr = sock.recvfrom(self.bufsize)
                      self.on_data_recv(data, addr)
            
          thread = ServerThread()
          thread.start()
          

          In Cinema 4D, you might also use the c4d.threading.C4DThread class.

          -Niklas

          1 Reply Last reply Reply Quote 0
          • H Offline
            Helper
            last edited by

            On 05/03/2013 at 04:52, xxxxxxxx wrote:

            Thank you Niklas for your efforts, i will try this in the evening when i am at home. 
            I thought it is easy to create a null object and put a little script to to change the position or rotation, but it looks more complicated 😉

            1 Reply Last reply Reply Quote 0
            • H Offline
              Helper
              last edited by

              On 07/03/2013 at 02:01, xxxxxxxx wrote:

              Hi Niklas,
              I didn't get it working :(. I tried to connect the script to a null object and check each frame if it is getting data from the udp then change the x position and go to the next frame. if there is no data go to the next frame without changing. i think that is a thread problem, you pointed on. perhaps you can give me a short example. thanks

              1 Reply Last reply Reply Quote 0
              • H Offline
                Helper
                last edited by

                On 07/03/2013 at 03:47, xxxxxxxx wrote:

                Hi Helge,
                what exactly  is the problem? Did an exception occure? Or did Cinema freeze again? Show also the code, please. I can't help you unless I know your actual problem.

                -Niklas

                1 Reply Last reply Reply Quote 0
                • H Offline
                  Helper
                  last edited by

                  On 07/03/2013 at 05:57, xxxxxxxx wrote:

                  ok, that is my actual code, connected to a null object.

                  import c4d
                  import socket
                  import threading

                  class ServerThread(threading.Thread) :

                  def __init__(self, host='127.0.0.1', port=20000, bufsize=1024) :
                          super(ClientThread, self).__init__()
                          self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                          self.sock.bind((host, port))
                          self.bufsize = int(bufsize)
                          self.running = False

                  def on_data_recv(self, data, addr) :
                          # Do some stuff with your data. Remember you're still running
                          # in a thread!
                          # c4d should check each frame if it is getting data
                          # if not go to the next frame, if data then change the x position
                          # and go to the next frame
                          [c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_X] = data

                  # Overrides: threading.Thread

                  def run(self) :
                          self.running = True
                          while self.running:
                              data, addr = sock.recvfrom(self.bufsize)
                              self.on_data_recv(data, addr)

                  thread = ServerThread()
                  thread.start()

                  time = doc.GetTime().GetFrame(doc.GetFps())

                  i think my problem is in connection of time and  thread. i am really new to python in c4d.

                  1 Reply Last reply Reply Quote 0
                  • H Offline
                    Helper
                    last edited by

                    On 07/03/2013 at 06:21, xxxxxxxx wrote:

                    [c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_X] = data

                    the instance for which __setitem__ should be called is missing, the code doesn't make much
                    sense this way.

                    1 Reply Last reply Reply Quote 0
                    • H Offline
                      Helper
                      last edited by

                      On 07/03/2013 at 06:32, xxxxxxxx wrote:

                      Hi Helge,

                      threading is recommended for plugins only. In order for the thread to stay alive, you require to
                      keep a reference to it, which can be garuanteed in a plugin, but not necessarily in a Python Tag
                      or any built-in scripting facility in Cinema (script, effector, object, tag). If the reference to the thread
                      is lost, it will be garbage collected and therefore stopped and eliminated.

                      Please encapsulate your code in the [*CODE][*/CODE] tags next time, sparing the * of course.

                      A Python Tag's main() function is called everytime the tag requires to be executed, to be more
                      precise: Everytime TagData.Execute() is invoked from Cinema 4D's plugin system, main() is invoked.
                      You do not have a main() function declared, therefore no main() function can be invoked.

                      And yes, you are again hitting threading-limitations. When you put your code into an expression
                      tag, you should do this because of a certain reason. What you are currently doing could also be put
                      into a command plugin, an object plugin or even video post plugin, because the code is totally
                      unrelated to its environment.

                      EDIT: I missed, what Ferdinand pointed out. 🙂 So you're not hitting threading limitations here,
                      _but if you would've applied this part correctly (with an object to invoke _setitem__ with [bracket
                      syntax], and convert the data to a numeric type) you wouldn't have seen the changes immediately.

                      Here's some example code you should use to kick off:

                      import c4d
                      import socket
                        
                      sock = None
                      HOST = 'localhost'
                      PORT = 20000
                      bufsize = 1024
                      timeout = 0.01
                        
                      def main() :
                          global sock
                          if not sock:
                              # No socket has yet been created.
                              sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                              sock.bind((HOST, PORT))
                        
                              # You don't want the receiving of data to block the complete
                              # evaluation process. It's bad when no data comes in, but it
                              # needs to be handled.
                              sock.settimeout(timeout)
                        
                          try:
                              data, addr = sock.recvfrom(bufsize)
                          except socket.timeout:
                              # No data has been received within the timeout. Need to handle
                              # this here!!
                              print "timeout reached"
                              return
                        
                          # `data` is a string with up to `bufsize` bytes, what to do with it?
                          pass
                      

                      This code will check each frame for incoming data! Your current code is completely independant
                      from the actual frames in Cinema. Remember that the data you recieve from the socket is a string
                      of up to 1024 bytes (can be less!), and not an integral or floating-point number. You can't assign
                      a string to a component of a vector like you're doing in your current code. You need to convert it.

                      -Niklas

                      1 Reply Last reply Reply Quote 0
                      • H Offline
                        Helper
                        last edited by

                        On 07/03/2013 at 08:53, xxxxxxxx wrote:

                        ok niklas,
                        i think i workout the command plugin tutorial on smart-page.net the next days. also i will study threading of a better understanding. after this i will try to connect your example.
                        thanks, helge

                        1 Reply Last reply Reply Quote 0
                        • H Offline
                          Helper
                          last edited by

                          On 07/03/2013 at 09:36, xxxxxxxx wrote:

                          Hi Helge,

                          just to clarify: The example above was intented to be used in a Python Scripting Tag.

                          Best,
                          -Niklas

                          1 Reply Last reply Reply Quote 0
                          • H Offline
                            Helper
                            last edited by

                            On 07/03/2013 at 10:31, xxxxxxxx wrote:

                            Yepp i know. 
                            I tested your script and yeah it works, i changed the pass arg ti print data to see the data in the console. If i go frame by frame it works fine, expect that the received message is a little bit strange, i create a counter fom zero to ten with delay of one second in max map and send it to c4d. If i skip the frame faster or longer then one second, c4d counts from 0 to 10.
                            furthermore, c4d crashed if i put the play button. i think both are threading problems so i think it is better to do it with an command line plugin and create the null object by the plugin. 
                            i also have to create an socket close like you mentioned. So I'm checking the tutorials and the i am back 😉

                            greetings - helge

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