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

    restructure project

    Scheduled Pinned Locked Moved PYTHON Development
    13 Posts 0 Posters 1.1k 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 20/02/2013 at 07:40, xxxxxxxx wrote:

      Hi all,

      I try to reduce data in a C4D File by combining Polygon-objects with the same material following in the structure dirctly after another.

      Running thrue the structure works!
      Finding materials works.
      But when I find two objekts with equal material the plugin stops.
      It seams to lose the actual objekt ?!?

      Here is my code:

        
      def walk(obj) :   
          if not obj: return   
          elif obj.GetDown() :   
              return obj.GetDown()   
          while obj.GetUp() and not obj.GetNext() :   
              obj = obj.GetUp()   
        
          print 'klick'   
          return obj.GetNext()   
        
      def walk_thrue_projekt(doc) :   
          print 'walk_thrue_projekt START'      
          obj = doc.GetFirstObject()   
          zaehler = 0   
          c4d.CallCommand(13324)                            # Alles deselektieren   
          material1 = 'Leer'   
          print material1   
          gui.MessageDialog('Stop1')   
          while obj:   
              zaehler = zaehler + 1   
              print zaehler   
              print c4d.BaseObject.GetName(obj)                         # Objektname lesen und ausgeben   
              obj.SetBit(c4d.BIT_ACTIVE)   
              textureTag = obj.GetTag(c4d.Ttexture)                     # Lesen TextureTag des aktuellen Objektes   
              if not textureTag:                                        # wenn Material nicht vorhanden dann   
                  print 'Kein Material-Tag gefunden'                    # nix tun   
                  obj.DelBit(c4d.BIT_ACTIVE)                            # Wenn kein Material vorhanden dann deaktivieren   
              else:                                                     # wenn Material vorhanden dann   
                  material2 = textureTag.GetMaterial()                  # Materialnamen auslesen   
                  print material2                                       # Materialnamen ausgeben   
                  print material1                                       # Materialnamen ausgeben   
                  obj.SetBit(c4d.BIT_ACTIVE)                            # Objekt aktivieren   
                  gui.MessageDialog('Stop2')   
                  if material1 == material2:                            # Wenn material1 = maderial 2 dann:   
                     gui.MessageDialog('zwei gleiche gefunden')   
                     c4d.CallCommand(16768)                            # Objekte verbinden + Löschen   
                     #return   
                  else:                                                 # Wenn material1 != maderial 2 dann:   
      #               c4d.CallCommand(13324)                            # Alles deselektieren   
                     gui.MessageDialog('zwei ungleiche hintereinander gefunden')                 
                     obj.DelBit(c4d.BIT_ACTIVE)                        # aktuelles Objekt aktivieren   
                     material1 = material2   
              obj = walk(obj)   
      

      To test the Plugin here is a testfile:
      http://www.vision4d.de/downloads/001 Testscene klein.c4d

      Can anybody help my please

      Thanks a lot

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

        On 20/02/2013 at 11:10, xxxxxxxx wrote:

        calling connect and delete on your object will cause you object reference to become None
        and therefor the walk method will return none which will cause your main method to break
        the loop.

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

          On 21/02/2013 at 01:02, xxxxxxxx wrote:

          OK Thanks to littledevil.

          But how can I solve the problem?
          I'm a try-and-error-Coder!
          Do you know anybody how can help me!
          (I would pay for the solution!)

          Thanks again

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

            On 21/02/2013 at 10:04, xxxxxxxx wrote:

            hm,

            there are multiple problems with your approach. here is how i would do it :

            http://codepad.org/DpEBjT7O

            i am taking a selection based approach, as this makes things a bit easier (and faster)
            and also adds the possibility to exclude objects from the process. simply select all objects
            manually or programmatically if you want to run it over the whole document.

            edit, the code, the codepad link won't last forever:

            import c4d
              
            # --- connect & delete all objects of the current selection, which have the same material
            # --- assigned to them. objects which have multiple materials assigend to them will be skipped.
            # --- objects with multiple material tags holding the same material will be connected.
            # ------------------------------------------------------------------------------------------------
            def main() :
                selection = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
                dic = buildDict(selection)
                for key in dic:
                    connect(dic[key]) 
              
            # --- connect & delete a object list
            # ------------------------------------------------------------------------------------------------
            def connect(objlist) :
                if len(objlist) > 1:
                    for i in xrange(len(objlist)) :
                        if i == 0:
                            doc.SetActiveObject(objlist[i], c4d.SELECTION_NEW)
                        else:
                            doc.SetActiveObject(objlist[i], c4d.SELECTION_ADD)
                    c4d.CallCommand(16768)
              
            # --- get material used by this baseobjct. returns none for multiple materials.
            # --> BaseMaterial | None
            # ------------------------------------------------------------------------------------------------
            def getMaterial(obj) :
                material = None
                if isinstance(obj, c4d.BaseObject) :
                    taglist  = obj.GetTags()
                    for tag in taglist:
                        if tag.GetType() == c4d.Ttexture:
                            # single tag
                            if material == None:
                                material = tag.GetMaterial()
                            # multiple tags of the same material
                            elif material == tag.GetMaterial() :
                                pass
                            # multiple tags
                            else: return None
                return material
              
            # --- build a dict of all materials in the given selection. each key contains a list
            # --- with the objects which carry only this material in their texturetag(s).
            # --> dict
            # ------------------------------------------------------------------------------------------------
            def buildDict(selection) :
                result = {}
                for objA in selection:
                    matA = getMaterial(objA)
                    for objB in selection:
                        if objA is not objB:
                            matB = getMaterial(objB)
                            if matA == matB and matA and matB:
                                mkey = matA.GetName()
                                if mkey in result:
                                    if objA not in result[mkey]:
                                        result[mkey].append(objA)
                                    if objB not in result[mkey]:
                                        result[mkey].append(objB)
                                else:
                                    result[mkey] = []
                                    result[mkey].append(objA)
                                    result[mkey].append(objB)
                return result
              
            if __name__=='__main__':
                main()
              
            
            

            edit : using the material name as a dict key isn't really a brilliant idea, as it would merge
            different material objects with the same name into one object. you should change the 
            dict key to a string repr of the material object ...  mkey = str(matA)

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

              On 22/02/2013 at 02:17, xxxxxxxx wrote:

                 
              You are my Hero!!!
              BUT:

              My eyplanation of my problem wasn't exact enought:

              I wantet to change form this structure

              Würleh0 Material-1
              Würfel1 Material-2
              Würfel2 Material-1
              Würfel3 Material-3 #merge and the next
              Würfel4 Material-3        +
              Würfel14 Material-1 #merge and the next
              Würfel15 Material-1        +
              Null
              |-- Würfel4 Material-1
              |-- Würfel2 Material-2
              Null1
                   |-- Würfel6 Material-2 #merge and the next
                   |-- Würfel7 Material-2        +
                   Null2
                   | |-- Würfel8 Material-1
                   |   |-- Würfel9 Material-2 #merge and the next
                   |   |-- Würfel10 Material-2        +
                   |
                   |-- Würfel11 Material-3 #merge and the next
                   |-- Würfel12 Material-2          +

              to the folowing:

              Würleh0 Material-1
              Würfel1 Material-2
              Würfel2 Material-1
              Würfel3 Material-3 #merged objects
              Würfel14 Material-1 #merged objects
              Null
              |-- Würfel4 Material-1
              |-- Würfel2 Material-2
              Null1
                   |-- Würfel6 Material-2 #merged objects
                   Null2
                   | |-- Würfel8 Material-1
                   |   |-- Würfel9 Material-2 merged objects
                   |
                   |-- Würfel11 Material-3 merged objects

              I uploaded the result-File here:

              http://www.vision4d.de/downloads/001%20Testscene%20klein%20-%20after%20restructure.c4d

              Mayby you can hlep me by this problem???
              Thanks a Lot lot lot lot............lot lot lot

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

                On 22/02/2013 at 05:49, xxxxxxxx wrote:

                ah ok, i thought this behaviour of your code was unintended. you could stick 
                more ore less with orginal code, but instead of merging the objects from within 
                your loop you would build up a result list. you could use the python tuple feature 
                to make things easier.

                result = []
                  
                if current_material == last_material:
                	result.append((last_object, current_object))
                  
                ...
                  
                for obja, objb in result:
                	merge(obja,objb)
                
                1 Reply Last reply Reply Quote 0
                • H Offline
                  Helper
                  last edited by

                  On 22/02/2013 at 06:27, xxxxxxxx wrote:

                  Hi LittleDevil;

                  It seams for me that it is very easy vor you to change the first code.

                  What shall I change?
                  Could you pleas make th changes?

                  Thanks a lot

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

                    On 22/02/2013 at 08:08, xxxxxxxx wrote:

                    as your pm sounded kind of desperate, i did the work for you 😉 this does now exactly what you
                    wanted it to do. for more you will have to dig yourself through python or hire someone as you suggested.

                    import c4d
                      
                    def main() :
                        connectList(buildList())
                      
                    def buildList() :
                        result           = []
                        current_object   = doc.GetFirstObject()
                        last_object      = None
                        current_material = None 
                        last_material    = None
                      
                        while current_object:
                            current_material = getMaterial(current_object)
                            if current_material != None and last_object != None:
                                if current_material == last_material:
                                    result.append((last_object, current_object))
                            last_material = current_material
                            last_object   = current_object
                            current_object = walk(current_object)
                        return result
                      
                    def connectList(objlist) :
                        for objA, objB in objlist:
                            doc.SetActiveObject(objA, c4d.SELECTION_NEW)
                            doc.SetActiveObject(objB, c4d.SELECTION_ADD)
                            c4d.CallCommand(16768)
                      
                    def getMaterial(obj) :
                        material = None
                        if isinstance(obj, c4d.BaseObject) :
                            taglist  = obj.GetTags()
                            for tag in taglist:
                                if tag.GetType() == c4d.Ttexture:
                                    if material == None:
                                        material = tag.GetMaterial()
                                    elif material == tag.GetMaterial() :
                                        pass
                                    else: return None
                        return material
                      
                    def walk(obj) :
                        if not obj: return
                        elif obj.GetDown() :
                            return obj.GetDown()
                        while obj.GetUp() and not obj.GetNext() :
                            obj = obj.GetUp()
                        return obj.GetNext()
                      
                    if __name__=='__main__':
                        main()
                    
                    1 Reply Last reply Reply Quote 0
                    • H Offline
                      Helper
                      last edited by

                      On 23/02/2013 at 03:10, xxxxxxxx wrote:

                      Hello at all,

                      and first of all my thanks to littledevil.

                      The problem seams to be not as easy.
                      The code above works with the postetd (reducesd) testscene well!
                      But with my original scene not.
                      It analysed it and it seams for me that the varriable result[] looses informations. (I did a print result)

                      Here is a new testscene:

                      http://www.vision4d.de/downloads/002_Testscene_klein.c4d

                      For that I can help me by my own, I need help at the following problem:
                      I try to explane in words:

                      goto first objekt                                         (no problem)
                      step throug the scene                               (no problem)
                      test if the actual object is a null-objekt     (no problem)
                      if yes:                                                        (no problem)
                         is a part of the name is "wand"              Problem starts here!
                             if yes:
                             merge all polygonal objekts in this null-objekt with the same
                             material to one object

                      The problem for me ist to find "all" polygon-objekts in a null-object and merge them to one!!!

                      Because:
                      when I find two following to each other and mergin them, the aktual objekt is not the merged on.
                      So i'm loosing my aktual position in the project.
                      How can I merge them and than place my aktual objekt pointer to the mergesd on?

                      Thanks a lot to all good ideas.

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

                        On 23/02/2013 at 09:35, xxxxxxxx wrote:

                        1. finding a substring in a string is pretty asy in python. str.find will return the index of 
                        the first occurance of the given substring. it will return -1 for no mtach.
                        'I am a string'.find('I am')

                        2. for changing the object count in the document and looping through the content - you
                        could use other methods, but the easiest approach would be to build up a list of objects
                        which have to be merged and do the merging after you have looped through all the objects.
                        like i did it in my examples.

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

                          On 24/02/2013 at 05:26, xxxxxxxx wrote:

                          @ ferdinand:
                          But why does your way stuggle with the biger scene I posted?

                          I looking for a way to build a list of all Polygonal objects listet in a Null-object whitch have the same material and combine them and then continue!.

                          The question is:
                          How could I store the next object to continue with this object after combining the collected objects?

                          Thanks a lot for your patience

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

                            On 24/02/2013 at 12:00, xxxxxxxx wrote:

                            ok, now I found the problem:
                            The code only works when:
                            not more than two objact following have the same material!!!
                            and:
                            when nor the first 2 objekts have the same material!!!

                            So, has anybody out there a idea how to bild the list for varriable amout of objekts with same material following to each other?

                            Thanks a lot!

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

                              On 25/02/2013 at 10:41, xxxxxxxx wrote:

                              you have just to build up a longer list instead of pairs, like in my first example. but as you do not 
                              care for earlier occurances of sequences of the current material you do not have to use a dict, you 
                              can just build up a list of lists.

                              import c4d
                                
                              def main() :
                                  connectList(buildList())
                                
                              def buildList() :
                                  result           = []
                                  templist         = []
                                  current_object   = doc.GetFirstObject()
                                  last_object      = None
                                  current_material = None 
                                  last_material    = None
                                
                                  while current_object:
                                      current_material = getMaterial(current_object)
                                      if current_material != None:
                                          if current_material == last_material and last_object != None:
                                              templist.append((current_object))
                                          else:
                                              if len(templist) > 1:
                                                  result.append(templist)
                                              templist = []
                                              templist.append(current_object)
                                      last_material = current_material
                                      last_object   = current_object
                                      current_object = walk(current_object)
                                  return result
                                
                              def connectList(objlist) :
                                  for sublist in objlist:
                                      for i in xrange(len(sublist)) :
                                          if i == 0: doc.SetActiveObject(sublist[i], c4d.SELECTION_NEW)
                                          else: doc.SetActiveObject(sublist[i], c4d.SELECTION_ADD)
                                      c4d.CallCommand(16768)
                                
                              def getMaterial(obj) :
                                  material = None
                                  if isinstance(obj, c4d.BaseObject) :
                                      taglist  = obj.GetTags()
                                      for tag in taglist:
                                          if tag.GetType() == c4d.Ttexture:
                                              if material == None:
                                                  material = tag.GetMaterial()
                                              elif material == tag.GetMaterial() :
                                                  pass
                                              else: return None
                                  return material
                                
                              def walk(obj) :
                                  if not obj: return
                                  elif obj.GetDown() :
                                      return obj.GetDown()
                                  while obj.GetUp() and not obj.GetNext() :
                                      obj = obj.GetUp()
                                  return obj.GetNext()
                                
                              if __name__=='__main__':
                                  main()
                              
                              1 Reply Last reply Reply Quote 0
                              • First post
                                Last post