Napisano 9 Wrzesień 20168 l Skleciłam sobie skrypt króry ustawia kości FK tak samo jak IK. Na tyle działa. Problem mam z umieszczeniem skryptu w interfacie, jestem początkująca. Doszłam do punktu że skrypt (tzn. button) po instalacji pojawia się w każdej kości obojętnie jakiej armatury w pose mode. Chciałabym jednak, żeby button był dostępny tylko z określonych kości określonych armatur, żebym mogła go "uaktywnić" jakoś ręcznie tylko dla armatur które w ogóle mają nogi IK/FK. Żeby to jakoś było zapisane w danej armaturze. Da się? Tu skrypt (odpuściłam część która kręci kośćmi, bo nie w tym problem). bl_info = { "name": "Align FK to IK", "category": "Animation", } import bpy class AlignFK_panel(bpy.types.Panel): """Creates a Panel in the Object properties window""" bl_label = "Align FK" bl_idname = "BONE_PT_alignFK" bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "bone" def draw(self, context): layout = self.layout row = layout.row() row.operator("pose.align_fk", text = "Align FK") class AlignFK(bpy.types.Operator): bl_idname = "pose.align_fk" bl_label = "Align FK" bl_options = {"UNDO"} def execute(self, context): #placeholder print("hello world you are aligned now") return {'FINISHED'} def register(): bpy.utils.register_class(AlignFK) bpy.utils.register_class(AlignFK_panel) def unregister(): bpy.utils.unregister_class(AlignFK) bpy.utils.unregister_class(AlignFK_panel) if __name__ == "__main__": register()
Napisano 9 Wrzesień 20168 l W pisaniu skryptów zupełnie się nie znam. Jak znajdę jakiś przydatny to sobie zapisuje i jak jest mi potrzebny to próbując logicznie myśląc, staram się tak pozmieniać linijki tekstu, tak aby zadziałał na moim rigu. Dlatego też gotowego rozwiązania niestety nie jestem w stanie Ci podać, ale wiem, że ten skrypt ma funkcje o którą prosisz. Używam go do większości moich rigów i jest łatwy do "rozgryzienia". Zdaje się, że w Twoim przypadku, pierwsze będziesz musiała zdefiniować imiona kości, tak aby skrypt wiedział która kość to która "#Define the names we'll use for bones" a potem tylko "#Define what controls to show depending on the bones selected". Ale tak jak pisałem, nie mam pojęcia czy to u Ciebie zadziała, musisz popróbować. :) ###RIG CONTROLS class RigUI(bpy.types.Panel): bl_label = "Rig Controls" bl_space_type = "VIEW_3D" bl_region_type = "UI" bl_context = "posemode" def draw(self, context): layout = self.layout row = layout.row() pose_bones = context.active_object.pose.bones try: selected_bones = [bone.name for bone in context.selected_pose_bones] selected_bones += [context.active_pose_bone.name] except (AttributeError, TypeError): return def is_selected(names): #Returns whether any of the named bones are selected if type(names) == list: for name in names: if name in selected_bones: return True elif names in selected_bones: return True return False #Define the names we'll use for bones head = "head" neck = "neck" ribs = "ribs" hips = "hips" shoulderl = "shoulder.L" uparmfkl = "upper_arm_FK.L" forearmfkl = "forearm_FK.L" handfkl = "hand_FK.L" shoulderr = "shoulder.R" uparmfkr = "upper_arm_FK.R" forearmfkr = "forearm_FK.R" handfkr = "hand_FK.R" thighfkl = "thigh_FK.L" shinfkl = "shin_FK.L" footfkl = "foot_FK.L" toefkl = "toe_FK.L" thighfkr = "thigh_FK.R" shinfkr = "shin_FK.R" footfkr = "foot_FK.R" toefkr = "toe_FK.R" handikl = "hand_IK.L" elbowpolel = "elbow_pole.L" handikr = "hand_IK.R" elbowpoler = "elbow_pole.R" footikl = "foot_IK.L" kneepolel = "knee_pole.L" footikr = "foot_IK.R" kneepoler = "knee_pole.R" #Define what controls to show depending on the bones selected if is_selected([head, neck]): layout.prop(pose_bones["head"], '["isolate head"]', slider=True) if is_selected([ribs, hips]): layout.prop(pose_bones["ribs"], '["isolate torso"]', slider=True) if is_selected([hips]): layout.prop(pose_bones["hips"], '["pivot slide"]', slider=True) if is_selected([shoulderl, uparmfkl, forearmfkl, handfkl]): layout.prop(pose_bones["upper_arm_FK.L"], '["isolate left arm"]', slider=True) if is_selected([shoulderr, uparmfkr, forearmfkr, handfkr]): layout.prop(pose_bones["upper_arm_FK.R"], '["isolate right arm"]', slider=True) if is_selected([thighfkl, shinfkl, footfkl, toefkl]): layout.prop(pose_bones["thigh_FK.L"], '["isolate left leg"]', slider=True) if is_selected([thighfkr, shinfkr, footfkr, toefkr]): layout.prop(pose_bones["thigh_FK.R"], '["isolate right leg"]', slider=True) if is_selected([handikl, elbowpolel, shoulderl, uparmfkl, forearmfkl, handfkl]): layout.prop(pose_bones["hand_IK.L"], '["fk/ik left arm"]', slider=True) if is_selected([handikr, elbowpoler, shoulderr, uparmfkr, forearmfkr, handfkr]): layout.prop(pose_bones["hand_IK.R"], '["fk/ik right arm"]', slider=True) if is_selected([footikl, kneepolel, thighfkl, shinfkl, footfkl, toefkl]): layout.prop(pose_bones["foot_IK.L"], '["fk/ik left leg"]', slider=True) if is_selected([footikr, kneepoler, thighfkr, shinfkr, footfkr, toefkr]): layout.prop(pose_bones["foot_IK.R"], '["fk/ik right leg"]', slider=True) ###RIG LAYERS class RigLayers(bpy.types.Panel): bl_label = "Rig Controls" bl_space_type = "VIEW_3D" bl_region_type = "UI" bl_label = "Rig Layers" def draw(self, context): layout = self.layout col = layout.column() #Layers row = col.row() row.prop(context.active_object.data, 'layers', index=0, toggle=True, text='head') row = col.row() row.prop(context.active_object.data, 'layers', index=7, toggle=True, text='torso') row = col.row() row.prop(context.active_object.data, 'layers', index=1, toggle=True, text='FK left arm') row = col.row() row.prop(context.active_object.data, 'layers', index=2, toggle=True, text='IK left arm') row = col.row() row.prop(context.active_object.data, 'layers', index=3, toggle=True, text='FK right arm') row = col.row() row.prop(context.active_object.data, 'layers', index=4, toggle=True, text='IK right arm') row = col.row() row.prop(context.active_object.data, 'layers', index=8, toggle=True, text='FK left leg') row = col.row() row.prop(context.active_object.data, 'layers', index=9, toggle=True, text='IK left leg') row = col.row() row.prop(context.active_object.data, 'layers', index=10, toggle=True, text='FK right leg') row = col.row() row.prop(context.active_object.data, 'layers', index=11, toggle=True, text='IK right leg') row = col.row() row.prop(context.active_object.data, 'layers', index=15, toggle=True, text='ROOT') bpy.utils.register_class(RigUI) bpy.utils.register_class(RigLayers)
Napisano 9 Wrzesień 20168 l Da sie, prostsze niż myślisz. W operatorze aktywujacym dodajesz Custom Property dla armatury, bool albo int. https://www.blender.org/api/blender_python_api_current/info_quickstart.html#custom-properties http://blender.stackexchange.com/questions/43785/adding-other-types-of-custom-properties Potem w kodzie interfaceu robisz łańcuch if'ów który sprawdza typ aktywnego obiektu i to czy ma twojego custom propa. If "my_prop1" in armature. Wtedy dopiero rysujesz button. IK możesz wykrywać iterując po bpy.context.active_object.pose.bones i korzystając z komendy in_ik_chain.
Napisano 9 Wrzesień 20168 l Autor Dzięki, działa (metoda Monia okazała się prostsza do zaimplementowania niż tamten skrypt, ale dzięki obu!)
Napisano 17 Listopad 20168 l Autor Nowy problem z tym samym skryptem: mam pliki: rycerz.blend oraz scena.blend do której ten rycerz jest podłączony z armaturą jako proxy. W pliku rycerz.blend odpalam skrypt, wszystko działa, otwieram scena.blend, wszystko działa. Niestety jeśli zamknę blendera, i potem otworzę nie rycerza ale od razu scena.blend, już nie działa, i muszę ponownie wchodzić do rycerz.blend, odpalić skrypt, żeby działało w scenie. Co dziwniejsze, button się pokazuje, tylko nie rusza kośćmi, tak jakby czytało tylko część skryptu. Haczyk Register pod okienkiem tekstowym jest aktywny, bo myślałam że to coś z tym, ale nie pomogło. Załączam skrypt. "fkp" to property kości o której pisał Monio. bl_info = { "name": "Align FK to IK", "category": "Animation", } import bpy class AlignFK_panel(bpy.types.Panel): """Creates a Panel in the Bone properties window""" bl_label = "Pose Tools" bl_idname = "BONE_PT_alignFK" bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "bone" def draw(self, context): try: if bpy.context.active_pose_bone["fkp"] == 1: layout = self.layout row = layout.row() row.operator("pose.align_fk", text = "Align FK") except: print("no fkp set") class AlignFK(bpy.types.Operator): bl_idname = "pose.align_fk" bl_label = "Align FK" bl_options = {"UNDO"} def execute(self, context): arm = bpy.context.active_object FK = bpy.context.active_pose_bone #["FK_tibia.L"] def copy_matrix(source, target): target.matrix = source.matrix return def align_bones(active, bonelist): if active in bonelist: for bon in bonelist: IK = arm.pose.bones["ik"+bon[2:]] FK = arm.pose.bones[bon] copy_matrix(IK,FK) bpy.data.scenes[0].update() bpy.ops.pose.select_all(action='DESELECT') for bon in bonelist: bpy.context.active_object.pose.bones[bon].bone.select=True bpy.data.scenes[0].update() bpy.ops.anim.keyframe_insert(type='Rotation') legbones = ["Fk_fem.L", "Fk_tib.L"] align_bones(FK.name, legbones) legbones = ["Fk_fem.R", "Fk_tib.R"] align_bones(FK.name, legbones) return {'FINISHED'} def register(): bpy.utils.register_class(AlignFK) bpy.utils.register_class(AlignFK_panel) def unregister(): bpy.utils.unregister_class(AlignFK) bpy.utils.unregister_class(AlignFK_panel) if __name__ == "__main__": register() Edytowane 17 Listopad 20168 l przez Ania
Napisano 17 Listopad 20168 l bl_info = { "name": "Align FK to IK", "category": "Animation", } import bpy ### Globalnie dodajesz typ Custom Property do typu kosci from bpy.props import IntProperty bpy.types.PoseBone.fkp = IntProperty(name = "FKP", default = 0) class AlignFK_panel(bpy.types.Panel): """Creates a Panel in the Bone properties window""" bl_label = "Pose Tools" bl_idname = "BONE_PT_alignFK" bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "bone" def draw(self, context): layout = self.layout col = layout.column() ### if bpy.context.active_object.mode == 'POSE': ### pbone = bpy.context.active_pose_bone if 'fkp' in pbone: col.prop(pbone, 'fkp') ### Czy to nie powinno być zamienione na wieksze niz zero ? if pbone.fkp == 1: col.operator("pose.align_fk", text = "Align FK") ### else: col.label("No FKP set", icon='ERROR') col.operator("pose.align_fk_initialize", text = "Initialize FKP") ### else: col.label("Enable Pose Mode", icon='ERROR') class AlignFKInitialize(bpy.types.Operator): bl_idname = "pose.align_fk_initialize" bl_label = "Align FK Initialize" bl_options = {"UNDO"} def execute(self, context): bpy.context.active_pose_bone.fkp = 1 return {'FINISHED'} class AlignFK(bpy.types.Operator): bl_idname = "pose.align_fk" bl_label = "Align FK" bl_options = {"UNDO"} def execute(self, context): arm = bpy.context.active_object FK = bpy.context.active_pose_bone #["FK_tibia.L"] def copy_matrix(source, target): target.matrix = source.matrix return def align_bones(active, bonelist): if active in bonelist: for bon in bonelist: IK = arm.pose.bones["ik"+bon[2:]] FK = arm.pose.bones[bon] copy_matrix(IK,FK) bpy.data.scenes[0].update() bpy.ops.pose.select_all(action='DESELECT') for bon in bonelist: bpy.context.active_object.pose.bones[bon].bone.select=True bpy.data.scenes[0].update() bpy.ops.anim.keyframe_insert(type='Rotation') legbones = ["Fk_fem.L", "Fk_tib.L"] align_bones(FK.name, legbones) legbones = ["Fk_fem.R", "Fk_tib.R"] align_bones(FK.name, legbones) return {'FINISHED'} def register(): bpy.utils.register_class(AlignFKInitialize) bpy.utils.register_class(AlignFK) bpy.utils.register_class(AlignFK_panel) def unregister(): bpy.utils.unregister_class(AlignFKInitialize) bpy.utils.unregister_class(AlignFK) bpy.utils.unregister_class(AlignFK_panel) if __name__ == "__main__": register() Nie wiem czy to rozwiąże twój problem. Wydaje mi się że to nie działało bo nie zdefiniowałaś typu Custom Property z poziomu Addona. Dodałem jakieś tam UI.
Napisano 18 Listopad 20168 l Autor Monio dzięki ale nie pomogło. Skrypt jest przez twoją zmianę wygodniejszy, bo nie muszę ręcznie dodawać property, ale w pliku w którym model jest jako proxy, interface nie pokazuje przycisków z twojego skryptu. Czy skrypty są ładowane jakoś lokalnie, tylko w pliku w którym jest ich tekst? Ale ten mój zaktywowałam nawet przez Properties/Addons, więc myślę że powinien być zdefiniowany globalnie, a on dalej nie działa. Jeśli zładuję tekst skryptu do pliku ze sceną, i dam run script, to potem działa, ale chyba też nie o to chodzi żeby to za każdym razem odpalać. Edytowane 18 Listopad 20168 l przez Ania
Napisano 22 Listopad 20168 l Autor Ok już wszystko działa. Blender czytał jakąś starą wersję skryptu którą sobie bez mojej wiedzy gdzieś zapisał (AppData/Roaming/..), a w tej wersji były tylko końskie nogi, nie rycerskie. Wykasowałam z tamtąd, zainstalowałam na nowo przez Properties/Addons, teraz wszystko gra.
Napisano 22 Listopad 20168 l Ah. Dlatego nie polecam komendy Instal from File. Lepiej sobie zrobić skrót do blender/scripts/addons i tam manualnie wrzucać.
Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto