0.7.0 - auto-detect foot to use for path animation - button to go back and forth between curve edit and armature pose mode - UI revamp showing better separation of tool categories
		
			
				
	
	
		
			135 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import bpy
 | |
| from . import fn
 | |
| 
 | |
| class UAC_PT_walk_cycle_anim_panel(bpy.types.Panel):
 | |
|     bl_space_type = "VIEW_3D"
 | |
|     bl_region_type = "UI"
 | |
|     bl_category = "Anim"
 | |
|     bl_label = "Walk Cycle Anim"
 | |
| 
 | |
|     def draw(self, context):
 | |
|         layout = self.layout
 | |
|         prefs = fn.get_addon_prefs()
 | |
|         ob = context.object
 | |
| 
 | |
|         settings = context.scene.anim_cycle_settings
 | |
|         tweak = settings.tweak
 | |
|         # need to know root orientation forward)
 | |
|         ## know direction to evaluate feet moves
 | |
|         ## Define Constraint axis (depend on root orientation)
 | |
|         
 | |
|         # layout.prop(settings, "forward_axis") # plain prop
 | |
|         row = layout.row()
 | |
|         row.label(text='Forward Axis')
 | |
|         row.prop(settings, "forward_axis", text='')
 | |
|         layout.operator("uac.autoset_axis", text='Auto-Set Axis')
 | |
|         
 | |
|         if not settings.path_to_follow:
 | |
|             layout.operator('anim.create_curve_path', text='Create Curve at Root Position', icon='CURVE_BEZCURVE')
 | |
|         
 | |
|         box = layout.box()
 | |
|         expand_icon = 'TRIA_DOWN' if tweak else 'TRIA_RIGHT'
 | |
|         box.prop(settings, 'tweak', text='Curve Options', icon=expand_icon)
 | |
|         if tweak:
 | |
|             #-# path and ground objects
 | |
|             box.prop_search(settings, "path_to_follow", context.scene, "objects")
 | |
|             box.prop_search(settings, "gnd", context.scene, "objects")
 | |
| 
 | |
|             row = box.row()
 | |
|             row.operator('anim.snap_curve_to_ground', text='Snap curve to ground', icon='SNAP_ON')
 | |
|             row.active = bool(settings.gnd)
 | |
|             
 | |
|             
 | |
|             # Determine if already has a constraint (a bit too much condition in a panel...)
 | |
|             constrained = False
 | |
|             if ob:
 | |
|                 if ob.type == 'ARMATURE':
 | |
|                     pb = ob.pose.bones.get(prefs.tgt_bone)
 | |
|                     if pb:
 | |
|                         follow = pb.constraints.get('Follow Path')
 | |
|                         if follow and follow.target:
 | |
|                             box.label(text=f'{pb.name} -> {follow.target.name}', icon='CON_FOLLOWPATH')
 | |
|                             constrained = True
 | |
|                             ## Put this in a setting popup or submenu
 | |
|                     # if context.mode == 'POSE':
 | |
|                     if not constrained:
 | |
|                         box.operator('anim.create_follow_path', text='Add follow path constraint', icon='CON_FOLLOWPATH')
 | |
|                     box.operator('uac.edit_curve', text='Edit Curve', icon='OUTLINER_DATA_CURVE') # FORCE_CURVE
 | |
|                 
 | |
|                 elif ob.type == 'CURVE':
 | |
|                     if context.mode in ('OBJECT', 'EDIT_CURVE') \
 | |
|                         and settings.path_to_follow \
 | |
|                             and ob == settings.path_to_follow:
 | |
|                         box.operator('uac.object_from_curve', text='Back To Object', icon='LOOP_BACK')                    
 | |
| 
 | |
|         box = layout.box()
 | |
|         col=box.column()
 | |
|         col.label(text='Motion:')
 | |
|         col.prop(settings, "start_frame", text='Start')
 | |
|         # col.prop(settings, "foot_axis", text='Foot Axis')
 | |
|         col.operator('anim.animate_path', text='Animate Forward Motion', icon='ANIM')
 | |
| 
 | |
|         row=col.row()
 | |
|         row.operator('anim.adjust_animation_length',  text='Adjust Forward Speed', icon='MOD_TIME')
 | |
| 
 | |
|         ## Bake cycle (on selected)
 | |
|         box = layout.box()
 | |
|         col=box.column()
 | |
|         col.label(text='Keys:')
 | |
|         row=col.row()
 | |
|         row.prop(settings, "linear", text='Linear')
 | |
|         row.prop(settings, "expand_on_selected_bones")
 | |
|         
 | |
|         txt = 'Bake keys' if settings.linear else 'Bake keys and step path'
 | |
|         col.operator('anim.bake_cycle_and_step', text=txt, icon='SHAPEKEY_DATA')
 | |
|         
 | |
|         # Pin feet
 | |
|         col.operator('anim.pin_feets', text='Pin feets', icon='PINNED')
 | |
| 
 | |
|         
 | |
| 
 | |
| class UAC_PT_anim_tools_panel(bpy.types.Panel):
 | |
|     bl_space_type = "VIEW_3D"
 | |
|     bl_region_type = "UI"
 | |
|     bl_category = "Anim"
 | |
|     bl_label = "Tools"
 | |
| 
 | |
|     def draw(self, context):
 | |
|         layout = self.layout
 | |
|         layout.operator('anim.contact_to_ground', text='Ground selected feet', icon='SNAP_OFF')
 | |
|         row = layout.row()
 | |
|         row.operator('anim.world_space_copy', text='Copy Pose', icon='COPYDOWN')
 | |
|         # row.operator('anim.world_space_paste', text='Paste', icon='PASTEDOWN')
 | |
|         # row = layout.row(align=False)
 | |
|         
 | |
|         ## multi buttons
 | |
|         # row.label(text='Paste and jump:')
 | |
|         # row = layout.row(align=True)
 | |
|         # row.operator('anim.world_space_paste_next', text='Prev key', icon='PREV_KEYFRAME').prev = True # Paste Prev key
 | |
|         # row.operator('anim.world_space_paste_next', text='Next key', icon='NEXT_KEYFRAME').prev = False # Paste Next key
 | |
|         # row = layout.row(align=True)
 | |
|         # row.operator('anim.world_space_paste_next_frame', text='Prev frame', icon='FRAME_PREV').prev = True # Paste Prev frame
 | |
|         # row.operator('anim.world_space_paste_next_frame', text='Next frame', icon='FRAME_NEXT').prev = False # Paste Next frame
 | |
|         
 | |
|         row = layout.row(align=True)
 | |
|         row.operator('anim.world_space_paste_next_frame', text='', icon='FRAME_PREV').prev = True
 | |
|         row.operator('anim.world_space_paste_next', text='', icon='PREV_KEYFRAME').prev = True
 | |
|         row.operator('anim.world_space_paste', text='', icon='PASTEDOWN')
 | |
|         row.operator('anim.world_space_paste_next', text='', icon='NEXT_KEYFRAME').prev = False
 | |
|         row.operator('anim.world_space_paste_next_frame', text='', icon='FRAME_NEXT').prev = False
 | |
|         row.scale_x = 2
 | |
| 
 | |
| 
 | |
| 
 | |
| classes=(
 | |
| UAC_PT_walk_cycle_anim_panel,
 | |
| UAC_PT_anim_tools_panel,
 | |
| )
 | |
| 
 | |
| def register():
 | |
|     for cls in classes:
 | |
|         bpy.utils.register_class(cls)
 | |
| 
 | |
| def unregister():
 | |
|     for cls in reversed(classes):
 | |
|         bpy.utils.unregister_class(cls) |