restructure project



  • 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



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



  • 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



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



  • 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



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


  • 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



  • 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()
    


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



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



  • 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



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



  • 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()
    

Log in to reply