improved ui and poll handling
0.6.0 - World paste and `Jump next frame` - more compact and improved ui for world paste - fix errors in some operatorsmaster
parent
3c5ccf422a
commit
c6a75f25f8
|
@ -32,8 +32,6 @@ def anim_path_from_translate():
|
|||
print(fn.helper())
|
||||
|
||||
ob = bpy.context.object
|
||||
if ob.type != 'ARMATURE':
|
||||
return ('ERROR', 'active is not an armature type')
|
||||
|
||||
# found curve through constraint
|
||||
b = bpy.context.active_pose_bone
|
||||
|
@ -216,6 +214,7 @@ class UAC_OT_animate_path(bpy.types.Operator):
|
|||
|
||||
def execute(self, context):
|
||||
# TODO clear previous animation (keys) if there is any
|
||||
|
||||
err = anim_path_from_translate()
|
||||
if err:
|
||||
self.report({err[0]}, err[1])
|
||||
|
|
|
@ -159,12 +159,13 @@ class UAC_OT_create_curve_path(bpy.types.Operator):
|
|||
class UAC_OT_create_follow_path(bpy.types.Operator):
|
||||
bl_idname = "anim.create_follow_path"
|
||||
bl_label = "Create Follow Path Constraint"
|
||||
bl_description = "Create follow path targeting curve in field"
|
||||
bl_description = "Create follow path targeting curve chosen in dedicated field"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.object and context.object.type == 'ARMATURE'
|
||||
return context.object and context.object.type == 'ARMATURE' \
|
||||
and context.scene.anim_cycle_settings.path_to_follow
|
||||
|
||||
def execute(self, context):
|
||||
ob = context.object
|
||||
|
|
|
@ -248,6 +248,13 @@ class UAC_OT_contact_to_ground(bpy.types.Operator):
|
|||
return context.object and context.object.type == 'ARMATURE'
|
||||
|
||||
def execute(self, context):
|
||||
# TODO: check if possible to auto detect a ground when gnd is not specified
|
||||
# (still instersteing to be able to get the ground user wants)
|
||||
|
||||
if not context.scene.anim_cycle_settings.gnd:
|
||||
self.report({'ERROR'}, 'need to choose a target mesh for "Ground"')
|
||||
return {"CANCELLED"}
|
||||
|
||||
# context.scene.anim_cycle_settings.expand_on_selected_bones
|
||||
err = snap_feet()
|
||||
if err:
|
||||
|
|
|
@ -85,11 +85,44 @@ class UAC_OT_world_space_paste_next(bpy.types.Operator):
|
|||
context.scene.frame_current = new_frame
|
||||
return {"FINISHED"}
|
||||
|
||||
class UAC_OT_world_space_paste_next_frame(bpy.types.Operator):
|
||||
bl_idname = "anim.world_space_paste_next_frame"
|
||||
bl_label = "World Paste Jump Frame"
|
||||
bl_description = "Paste world space transforms and keyframe available chanels\nThen jump to prev/next frame"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.object and context.mode == 'POSE' and context.active_pose_bone
|
||||
|
||||
prev: bpy.props.BoolProperty()
|
||||
|
||||
def execute(self, context):
|
||||
# apply matrix
|
||||
context.active_pose_bone.matrix = context.object.matrix_world.inverted() @ bpy.context.view_layer.world_space_store
|
||||
|
||||
# insert keyframe at value
|
||||
# context.object.keyframe_insert(data_path, index=-1, frame=bpy.context.scene.frame_current, group="", options={'INSERTKEY_AVAILABLE'})
|
||||
bpy.ops.anim.keyframe_insert_menu(type='Available')
|
||||
|
||||
# jump to next frame
|
||||
act = fn.get_obj_action(context.object)
|
||||
if not act:
|
||||
self.report({'ERROR'}, 'No action on armature')
|
||||
return {'CANCELLED'}
|
||||
|
||||
offset = -1 if self.prev else 1
|
||||
new_frame = context.scene.frame_current + offset
|
||||
|
||||
context.scene.frame_current = new_frame
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
classes=(
|
||||
UAC_OT_world_space_copy,
|
||||
UAC_OT_world_space_paste,
|
||||
UAC_OT_world_space_paste_next,
|
||||
UAC_OT_world_space_paste_next_frame,
|
||||
)
|
||||
|
||||
def register():
|
||||
|
|
|
@ -56,6 +56,13 @@ Bonus:
|
|||
|
||||
## Changelog:
|
||||
|
||||
|
||||
0.6.0
|
||||
|
||||
- World paste and `Jump next frame`
|
||||
- more compact and improved ui for world paste
|
||||
- fix errors in some operators
|
||||
|
||||
0.5.0
|
||||
|
||||
- pin feet working
|
||||
|
|
|
@ -2,7 +2,7 @@ bl_info = {
|
|||
"name": "Unfold Anim Cycle",
|
||||
"description": "Anim tools to develop walk/run cycles along a curve",
|
||||
"author": "Samuel Bernou",
|
||||
"version": (0, 5, 0),
|
||||
"version": (0, 6, 0),
|
||||
"blender": (3, 0, 0),
|
||||
"location": "View3D",
|
||||
"warning": "WIP",
|
||||
|
|
1
fn.py
1
fn.py
|
@ -59,6 +59,7 @@ def get_follow_curve_from_armature(arm):
|
|||
name = get_root_name()
|
||||
|
||||
parents = []
|
||||
const = False
|
||||
# root = b.id_data.pose.bones.get(name)
|
||||
root = arm.pose.bones.get(name)
|
||||
for c in root.constraints:
|
||||
|
|
31
panels.py
31
panels.py
|
@ -13,8 +13,12 @@ class UAC_PT_walk_cycle_anim_panel(bpy.types.Panel):
|
|||
# need to know root orientation forward)
|
||||
## know direction to evaluate feet moves
|
||||
## Define Constraint axis (depend on root orientation)
|
||||
layout.prop(settings, "forward_axis")
|
||||
layout.operator("uac.autoset_axis", text='Auto-Set Axis')
|
||||
|
||||
# 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')
|
||||
|
||||
box = layout.box()
|
||||
if not settings.path_to_follow:
|
||||
|
@ -81,10 +85,25 @@ class UAC_PT_anim_tools_panel(bpy.types.Panel):
|
|||
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()
|
||||
row.operator('anim.world_space_paste_next', text='Paste Prev', icon='PASTEDOWN').prev = True
|
||||
row.operator('anim.world_space_paste_next', text='Paste Next', icon='PASTEDOWN').prev = False
|
||||
# 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
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ class UAC_PG_settings(bpy.types.PropertyGroup) :
|
|||
|
||||
forward_axis : bpy.props.EnumProperty(
|
||||
name='Forward Axis',
|
||||
default='TRACK_NEGATIVE_Y', # Modifier default is FORWARD_X
|
||||
default='FORWARD_Z', # Modifier default is FORWARD_X (should be TRACK_NEGATIVE_Y for a good rig)
|
||||
description='Local axis of the "root" bone that point forward',
|
||||
items=(
|
||||
('FORWARD_X', 'X', ''),
|
||||
|
|
Loading…
Reference in New Issue