diff --git a/CHANGELOG.md b/CHANGELOG.md index 70878a8..444ba6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +1.4.4 + +- changed: default start to 100 +- fixed: can now add shortcut to world copy/paste +- fixed: snap curve to ground + 1.4.3 - fixed: reset constrained bone position and add a location key at (0,0,0) diff --git a/OP_world_copy_paste.py b/OP_world_copy_paste.py index 9743d26..a1dad7e 100644 --- a/OP_world_copy_paste.py +++ b/OP_world_copy_paste.py @@ -3,7 +3,7 @@ from . import fn class AW_OT_world_space_copy(bpy.types.Operator): - bl_idname = "autowalk.world_space_copy" + bl_idname = "pose.world_space_copy" bl_label = "World Copy" bl_description = "Copy world space transforms. Store active bone matrix" bl_options = {"REGISTER", "UNDO"} @@ -18,13 +18,16 @@ class AW_OT_world_space_copy(bpy.types.Operator): return {"FINISHED"} class AW_OT_world_space_paste(bpy.types.Operator): - bl_idname = "autowalk.world_space_paste" + bl_idname = "pose.world_space_paste" bl_label = "World Paste" bl_description = "Paste world space transforms. Apply stored matrix to active bone" bl_options = {"REGISTER", "UNDO"} @classmethod def poll(cls, context): + if not hasattr(bpy.context.view_layer, 'world_space_store'): + cls.poll_message_set("Nothing To Paste") + return False return context.object and context.mode == 'POSE' and context.active_pose_bone @@ -37,13 +40,16 @@ class AW_OT_world_space_paste(bpy.types.Operator): return {"FINISHED"} class AW_OT_world_space_paste_next(bpy.types.Operator): - bl_idname = "autowalk.world_space_paste_next" + bl_idname = "pose.world_space_paste_next" bl_label = "World Paste Jump" bl_description = "Paste world space transforms and keyframe available chanels\nThen jump to prev/next key" bl_options = {"REGISTER", "UNDO"} @classmethod def poll(cls, context): + if not hasattr(bpy.context.view_layer, 'world_space_store'): + cls.poll_message_set("Nothing To Paste") + return False return context.object and context.mode == 'POSE' and context.active_pose_bone prev: bpy.props.BoolProperty() @@ -86,13 +92,16 @@ class AW_OT_world_space_paste_next(bpy.types.Operator): return {"FINISHED"} class AW_OT_world_space_paste_next_frame(bpy.types.Operator): - bl_idname = "autowalk.world_space_paste_next_frame" + bl_idname = "pose.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): + if not hasattr(bpy.context.view_layer, 'world_space_store'): + cls.poll_message_set("Nothing To Paste") + return False return context.object and context.mode == 'POSE' and context.active_pose_bone prev: bpy.props.BoolProperty() diff --git a/__init__.py b/__init__.py index c7e9f81..95fdb55 100644 --- a/__init__.py +++ b/__init__.py @@ -4,7 +4,7 @@ bl_info = { "name": "Auto Walk", "description": "Develop a walk/run cycles along a curve and pin feets", "author": "Samuel Bernou", - "version": (1, 4, 3), + "version": (1, 4, 4), "blender": (3, 0, 0), "location": "View3D", "warning": "", diff --git a/fn.py b/fn.py index 90065e6..e56d4b3 100644 --- a/fn.py +++ b/fn.py @@ -58,11 +58,16 @@ def convertAttr(Attr): def get_gnd(): - for o in bpy.context.scene.objects: - if o.type == 'MESH' and o.name.lower() in ('ground', 'gnd'): - return o - # nothing found - print('ERROR', 'No "gnd" object found') + gnd = bpy.context.scene.anim_cycle_settings.gnd + if not gnd: + for o in bpy.context.scene.objects: + if o.type == 'MESH' and o.name.lower() in ('ground', 'gnd'): + return o + if not gnd: + # nothing found + print('ERROR', 'No "gnd" object found') + return gnd + def get_follow_curve_from_armature(arm): @@ -412,10 +417,12 @@ def snap_curve(): curve_act = None anim_frame = None + # if it's on a snap curve, fetch original if '_snap' in curve.name: org_name = re.sub(r'_snap\.?\d{0,3}$', '', curve.name) org_curve = bpy.context.scene.objects.get(org_name) + if org_curve: const.target = org_curve diff --git a/panels.py b/panels.py index a1bd5bf..b83807b 100644 --- a/panels.py +++ b/panels.py @@ -135,7 +135,7 @@ class AW_PT_anim_tools_panel(bpy.types.Panel): # layout.operator('autowalk.contact_to_ground', text='Ground selected feet', icon='SNAP_OFF') row = layout.row() - row.operator('autowalk.world_space_copy', text='Copy Pose', icon='COPYDOWN') + row.operator('pose.world_space_copy', text='Copy Pose', icon='COPYDOWN') # row.operator('autowalk.world_space_paste', text='Paste', icon='PASTEDOWN') # row = layout.row(align=False) @@ -150,11 +150,11 @@ class AW_PT_anim_tools_panel(bpy.types.Panel): # row.operator('autowalk.world_space_paste_next_frame', text='Next frame', icon='FRAME_NEXT').prev = False # Paste Next frame row = layout.row(align=True) - row.operator('autowalk.world_space_paste_next_frame', text='', icon='FRAME_PREV').prev = True - row.operator('autowalk.world_space_paste_next', text='', icon='PREV_KEYFRAME').prev = True - row.operator('autowalk.world_space_paste', text='', icon='PASTEDOWN') - row.operator('autowalk.world_space_paste_next', text='', icon='NEXT_KEYFRAME').prev = False - row.operator('autowalk.world_space_paste_next_frame', text='', icon='FRAME_NEXT').prev = False + row.operator('pose.world_space_paste_next_frame', text='', icon='FRAME_PREV').prev = True + row.operator('pose.world_space_paste_next', text='', icon='PREV_KEYFRAME').prev = True + row.operator('pose.world_space_paste', text='', icon='PASTEDOWN') + row.operator('pose.world_space_paste_next', text='', icon='NEXT_KEYFRAME').prev = False + row.operator('pose.world_space_paste_next_frame', text='', icon='FRAME_NEXT').prev = False row.scale_x = 2 class AW_PT_nla_tools_panel(bpy.types.Panel): diff --git a/properties.py b/properties.py index c195417..e43ae9d 100644 --- a/properties.py +++ b/properties.py @@ -35,7 +35,7 @@ class AW_PG_settings(bpy.types.PropertyGroup) : start_frame : bpy.props.IntProperty( name="Start Frame", description="Starting frame for animation path", - default=101, + default=100, min=0, max=2**31-1, soft_min=0, soft_max=2**31-1, step=1, options={'HIDDEN'})#, subtype='PIXEL' end_frame : bpy.props.IntProperty(