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

    Identify name of clone source at index

    PYTHON Development
    0
    3
    615
    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
      Helper
      last edited by

      On 23/03/2017 at 14:02, xxxxxxxx wrote:

      I'm playing about with python effectors again, trying to figure out best approach to controlling clones based on their source object names..

      I made a cloner with a range of motext objects inside; 0 .. 9, a.. b, A.. B

      My end goal is to be able to set clones to specific characters at specific indices.

      So far I have found out about the MODATA_CLONE id value, which defines which cloner child object  to use at the specified index.

      This is sort of useful I think, but is it the best method for what I want; 
      Since I couldn't find any easy way to access the name (maybe I missed something obvious?)
      I am trying to figure out a way to do it with this MODATA_CLONE value:

      I could get all the childs of the cloner object, as an array, look up the letter which I would like to set at a specific index in the cloner, using something like:

        
      def getCValue(childArray, letter) :
        
          length = len(childArray)
          
          for i, L in enumerate(childArray) :
        
              if str(letter) in L.GetName() :
        
                  return float(i)/length
              
      

      then to set the new values

       
          childs = clonerObj.GetChildren()
        
          value = getCValue(childs, "a")
        
          md.SetArray(c4d.MODATA_CLONE, fillArray(value, cnt),True)
        
      
      

      This works, but very dodgy-ly as you might imagine, most of the letters work and set the correct clones but sometimes it doesn't work and it's off by one character, I assume because its not quite matching up with the float value which the cloner uses.

      Is there a more surefire way to get/set which object is used at a specific index?
      Is this the best way to do this?
      Thanks for your time!

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

        On 24/03/2017 at 06:53, xxxxxxxx wrote:

        Hi,

        The formula to get the index of a MoGraph generator's child object from a float value in MODATA_CLONE is:

        cloneIndex = floor(clamp(cloneValue * numChildren, 0, numChildren-1))
        

        Here is a Python effector code that prints these indices and the children names:

        import c4d
        from c4d import utils
        from c4d.modules import mograph as mo
          
        import math
          
          
        def main() :
            md = mo.GeGetMoData(op)
            if md is None: return
            
            children = gen.GetChildren()
            numChildren = len(children)
            if numChildren == 0: return
            
            mdCount = md.GetCount()
            mdClone = md.GetArray(c4d.MODATA_CLONE)
            
            for cloneIdx in xrange(mdCount) :
                childIdx = int(math.floor(utils.ClampValue(mdClone[cloneIdx] * numChildren, 0, numChildren-1)))
                print childIdx, children[childIdx].GetName()
        

        Note 'gen' variable is the generator object that uses the Python effector.
        Also the code has to be executed in a Python effector set to Full Control mode.

        About the offset by one character, add a half step to the new value to set in the MODATA_CLONE array. This half step value would be 1.0/numChildren.

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

          On 24/03/2017 at 10:36, xxxxxxxx wrote:

          Hi Yannick!
          Thanks so much for the advice, this is excellent.
          Great idea to use ClampValue.

          I ended up doing +0.5 / numChildren, 1.0 seemed to make it worse, but 0.5 seems perfect..
          context:

          def clonerString(childArray, iString, cCount) : #cCount = clones count
                 
              length = len(childArray)
              
              myList = [0.0] * cCount
              
              for i, c in enumerate(iString) :
                  
                  for j, L in enumerate(childArray) :
                      
                      if str(c) in L.GetName() :
                          myList[i] = float(j)/length + 0.5/length
              
              return myList
          
          1 Reply Last reply Reply Quote 0
          • First post
            Last post