Ania Napisano 9 Wrzesień 2016 Napisano 9 Wrzesień 2016 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()
NuttyART Napisano 9 Wrzesień 2016 Napisano 9 Wrzesień 2016 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)
Monio Napisano 9 Wrzesień 2016 Napisano 9 Wrzesień 2016 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.
Ania Napisano 9 Wrzesień 2016 Autor Napisano 9 Wrzesień 2016 Dzięki, działa (metoda Monia okazała się prostsza do zaimplementowania niż tamten skrypt, ale dzięki obu!)
Ania Napisano 17 Listopad 2016 Autor Napisano 17 Listopad 2016 (edytowane) 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 2016 przez Ania
Monio Napisano 17 Listopad 2016 Napisano 17 Listopad 2016 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.
Ania Napisano 18 Listopad 2016 Autor Napisano 18 Listopad 2016 (edytowane) 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 2016 przez Ania
Ania Napisano 22 Listopad 2016 Autor Napisano 22 Listopad 2016 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.
Monio Napisano 22 Listopad 2016 Napisano 22 Listopad 2016 Ah. Dlatego nie polecam komendy Instal from File. Lepiej sobie zrobić skrót do blender/scripts/addons i tam manualnie wrzucać.
Rekomendowane odpowiedzi
Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto
Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.
Zarejestruj nowe konto
Załóż nowe konto. To bardzo proste!
Zarejestruj sięZaloguj się
Posiadasz już konto? Zaloguj się poniżej.
Zaloguj się