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.c4dCan 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 :
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 objectsI 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 objectThe 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()