From cd23f50c55cf17ca468809d320aba42536e3d570 Mon Sep 17 00:00:00 2001 From: Pullusb Date: Wed, 20 Apr 2022 17:54:49 +0200 Subject: [PATCH] remove path constraint and some fix 1.3.1 - added: button to remove follow path constraint --- CHANGELOG.md | 5 +++++ OP_animate_path.py | 25 ++++++++++++++++++++++++- OP_setup.py | 2 +- OP_setup_curve_a_to_b.py | 10 +++++++++- OP_setup_curve_path.py | 33 +++++++++++++++++++++++++++++++++ __init__.py | 2 +- panels.py | 9 ++++++--- properties.py | 5 +++++ 8 files changed, 84 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b001114..2c00fd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +1.3.1 + +- added: button to remove follow path constraint + + 1.3.0 - changed: rename addon: `unfold anim cycle` >> `auto walk` diff --git a/OP_animate_path.py b/OP_animate_path.py index fd58f5a..a2addc0 100644 --- a/OP_animate_path.py +++ b/OP_animate_path.py @@ -187,7 +187,8 @@ def anim_path_from_translate(): act = fn.get_obj_action(ob) if not act: return ('ERROR', f'No action active on {ob.name}') - + + base_act = None # use original action as ref if '_baked' in act.name: base_act_name = act.name.split('_baked')[0] @@ -362,6 +363,28 @@ def anim_path_from_translate(): # for k in t_fcu.keyframe_points: # 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') class AW_OT_animate_path(bpy.types.Operator): diff --git a/OP_setup.py b/OP_setup.py index 092ca0d..284fe02 100644 --- a/OP_setup.py +++ b/OP_setup.py @@ -1,7 +1,7 @@ import bpy +import numpy as np from mathutils import Vector, Quaternion from math import sin, cos, radians -import numpy as np from . import fn ## all action needed to setup the walk diff --git a/OP_setup_curve_a_to_b.py b/OP_setup_curve_a_to_b.py index adba1a2..6960fec 100644 --- a/OP_setup_curve_a_to_b.py +++ b/OP_setup_curve_a_to_b.py @@ -61,6 +61,9 @@ class AW_OT_create_a_b_step(bpy.types.Operator): a = markers[0].location 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 curve = fn.generate_curve(location=a, direction=b, name='curve_path', context=context) 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) - # remove all markers or keep for later reuse ? + ## remove all markers or keep for later reuse ? remove_spacetime_keys(context=None) + # 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"} class AW_OT_remove_a_b_step(bpy.types.Operator): diff --git a/OP_setup_curve_path.py b/OP_setup_curve_path.py index 6d29aa2..2f23fb1 100644 --- a/OP_setup_curve_path.py +++ b/OP_setup_curve_path.py @@ -63,6 +63,38 @@ class AW_OT_create_follow_path(bpy.types.Operator): return {"CANCELLED"} 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): bl_idname = "autowalk.snap_curve_to_ground" bl_label = "Snap Curve" @@ -195,6 +227,7 @@ class AW_OT_object_from_curve(bpy.types.Operator): classes=( AW_OT_create_curve_path, AW_OT_create_follow_path, +AW_OT_remove_follow_path, AW_OT_snap_curve_to_ground, AW_OT_edit_curve, AW_OT_go_to_object, diff --git a/__init__.py b/__init__.py index fc50328..93a5525 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, 3, 0), + "version": (1, 3, 1), "blender": (3, 0, 0), "location": "View3D", "warning": "", diff --git a/panels.py b/panels.py index 6c636bd..cc661bd 100644 --- a/panels.py +++ b/panels.py @@ -78,7 +78,9 @@ class AW_PT_walk_cycle_anim_panel(bpy.types.Panel): 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') + 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 ## Put this in a setting popup or submenu # if context.mode == 'POSE': @@ -89,8 +91,9 @@ class AW_PT_walk_cycle_anim_panel(bpy.types.Panel): 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') + row = col.row(align=True) + 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') row=col.row() diff --git a/properties.py b/properties.py index e476fbb..c195417 100644 --- a/properties.py +++ b/properties.py @@ -38,6 +38,11 @@ class AW_PG_settings(bpy.types.PropertyGroup) : default=101, 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( name='Forward Axis', default='FORWARD_Z', # Modifier default is FORWARD_X (should be TRACK_NEGATIVE_Y for a good rig)