Ankündigung

Einklappen
Keine Ankündigung bisher.

Wie aktualisiert man mehrere gleiche Armatures am besten?

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Ungelöst Wie aktualisiert man mehrere gleiche Armatures am besten?

    Hallo.

    Bei Armature-Datalinks hab ich festgestellt dass die Constraints nicht mitverlinkt werden, man bekommt also nur das blanke Bone-Gerüst. Wenn ich Constraints verändere und die auch so bei allen verlinkten Armatures so haben will, fällt mir momentan nur eine Methode ein:
    Die aktuelle Armature duplizieren, die veraltete damit ersetzen, gegebenfalls Objektabhängigkeiten erneuern oder halt mit dem Befehl "Join" die Armature in die alte einfügen. Und das alles eben so oft wie nötig, ziemlich aufwendig.

    Ich würde gern wissen, ob ihr da andere Methoden kennt oder ob Blender da irgendeinen Befehl hat wo das ...geschmeidiger geht. Gibts da irgendwas?

  • #2
    Der Begriff "Armature-Datalink" ist mir so nicht geläufig.
    Wenn ich eine Armature per shift-D oder alt-D dupliziere/verlinke werden die constraints mit kopiert, allerdings nicht verändert, wenn ich am "Original" die constraints verändere oder lösche. Ich sehe auch keine (einfache) Möglichkeit wie man sie kopieren könnte.
    Beim herkömmlichen verlinken aus einer Datei klappt es aber problemlos. Die constraints werden mitverlinkt und auch alle Änderungen im Original werden übertragen.

    Kommentar


    • #3
      Keine Ahnung wie das heißt, ich meinte wenn der Armature Datablock derselbe ist.

      Wenn ich die Armature als Objekt verlinke kann ich davon leider nur 1x den Proxy benutzen.
      Wollte halt eine Armature mehrmals im selben File verwenden.

      Kommentar


      • #4
        In Blender 2.7 ist das offenbar ein größeres Problem für das ich keine Lösung gefunden habe (stackexchange beantwortet das auch negativ).
        In 2.8 geht es vielleicht (aber Achtung, Dateien die einmal mit 2.8 gespeichert wurden machen in 2.7 Probleme; bis hin zum crash):

        Du kannst eine Armature ganz normal aus einer Datei heraus in eine andere verlinken und dann einen Proxy erstellen. Das geht auch mehrmals !
        Änderungen im Edit-Mode an der Armature aus der Quelldatei werden damit übernommen.
        Nachträglich veränderte, gelöschte oder hinzugefügte constraints allerdings nicht.
        In 2.8 gibt es aber multi-editing, d.h. du kannst alle proxies auswählen und zugleich in den pose-mode gehen. Dann änderst du eine constraint oder fügst eine hinzu und kopierst über pose->constraints->"copy constraints" die constraints auf die anderen bones.
        Allerdings kopiert die Funktion exakt, d.h. auch das target der kopierten constraints ist die Proxy-Armature, von der kopiert wurde.
        D.h. bei z.B. einer copy-rotation beziehen sich jetzt alle kopierten constraints auf die Rotation von bone x in der Armature y, was wahrscheinlich nicht das ist, was du willst.
        Dem kann man aber mit folgendem script abhelfen:
        Code:
        import bpy
        
        arms = [ob for ob in bpy.data.objects[:] if ob.type=="ARMATURE"]
        
        for arm in arms:
            arm_obj = bpy.data.objects[arm.name]
            for bone in arm_obj.pose.bones:
                for constr in bone.constraints:
                    constr.target = arm_obj
        Das Skript steckt alle Armatures in der Szene in die Liste arms. Dann geht es die Liste durch, dort in jeder Armature alle Bones, dort alle constraints und ersetzt das target des constraints durch die Armature aus der der bone stammt.
        Damit werden die constraints praktisch "lokalisiert".

        Insgesamt keine "ein-Knopf"-Lösung, aber immerhin, vielleicht hilft es weiter.

        Kommentar


        • #5
          Das mit dem Constraints-Kopieren find ich gut. Aber ich will noch nicht mit 2.8 arbeiten solange das nicht released ist.

          Lassen sich komplette Constraint-Daten von einem Bone eigentlich irgendwie speichern? Weil dann könnte ich sagen:
          kopiere Arm1.Bone["Name"] Constraints und
          überschreibe damit Arm2.Bone["Name"] Constraints
          = Copy/Paste von der Constraint Liste.


          Kommentar


          • #6
            Ich habe mich hier:
            https://blender.stackexchange.com/qu...one-to-another
            inspirieren lassen:
            Code:
            import bpy
            
            target = bpy.context.selected_objects
            source =  bpy.context.active_object
            target.remove(source)
            
            bones_source = source.pose.bones
            
            for arm in target:
                for bone in arm.pose.bones:
                        cons = bone.constraints
                        for con in cons:
                            bone.constraints.remove(con)        
            
            for bone in bones_source:
                name = bone.name
                constraints_source = bone.constraints
            
                for arm in target:
                    bone_target = arm.pose.bones[name]
            
                    for constr in constraints_source:
                        new_con = bone_target.constraints.new( constr.type)
            
                        for prop in dir(constr):
                            try:
                                setattr(new_con, prop, getattr(constr, prop))
                                if prop == "target":
                                    setattr(new_con, prop, arm)
                            except:
                                pass
            Man wählt alle Armatures aus, zu denen kopiert werden soll, als letztes die "Quelle".
            Dann lässt man das Skript laufen.
            In Zeile 9-13 werden alle(!) constraints auf den "Ziel"-Armatures, also alle selektierten, mit Ausnahme der aktiven, gelöscht (wenn man das nicht tut kommen immer mehr und mehr constraints dazu).
            Zeile 15-31 geht dann alle bones in der Quelle durch und kopiert deren constraints, inklusive aller properties, auf die gleichnamigen(!) Bones der Ziel-Armatures.
            Es wird also voraus gesetzt, dass die bones in Quelle und Ziel gleich heißen !
            Zeile 29 ersetzt dann noch die target-property durch die eigene Armature.
            Sonst hat man wieder das Problem, dass sich alle constraints auf die Quelle beziehen. Das funktioniert im Moment aber nur bei targets, deren Eintrag eine Armature ist, also z.B. copy-rotation. Bei Spline- oder follow-path bleibt der entsprechende Eintrag dann leer, weil die Armature als Eintrag nicht aktzeptiert wird.

            Kommentar


            • #7
              Funktioniert astrein, vielen Dank!
              Den Weg mit dem dir(constr) kannte ich nicht. Ich hatte schon im Kopf für jeden Constraint extra eine Liste für die individuellen Einstellungen anzulegen, aber das wär mir vermutlich zuviel gewesen.

              Nur ist mir jetzt aufgefallen dass ich noch einige andre Einstellungen übernehmen müsste...
              Bone-Groups, Custom Shapes, IK-Limits, Bendy Bone custom handles und so ein Zeug.

              Gibt es da auch so eine Kurzform mit dem dir()? Ansonsten mach ich das einzeln, ist wahrscheinlich nicht so dramatisch.
              Zuletzt geändert von Failsafe; 17.10.2018, 17:05.

              Kommentar


              • #8
                Wäre schön, wenn es dort genau so gehen würde, aber offenbar ist es teilweise etwas verwickelter, bzw. schlicht anders, z.B. bei den Bone Groups.
                Ich habe etwas weiter gebastelt, aber wenig getestet, also Vorsicht.
                Code:
                import bpy
                
                target = bpy.context.selected_objects
                source =  bpy.context.active_object
                target.remove(source)
                
                bones_source = source.pose.bones
                
                for arm in target:
                    for bone in arm.pose.bones:
                            cons = bone.constraints
                            for con in cons:
                                bone.constraints.remove(con)        
                
                for bone in bones_source:
                    name = bone.name
                    constraints_source = bone.constraints
                
                    for arm in target:
                        bone_target = arm.pose.bones[name]
                
                        for constr in constraints_source:
                            new_con = bone_target.constraints.new( constr.type)
                
                            for prop in dir(constr):
                                try:
                                    setattr(new_con, prop, getattr(constr, prop))
                                    if prop == "target":
                                        setattr(new_con, prop, arm)
                                except:
                                    pass
                
                
                for arm in target:
                    for group in arm.pose.bone_groups:
                        arm.pose.bone_groups.remove(group)
                    for group in source.pose.bone_groups:
                        arm.pose.bone_groups.new(name=group.name)
                
                for group in source.pose.bone_groups:
                    color_set = group.color_set
                    name = group.name
                    for arm in target:
                        arm.pose.bone_groups[name].color_set = color_set
                        arm.pose.bone_groups[name].color_set = color_set
                
                for bone in source.pose.bones:
                    name = bone.name
                    s_index = bone.bone_group_index
                    s_shape = bone.custom_shape
                    for arm in target:
                        arm.pose.bones[name].bone_group_index = s_index
                        arm.pose.bones[name].custom_shape = s_shape
                
                
                not_copy=("matrix", "dimension", "dupli", "name", "parent", "pose", "proxy", "select", "bl_rna", "bound_box", "children", "location", "rotation", "scale")
                for arm in target:
                    for prop in dir(source):
                        try:
                            if not any(x in prop for x in not_copy):
                                setattr(arm, prop, getattr(source, prop))
                        except:
                            pass
                Zeile 1-33 wie bisher
                34-38 löscht bestehende Bone-Groups in den Ziel-Armatures und fügt neue gemäß der Quelle hinzu
                40-45 fügt dann die Color-Sets hinzu
                47-53 ordnet dann die Bones den Bone-Gruppen zu und fügt auch noch evtl. Custom-Shapes ein
                57-63 kopiert die ganzen Properties der Armature (ursprünglich dabei auch noch location, rotation und scale, weshalb ich das und einiges anderes durch das tuple not_copy ausgeschlossen habe)
                Würde man den letzten Block, also 57-63 auf die bones der Ziel-Armatures anwenden, würden wahrscheinlich Sachen wie Bendy-Bones und IK_limits kopiert, habe ich aber noch nicht probiert.

                Kommentar


                • #9
                  Jetzt habe ich es probiert und es sieht tatsächlich so aus, als ob es funktionieren würde:
                  Code:
                  import bpy
                  
                  target = bpy.context.selected_objects
                  source =  bpy.context.active_object
                  target.remove(source)
                  
                  bones_source = source.pose.bones
                  
                  for arm in target:
                      for bone in arm.pose.bones:
                              cons = bone.constraints
                              for con in cons:
                                  bone.constraints.remove(con)        
                  
                  for bone in bones_source:
                      name = bone.name
                      constraints_source = bone.constraints
                  
                      for arm in target:
                          bone_target = arm.pose.bones[name]
                  
                          for constr in constraints_source:
                              new_con = bone_target.constraints.new( constr.type)
                  
                              for prop in dir(constr):
                                  try:
                                      setattr(new_con, prop, getattr(constr, prop))
                                      if prop == "target":
                                          setattr(new_con, prop, arm)
                                  except:
                                      pass
                  
                  
                  for arm in target:
                      for group in arm.pose.bone_groups:
                          arm.pose.bone_groups.remove(group)
                      for group in source.pose.bone_groups:
                          arm.pose.bone_groups.new(name=group.name)
                  
                  for group in source.pose.bone_groups:
                      color_set = group.color_set
                      name = group.name
                      for arm in target:
                          arm.pose.bone_groups[name].color_set = color_set
                          arm.pose.bone_groups[name].color_set = color_set
                  
                  for bone in source.pose.bones:
                      name = bone.name
                      s_index = bone.bone_group_index
                      s_shape = bone.custom_shape
                      for arm in target:
                          arm.pose.bones[name].bone_group_index = s_index
                          arm.pose.bones[name].custom_shape = s_shape
                  
                  
                  not_copy=("matrix", "dimension", "dupli", "name", "parent", "pose", "proxy", "select", "bl_rna", "bound_box", "children", "location", "rotation", "scale")
                  for arm in target:
                      for prop in dir(source):
                          try:
                              if not any(x in prop for x in not_copy):
                                  setattr(arm, prop, getattr(source, prop))
                          except:
                              pass
                  
                  for bone in source.pose.bones:
                      name = bone.name
                      for arm in target:
                          t_bone = arm.pose.bones[name]
                          for prop in dir(bone):
                              try:
                                  if not any(x in prop for x in not_copy):
                                      setattr(t_bone, prop, getattr(bone, prop))
                              except:
                                  pass
                  Zeile 65-74 kopiert offenbar die ganzen einzelnen bone-properties, wie bendy-bones, ik-limits, etc.

                  Kommentar

                  Lädt...
                  X