store / restore values with a context manager
parent
d77ab84c06
commit
037f568a4b
|
@ -2,6 +2,7 @@ import bpy
|
||||||
from . import fn
|
from . import fn
|
||||||
from mathutils import Vector, Euler
|
from mathutils import Vector, Euler
|
||||||
from mathutils.geometry import intersect_line_plane
|
from mathutils.geometry import intersect_line_plane
|
||||||
|
|
||||||
## step 2 : Auto animate the path (with feet selection) and modal to adjust speed
|
## step 2 : Auto animate the path (with feet selection) and modal to adjust speed
|
||||||
|
|
||||||
def get_bone_transform_at_frame(b, act, frame):
|
def get_bone_transform_at_frame(b, act, frame):
|
||||||
|
@ -41,6 +42,7 @@ def anim_path_from_translate():
|
||||||
# return ('ERROR', 'No "foot" in active bone name\n-> Select foot that has the most reliable contact')
|
# return ('ERROR', 'No "foot" in active bone name\n-> Select foot that has the most reliable contact')
|
||||||
settings = bpy.context.scene.anim_cycle_settings
|
settings = bpy.context.scene.anim_cycle_settings
|
||||||
axis = settings.forward_axis
|
axis = settings.forward_axis
|
||||||
|
|
||||||
curve = None
|
curve = None
|
||||||
if settings.path_to_follow:
|
if settings.path_to_follow:
|
||||||
curve = settings.path_to_follow
|
curve = settings.path_to_follow
|
||||||
|
@ -161,7 +163,6 @@ def anim_path_from_translate():
|
||||||
if fcu.data_path == 'eval_time':
|
if fcu.data_path == 'eval_time':
|
||||||
curve.data.animation_data.action.fcurves.remove(fcu)
|
curve.data.animation_data.action.fcurves.remove(fcu)
|
||||||
break
|
break
|
||||||
|
|
||||||
## add eval time animation on curve
|
## add eval time animation on curve
|
||||||
anim_frame = settings.start_frame
|
anim_frame = settings.start_frame
|
||||||
curve.data.path_duration = frame_duration
|
curve.data.path_duration = frame_duration
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import bpy, re
|
import bpy, re
|
||||||
from . import fn
|
from . import fn
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
## step 3
|
## step 3
|
||||||
# - Bake cycle modifier keys -chained with- step the animation path
|
# - Bake cycle modifier keys -chained with- step the animation path
|
||||||
# - Pin the feet (separated ops)
|
# - Pin the feet (separated ops)
|
||||||
|
@ -227,6 +228,12 @@ class UAC_OT_bake_cycle_and_step(bpy.types.Operator):
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
# detect contact key
|
||||||
|
# [ 'array_index', 'auto_smoothing', 'bl_rna', 'color', 'color_mode', 'convert_to_keyframes', 'convert_to_samples', 'data_path',
|
||||||
|
# 'driver', 'evaluate', 'extrapolation', 'group', 'hide', 'is_empty', 'is_valid', 'keyframe_points', 'lock', 'modifiers', 'mute',
|
||||||
|
# 'range', 'rna_type', 'sampled_points', 'select', 'update', 'update_autoflags']
|
||||||
|
|
||||||
|
|
||||||
def pin_down_feets():
|
def pin_down_feets():
|
||||||
print(fn.helper())
|
print(fn.helper())
|
||||||
obj = bpy.context.object
|
obj = bpy.context.object
|
||||||
|
@ -241,36 +248,32 @@ def pin_down_feets():
|
||||||
return ('ERROR', f'No action on {obj.name}')
|
return ('ERROR', f'No action on {obj.name}')
|
||||||
print('action', act.name)
|
print('action', act.name)
|
||||||
|
|
||||||
# detect contact key
|
|
||||||
# [ 'array_index', 'auto_smoothing', 'bl_rna', 'color', 'color_mode', 'convert_to_keyframes', 'convert_to_samples', 'data_path',
|
|
||||||
# 'driver', 'evaluate', 'extrapolation', 'group', 'hide', 'is_empty', 'is_valid', 'keyframe_points', 'lock', 'modifiers', 'mute',
|
|
||||||
# 'range', 'rna_type', 'sampled_points', 'select', 'update', 'update_autoflags']
|
|
||||||
|
|
||||||
act = obj.animation_data.action
|
act = obj.animation_data.action
|
||||||
org_frame = bpy.context.scene.frame_current
|
|
||||||
|
|
||||||
# TODO autodetect contact frame ?
|
|
||||||
|
|
||||||
|
to_change_list = [
|
||||||
|
(bpy.context.scene, 'frame_current', '_undefined'), # use '_undefined' when no value to assign for now
|
||||||
|
(bpy.context.scene.render, 'use_simplify', True),
|
||||||
|
(bpy.context.scene.render, 'simplify_subdivision', 0),
|
||||||
|
]
|
||||||
## Link armature in a new collection and exclude all the others
|
## Link armature in a new collection and exclude all the others
|
||||||
|
|
||||||
## STORE AND MODIFY /-
|
## STORE for context manager store/restore /-
|
||||||
|
tmp_col = bpy.data.collections.get('TMP_COLLECTION_PINNING')
|
||||||
|
if not tmp_col:
|
||||||
tmp_col = bpy.data.collections.new('TMP_COLLECTION_PINNING')
|
tmp_col = bpy.data.collections.new('TMP_COLLECTION_PINNING')
|
||||||
|
if tmp_col.name not in bpy.context.scene.collection.children:
|
||||||
bpy.context.scene.collection.children.link(tmp_col)
|
bpy.context.scene.collection.children.link(tmp_col)
|
||||||
|
if obj not in tmp_col.objects[:]:
|
||||||
tmp_col.objects.link(obj)
|
tmp_col.objects.link(obj)
|
||||||
|
|
||||||
simplify = bpy.context.scene.render.use_simplify
|
|
||||||
simplify_subdiv = bpy.context.scene.render.simplify_subdivision
|
|
||||||
bpy.context.scene.render.use_simplify = True
|
|
||||||
bpy.context.scene.render.simplify_subdivision = 0
|
|
||||||
|
|
||||||
showed_col = []
|
|
||||||
for vlc in bpy.context.view_layer.layer_collection.children:
|
for vlc in bpy.context.view_layer.layer_collection.children:
|
||||||
if vlc.collection == tmp_col:
|
if vlc.collection == tmp_col:
|
||||||
continue
|
continue
|
||||||
showed_col.append([vlc, vlc.exclude])
|
to_change_list.append((vlc, 'exclude', True))
|
||||||
vlc.exclude = True
|
|
||||||
#-/
|
#-/
|
||||||
|
|
||||||
|
with fn.attr_set(to_change_list):
|
||||||
t0 = time()
|
t0 = time()
|
||||||
ct = 0
|
ct = 0
|
||||||
done = {}
|
done = {}
|
||||||
|
@ -294,7 +297,7 @@ def pin_down_feets():
|
||||||
for k in fcu.keyframe_points:
|
for k in fcu.keyframe_points:
|
||||||
|
|
||||||
if k.type == 'EXTREME':
|
if k.type == 'EXTREME':
|
||||||
bpy.context.scene.frame_set(k.co[0])
|
bpy.context.scene.frame_set(int(k.co[0]))
|
||||||
if start_contact is None:
|
if start_contact is None:
|
||||||
start_contact=k.co[0]
|
start_contact=k.co[0]
|
||||||
# record coordinate relative to referent object (or world coord)
|
# record coordinate relative to referent object (or world coord)
|
||||||
|
@ -356,16 +359,10 @@ def pin_down_feets():
|
||||||
# with all collection excluded >> 433 keys changed in 25.00s
|
# with all collection excluded >> 433 keys changed in 25.00s
|
||||||
# with simplify >> 9.57s
|
# with simplify >> 9.57s
|
||||||
|
|
||||||
bpy.context.scene.render.use_simplify = simplify
|
|
||||||
bpy.context.scene.render.simplify_subdivision = simplify_subdiv
|
|
||||||
|
|
||||||
for exclude_pairs in showed_col:
|
|
||||||
exclude_pairs[0].exclude = exclude_pairs[1]
|
|
||||||
tmp_col.objects.unlink(obj)
|
tmp_col.objects.unlink(obj)
|
||||||
bpy.data.collections.remove(tmp_col)
|
bpy.data.collections.remove(tmp_col)
|
||||||
|
|
||||||
bpy.context.scene.frame_current = org_frame
|
|
||||||
# detect last key in contact
|
|
||||||
|
|
||||||
|
|
||||||
class UAC_OT_pin_feets(bpy.types.Operator):
|
class UAC_OT_pin_feets(bpy.types.Operator):
|
||||||
|
|
|
@ -39,6 +39,10 @@ Sidebar > Anim > unfold anim cycle
|
||||||
|
|
||||||
## Changelog:
|
## Changelog:
|
||||||
|
|
||||||
|
0.4.2
|
||||||
|
|
||||||
|
- context manager for `expand cycle step` store / restore
|
||||||
|
|
||||||
0.4.1
|
0.4.1
|
||||||
|
|
||||||
- update fcurve after bake
|
- update fcurve after bake
|
||||||
|
|
|
@ -2,7 +2,7 @@ bl_info = {
|
||||||
"name": "Unfold Anim Cycle",
|
"name": "Unfold Anim Cycle",
|
||||||
"description": "Anim tools to develop walk/run cycles along a curve",
|
"description": "Anim tools to develop walk/run cycles along a curve",
|
||||||
"author": "Samuel Bernou",
|
"author": "Samuel Bernou",
|
||||||
"version": (0, 4, 1),
|
"version": (0, 4, 2),
|
||||||
"blender": (3, 0, 0),
|
"blender": (3, 0, 0),
|
||||||
"location": "View3D",
|
"location": "View3D",
|
||||||
"warning": "WIP",
|
"warning": "WIP",
|
||||||
|
|
23
fn.py
23
fn.py
|
@ -312,3 +312,26 @@ def update_action(act):
|
||||||
if area.type == 'GRAPH_EDITOR':
|
if area.type == 'GRAPH_EDITOR':
|
||||||
area.tag_redraw()
|
area.tag_redraw()
|
||||||
|
|
||||||
|
### --- context manager - store / restore
|
||||||
|
|
||||||
|
|
||||||
|
class attr_set():
|
||||||
|
'''Receive a list of tuple [(data_path:python_obj, "attribute":str, "wanted value":str)]
|
||||||
|
before with statement : Store existing values, assign wanted value
|
||||||
|
after with statement: Restore values to their old values
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, attrib_list):
|
||||||
|
self.store = []
|
||||||
|
for prop, attr, new_val in attrib_list:
|
||||||
|
self.store.append( (prop, attr, getattr(prop, attr)) )
|
||||||
|
if new_val == '_undefined': # None -> what if we want to apply None state ?
|
||||||
|
continue
|
||||||
|
setattr(prop, attr, new_val)
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_value, exc_traceback):
|
||||||
|
for prop, attr, old_val in self.store:
|
||||||
|
setattr(prop, attr, old_val)
|
||||||
|
|
Loading…
Reference in New Issue