keymapable buttons and snap curve to ground

1.4.4

- changed: default start to 100
- fixed: can now add shortcut to world copy/paste
- fixed: snap curve to ground
master
Pullusb 2022-04-27 12:01:39 +02:00
parent 07118dafc8
commit 578e0d7266
6 changed files with 39 additions and 17 deletions

View File

@ -1,5 +1,11 @@
# Changelog # 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 1.4.3
- fixed: reset constrained bone position and add a location key at (0,0,0) - fixed: reset constrained bone position and add a location key at (0,0,0)

View File

@ -3,7 +3,7 @@ from . import fn
class AW_OT_world_space_copy(bpy.types.Operator): 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_label = "World Copy"
bl_description = "Copy world space transforms. Store active bone matrix" bl_description = "Copy world space transforms. Store active bone matrix"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
@ -18,13 +18,16 @@ class AW_OT_world_space_copy(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
class AW_OT_world_space_paste(bpy.types.Operator): 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_label = "World Paste"
bl_description = "Paste world space transforms. Apply stored matrix to active bone" bl_description = "Paste world space transforms. Apply stored matrix to active bone"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
@classmethod @classmethod
def poll(cls, context): 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 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"} return {"FINISHED"}
class AW_OT_world_space_paste_next(bpy.types.Operator): 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_label = "World Paste Jump"
bl_description = "Paste world space transforms and keyframe available chanels\nThen jump to prev/next key" bl_description = "Paste world space transforms and keyframe available chanels\nThen jump to prev/next key"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
@classmethod @classmethod
def poll(cls, context): 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 return context.object and context.mode == 'POSE' and context.active_pose_bone
prev: bpy.props.BoolProperty() prev: bpy.props.BoolProperty()
@ -86,13 +92,16 @@ class AW_OT_world_space_paste_next(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
class AW_OT_world_space_paste_next_frame(bpy.types.Operator): 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_label = "World Paste Jump Frame"
bl_description = "Paste world space transforms and keyframe available chanels\nThen jump to prev/next frame" bl_description = "Paste world space transforms and keyframe available chanels\nThen jump to prev/next frame"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
@classmethod @classmethod
def poll(cls, context): 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 return context.object and context.mode == 'POSE' and context.active_pose_bone
prev: bpy.props.BoolProperty() prev: bpy.props.BoolProperty()

View File

@ -4,7 +4,7 @@ bl_info = {
"name": "Auto Walk", "name": "Auto Walk",
"description": "Develop a walk/run cycles along a curve and pin feets", "description": "Develop a walk/run cycles along a curve and pin feets",
"author": "Samuel Bernou", "author": "Samuel Bernou",
"version": (1, 4, 3), "version": (1, 4, 4),
"blender": (3, 0, 0), "blender": (3, 0, 0),
"location": "View3D", "location": "View3D",
"warning": "", "warning": "",

7
fn.py
View File

@ -58,11 +58,16 @@ def convertAttr(Attr):
def get_gnd(): def get_gnd():
gnd = bpy.context.scene.anim_cycle_settings.gnd
if not gnd:
for o in bpy.context.scene.objects: for o in bpy.context.scene.objects:
if o.type == 'MESH' and o.name.lower() in ('ground', 'gnd'): if o.type == 'MESH' and o.name.lower() in ('ground', 'gnd'):
return o return o
if not gnd:
# nothing found # nothing found
print('ERROR', 'No "gnd" object found') print('ERROR', 'No "gnd" object found')
return gnd
def get_follow_curve_from_armature(arm): def get_follow_curve_from_armature(arm):
@ -412,10 +417,12 @@ def snap_curve():
curve_act = None curve_act = None
anim_frame = None anim_frame = None
# if it's on a snap curve, fetch original # if it's on a snap curve, fetch original
if '_snap' in curve.name: if '_snap' in curve.name:
org_name = re.sub(r'_snap\.?\d{0,3}$', '', curve.name) org_name = re.sub(r'_snap\.?\d{0,3}$', '', curve.name)
org_curve = bpy.context.scene.objects.get(org_name) org_curve = bpy.context.scene.objects.get(org_name)
if org_curve: if org_curve:
const.target = org_curve const.target = org_curve

View File

@ -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') # layout.operator('autowalk.contact_to_ground', text='Ground selected feet', icon='SNAP_OFF')
row = layout.row() 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.operator('autowalk.world_space_paste', text='Paste', icon='PASTEDOWN')
# row = layout.row(align=False) # 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.operator('autowalk.world_space_paste_next_frame', text='Next frame', icon='FRAME_NEXT').prev = False # Paste Next frame
row = layout.row(align=True) row = layout.row(align=True)
row.operator('autowalk.world_space_paste_next_frame', text='', icon='FRAME_PREV').prev = True row.operator('pose.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('pose.world_space_paste_next', text='', icon='PREV_KEYFRAME').prev = True
row.operator('autowalk.world_space_paste', text='', icon='PASTEDOWN') row.operator('pose.world_space_paste', text='', icon='PASTEDOWN')
row.operator('autowalk.world_space_paste_next', text='', icon='NEXT_KEYFRAME').prev = False row.operator('pose.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_NEXT').prev = False
row.scale_x = 2 row.scale_x = 2
class AW_PT_nla_tools_panel(bpy.types.Panel): class AW_PT_nla_tools_panel(bpy.types.Panel):

View File

@ -35,7 +35,7 @@ class AW_PG_settings(bpy.types.PropertyGroup) :
start_frame : bpy.props.IntProperty( start_frame : bpy.props.IntProperty(
name="Start Frame", description="Starting frame for animation path", 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' 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( end_frame : bpy.props.IntProperty(