123 lines
4.2 KiB
Python
123 lines
4.2 KiB
Python
import bpy, re
|
|
from . import fn
|
|
|
|
## step 1 : Create the curve
|
|
|
|
# need to determine a specific acceleration envelope factor to go to end of curve
|
|
# (set on curves)
|
|
|
|
def remove_spacetime_keys(context=None):
|
|
if not context:
|
|
context = bpy.context
|
|
# remove all spacetime markers and walk collection
|
|
col_name = 'walk_markers'
|
|
walk_col = context.scene.collection.children.get(col_name)
|
|
if walk_col:
|
|
for o in reversed(walk_col.objects):
|
|
if o.name.startswith('spacetime_marker_'):
|
|
bpy.data.objects.remove(o)
|
|
bpy.data.collections.remove(walk_col)
|
|
|
|
class AW_OT_create_a_b_step(bpy.types.Operator):
|
|
bl_idname = "autowalk.create_a_b_step"
|
|
bl_label = "Create Two Points Curve"
|
|
bl_description = "Create a straight curve between two defined position and time"
|
|
bl_options = {"REGISTER", "UNDO", "INTERNAL"}
|
|
|
|
# first time ops is launched just set an empty (with market time)
|
|
# second time (if a mark empty exists determine a AB path to set curve)
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return context.object and context.object.type == 'ARMATURE'
|
|
|
|
def create_marker(self, context):
|
|
m_name = f'spacetime_marker_{context.scene.frame_current}'
|
|
mark = bpy.data.objects.new(m_name, None)
|
|
mark.location = self.position
|
|
mark.empty_display_size = 2
|
|
self.walk_col.objects.link(mark)
|
|
return mark
|
|
|
|
def execute(self, context):
|
|
ob = context.object
|
|
prefs = fn.get_addon_prefs()
|
|
root_name = prefs.tgt_bone
|
|
root = ob.pose.bones.get(root_name)
|
|
self.position = (ob.matrix_world @ root.matrix).to_translation()
|
|
|
|
col_name = 'walk_markers'
|
|
self.walk_col = fn.get_col(col_name, create=True) # link in scene collection by default
|
|
|
|
markers = [o for o in self.walk_col.objects if o.type == 'EMPTY' and o.name.startswith('spacetime_marker_')]
|
|
if not markers:
|
|
self.create_marker(context)
|
|
return {"FINISHED"}
|
|
|
|
# Create the second marker and append to marker list
|
|
markers.append(self.create_marker(context))
|
|
markers.sort(key=lambda x: x.name) # sort by time (frame written in name)
|
|
|
|
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].split('.')[0])
|
|
b_frame = int(markers[1].name.split('_')[-1].split('.')[0])
|
|
|
|
# Set the curve and constraint
|
|
curve = fn.generate_curve(location=a, direction=b, name='curve_path', context=context)
|
|
settings = context.scene.anim_cycle_settings
|
|
settings.path_to_follow = curve
|
|
fn.create_follow_path_constraint(ob, curve)
|
|
|
|
# reset location to remove offset
|
|
root.location = (0,0,0)
|
|
root.keyframe_insert('location', frame=a_frame)
|
|
root.rotation_euler = (0,0,0)
|
|
root.keyframe_insert('rotation_euler', frame=a_frame)
|
|
|
|
# refresh evaluation so constraint shows up correctly
|
|
bpy.context.scene.frame_set(bpy.context.scene.frame_current)
|
|
|
|
# set offset animation ??? (but movement not in sync until action is retimed in NLA)
|
|
|
|
## remove all markers or keep for later reuse ?
|
|
remove_spacetime_keys(context=None)
|
|
|
|
# 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):
|
|
bl_idname = "autowalk.remove_a_b_step"
|
|
bl_label = "Remove First Position"
|
|
bl_description = "remove first point defining step"
|
|
bl_options = {"REGISTER", "UNDO", "INTERNAL"}
|
|
|
|
# Define what is first and last according to time
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return context.object and context.object.type == 'ARMATURE'
|
|
|
|
def execute(self, context):
|
|
remove_spacetime_keys(context=None)
|
|
return {"FINISHED"}
|
|
|
|
|
|
classes=(
|
|
AW_OT_create_a_b_step,
|
|
AW_OT_remove_a_b_step,
|
|
)
|
|
|
|
def register():
|
|
for cls in classes:
|
|
bpy.utils.register_class(cls)
|
|
|
|
def unregister():
|
|
for cls in reversed(classes):
|
|
bpy.utils.unregister_class(cls)
|
|
|
|
# if __name__ == "__main__":
|
|
# register() |