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
    The forum rollback caused push notifications and recent user data to malfunction. The problem will fix itself naturally within the next days. See the topic Broken Push Notifications for a more in detail explanation. You can fix this yourself by forcibly clearing your browser cache (for most browsers: CTRL + F5).

    The code entered in the Python emitter has no effect.

    Cinema 4D SDK
    r25 python windows
    2
    4
    493
    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.
    • F
      Fabio B
      last edited by ferdinand

      Hello, in theory, the Python code linked to the Python effector should randomly move the object in the cloner by 100 cm along the Y axis — why isn't it working

      import c4d
      import random
      
      def main() -> bool:
          md = c4d.modules.mograph.GeGetMoData(op)
          if md is None:
              return True
      
          count = md.GetCount()
          matrices = md.GetArray(c4d.MODATA_MATRIX)
      
          # Inizializza la lista dei frame solo una volta
          if not hasattr(op, "frames"):
              random.seed(42)
              op.frames = [random.randint(0, 75) for _ in range(count)]
      
          fps = doc.GetFps()
          current_frame = doc.GetTime().GetFrame(fps)
      
          for i in range(count):
              if current_frame >= op.frames[i]:
                  # Sposta il clone fuori scena (es. +100 cm su Y)
                  m = matrices[i]
                  m.off.y = 100
                  matrices[i] = m
              else:
                  # Mantieni la posizione originale (nessuna modifica)
                  pass
      
          md.SetArray(c4d.MODATA_MATRIX, matrices, True)
          return True
      

      15x10.c4d

      edit (@ferdinand): moved file link out of source code.

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

        @Fabio-B Welcome to the Maxon developers forum and its community, it is great to have you with us!

        Getting Started

        Before creating your next postings, we would recommend making yourself accustomed with our forum and support procedures. You did not do anything wrong, we point all new users to these rules.

        • Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment.
        • Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support.
        • Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads.

        It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: How to Ask Questions.

        About your First Question

        Your code contains a syntax error:

        op.frames = [random.randint(0, 75) for _ in range(count)]
        

        op is in this context a BaseObject, more precisely the effector for which this code is running. Since this type (BaseObject) has been implemented in C++, you cannot just put there an attribute named frames on it. That is simply not how it works. Did you write this code yourself or did you use an AI?

        When I check the DOCUMENT_INFO_FILEVERSION of the document you submitted, I get there '2025.2.1', i.e., the last public release, and not R25 (released in 2021). I will answer as if you are using Cinema 4D 2025. The code I show below will not run in R25.

        To set the height of each particle to a fixed position, while using full control mode, you can basically use the barely modified default code.

        """Realizes an effector that sets all particles to a y position of 25.
        """
        import c4d
        
        op: c4d.BaseObject # The Python Effector object containing this code.
        gen: c4d.BaseObject # The MoGraph Generator executing `op`.
        doc: c4d.documents.BaseDocument # The document `op` and `gen`are contained in.
        
        def main() -> bool:
            """Called by Cinema 4D to evaluate the effector.
            """
            # Get the particle data for the effector #op. Get out when either the data cannot be retrieved.
            data: c4d.modules.mograph.MoData = c4d.modules.mograph.GeGetMoData(op)
            if data is None:
                return 1.0
        
            # Get the matrices of the particles. This is the array we will modify.
            matrices: list[c4d.Matrix] = data.GetArray(c4d.MODATA_MATRIX)
        
            # For each particle write the new position to the matrix array.
            for i in range(data.GetCount()):
                old: c4d.Vector = matrices[i].off
                matrices[i].off = c4d.Vector(old.x, 25, old.z)
        
            # Write the new data back.
            data.SetArray(c4d.MODATA_MATRIX, matrices, op[c4d.FIELDS].HasContent())
            return True 
        

        When you want to give each particle a random height value, you could use mxutils.Random as it has been built for tasks exactly like this:

        """Realizes an effector that sets all particles to a y position of 25..
        """
        import c4d
        import mxutils
        
        op: c4d.BaseObject # The Python Effector object containing this code.
        gen: c4d.BaseObject # The MoGraph Generator executing `op`.
        doc: c4d.documents.BaseDocument # The document `op` and `gen`are contained in.
        
        def main() -> bool:
            """Called by Cinema 4D to evaluate the effector.
            """
            # Get the particle data for the effector #op. Get out when either the data cannot be retrieved.
            data: c4d.modules.mograph.MoData = c4d.modules.mograph.GeGetMoData(op)
            if data is None:
                return 1.0
        
            # Get the matrices of the particles. This is the array we will modify.
            matrices: list[c4d.Matrix] = data.GetArray(c4d.MODATA_MATRIX)
        
            # For each particle write a new persistent random height value, hashed over the index of the 
            # particle. This will cause the height each time to be the same, as long as the index of the
            # particle does not change. One could also hash the position of the original particle to get a
            # height value that is not dependent on the index of the particle (e.g., when the user changes 
            # the order of the particles in the Matrix object).
            for i in range(data.GetCount()):
                old: c4d.Vector = matrices[i].off
                matrices[i].off = c4d.Vector(old.x, mxutils.g_random.HashNumberToNumber(i) * 25.0, old.z)
        
                # Hash a height value over the position of the particle.
                # y: float = mxutils.g_random.HashVectorToNumber(matrices[i].off) * 25.0
        
            # Write the new data back.
            data.SetArray(c4d.MODATA_MATRIX, matrices, op[c4d.FIELDS].HasContent())
            return True
        

        Result:
        3528058b-e5ad-499e-8fe4-16ff6fff27c1-image.png

        Cheers,
        Ferdinand

        MAXON SDK Specialist
        developers.maxon.net

        F 1 Reply Last reply Reply Quote 0
        • F
          Fabio B @ferdinand
          last edited by

          @ferdinand Thanks, Ferdinando. The code was written by the AI. Basically, I wanted a certain number of 2cm x 2cm planes to move randomly along the Y axis. My original grid contains 62,000 of them, but for convenience, the one I posted contains 150. Since my view is oriented in a certain way, as the clones move, they'll disappear from the scene, creating a sort of shimmering or swarming fade-out effect.

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

            Hey @Fabio-B,

            ⚠ Please note that we cannot provide support for AI generated code. See Support Procedures: Scope of Support for details.

            When you want the clones to move, or in other words to be animated over time, you will need a noise and cannot use hashes or random values, as they are not interpolated, i.e., continous.

            """Realizes an effector that attracts MoGraph particles spherically around its origin.
            
            Add the example to a Matrix object to understand its effect. In Full Control mode we can realize
            a true attraction force as we have full control over the particle values. Compare this example to
            Parameter Control mode to understand the difference.
            """
            import c4d
            import mxutils
            
            op: c4d.BaseObject # The Python Effector object containing this code.
            gen: c4d.BaseObject # The MoGraph Generator executing `op`.
            doc: c4d.documents.BaseDocument # The document `op` and `gen`are contained in.
            
            def main() -> bool:
                """Called by Cinema 4D to evaluate the effector.
                """
                # Get the particle data for the effector #op. Get out when either the data cannot be retrieved.
                data: c4d.modules.mograph.MoData = c4d.modules.mograph.GeGetMoData(op)
                if data is None:
                    return 1.0
            
                # Get the matrices of the particles. This is the array we will modify.
                matrices: list[c4d.Matrix] = data.GetArray(c4d.MODATA_MATRIX)
            
                # For each particle write a new persistent random height value, hashed over the index of the 
                # particle. This will cause the height each time to be the same, as long as the index of the
                # particle does not change. One could also hash the position of the original particle to get a
                # height value that is not dependent on the index of the particle (e.g., when the user changes 
                # the order of the particles in the Matrix object).
                for i in range(data.GetCount()):
                    pos: c4d.Vector = matrices[i].off
                    y: float = c4d.utils.noise.Noise(matrices[i].off, doc.GetTime().Get()) * 25.0
                    matrices[i].off = c4d.Vector(pos.x, y, pos.z)
            
                    # Hash a height value over the position of the particle.
                    # y: float = mxutils.g_random.HashVectorToNumber(matrices[i].off) * 25.0
            
                # Write the new data back.
                data.SetArray(c4d.MODATA_MATRIX, matrices, op[c4d.FIELDS].HasContent())
                return True
            

            Cheers,
            Ferdinand

            MAXON SDK Specialist
            developers.maxon.net

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