remove path constraint and some fix

1.3.1

- added: button to remove follow path constraint
master
Pullusb 2022-04-20 17:54:49 +02:00
parent b982c1a6f0
commit cd23f50c55
8 changed files with 84 additions and 7 deletions

View File

@ -1,5 +1,10 @@
# Changelog # Changelog
1.3.1
- added: button to remove follow path constraint
1.3.0 1.3.0
- changed: rename addon: `unfold anim cycle` >> `auto walk` - changed: rename addon: `unfold anim cycle` >> `auto walk`

View File

@ -187,7 +187,8 @@ def anim_path_from_translate():
act = fn.get_obj_action(ob) act = fn.get_obj_action(ob)
if not act: if not act:
return ('ERROR', f'No action active on {ob.name}') return ('ERROR', f'No action active on {ob.name}')
base_act = None
# use original action as ref # use original action as ref
if '_baked' in act.name: if '_baked' in act.name:
base_act_name = act.name.split('_baked')[0] base_act_name = act.name.split('_baked')[0]
@ -362,6 +363,28 @@ def anim_path_from_translate():
# for k in t_fcu.keyframe_points: # for k in t_fcu.keyframe_points:
# k.interpolation = 'CONSTANT' # k.interpolation = 'CONSTANT'
# speed indicator if animator wants to adapt the cycle
## Show a marker to determine cycle range if needed to reach a
''' # Does not work yet
if settings.end_frame > settings.start_frame:
all_keys_list = [k.co.x for fc in act.fcurves if 'foot' in fc.data_path for k in fc.keyframe_points]
base_start = int(min(all_keys_list))
base_end = int(max(all_keys_list))
base_range = base_end - base_start
wanted_duration = settings.end_frame - settings.start_frame # defined in "autowalk > motion" interface
range_needed_to_go_full_curve = base_range * (wanted_duration / frame_duration)
# create marker
mark_name = 'range to fill path'
speed_mark = bpy.context.scene.timeline_markers.get(mark_name)
if not speed_mark:
speed_mark = bpy.context.scene.timeline_markers.new(mark_name)
speed_mark.frame = int(base_start + range_needed_to_go_full_curve)
'''
if debug: print('end of set_follow_path_anim') if debug: print('end of set_follow_path_anim')
class AW_OT_animate_path(bpy.types.Operator): class AW_OT_animate_path(bpy.types.Operator):

View File

@ -1,7 +1,7 @@
import bpy import bpy
import numpy as np
from mathutils import Vector, Quaternion from mathutils import Vector, Quaternion
from math import sin, cos, radians from math import sin, cos, radians
import numpy as np
from . import fn from . import fn
## all action needed to setup the walk ## all action needed to setup the walk

View File

@ -61,6 +61,9 @@ class AW_OT_create_a_b_step(bpy.types.Operator):
a = markers[0].location a = markers[0].location
b = markers[1].location - a # remove a postion to get position in curve object space b = markers[1].location - a # remove a postion to get position in curve object space
a_frame = int(markers[0].name.split('_')[-1])
b_frame = int(markers[1].name.split('_')[-1])
# Set the curve and constraint # Set the curve and constraint
curve = fn.generate_curve(location=a, direction=b, name='curve_path', context=context) curve = fn.generate_curve(location=a, direction=b, name='curve_path', context=context)
settings = context.scene.anim_cycle_settings settings = context.scene.anim_cycle_settings
@ -72,9 +75,14 @@ class AW_OT_create_a_b_step(bpy.types.Operator):
# set offset animation ??? (but movement not in sync until action is retimed in NLA) # set offset animation ??? (but movement not in sync until action is retimed in NLA)
# remove all markers or keep for later reuse ? ## remove all markers or keep for later reuse ?
remove_spacetime_keys(context=None) remove_spacetime_keys(context=None)
# if speed calculation is done later need to know start and end frame... # if speed calculation is done later need to know start and end frame...
# Set frame start and end
settings.start_frame = a_frame
settings.end_frame = b_frame
return {"FINISHED"} return {"FINISHED"}
class AW_OT_remove_a_b_step(bpy.types.Operator): class AW_OT_remove_a_b_step(bpy.types.Operator):

View File

@ -63,6 +63,38 @@ class AW_OT_create_follow_path(bpy.types.Operator):
return {"CANCELLED"} return {"CANCELLED"}
return {"FINISHED"} return {"FINISHED"}
class AW_OT_remove_follow_path(bpy.types.Operator):
bl_idname = "autowalk.remove_follow_path"
bl_label = "Remove Follow Path Constraint"
bl_description = "Remove follow path on target bone"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return context.object and context.object.type == 'ARMATURE'
def execute(self, context):
ob = context.object
# curve = context.scene.anim_cycle_settings.path_to_follow
tgt_bone = fn.get_addon_prefs().tgt_bone
bone = ob.pose.bones.get(tgt_bone)
if not bone:
self.report({'ERROR'}, f'No bone "{tgt_bone}" found')
return {"CANCELLED"}
const = next((c for c in bone.constraints if c.type == 'FOLLOW_PATH'), None)
if not const:
self.report({'ERROR'}, f'No follow path constraint on "{tgt_bone}" found')
return {"CANCELLED"}
bone.constraints.remove(const)
self.report({'INFO'}, f'removed follow_path constraint on bone "{tgt_bone}"')
# Also remove offset action ? myabe give the choice
return {"FINISHED"}
class AW_OT_snap_curve_to_ground(bpy.types.Operator): class AW_OT_snap_curve_to_ground(bpy.types.Operator):
bl_idname = "autowalk.snap_curve_to_ground" bl_idname = "autowalk.snap_curve_to_ground"
bl_label = "Snap Curve" bl_label = "Snap Curve"
@ -195,6 +227,7 @@ class AW_OT_object_from_curve(bpy.types.Operator):
classes=( classes=(
AW_OT_create_curve_path, AW_OT_create_curve_path,
AW_OT_create_follow_path, AW_OT_create_follow_path,
AW_OT_remove_follow_path,
AW_OT_snap_curve_to_ground, AW_OT_snap_curve_to_ground,
AW_OT_edit_curve, AW_OT_edit_curve,
AW_OT_go_to_object, AW_OT_go_to_object,

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, 3, 0), "version": (1, 3, 1),
"blender": (3, 0, 0), "blender": (3, 0, 0),
"location": "View3D", "location": "View3D",
"warning": "", "warning": "",

View File

@ -78,7 +78,9 @@ class AW_PT_walk_cycle_anim_panel(bpy.types.Panel):
if pb: if pb:
follow = pb.constraints.get('Follow Path') follow = pb.constraints.get('Follow Path')
if follow and follow.target: if follow and follow.target:
box.label(text=f'{pb.name} -> {follow.target.name}', icon='CON_FOLLOWPATH') row = box.row()
row.label(text=f'{pb.name} -> {follow.target.name}', icon='CON_FOLLOWPATH')
row.operator('autowalk.remove_follow_path', text='', icon='X')
constrained = True constrained = True
## Put this in a setting popup or submenu ## Put this in a setting popup or submenu
# if context.mode == 'POSE': # if context.mode == 'POSE':
@ -89,8 +91,9 @@ class AW_PT_walk_cycle_anim_panel(bpy.types.Panel):
box = layout.box() box = layout.box()
col=box.column() col=box.column()
col.label(text='Motion:') col.label(text='Motion:')
col.prop(settings, "start_frame", text='Start') row = col.row(align=True)
# col.prop(settings, "foot_axis", text='Foot Axis') row.prop(settings, "start_frame", text='Start')
row.prop(settings, "end_frame", text='End')
col.operator('autowalk.animate_path', text='Animate Forward Motion', icon='ANIM') col.operator('autowalk.animate_path', text='Animate Forward Motion', icon='ANIM')
row=col.row() row=col.row()

View File

@ -38,6 +38,11 @@ class AW_PG_settings(bpy.types.PropertyGroup) :
default=101, default=101,
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(
name="End Frame", description="End frame, to calculate when character should reach the end of the path",
default=101,
min=0, max=2**31-1, soft_min=0, soft_max=2**31-1, step=1, options={'HIDDEN'})#, subtype='PIXEL'
forward_axis : bpy.props.EnumProperty( forward_axis : bpy.props.EnumProperty(
name='Forward Axis', name='Forward Axis',
default='FORWARD_Z', # Modifier default is FORWARD_X (should be TRACK_NEGATIVE_Y for a good rig) default='FORWARD_Z', # Modifier default is FORWARD_X (should be TRACK_NEGATIVE_Y for a good rig)