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
    • Unread
    • 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 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