black format
This commit is contained in:
+5
-5
@@ -1,14 +1,14 @@
|
||||
from asset_library.pose import operators
|
||||
|
||||
from asset_library.pose import (
|
||||
operators)
|
||||
|
||||
if 'bpy' in locals():
|
||||
if "bpy" in locals():
|
||||
import importlib
|
||||
|
||||
importlib.reload(operators)
|
||||
|
||||
|
||||
def register():
|
||||
operators.register()
|
||||
|
||||
|
||||
def unregister():
|
||||
operators.unregister()
|
||||
operators.unregister()
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ def convert_old_poselib(old_poselib: Action) -> Collection[Action]:
|
||||
# appropriate frame in the scene (to set up things like the background
|
||||
# colour), but the old-style poselib doesn't contain such information. All
|
||||
# we can do is just render on the current frame.
|
||||
bpy.ops.asset.mark({'selected_ids': pose_assets})
|
||||
bpy.ops.asset.mark({"selected_ids": pose_assets})
|
||||
|
||||
return pose_assets
|
||||
|
||||
|
||||
+149
-92
@@ -22,7 +22,13 @@ import subprocess
|
||||
import uuid
|
||||
import time
|
||||
|
||||
from bpy.props import BoolProperty, CollectionProperty, EnumProperty, PointerProperty, StringProperty
|
||||
from bpy.props import (
|
||||
BoolProperty,
|
||||
CollectionProperty,
|
||||
EnumProperty,
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
)
|
||||
from bpy.types import (
|
||||
Action,
|
||||
Context,
|
||||
@@ -40,11 +46,7 @@ from asset_library.action.functions import (
|
||||
get_keyframes,
|
||||
)
|
||||
|
||||
from asset_library.common.bl_utils import (
|
||||
get_view3d_persp,
|
||||
load_assets_from,
|
||||
split_path
|
||||
)
|
||||
from asset_library.common.bl_utils import get_view3d_persp, load_assets_from, split_path
|
||||
|
||||
|
||||
class POSELIB_OT_create_pose_asset(Operator):
|
||||
@@ -59,25 +61,28 @@ class POSELIB_OT_create_pose_asset(Operator):
|
||||
pose_name: StringProperty(name="Pose Name") # type: ignore
|
||||
activate_new_action: BoolProperty(name="Activate New Action", default=True) # type: ignore
|
||||
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context: Context) -> bool:
|
||||
# Make sure that if there is an asset browser open, the artist can see the newly created pose asset.
|
||||
asset_browse_area: Optional[bpy.types.Area] = asset_browser.area_from_context(context)
|
||||
asset_browse_area: Optional[bpy.types.Area] = asset_browser.area_from_context(
|
||||
context
|
||||
)
|
||||
if not asset_browse_area:
|
||||
# No asset browser is visible, so there also aren't any expectations
|
||||
# that this asset will be visible.
|
||||
return True
|
||||
|
||||
|
||||
asset_space_params = asset_browser.params(asset_browse_area)
|
||||
if asset_space_params.asset_library_ref != 'LOCAL':
|
||||
cls.poll_message_set("Asset Browser must be set to the Current File library")
|
||||
if asset_space_params.asset_library_ref != "LOCAL":
|
||||
cls.poll_message_set(
|
||||
"Asset Browser must be set to the Current File library"
|
||||
)
|
||||
return False
|
||||
|
||||
|
||||
return True
|
||||
|
||||
def execute(self, context: Context) -> Set[str]:
|
||||
#pose_name = self.pose_name or context.object.name
|
||||
# pose_name = self.pose_name or context.object.name
|
||||
pose_name = False
|
||||
if context.object.animation_data:
|
||||
if context.object.animation_data.action:
|
||||
@@ -85,28 +90,28 @@ class POSELIB_OT_create_pose_asset(Operator):
|
||||
|
||||
if pose_name:
|
||||
prefix = True
|
||||
asset_name = Path(bpy.data.filepath).stem.split('_')[0]
|
||||
asset_name = Path(bpy.data.filepath).stem.split("_")[0]
|
||||
|
||||
action_asset_name = re.search(f'^{asset_name}.', pose_name)
|
||||
action_asset_name = re.search(f"^{asset_name}.", pose_name)
|
||||
if action_asset_name:
|
||||
pose_name = pose_name.replace(action_asset_name.group(0), '')
|
||||
pose_name = pose_name.replace(action_asset_name.group(0), "")
|
||||
|
||||
side = re.search('_\w$', pose_name)
|
||||
side = re.search("_\w$", pose_name)
|
||||
if side:
|
||||
pose_name = pose_name.replace(side.group(0), '')
|
||||
pose_name = pose_name.replace(side.group(0), "")
|
||||
|
||||
if 'hands' in context.object.animation_data.action.name.lower():
|
||||
pose_name = f'hand_{pose_name}'
|
||||
|
||||
if pose_name.startswith('lips_'):
|
||||
pose_name.replace('lips_', '')
|
||||
split = pose_name.split('_')
|
||||
pose_name = '-'.join([s for s in split if s.isupper()])
|
||||
pose_name = f'{pose_name}_{split[-1]}'
|
||||
if "hands" in context.object.animation_data.action.name.lower():
|
||||
pose_name = f"hand_{pose_name}"
|
||||
|
||||
if pose_name.startswith("lips_"):
|
||||
pose_name.replace("lips_", "")
|
||||
split = pose_name.split("_")
|
||||
pose_name = "-".join([s for s in split if s.isupper()])
|
||||
pose_name = f"{pose_name}_{split[-1]}"
|
||||
prefix = False
|
||||
|
||||
|
||||
if prefix and not pose_name.startswith(asset_name):
|
||||
pose_name = f'{asset_name}_{pose_name}'
|
||||
pose_name = f"{asset_name}_{pose_name}"
|
||||
|
||||
else:
|
||||
pose_name = self.pose_name or context.object.name
|
||||
@@ -126,7 +131,6 @@ class POSELIB_OT_create_pose_asset(Operator):
|
||||
if context.scene.camera:
|
||||
data_dict.update(dict(camera=context.scene.camera.name))
|
||||
|
||||
|
||||
for k, v in data_dict.items():
|
||||
data[k] = v
|
||||
###
|
||||
@@ -134,7 +138,7 @@ class POSELIB_OT_create_pose_asset(Operator):
|
||||
if self.activate_new_action:
|
||||
self._set_active_action(context, asset)
|
||||
self._activate_asset_in_browser(context, asset)
|
||||
return {'FINISHED'}
|
||||
return {"FINISHED"}
|
||||
|
||||
def _set_active_action(self, context: Context, asset: Action) -> None:
|
||||
self._prevent_action_loss(context.object)
|
||||
@@ -149,7 +153,9 @@ class POSELIB_OT_create_pose_asset(Operator):
|
||||
This makes it possible to immediately check & edit the created pose asset.
|
||||
"""
|
||||
|
||||
asset_browse_area: Optional[bpy.types.Area] = asset_browser.area_from_context(context)
|
||||
asset_browse_area: Optional[bpy.types.Area] = asset_browser.area_from_context(
|
||||
context
|
||||
)
|
||||
if not asset_browse_area:
|
||||
return
|
||||
|
||||
@@ -181,7 +187,9 @@ class POSELIB_OT_create_pose_asset(Operator):
|
||||
return
|
||||
|
||||
action.use_fake_user = True
|
||||
self.report({'WARNING'}, "Action %s marked Fake User to prevent loss" % action.name)
|
||||
self.report(
|
||||
{"WARNING"}, "Action %s marked Fake User to prevent loss" % action.name
|
||||
)
|
||||
|
||||
|
||||
class POSELIB_OT_restore_previous_action(Operator):
|
||||
@@ -215,17 +223,17 @@ class POSELIB_OT_restore_previous_action(Operator):
|
||||
self._timer = wm.event_timer_add(0.001, window=context.window)
|
||||
wm.modal_handler_add(self)
|
||||
|
||||
return {'RUNNING_MODAL'}
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
def modal(self, context, event):
|
||||
if event.type != 'TIMER':
|
||||
return {'RUNNING_MODAL'}
|
||||
if event.type != "TIMER":
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
wm = context.window_manager
|
||||
wm.event_timer_remove(self._timer)
|
||||
|
||||
context.object.pose.apply_pose_from_action(self.pose_action)
|
||||
return {'FINISHED'}
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class ASSET_OT_assign_action(Operator):
|
||||
@@ -257,7 +265,9 @@ class ASSET_OT_assign_action(Operator):
|
||||
class POSELIB_OT_copy_as_asset(Operator):
|
||||
bl_idname = "poselib.copy_as_asset"
|
||||
bl_label = "Copy Pose As Asset"
|
||||
bl_description = "Create a new pose asset on the clipboard, to be pasted into an Asset Browser"
|
||||
bl_description = (
|
||||
"Create a new pose asset on the clipboard, to be pasted into an Asset Browser"
|
||||
)
|
||||
bl_options = {"REGISTER"}
|
||||
|
||||
CLIPBOARD_ASSET_MARKER = "ASSET-BLEND="
|
||||
@@ -289,7 +299,10 @@ class POSELIB_OT_copy_as_asset(Operator):
|
||||
filepath,
|
||||
)
|
||||
asset_browser.tag_redraw(context.screen)
|
||||
self.report({"INFO"}, "Pose Asset copied, use Paste As New Asset in any Asset Browser to paste")
|
||||
self.report(
|
||||
{"INFO"},
|
||||
"Pose Asset copied, use Paste As New Asset in any Asset Browser to paste",
|
||||
)
|
||||
|
||||
# The asset has been saved to disk, so to clean up it has to loose its asset & fake user status.
|
||||
asset.asset_clear()
|
||||
@@ -300,7 +313,10 @@ class POSELIB_OT_copy_as_asset(Operator):
|
||||
if asset.users > 0:
|
||||
# This should never happen, and indicates a bug in the code. Having a warning about it is nice,
|
||||
# but it shouldn't stand in the way of actually cleaning up the meant-to-be-temporary datablock.
|
||||
self.report({"WARNING"}, "Unexpected non-zero user count for the asset, please report this as a bug")
|
||||
self.report(
|
||||
{"WARNING"},
|
||||
"Unexpected non-zero user count for the asset, please report this as a bug",
|
||||
)
|
||||
|
||||
bpy.data.actions.remove(asset)
|
||||
return {"FINISHED"}
|
||||
@@ -331,8 +347,10 @@ class POSELIB_OT_paste_asset(Operator):
|
||||
return False
|
||||
|
||||
asset_lib_ref = context.space_data.params.asset_library_ref
|
||||
if asset_lib_ref != 'LOCAL':
|
||||
cls.poll_message_set("Asset Browser must be set to the Current File library")
|
||||
if asset_lib_ref != "LOCAL":
|
||||
cls.poll_message_set(
|
||||
"Asset Browser must be set to the Current File library"
|
||||
)
|
||||
return False
|
||||
|
||||
# Delay checking the clipboard as much as possible, as it's CPU-heavier than the other checks.
|
||||
@@ -348,7 +366,6 @@ class POSELIB_OT_paste_asset(Operator):
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def execute(self, context: Context) -> Set[str]:
|
||||
clipboard = context.window_manager.clipboard
|
||||
marker_len = len(POSELIB_OT_copy_as_asset.CLIPBOARD_ASSET_MARKER)
|
||||
@@ -379,18 +396,18 @@ class POSELIB_OT_paste_asset(Operator):
|
||||
class POSELIB_OT_pose_asset_select_bones(Operator):
|
||||
bl_idname = "poselib.pose_asset_select_bones"
|
||||
bl_label = "Select Bones"
|
||||
#bl_description = "Select those bones that are used in this pose"
|
||||
# bl_description = "Select those bones that are used in this pose"
|
||||
bl_description = "Click: Select used Bones\nAlt+Click: Select Flipped Bones\nCtrl+Click: Select Both sides."
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
#bl_property = "selected_side"
|
||||
# bl_property = "selected_side"
|
||||
|
||||
selected_side: EnumProperty(
|
||||
name='Selected Side',
|
||||
name="Selected Side",
|
||||
items=(
|
||||
('CURRENT', "Current", ""),
|
||||
('FLIPPED', "Flipped", ""),
|
||||
('BOTH', "Both", ""),
|
||||
)
|
||||
("CURRENT", "Current", ""),
|
||||
("FLIPPED", "Flipped", ""),
|
||||
("BOTH", "Both", ""),
|
||||
),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@@ -402,7 +419,7 @@ class POSELIB_OT_pose_asset_select_bones(Operator):
|
||||
and context.asset_file_handle
|
||||
):
|
||||
return False
|
||||
return context.asset_file_handle.id_type == 'ACTION'
|
||||
return context.asset_file_handle.id_type == "ACTION"
|
||||
|
||||
def execute(self, context: Context) -> Set[str]:
|
||||
asset: FileSelectEntry = context.asset_file_handle
|
||||
@@ -417,7 +434,9 @@ class POSELIB_OT_pose_asset_select_bones(Operator):
|
||||
def _load_and_use_pose(self, context: Context) -> Set[str]:
|
||||
asset_library_ref = context.asset_library_ref
|
||||
asset = context.asset_file_handle
|
||||
asset_lib_path = bpy.types.AssetHandle.get_full_library_path(asset, asset_library_ref)
|
||||
asset_lib_path = bpy.types.AssetHandle.get_full_library_path(
|
||||
asset, asset_library_ref
|
||||
)
|
||||
|
||||
if not asset_lib_path:
|
||||
self.report( # type: ignore
|
||||
@@ -426,7 +445,7 @@ class POSELIB_OT_pose_asset_select_bones(Operator):
|
||||
f"Selected asset {asset.name} could not be located inside the asset library",
|
||||
)
|
||||
return {"CANCELLED"}
|
||||
if asset.id_type != 'ACTION':
|
||||
if asset.id_type != "ACTION":
|
||||
self.report( # type: ignore
|
||||
{"ERROR"},
|
||||
f"Selected asset {asset.name} is not an Action",
|
||||
@@ -442,10 +461,13 @@ class POSELIB_OT_pose_asset_select_bones(Operator):
|
||||
|
||||
def use_pose(self, context: Context, pose_asset: Action) -> Set[str]:
|
||||
arm_object: Object = context.object
|
||||
#pose_usage.select_bones(arm_object, pose_asset, select=self.select, flipped=self.flipped)
|
||||
pose_usage.select_bones(arm_object, pose_asset, selected_side=self.selected_side)
|
||||
# pose_usage.select_bones(arm_object, pose_asset, select=self.select, flipped=self.flipped)
|
||||
pose_usage.select_bones(
|
||||
arm_object, pose_asset, selected_side=self.selected_side
|
||||
)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
# This operator takes the Window Manager's `actionlib_flipped` property, and
|
||||
# passes it to the `POSELIB_OT_blend_pose_asset` operator. This makes it
|
||||
# possible to bind a key to the operator and still have it respect the global
|
||||
@@ -464,7 +486,7 @@ class POSELIB_OT_blend_pose_asset_for_keymap(Operator):
|
||||
@classmethod
|
||||
def poll(cls, context: Context) -> bool:
|
||||
return bpy.ops.poselib.blend_pose_asset.poll(context.copy())
|
||||
|
||||
|
||||
"""
|
||||
def invoke(self, context, event):
|
||||
if event.type == 'LEFTMOUSE':
|
||||
@@ -478,10 +500,14 @@ class POSELIB_OT_blend_pose_asset_for_keymap(Operator):
|
||||
"""
|
||||
|
||||
def invoke(self, context: Context, event: Event) -> Set[str]:
|
||||
return bpy.ops.poselib.blend_pose_asset(context.copy(), 'INVOKE_DEFAULT', flipped=self.flipped)
|
||||
return bpy.ops.poselib.blend_pose_asset(
|
||||
context.copy(), "INVOKE_DEFAULT", flipped=self.flipped
|
||||
)
|
||||
|
||||
def execute(self, context: Context) -> Set[str]:
|
||||
return bpy.ops.poselib.blend_pose_asset(context.copy(), 'EXEC_DEFAULT', flipped=self.flipped)
|
||||
return bpy.ops.poselib.blend_pose_asset(
|
||||
context.copy(), "EXEC_DEFAULT", flipped=self.flipped
|
||||
)
|
||||
|
||||
|
||||
# This operator takes the Window Manager's `actionlib_flipped` property, and
|
||||
@@ -489,14 +515,15 @@ class POSELIB_OT_blend_pose_asset_for_keymap(Operator):
|
||||
# possible to bind a key to the operator and still have it respect the global
|
||||
# "Flip Pose" checkbox.
|
||||
|
||||
|
||||
class POSELIB_OT_apply_pose_asset_for_keymap(Operator):
|
||||
bl_idname = "poselib.apply_pose_asset_for_keymap"
|
||||
bl_options = {"REGISTER", "UNDO", "INTERNAL"}
|
||||
|
||||
_rna = bpy.ops.poselib.apply_pose_asset.get_rna_type()
|
||||
bl_label = _rna.name
|
||||
#bl_description = _rna.description
|
||||
bl_description = 'Apply Pose to Bones'
|
||||
# bl_description = _rna.description
|
||||
bl_description = "Apply Pose to Bones"
|
||||
del _rna
|
||||
|
||||
flipped: BoolProperty(name="Flipped", default=False) # type: ignore
|
||||
@@ -506,27 +533,42 @@ class POSELIB_OT_apply_pose_asset_for_keymap(Operator):
|
||||
if not asset_utils.SpaceAssetInfo.is_asset_browser(context.space_data):
|
||||
return False
|
||||
return bpy.ops.poselib.apply_pose_asset.poll(context.copy())
|
||||
|
||||
|
||||
def execute(self, context: Context) -> Set[str]:
|
||||
if self.flipped:
|
||||
action = bpy.data.actions.get(context.active_file.name)
|
||||
|
||||
store_bones = {}
|
||||
|
||||
|
||||
bones = [
|
||||
'blendshape-eyes', 'blendshape-eye.L', 'blendshape-eye.R',
|
||||
'blendshape-corner-mouth', 'blendshape-corner-mouth.L',
|
||||
'blendshape-corner-down-mouth.L', 'blendshape-corner-up-mouth.L',
|
||||
'blendshape-corner-mouth-add.L','blendshape-corner-mouth.R',
|
||||
'blendshape-corner-down-mouth.R', 'blendshape-corner-up-mouth.R',
|
||||
'blendshape-corner-mouth-add.R', 'blendshape-center-up-mouth',
|
||||
'blendshape-center-down-mouth',
|
||||
'hat1.R', 'hat2.R', 'hat3.R', 'hat1.L', 'hat2.L', 'hat3.L',
|
||||
"blendshape-eyes",
|
||||
"blendshape-eye.L",
|
||||
"blendshape-eye.R",
|
||||
"blendshape-corner-mouth",
|
||||
"blendshape-corner-mouth.L",
|
||||
"blendshape-corner-down-mouth.L",
|
||||
"blendshape-corner-up-mouth.L",
|
||||
"blendshape-corner-mouth-add.L",
|
||||
"blendshape-corner-mouth.R",
|
||||
"blendshape-corner-down-mouth.R",
|
||||
"blendshape-corner-up-mouth.R",
|
||||
"blendshape-corner-mouth-add.R",
|
||||
"blendshape-center-up-mouth",
|
||||
"blendshape-center-down-mouth",
|
||||
"hat1.R",
|
||||
"hat2.R",
|
||||
"hat3.R",
|
||||
"hat1.L",
|
||||
"hat2.L",
|
||||
"hat3.L",
|
||||
]
|
||||
|
||||
attributes = [
|
||||
'location', 'rotation_quaternion',
|
||||
'rotation_euler', 'rotation_axis_angle', 'scale'
|
||||
"location",
|
||||
"rotation_quaternion",
|
||||
"rotation_euler",
|
||||
"rotation_axis_angle",
|
||||
"scale",
|
||||
]
|
||||
|
||||
if action:
|
||||
@@ -534,7 +576,7 @@ class POSELIB_OT_apply_pose_asset_for_keymap(Operator):
|
||||
bone_name, prop_name = split_path(fc.data_path)
|
||||
if bone_name not in bones:
|
||||
continue
|
||||
|
||||
|
||||
if not bone_name in store_bones.keys():
|
||||
store_bones[bone_name] = {}
|
||||
|
||||
@@ -543,30 +585,40 @@ class POSELIB_OT_apply_pose_asset_for_keymap(Operator):
|
||||
if not prop_name in store_bones[bone_name].keys():
|
||||
store_bones[bone_name][prop_name] = []
|
||||
|
||||
val = getattr(context.object.pose.bones[bone_name], prop_name)
|
||||
val = getattr(
|
||||
context.object.pose.bones[bone_name], prop_name
|
||||
)
|
||||
|
||||
store_bones[bone_name][prop_name].append(fc.evaluate(context.scene.frame_current))
|
||||
|
||||
bpy.ops.poselib.apply_pose_asset(context.copy(), 'EXEC_DEFAULT', flipped=True)
|
||||
store_bones[bone_name][prop_name].append(
|
||||
fc.evaluate(context.scene.frame_current)
|
||||
)
|
||||
|
||||
bpy.ops.poselib.apply_pose_asset(
|
||||
context.copy(), "EXEC_DEFAULT", flipped=True
|
||||
)
|
||||
|
||||
for bone, v in store_bones.items():
|
||||
for attr, attr_val in v.items():
|
||||
flipped_vector = 1
|
||||
|
||||
|
||||
### TODO FAIRE ÇA PROPREMENT AVEC UNE COMPREHENSION LIST OU AUTRE
|
||||
if re.search(r'\.[RL]$', bone):
|
||||
if re.search(r"\.[RL]$", bone):
|
||||
flipped_bone = pose_usage.flip_side_name(bone)
|
||||
if attr == 'location':
|
||||
if attr == "location":
|
||||
flipped_vector = Vector((-1, 1, 1))
|
||||
# print('-----', store_bones.get(flipped_bone)[attr])
|
||||
attr_val = Vector(store_bones.get(flipped_bone)[attr]) * flipped_vector
|
||||
|
||||
attr_val = (
|
||||
Vector(store_bones.get(flipped_bone)[attr]) * flipped_vector
|
||||
)
|
||||
|
||||
setattr(context.object.pose.bones[bone], attr, attr_val)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
else:
|
||||
return bpy.ops.poselib.apply_pose_asset(context.copy(), 'EXEC_DEFAULT', flipped=False)
|
||||
return bpy.ops.poselib.apply_pose_asset(
|
||||
context.copy(), "EXEC_DEFAULT", flipped=False
|
||||
)
|
||||
|
||||
|
||||
class POSELIB_OT_convert_old_poselib(Operator):
|
||||
@@ -577,12 +629,18 @@ class POSELIB_OT_convert_old_poselib(Operator):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context: Context) -> bool:
|
||||
action = context.object and context.object.animation_data and context.object.animation_data.action
|
||||
action = (
|
||||
context.object
|
||||
and context.object.animation_data
|
||||
and context.object.animation_data.action
|
||||
)
|
||||
if not action:
|
||||
cls.poll_message_set("Active object has no Action")
|
||||
return False
|
||||
if not action.pose_markers:
|
||||
cls.poll_message_set("Action %r is not a old-style pose library" % action.name)
|
||||
cls.poll_message_set(
|
||||
"Action %r is not a old-style pose library" % action.name
|
||||
)
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -593,12 +651,11 @@ class POSELIB_OT_convert_old_poselib(Operator):
|
||||
new_actions = conversion.convert_old_poselib(old_poselib)
|
||||
|
||||
if not new_actions:
|
||||
self.report({'ERROR'}, "Unable to convert to pose assets")
|
||||
return {'CANCELLED'}
|
||||
|
||||
self.report({'INFO'}, "Converted %d poses to pose assets" % len(new_actions))
|
||||
return {'FINISHED'}
|
||||
self.report({"ERROR"}, "Unable to convert to pose assets")
|
||||
return {"CANCELLED"}
|
||||
|
||||
self.report({"INFO"}, "Converted %d poses to pose assets" % len(new_actions))
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
classes = (
|
||||
@@ -609,7 +666,7 @@ classes = (
|
||||
POSELIB_OT_create_pose_asset,
|
||||
POSELIB_OT_paste_asset,
|
||||
POSELIB_OT_pose_asset_select_bones,
|
||||
POSELIB_OT_restore_previous_action
|
||||
POSELIB_OT_restore_previous_action,
|
||||
)
|
||||
|
||||
register, unregister = bpy.utils.register_classes_factory(classes)
|
||||
|
||||
+19
-7
@@ -129,7 +129,9 @@ class PoseActionCreator:
|
||||
continue
|
||||
|
||||
try:
|
||||
value = self._current_value(armature_ob, fcurve.data_path, fcurve.array_index)
|
||||
value = self._current_value(
|
||||
armature_ob, fcurve.data_path, fcurve.array_index
|
||||
)
|
||||
except UnresolvablePathError:
|
||||
# A once-animated property no longer exists.
|
||||
continue
|
||||
@@ -197,7 +199,9 @@ class PoseActionCreator:
|
||||
|
||||
fcurve: Optional[FCurve] = dst_action.fcurves.find(rna_path, index=array_index)
|
||||
if fcurve is None:
|
||||
fcurve = dst_action.fcurves.new(rna_path, index=array_index, action_group=bone_name)
|
||||
fcurve = dst_action.fcurves.new(
|
||||
rna_path, index=array_index, action_group=bone_name
|
||||
)
|
||||
|
||||
fcurve.keyframe_points.insert(self.params.src_frame_nr, value=value)
|
||||
fcurve.update()
|
||||
@@ -296,10 +300,13 @@ def create_pose_asset(
|
||||
pose_action.asset_generate_preview()
|
||||
return pose_action
|
||||
|
||||
#def create_pose_asset_from_context(context: Context, new_asset_name: str, selection=True) -> Optional[Action]:
|
||||
def create_pose_asset_from_context(context: Context, new_asset_name: str) -> Optional[Action]:
|
||||
|
||||
# def create_pose_asset_from_context(context: Context, new_asset_name: str, selection=True) -> Optional[Action]:
|
||||
def create_pose_asset_from_context(
|
||||
context: Context, new_asset_name: str
|
||||
) -> Optional[Action]:
|
||||
"""Create Action asset from active object & selected bones."""
|
||||
|
||||
|
||||
bones = context.selected_pose_bones_from_active_object
|
||||
bone_names = {bone.name for bone in bones}
|
||||
|
||||
@@ -369,7 +376,10 @@ def copy_keyframe(dst_fcurve: FCurve, src_keyframe: Keyframe) -> Keyframe:
|
||||
"""Copy a keyframe from one FCurve to the other."""
|
||||
|
||||
dst_keyframe = dst_fcurve.keyframe_points.insert(
|
||||
src_keyframe.co.x, src_keyframe.co.y, options={'FAST'}, keyframe_type=src_keyframe.type
|
||||
src_keyframe.co.x,
|
||||
src_keyframe.co.y,
|
||||
options={"FAST"},
|
||||
keyframe_type=src_keyframe.type,
|
||||
)
|
||||
|
||||
for propname in {
|
||||
@@ -412,7 +422,9 @@ def find_keyframe(fcurve: FCurve, frame: float) -> Optional[Keyframe]:
|
||||
return None
|
||||
|
||||
|
||||
def assign_from_asset_browser(asset: Action, asset_browser_area: bpy.types.Area) -> None:
|
||||
def assign_from_asset_browser(
|
||||
asset: Action, asset_browser_area: bpy.types.Area
|
||||
) -> None:
|
||||
"""Assign some things from the asset browser to the asset.
|
||||
|
||||
This sets the current catalog ID, and in the future could include tags
|
||||
|
||||
+6
-7
@@ -14,7 +14,7 @@ from bpy.types import (
|
||||
)
|
||||
|
||||
|
||||
#def select_bones(arm_object: Object, action: Action, *, select: bool, flipped: bool, both=False) -> None:
|
||||
# def select_bones(arm_object: Object, action: Action, *, select: bool, flipped: bool, both=False) -> None:
|
||||
def select_bones(arm_object: Object, action: Action, *, selected_side, toggle=True):
|
||||
pose_bone_re = re.compile(r'pose.bones\["([^"]+)"\]')
|
||||
pose = arm_object.pose
|
||||
@@ -34,15 +34,14 @@ def select_bones(arm_object: Object, action: Action, *, selected_side, toggle=Tr
|
||||
if bone_name in seen_bone_names:
|
||||
continue
|
||||
seen_bone_names.add(bone_name)
|
||||
|
||||
if selected_side == 'FLIPPED':
|
||||
|
||||
if selected_side == "FLIPPED":
|
||||
bones_to_select.add(bone_name_flip)
|
||||
elif selected_side == 'BOTH':
|
||||
elif selected_side == "BOTH":
|
||||
bones_to_select.add(bone_name_flip)
|
||||
bones_to_select.add(bone_name)
|
||||
elif selected_side == 'CURRENT':
|
||||
elif selected_side == "CURRENT":
|
||||
bones_to_select.add(bone_name)
|
||||
|
||||
|
||||
for bone in bones_to_select:
|
||||
pose_bone = pose.bones.get(bone)
|
||||
@@ -174,7 +173,7 @@ def flip_side_name(to_flip: str) -> str:
|
||||
return prefix + replace + suffix + number
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
print(f"Test result: {doctest.testmod()}")
|
||||
|
||||
Reference in New Issue
Block a user