Compare commits
25 Commits
3dc5cff0a2
...
rename-eve
Author | SHA1 | Date | |
---|---|---|---|
3ebf0184ee | |||
23ffed939a | |||
21f2278990 | |||
cb3999de33 | |||
5f0a4c93c2 | |||
efd8acd9a9 | |||
e9d33b7f87 | |||
d008e4750c | |||
b2fc121a88 | |||
a4abb41c73 | |||
8f936ec085 | |||
edeaa12f5e | |||
b6bfb2db00 | |||
fecc9d6be5 | |||
4930b15046 | |||
7c9bd136d8 | |||
6b1f215517 | |||
0d2d51ac74 | |||
76133ef3db | |||
0f2460f6b5 | |||
cbdd63ef0d | |||
164dec9ab5 | |||
1d25f45735 | |||
4157a12531 | |||
13146b5a75 |
65
README.md
65
README.md
@ -1,6 +1,63 @@
|
|||||||
# Damn Simple Pose Library
|
# Yet Another Pose Library
|
||||||
|
|
||||||
In Blender 3.x, a new Asset-based Pose system was introduced.
|
For Blender 3.5 - 4.3 (4.1 recommended).
|
||||||
That's fine and dandy, however because of that, the old Pose Library was deprecated and gutted out real quick-like. Too quick.
|
|
||||||
|
|
||||||
This brings it back as best as it can.
|
During the Blender 3.x releases, a new Asset-based Pose system was introduced. That's fine and dandy, but it was not (and still is not as of Jan 2025) ready to replace the old Action-based Pose Library system. The former Pose Library was quickly deprecated and removed, leaving legacy users high and dry.
|
||||||
|
|
||||||
|
This addon brings the Legacy Pose Library back as best as it can in a modern panel, and tries to stick as close to the old system as possible. Most, if not all existing Pose Libraries should work without any modifications. Little new is introduced outside of UI enhancements and handling for new data.
|
||||||
|
|
||||||
|
These excellent addons also address this removal in their own ways, check them out:
|
||||||
|
- [Sakura Poselib](https://github.com/kafuji/Sakura_Poselib)
|
||||||
|
- [gret](https://github.com/greisane/gret?tab=readme-ov-file#animation-actions-panel)
|
||||||
|
- [Amarillo's Pose Library](https://github.com/AmarilloArts/Amarillos-Pose-Library)
|
||||||
|
|
||||||
|
## Old Features
|
||||||
|
|
||||||
|
- The Pose Library list panel is ported from Armature Data Properties to a Sidebar (N) panel.
|
||||||
|
|
||||||
|
- Operators and data property [that were removed in 3.5](https://projects.blender.org/blender/blender/issues/93406) are ported from C to Python:
|
||||||
|
- `yapl.apply_pose`
|
||||||
|
- `yapl.browse_poses`
|
||||||
|
- `yapl.create_pose_library`
|
||||||
|
- `yapl.convert_pose_library`
|
||||||
|
- `yapl.add_pose`
|
||||||
|
- `yapl.move_pose`
|
||||||
|
- `yapl.remove_pose`
|
||||||
|
- `yapl.rename_pose`
|
||||||
|
- `yapl.unlink_pose_library`
|
||||||
|
- `Object.pose_library`
|
||||||
|
|
||||||
|
## New Features
|
||||||
|
|
||||||
|
- New panel interface for interacting with pose libraries, inspired by [gret's Actions Panel feature](https://github.com/greisane/gret?tab=readme-ov-file#animation-actions-panel).
|
||||||
|
- Hover over buttons for tooltips
|
||||||
|
|
||||||
|
- Operator to protect potentially-orphaned pose data (read Considerations)
|
||||||
|
- `yapl.protect_orphan_pose_library`
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
1. [Download the repository as a zip](https://git.bkspl.me/breakingspell/YetAnotherPoseLibrary/archive/develop.zip), or otherwise clone the repository.
|
||||||
|
2. Install as an Add-on in Blender via Install -> Zip, and enable.
|
||||||
|
3. Optionally configure the suffix strings to fit your workflow, and whether the orhpan checker should run at startup.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
1. Open Sidebar (`N`), and choose the `Pose` tab.
|
||||||
|
2. Select an Armature Object, or an Object parented to an Armature.
|
||||||
|
3. Select existing Pose Library from drop-down, or create a new library.
|
||||||
|
|
||||||
|
### 3D View Hotkeys:
|
||||||
|
- `Shift + L` - Add/Replace Pose
|
||||||
|
- `Alt + L` - Browse Poses with Arrow Keys
|
||||||
|
### New Panel Controls
|
||||||
|
- `Single click` - Apply Pose
|
||||||
|
- `Shift + Click` - Rename Pose
|
||||||
|
- `Alt + Click` - Remove Pose
|
||||||
|
- `Ctrl + Click ` - Select Pose
|
||||||
|
- Choose `Edit` for fast Move/Rename/Removal
|
||||||
|
|
||||||
|
## Considerations
|
||||||
|
- Opening older scenes will cause existing Pose Libraries to unlink from their former targets and fall into orphan state. They can be re-linked and will retain their link when saved afterwards, but would otherwise disappear if saved without linking or protecting the datablock.
|
||||||
|
- This is due to the core DNA type `poselib` having been removed, so objects will drop the data. [There is no way to prevent this](https://developer.blender.org/docs/features/core/rna/#internals) as Python ID properties cannot be present at program runtime, only once the add-on is initialized.
|
||||||
|
- To mitgate, an operator is provided to protect orphaned pose libraries: `yapl.protect_orphan_pose_library`.
|
||||||
|
|
||||||
|
- This add-on was made much easier by the `pose_markers` property being retained for converting old pose libraries to the new asset system. If they decide to remove that property as well, there will be a need to improvise an index-based lookup.
|
||||||
|
97
__init__.py
97
__init__.py
@ -1,13 +1,12 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from . import gui, operators, common
|
from . import gui, operators, common, keymaps
|
||||||
from typing import List, Tuple
|
|
||||||
bl_info = \
|
bl_info = \
|
||||||
{
|
{
|
||||||
"name": "Damn Simple Pose Library",
|
"name": "Yet Another Pose Library",
|
||||||
"author": "jackie",
|
"author": "breakingspell",
|
||||||
"version": (4, 1, 0),
|
"version": (0, 1, 0),
|
||||||
"blender": (3, 5, 0),
|
"blender": (3, 6, 0),
|
||||||
"description": "woah",
|
"description": "Re-implement 3.x legacy Pose Library",
|
||||||
"category": "Object Data",
|
"category": "Object Data",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,90 +18,48 @@ if _need_reload:
|
|||||||
|
|
||||||
gui = importlib.reload(gui)
|
gui = importlib.reload(gui)
|
||||||
common = importlib.reload(common)
|
common = importlib.reload(common)
|
||||||
# keymaps = importlib.reload(keymaps)
|
keymaps = importlib.reload(keymaps)
|
||||||
operators = importlib.reload(operators)
|
operators = importlib.reload(operators)
|
||||||
|
|
||||||
# addon_keymaps: List[Tuple[bpy.types.KeyMap, bpy.types.KeyMapItem]] = []
|
|
||||||
# addon_keymaps = []
|
|
||||||
|
|
||||||
|
class yaplSettings(bpy.types.PropertyGroup):
|
||||||
class dsplObj(bpy.types.PropertyGroup):
|
|
||||||
pose_library: bpy.props.PointerProperty(
|
|
||||||
name="Active Pose Library", description="",
|
|
||||||
override={'LIBRARY_OVERRIDABLE'}, type=bpy.types.Action)
|
|
||||||
# update = common.poselib_update)
|
|
||||||
# , update = anim_layers.layer_name_update
|
|
||||||
|
|
||||||
|
|
||||||
class dsplVars(bpy.types.PropertyGroup):
|
|
||||||
pose_index: bpy.props.IntProperty(
|
|
||||||
name="Pose Index", description="", override={'LIBRARY_OVERRIDABLE'})
|
|
||||||
pose_new_name: bpy.props.StringProperty(
|
|
||||||
name="Pose Name", description="New name for pose",
|
|
||||||
default="Pose", override={'LIBRARY_OVERRIDABLE'})
|
|
||||||
only_selected: bpy.props.BoolProperty(
|
|
||||||
name="Only selected Bones", description="Process only selected bones",
|
|
||||||
default=False, options={'HIDDEN'}, override={'LIBRARY_OVERRIDABLE'})
|
|
||||||
numero: bpy.props.IntProperty(
|
|
||||||
name='Numero', default=666, override={'LIBRARY_OVERRIDABLE'})
|
|
||||||
|
|
||||||
|
|
||||||
class dsplSettings(bpy.types.PropertyGroup):
|
|
||||||
new_menu: bpy.props.BoolProperty(
|
new_menu: bpy.props.BoolProperty(
|
||||||
name="New Menu", description="Toggle New Menu", default=False)
|
name="New Menu", description="Toggle New Menu", default=True)
|
||||||
edit_mode: bpy.props.BoolProperty(
|
edit_mode: bpy.props.BoolProperty(
|
||||||
name="Edit Mode", description="Toggle Edit Mode", default=False)
|
name="Edit Mode", description="Toggle Edit Mode", default=False)
|
||||||
|
|
||||||
classes = (dsplObj, dsplVars, dsplSettings)
|
classes = yaplSettings
|
||||||
|
|
||||||
|
def pose_libraries_poll(self, action):
|
||||||
|
if getattr(action, "pose_markers", None):
|
||||||
|
return True
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
from bpy.utils import register_class
|
from bpy.utils import register_class
|
||||||
for cls in classes:
|
register_class(yaplSettings)
|
||||||
register_class(cls)
|
|
||||||
|
|
||||||
# bpy.types.Armature.pose_library = bpy.props.PointerProperty(
|
bpy.types.Object.pose_library = bpy.props.PointerProperty(
|
||||||
# type=dsplObj, override={'LIBRARY_OVERRIDABLE'})
|
name="Active Pose Library", description="",
|
||||||
|
type=bpy.types.Action, override={'LIBRARY_OVERRIDABLE'},
|
||||||
|
poll=pose_libraries_poll)
|
||||||
|
|
||||||
# bpy.types.Object.pose_library = bpy.props.PointerProperty(
|
bpy.types.Scene.yaplSettings = bpy.props.PointerProperty(
|
||||||
# type=bpy.types.Action, options={'LIBRARY_EDITABLE'}, override={'LIBRARY_OVERRIDABLE'})
|
type=yaplSettings, override={'LIBRARY_OVERRIDABLE'})
|
||||||
|
|
||||||
bpy.types.Object.dspl = bpy.props.PointerProperty(
|
|
||||||
type=dsplObj, override={'LIBRARY_OVERRIDABLE'})
|
|
||||||
bpy.types.Object.dsplvars = bpy.props.PointerProperty(
|
|
||||||
type=dsplVars, override={'LIBRARY_OVERRIDABLE'})
|
|
||||||
bpy.types.Scene.dsplSettings = bpy.props.PointerProperty(
|
|
||||||
type=dsplSettings, override={'LIBRARY_OVERRIDABLE'})
|
|
||||||
|
|
||||||
gui.register()
|
gui.register()
|
||||||
operators.register()
|
operators.register()
|
||||||
|
keymaps.register()
|
||||||
|
|
||||||
# kc = bpy.context.window_manager.keyconfigs.addon
|
def unregister():
|
||||||
# km = kc.keymaps.new(name='3D View', space_type='VIEW_3D')
|
|
||||||
# kmi = [
|
|
||||||
# km.keymap_items.new("dspl.add_pose", type='L', value='PRESS', shift=True),
|
|
||||||
# km.keymap_items.new("dspl.browse_poses", type='L', value='PRESS', alt=True),
|
|
||||||
# ]
|
|
||||||
# addon_keymaps.append((km, kmi))
|
|
||||||
|
|
||||||
|
|
||||||
def unregister() -> None:
|
|
||||||
from bpy.utils import unregister_class
|
from bpy.utils import unregister_class
|
||||||
for cls in classes:
|
unregister_class(yaplSettings)
|
||||||
unregister_class(cls)
|
|
||||||
|
|
||||||
del bpy.types.Object.dspl
|
del bpy.types.Scene.yaplSettings
|
||||||
del bpy.types.Object.dsplvars
|
del bpy.types.Object.pose_library
|
||||||
del bpy.types.Scene.dsplSettings
|
|
||||||
|
|
||||||
gui.unregister()
|
keymaps.unregister()
|
||||||
operators.unregister()
|
operators.unregister()
|
||||||
|
gui.unregister()
|
||||||
# for km, kmi in addon_keymaps:
|
|
||||||
# km.keymap_items.remove(kmi)
|
|
||||||
# addon_keymaps.clear()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
register()
|
register()
|
||||||
|
|
||||||
|
218
common.py
218
common.py
@ -1,51 +1,32 @@
|
|||||||
import bpy
|
import bpy
|
||||||
|
import mathutils
|
||||||
|
|
||||||
|
|
||||||
def getArmatureObject(context):
|
def get_armature_data(context):
|
||||||
obj = context.active_object
|
|
||||||
if obj:
|
|
||||||
if obj.type == "ARMATURE":
|
|
||||||
return obj
|
|
||||||
elif obj.parent is not None and obj.parent.type == "ARMATURE":
|
|
||||||
return obj.parent
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def getLegacyPoseLibrary(context):
|
|
||||||
arm = getArmatureObject(context)
|
|
||||||
return getattr(arm, "pose_library", None)
|
|
||||||
|
|
||||||
|
|
||||||
def getArmatureAction(context):
|
|
||||||
arm = getArmatureObject(context)
|
|
||||||
return getattr(arm.animation_data, "action", None)
|
|
||||||
|
|
||||||
|
|
||||||
def getDsplAction(context):
|
|
||||||
arm = getArmatureObject(context)
|
|
||||||
return getattr(arm.dspl, "pose_library", None)
|
|
||||||
|
|
||||||
|
|
||||||
def getPoseLib(context):
|
|
||||||
arm = getArmatureObject(context)
|
|
||||||
pose_library_dspl = getDsplAction(context)
|
|
||||||
pose_library_action = getArmatureAction(context)
|
|
||||||
pose_library_legacy = getLegacyPoseLibrary(context)
|
|
||||||
|
|
||||||
if pose_library_dspl:
|
|
||||||
return pose_library_dspl
|
|
||||||
elif pose_library_action and not pose_library_dspl:
|
|
||||||
return pose_library_action
|
|
||||||
elif pose_library_legacy and not pose_library_dspl:
|
|
||||||
return pose_library_legacy
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def searchPoseMarker(context, posename, type):
|
|
||||||
try:
|
try:
|
||||||
pose_library = getPoseLib(context)
|
arm_object = context.active_object
|
||||||
|
if arm_object and arm_object.type == "ARMATURE":
|
||||||
|
return arm_object, getattr(arm_object, "pose_library", None)
|
||||||
|
elif arm_object and arm_object.parent and arm_object.parent.type == "ARMATURE":
|
||||||
|
return arm_object.parent, getattr(arm_object.parent, "pose_library", None)
|
||||||
|
else:
|
||||||
|
return None, None
|
||||||
|
except:
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
|
||||||
|
def get_armature_action(context):
|
||||||
|
try:
|
||||||
|
arm_object, pose_library = get_armature_data(context)
|
||||||
|
if getattr(arm_object.animation_data.action, "pose_markers", None):
|
||||||
|
return getattr(arm_object.animation_data, "action", None)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def search_pose_marker(context, posename, type):
|
||||||
|
try:
|
||||||
|
arm_object, pose_library = get_armature_data(context)
|
||||||
if type == "marker":
|
if type == "marker":
|
||||||
return pose_library.pose_markers.get(posename, None)
|
return pose_library.pose_markers.get(posename, None)
|
||||||
if type == "frame":
|
if type == "frame":
|
||||||
@ -56,13 +37,12 @@ def searchPoseMarker(context, posename, type):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def findFcurve(context, bone_name, transform, index_int):
|
def find_fcurve(context, bone_name, transform, index_int):
|
||||||
arm_object = getArmatureObject(context)
|
arm_object, pose_library = get_armature_data(context)
|
||||||
action_object = getPoseLib(context)
|
pose_markers = pose_library.pose_markers
|
||||||
pose_markers = action_object.pose_markers
|
|
||||||
active_frame = pose_markers.active.frame
|
active_frame = pose_markers.active.frame
|
||||||
|
|
||||||
fcurve_object = action_object.fcurves.find(
|
fcurve_object = pose_library.fcurves.find(
|
||||||
'pose.bones["'+bone_name+'"].'+transform+'', index=index_int)
|
'pose.bones["'+bone_name+'"].'+transform+'', index=index_int)
|
||||||
if hasattr(fcurve_object, 'evaluate'):
|
if hasattr(fcurve_object, 'evaluate'):
|
||||||
return fcurve_object.evaluate(active_frame)
|
return fcurve_object.evaluate(active_frame)
|
||||||
@ -70,36 +50,38 @@ def findFcurve(context, bone_name, transform, index_int):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def createFcurve(context, bone_name, transform, index_int):
|
def create_fcurve(context, bone_name, transform, index_int):
|
||||||
arm_object = getArmatureObject(context)
|
arm_object, pose_library = get_armature_data(context)
|
||||||
action_object = getPoseLib(context)
|
pose_markers = pose_library.pose_markers
|
||||||
pose_markers = action_object.pose_markers
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
action_object.fcurves.new(
|
pose_library.fcurves.new(
|
||||||
'pose.bones["'+bone_name+'"].'+transform+'', index=index_int, action_group=bone_name)
|
'pose.bones["'+bone_name+'"].'+transform+'', index=index_int, action_group=bone_name)
|
||||||
return
|
return
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def createKeyframe(context, bone_name, transform, index_int, new_marker, loc):
|
def create_keyframe(context, bone_name, transform, index_int, new_marker, loc):
|
||||||
arm_object = getArmatureObject(context)
|
arm_object, pose_library = get_armature_data(context)
|
||||||
action_object = getPoseLib(context)
|
pose_markers = pose_library.pose_markers
|
||||||
pose_markers = action_object.pose_markers
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
action_object.fcurves.find(
|
pose_library.fcurves.find(
|
||||||
'pose.bones["'+bone_name+'"].'+transform+'', index=index_int).keyframe_points.insert(new_marker, loc)
|
'pose.bones["'+bone_name+'"].'+transform+'', index=index_int).keyframe_points.insert(new_marker, loc)
|
||||||
return
|
return
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def setKeyframesFromBones(context, new_marker):
|
def set_keyframes_from_bones(context, arm_object, new_marker):
|
||||||
arm_object = getArmatureObject(context)
|
none_selected = True
|
||||||
for bone in arm_object.pose.bones:
|
for bone in arm_object.pose.bones:
|
||||||
if bone.bone.select or arm_object.dsplvars.only_selected == False:
|
if bone.bone.select:
|
||||||
|
none_selected = False
|
||||||
|
|
||||||
|
for bone in arm_object.pose.bones:
|
||||||
|
if bone.bone.select or none_selected == True:
|
||||||
bone_name = bone.name
|
bone_name = bone.name
|
||||||
|
|
||||||
if bone.rotation_mode == "XYZ":
|
if bone.rotation_mode == "XYZ":
|
||||||
@ -111,49 +93,107 @@ def setKeyframesFromBones(context, new_marker):
|
|||||||
elif bone.rotation_mode == "QUATERNION":
|
elif bone.rotation_mode == "QUATERNION":
|
||||||
rot_mode = "rotation_quaternion"
|
rot_mode = "rotation_quaternion"
|
||||||
else:
|
else:
|
||||||
print("Unsupported bone!")
|
self.report({'WARNING'}, "YAPL: Unsupported bone: " + bone.name + ": " + bone.rotation_mode)
|
||||||
rot_mode = None
|
rot_mode = None
|
||||||
|
|
||||||
loc_x = bone.location[0]
|
loc_x = bone.location[0]
|
||||||
loc_y = bone.location[1]
|
loc_y = bone.location[1]
|
||||||
loc_z = bone.location[2]
|
loc_z = bone.location[2]
|
||||||
createFcurve(context, bone_name, "location", 0)
|
create_fcurve(context, bone_name, "location", 0)
|
||||||
createFcurve(context, bone_name, "location", 1)
|
create_fcurve(context, bone_name, "location", 1)
|
||||||
createFcurve(context, bone_name, "location", 2)
|
create_fcurve(context, bone_name, "location", 2)
|
||||||
createKeyframe(context, bone_name, "location", 0, new_marker, loc_x)
|
create_keyframe(context, bone_name, "location", 0, new_marker, loc_x)
|
||||||
createKeyframe(context, bone_name, "location", 1, new_marker, loc_y)
|
create_keyframe(context, bone_name, "location", 1, new_marker, loc_y)
|
||||||
createKeyframe(context, bone_name, "location", 2, new_marker, loc_z)
|
create_keyframe(context, bone_name, "location", 2, new_marker, loc_z)
|
||||||
if rot_mode == "rotation_quaternion":
|
if rot_mode == "rotation_quaternion":
|
||||||
rot_w = bone.rotation_quaternion[0]
|
rot_w = bone.rotation_quaternion[0]
|
||||||
rot_x = bone.rotation_quaternion[1]
|
rot_x = bone.rotation_quaternion[1]
|
||||||
rot_y = bone.rotation_quaternion[2]
|
rot_y = bone.rotation_quaternion[2]
|
||||||
rot_z = bone.rotation_quaternion[3]
|
rot_z = bone.rotation_quaternion[3]
|
||||||
createFcurve(context, bone_name, rot_mode, 0)
|
create_fcurve(context, bone_name, rot_mode, 0)
|
||||||
createFcurve(context, bone_name, rot_mode, 1)
|
create_fcurve(context, bone_name, rot_mode, 1)
|
||||||
createFcurve(context, bone_name, rot_mode, 2)
|
create_fcurve(context, bone_name, rot_mode, 2)
|
||||||
createFcurve(context, bone_name, rot_mode, 3)
|
create_fcurve(context, bone_name, rot_mode, 3)
|
||||||
createKeyframe(context, bone_name, rot_mode, 0, new_marker, rot_w)
|
create_keyframe(context, bone_name, rot_mode, 0, new_marker, rot_w)
|
||||||
createKeyframe(context, bone_name, rot_mode, 1, new_marker, rot_x)
|
create_keyframe(context, bone_name, rot_mode, 1, new_marker, rot_x)
|
||||||
createKeyframe(context, bone_name, rot_mode, 2, new_marker, rot_y)
|
create_keyframe(context, bone_name, rot_mode, 2, new_marker, rot_y)
|
||||||
createKeyframe(context, bone_name, rot_mode, 3, new_marker, rot_z)
|
create_keyframe(context, bone_name, rot_mode, 3, new_marker, rot_z)
|
||||||
elif rot_mode == "rotation_euler":
|
elif rot_mode == "rotation_euler":
|
||||||
rot_x = bone.rotation_euler[0]
|
rot_x = bone.rotation_euler[0]
|
||||||
rot_y = bone.rotation_euler[1]
|
rot_y = bone.rotation_euler[1]
|
||||||
rot_z = bone.rotation_euler[2]
|
rot_z = bone.rotation_euler[2]
|
||||||
createFcurve(context, bone_name, rot_mode, 0)
|
create_fcurve(context, bone_name, rot_mode, 0)
|
||||||
createFcurve(context, bone_name, rot_mode, 1)
|
create_fcurve(context, bone_name, rot_mode, 1)
|
||||||
createFcurve(context, bone_name, rot_mode, 2)
|
create_fcurve(context, bone_name, rot_mode, 2)
|
||||||
createKeyframe(context, bone_name, rot_mode, 0, new_marker, rot_x)
|
create_keyframe(context, bone_name, rot_mode, 0, new_marker, rot_x)
|
||||||
createKeyframe(context, bone_name, rot_mode, 1, new_marker, rot_y)
|
create_keyframe(context, bone_name, rot_mode, 1, new_marker, rot_y)
|
||||||
createKeyframe(context, bone_name, rot_mode, 2, new_marker, rot_z)
|
create_keyframe(context, bone_name, rot_mode, 2, new_marker, rot_z)
|
||||||
scl_x = bone.scale[0]
|
scl_x = bone.scale[0]
|
||||||
scl_y = bone.scale[1]
|
scl_y = bone.scale[1]
|
||||||
scl_z = bone.scale[2]
|
scl_z = bone.scale[2]
|
||||||
createFcurve(context, bone_name, "scale", 0)
|
create_fcurve(context, bone_name, "scale", 0)
|
||||||
createFcurve(context, bone_name, "scale", 1)
|
create_fcurve(context, bone_name, "scale", 1)
|
||||||
createFcurve(context, bone_name, "scale", 2)
|
create_fcurve(context, bone_name, "scale", 2)
|
||||||
createKeyframe(context, bone_name, "scale", 0, new_marker, scl_x)
|
create_keyframe(context, bone_name, "scale", 0, new_marker, scl_x)
|
||||||
createKeyframe(context, bone_name, "scale", 1, new_marker, scl_y)
|
create_keyframe(context, bone_name, "scale", 1, new_marker, scl_y)
|
||||||
createKeyframe(context, bone_name, "scale", 2, new_marker, scl_z)
|
create_keyframe(context, bone_name, "scale", 2, new_marker, scl_z)
|
||||||
|
|
||||||
|
|
||||||
|
def set_bones_from_keyframes(context, arm_object, active_marker):
|
||||||
|
none_selected = True
|
||||||
|
for bone in arm_object.pose.bones:
|
||||||
|
if bone.bone.select:
|
||||||
|
none_selected = False
|
||||||
|
|
||||||
|
for bone in arm_object.pose.bones:
|
||||||
|
if bone.bone.select or none_selected == True:
|
||||||
|
bone_name = bone.name
|
||||||
|
|
||||||
|
if bone.rotation_mode == "XYZ":
|
||||||
|
rot_mode = "rotation_euler"
|
||||||
|
elif bone.rotation_mode == "YZX":
|
||||||
|
rot_mode = "rotation_euler"
|
||||||
|
elif bone.rotation_mode == "ZXY":
|
||||||
|
rot_mode = "rotation_euler"
|
||||||
|
elif bone.rotation_mode == "QUATERNION":
|
||||||
|
rot_mode = "rotation_quaternion"
|
||||||
|
else:
|
||||||
|
self.report({'WARNING'}, "YAPL: Unsupported bone: " + bone.name + ": " + bone.rotation_mode)
|
||||||
|
rot_mode = None
|
||||||
|
|
||||||
|
loc_x = find_fcurve(context, bone_name, "location", 0) or 0.0
|
||||||
|
loc_y = find_fcurve(context, bone_name, "location", 1) or 0.0
|
||||||
|
loc_z = find_fcurve(context, bone_name, "location", 2) or 0.0
|
||||||
|
if rot_mode == "rotation_quaternion":
|
||||||
|
rot_w = find_fcurve(context, bone_name, rot_mode, 0) or 1.0
|
||||||
|
rot_x = find_fcurve(context, bone_name, rot_mode, 1) or 0.0
|
||||||
|
rot_y = find_fcurve(context, bone_name, rot_mode, 2) or 0.0
|
||||||
|
rot_z = find_fcurve(context, bone_name, rot_mode, 3) or 0.0
|
||||||
|
elif rot_mode == "rotation_euler":
|
||||||
|
rot_x = find_fcurve(context, bone_name, rot_mode, 0) or 0.0
|
||||||
|
rot_y = find_fcurve(context, bone_name, rot_mode, 1) or 0.0
|
||||||
|
rot_z = find_fcurve(context, bone_name, rot_mode, 2) or 0.0
|
||||||
|
scl_x = find_fcurve(context, bone_name, "scale", 0) or 1.0
|
||||||
|
scl_y = find_fcurve(context, bone_name, "scale", 1) or 1.0
|
||||||
|
scl_z = find_fcurve(context, bone_name, "scale", 2) or 1.0
|
||||||
|
|
||||||
|
bone.location = mathutils.Vector((loc_x, loc_y, loc_z))
|
||||||
|
if bone.rotation_mode == "XYZ":
|
||||||
|
bone.rotation_euler = mathutils.Euler(
|
||||||
|
(rot_x, rot_y, rot_z))
|
||||||
|
elif bone.rotation_mode == "YZX":
|
||||||
|
bone.rotation_euler = mathutils.Euler(
|
||||||
|
(rot_x, rot_y, rot_z))
|
||||||
|
elif bone.rotation_mode == "ZXY":
|
||||||
|
bone.rotation_euler = mathutils.Euler(
|
||||||
|
(rot_z, rot_x, rot_y))
|
||||||
|
elif bone.rotation_mode == "YXZ":
|
||||||
|
bone.rotation_euler = mathutils.Euler(
|
||||||
|
(rot_y, rot_x, rot_z))
|
||||||
|
elif bone.rotation_mode == "XZY":
|
||||||
|
bone.rotation_euler = mathutils.Euler(
|
||||||
|
(rot_x, rot_z, rot_y))
|
||||||
|
elif rot_mode == "rotation_quaternion":
|
||||||
|
bone.rotation_quaternion = mathutils.Quaternion(
|
||||||
|
(rot_w, rot_x, rot_y, rot_z))
|
||||||
|
bone.scale = mathutils.Vector((scl_x, scl_y, scl_z))
|
141
gui.py
141
gui.py
@ -2,9 +2,9 @@ import bpy
|
|||||||
from .common import *
|
from .common import *
|
||||||
|
|
||||||
|
|
||||||
class DATA_PT_DSPLPanel(bpy.types.Panel):
|
class DATA_PT_YaplPanel(bpy.types.Panel):
|
||||||
bl_label = "Damn Simple Pose Library"
|
bl_label = "Yet Another Pose Library"
|
||||||
bl_id = "DATA_PT_DSPLPanel"
|
bl_id = "DATA_PT_YaplPanel"
|
||||||
bl_space_type = 'VIEW_3D'
|
bl_space_type = 'VIEW_3D'
|
||||||
bl_region_type = 'UI'
|
bl_region_type = 'UI'
|
||||||
bl_category = 'Pose'
|
bl_category = 'Pose'
|
||||||
@ -14,13 +14,14 @@ class DATA_PT_DSPLPanel(bpy.types.Panel):
|
|||||||
return len(bpy.context.selected_objects)
|
return len(bpy.context.selected_objects)
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
dspl_panel_layout = self.layout
|
yapl_panel_layout = self.layout
|
||||||
dsplsettings = bpy.context.scene.dsplSettings
|
yaplsettings = bpy.context.scene.yaplSettings
|
||||||
|
|
||||||
# Detect Armature object and parent
|
# Detect Armature object and parent
|
||||||
armature_layout = dspl_panel_layout.column(align=True)
|
armature_layout = yapl_panel_layout.column(align=True)
|
||||||
active_obj = context.active_object
|
active_obj = context.active_object
|
||||||
arm_object = getArmatureObject(context)
|
arm_object, pose_library = get_armature_data(context)
|
||||||
|
pose_library_action = get_armature_action(context)
|
||||||
|
|
||||||
if arm_object:
|
if arm_object:
|
||||||
if arm_object == active_obj:
|
if arm_object == active_obj:
|
||||||
@ -29,121 +30,113 @@ class DATA_PT_DSPLPanel(bpy.types.Panel):
|
|||||||
armature_layout.label(text=arm_object.name + " (Parent)")
|
armature_layout.label(text=arm_object.name + " (Parent)")
|
||||||
|
|
||||||
# Attach or create pose library
|
# Attach or create pose library
|
||||||
pose_library_dspl = getDsplAction(context)
|
if pose_library or pose_library_action:
|
||||||
pose_library_action = getArmatureAction(context)
|
if pose_library and not pose_library_action:
|
||||||
|
|
||||||
if pose_library_dspl or pose_library_action:
|
|
||||||
if pose_library_dspl and not pose_library_action:
|
|
||||||
active_pose_library = pose_library_dspl
|
|
||||||
armature_layout.template_ID(
|
armature_layout.template_ID(
|
||||||
arm_object.dspl, "pose_library", new="dspl.create_pose_library", unlink="dspl.unlink_pose_library")
|
arm_object, "pose_library", new="yapl.create_pose_library", unlink="yapl.unlink_pose_library")
|
||||||
|
|
||||||
elif pose_library_action and not pose_library_dspl:
|
elif pose_library_action and not pose_library:
|
||||||
active_pose_library = pose_library_action
|
|
||||||
armature_layout.template_ID(
|
armature_layout.template_ID(
|
||||||
arm_object.animation_data, "action", new="dspl.create_pose_library")
|
arm_object.animation_data, "action", new="yapl.create_pose_library")
|
||||||
armature_layout.label(
|
armature_layout.label(
|
||||||
text="Legacy Pose Library detected.")
|
text="Pose Library detected as Action")
|
||||||
armature_layout.label(
|
armature_layout.label(
|
||||||
text="You may convert to avoid problems")
|
text="You should convert to avoid problems")
|
||||||
armature_layout.operator(
|
armature_layout.operator(
|
||||||
"dspl.convert_pose_library", icon='PLUGIN', text="Convert to DSPL")
|
"yapl.convert_pose_library", icon='PLUGIN', text="Convert to Pose Library")
|
||||||
|
|
||||||
elif pose_library_action and pose_library_dspl:
|
elif pose_library and pose_library_action:
|
||||||
armature_layout.template_ID(
|
armature_layout.template_ID(
|
||||||
arm_object.dspl, "pose_library", new="dspl.create_pose_library")
|
arm_object, "pose_library", new="yapl.create_pose_library")
|
||||||
armature_layout.label(text="Double pose configuration!!")
|
armature_layout.label(text="Pose Library is opened as Action")
|
||||||
armature_layout.label(text="You should not proceed")
|
armature_layout.label(text="Keyframes will affect pose")
|
||||||
armature_layout.operator(
|
armature_layout.operator(
|
||||||
"dspl.convert_pose_library", icon='PLUGIN', text="Convert to DSPL")
|
"yapl.convert_pose_library", icon='PLUGIN', text="Unlink from Action")
|
||||||
active_pose_library = pose_library_dspl
|
|
||||||
|
|
||||||
|
|
||||||
# List poses in pose library
|
# List poses in pose library
|
||||||
if active_pose_library:
|
if pose_library:
|
||||||
pose_box_layout = dspl_panel_layout.column()
|
pose_box_layout = yapl_panel_layout.column()
|
||||||
|
|
||||||
# Menu switcher
|
# Menu switcher
|
||||||
pose_box_menu_switcher_layout = pose_box_layout.row()
|
pose_box_menu_switcher_layout = pose_box_layout.row()
|
||||||
pose_box_menu_switcher_layout.prop(
|
pose_box_menu_switcher_layout.prop(
|
||||||
dsplsettings, "new_menu", icon='PMARKER_ACT', text="New Menu", toggle=True)
|
yaplsettings, "new_menu", icon='PMARKER_ACT', text="New Menu", toggle=True)
|
||||||
|
|
||||||
# Quick controls
|
# Quick controls
|
||||||
quick_pose_controls_layout = pose_box_layout.column()
|
quick_pose_controls_layout = pose_box_layout.column()
|
||||||
quick_pose_controls_layout.menu(
|
quick_pose_controls_layout.menu(
|
||||||
OBJECT_MT_AddPoseMenu.bl_idname, icon='ADD', text="New Pose")
|
OBJECT_MT_AddPoseMenu.bl_idname, icon='ADD', text="New Pose")
|
||||||
if active_pose_library.pose_markers.active:
|
if pose_library.pose_markers.active:
|
||||||
quick_apply_layout = quick_pose_controls_layout.split(
|
quick_apply_layout = quick_pose_controls_layout.split(
|
||||||
align=True)
|
align=True)
|
||||||
quick_apply_layout.prop(arm_object.dsplvars,
|
|
||||||
"only_selected", icon='GROUP_BONE', text="Selected", toggle=True)
|
|
||||||
quick_apply_layout.operator(
|
quick_apply_layout.operator(
|
||||||
"dspl.browse_poses", icon='CON_ARMATURE', text="Browse")
|
"yapl.browse_poses", icon='CON_ARMATURE', text="Browse")
|
||||||
if dsplsettings.new_menu == False:
|
if yaplsettings.new_menu == False:
|
||||||
quick_apply_layout.operator(
|
quick_apply_layout.operator(
|
||||||
"dspl.apply_pose", icon='ARMATURE_DATA', text="Apply Pose").posename = active_pose_library.pose_markers.active.name
|
"yapl.apply_pose", icon='ARMATURE_DATA', text="Apply Pose").posename = pose_library.pose_markers.active.name
|
||||||
else:
|
else:
|
||||||
quick_apply_layout.prop(dsplsettings,
|
quick_apply_layout.prop(yaplsettings,
|
||||||
"edit_mode", icon='GREASEPENCIL', text="Edit", toggle=True)
|
"edit_mode", icon='GREASEPENCIL', text="Edit", toggle=True)
|
||||||
|
|
||||||
# New menu
|
# New menu
|
||||||
if dsplsettings.new_menu == True:
|
if yaplsettings.new_menu == True:
|
||||||
pose_button_layout = pose_box_layout.row()
|
pose_button_layout = pose_box_layout.row()
|
||||||
pose_button_entries_layout = pose_button_layout.column(align=True)
|
pose_button_entries_layout = pose_button_layout.column(align=True)
|
||||||
for pm in active_pose_library.pose_markers:
|
for pm in pose_library.pose_markers:
|
||||||
row = pose_button_entries_layout.row(align=True)
|
row = pose_button_entries_layout.row(align=True)
|
||||||
|
|
||||||
# Selected indicator
|
# Selected indicator
|
||||||
selected = pm.frame == active_pose_library.pose_markers.active.frame
|
selected = pm.frame == pose_library.pose_markers.active.frame
|
||||||
if dsplsettings.edit_mode == False:
|
if yaplsettings.edit_mode == False:
|
||||||
row.label(text="", icon='PMARKER_ACT' if selected else 'PMARKER_SEL')
|
row.label(text="", icon='PMARKER_ACT' if selected else 'PMARKER_SEL')
|
||||||
|
|
||||||
# Pose operator buttons
|
# Pose operator buttons
|
||||||
if dsplsettings.edit_mode == True:
|
if yaplsettings.edit_mode == True:
|
||||||
row.operator('dspl.rename_pose', text=pm.name).posename = pm.name
|
row.operator('yapl.rename_pose', text=pm.name).posename = pm.name
|
||||||
else:
|
else:
|
||||||
row.operator('dspl.apply_pose', text=pm.name).posename = pm.name
|
row.operator('yapl.apply_pose', text=pm.name).posename = pm.name
|
||||||
|
|
||||||
if dsplsettings.edit_mode == True:
|
if yaplsettings.edit_mode == True:
|
||||||
movebuttondown = row.operator("dspl.move_pose", icon='TRIA_DOWN', text="")
|
movebuttondown = row.operator("yapl.move_pose", icon='TRIA_DOWN', text="")
|
||||||
movebuttondown.direction = "DOWN"
|
movebuttondown.direction = "DOWN"
|
||||||
movebuttondown.posename = pm.name
|
movebuttondown.posename = pm.name
|
||||||
movebuttonup = row.operator("dspl.move_pose", icon='TRIA_UP', text="")
|
movebuttonup = row.operator("yapl.move_pose", icon='TRIA_UP', text="")
|
||||||
movebuttonup.direction = "UP"
|
movebuttonup.direction = "UP"
|
||||||
movebuttonup.posename = pm.name
|
movebuttonup.posename = pm.name
|
||||||
|
|
||||||
row.operator("dspl.remove_pose", icon='REMOVE', text="").posename = pm.name
|
row.operator("yapl.remove_pose", icon='REMOVE', text="").posename = pm.name
|
||||||
|
|
||||||
# Old menu
|
# Old menu
|
||||||
elif dsplsettings.new_menu == False:
|
elif yaplsettings.new_menu == False:
|
||||||
pose_list_layout = pose_box_layout.column()
|
pose_list_layout = pose_box_layout.column()
|
||||||
|
|
||||||
# Pose list
|
# Pose list
|
||||||
pose_list_entries_layout = pose_list_layout.row()
|
pose_list_entries_layout = pose_list_layout.row()
|
||||||
pose_list_entries_layout.template_list("UI_UL_list","pose_markers",
|
pose_list_entries_layout.template_list("UI_UL_list","pose_markers",
|
||||||
active_pose_library, "pose_markers",
|
pose_library, "pose_markers",
|
||||||
active_pose_library.pose_markers, "active_index", rows=4)
|
pose_library.pose_markers, "active_index", rows=4)
|
||||||
|
|
||||||
# Pose operators
|
# Pose operators
|
||||||
pose_ops_layout = pose_list_entries_layout.column(align=True)
|
pose_ops_layout = pose_list_entries_layout.column(align=True)
|
||||||
pose_ops_layout.operator(
|
pose_ops_layout.operator(
|
||||||
"dspl.draw_new_pose_menu", icon='ADD', text="")
|
"wm.call_menu", icon='ADD', text="").name = "OBJECT_MT_AddPoseMenu"
|
||||||
if active_pose_library.pose_markers.active:
|
if pose_library.pose_markers.active:
|
||||||
pose_ops_layout.operator(
|
pose_ops_layout.operator(
|
||||||
"dspl.remove_pose", icon='REMOVE', text="")
|
"yapl.remove_pose", icon='REMOVE', text="")
|
||||||
pose_ops_layout.operator(
|
pose_ops_layout.operator(
|
||||||
"dspl.apply_pose", icon='ARMATURE_DATA', text=""
|
"yapl.apply_pose", icon='ARMATURE_DATA', text=""
|
||||||
).posename = active_pose_library.pose_markers.active.name
|
).posename = pose_library.pose_markers.active.name
|
||||||
pose_ops_layout.operator(
|
pose_ops_layout.operator(
|
||||||
"dspl.move_pose", icon='TRIA_UP', text="").direction = "UP"
|
"yapl.move_pose", icon='TRIA_UP', text="").direction = "UP"
|
||||||
pose_ops_layout.operator(
|
pose_ops_layout.operator(
|
||||||
"dspl.move_pose", icon='TRIA_DOWN', text="").direction = "DOWN"
|
"yapl.move_pose", icon='TRIA_DOWN', text="").direction = "DOWN"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
armature_layout.label(
|
armature_layout.label(
|
||||||
text="No Action or Pose Library detected")
|
text="No Action or Pose Library detected")
|
||||||
armature_layout.template_ID(
|
armature_layout.template_ID(
|
||||||
arm_object.dspl, "pose_library", new="dspl.create_pose_library")
|
arm_object, "pose_library", new="yapl.create_pose_library")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
armature_layout.label(text="No armature or parent selected")
|
armature_layout.label(text="No armature or parent selected")
|
||||||
@ -154,20 +147,34 @@ class OBJECT_MT_AddPoseMenu(bpy.types.Menu):
|
|||||||
bl_label = "Add Pose"
|
bl_label = "Add Pose"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
arm_object = getArmatureObject(context)
|
arm_object, pose_library = get_armature_data(context)
|
||||||
action_object = getPoseLib(context)
|
|
||||||
|
|
||||||
dspl_add_menu_layout = self.layout
|
yapl_add_menu_layout = self.layout
|
||||||
dspl_add_menu_layout.operator(
|
yapl_add_menu_layout.operator(
|
||||||
"dspl.draw_new_pose_menu", icon='DECORATE_DRIVER', text="Add New Pose")
|
"yapl.add_pose", icon='ADD', text="Add New Pose")
|
||||||
if action_object.pose_markers.active:
|
if len(pose_library.pose_markers):
|
||||||
dspl_add_menu_layout.operator(
|
yapl_add_menu_layout.menu(
|
||||||
"dspl.add_pose", icon='DECORATE_OVERRIDE', text="Replace Existing Pose").replace = True
|
"OBJECT_MT_ReplacePoseMenu", text="Replace Existing Pose", icon="DECORATE_OVERRIDE")
|
||||||
|
|
||||||
|
|
||||||
|
class OBJECT_MT_ReplacePoseMenu(bpy.types.Menu):
|
||||||
|
bl_idname = "OBJECT_MT_ReplacePoseMenu"
|
||||||
|
bl_label = "Add Pose"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
arm_object, pose_library = get_armature_data(context)
|
||||||
|
|
||||||
|
yapl_replace_menu_layout = self.layout
|
||||||
|
for pm in pose_library.pose_markers:
|
||||||
|
op = yapl_replace_menu_layout.operator("yapl.add_pose", text=pm.name, icon="PMARKER")
|
||||||
|
op.replace = True
|
||||||
|
op.posename = pm.name
|
||||||
|
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
DATA_PT_DSPLPanel,
|
DATA_PT_YaplPanel,
|
||||||
OBJECT_MT_AddPoseMenu,
|
OBJECT_MT_AddPoseMenu,
|
||||||
|
OBJECT_MT_ReplacePoseMenu,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
30
keymaps.py
30
keymaps.py
@ -1,28 +1,30 @@
|
|||||||
# SPDX-FileCopyrightText: 2010-2023 Blender Foundation
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
from .operators import *
|
|
||||||
from typing import List, Tuple
|
|
||||||
|
|
||||||
|
|
||||||
addon_keymaps = []
|
addon_keymaps = []
|
||||||
|
|
||||||
|
|
||||||
def register() -> None:
|
def register_keymaps():
|
||||||
wm = bpy.context.window_manager
|
wm = bpy.context.window_manager
|
||||||
kc = wm.keyconfigs.addon
|
|
||||||
if kc is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
km = kc.keymaps.new(name="File Browser Main")
|
# Add Pose
|
||||||
kmi = km.keymap_items.new("dspl.browse_poses", type="L", value="PRESS", alt=True)
|
km = wm.keyconfigs.addon.keymaps.new(name='Pose', space_type='EMPTY')
|
||||||
kmi.active = True
|
kmi = km.keymap_items.new('wm.call_menu', 'L', 'PRESS', shift=True)
|
||||||
|
kmi.properties.name = "OBJECT_MT_AddPoseMenu"
|
||||||
addon_keymaps.append((km, kmi))
|
addon_keymaps.append((km, kmi))
|
||||||
|
|
||||||
|
# Browse Poses
|
||||||
|
km = wm.keyconfigs.addon.keymaps.new(name='Pose', space_type='EMPTY')
|
||||||
|
kmi = km.keymap_items.new('yapl.browse_poses', 'L', 'PRESS', alt=True)
|
||||||
|
addon_keymaps.append((km, kmi))
|
||||||
|
|
||||||
def unregister() -> None:
|
def unregister_keymaps():
|
||||||
for km, kmi in addon_keymaps:
|
for km, kmi in addon_keymaps:
|
||||||
km.keymap_items.remove(kmi)
|
km.keymap_items.remove(kmi)
|
||||||
addon_keymaps.clear()
|
addon_keymaps.clear()
|
||||||
|
|
||||||
|
def register():
|
||||||
|
register_keymaps()
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
unregister_keymaps()
|
363
operators.py
363
operators.py
@ -1,5 +1,4 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import mathutils
|
|
||||||
import blf
|
import blf
|
||||||
from .common import *
|
from .common import *
|
||||||
|
|
||||||
@ -7,136 +6,55 @@ from .common import *
|
|||||||
# Operator to create a new pose library
|
# Operator to create a new pose library
|
||||||
|
|
||||||
|
|
||||||
class DSPL_OT_CreatePoseLibrary(bpy.types.Operator):
|
class YAPL_OT_CreatePoseLibrary(bpy.types.Operator):
|
||||||
bl_idname = "dspl.create_pose_library"
|
bl_idname = "yapl.create_pose_library"
|
||||||
bl_label = "Create Pose Library"
|
bl_label = "Create Pose Library"
|
||||||
bl_description = "Create Pose Library"
|
bl_description = "Create Pose Library"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
arm_object = getArmatureObject(context)
|
arm_object, pose_library = get_armature_data(context)
|
||||||
arm_object.dspl.pose_library = bpy.data.actions.new(
|
arm_object.pose_library = bpy.data.actions.new(
|
||||||
name=arm_object.name + "_PoseLib")
|
name=arm_object.name + "_PoseLib")
|
||||||
arm_object.dspl.pose_library.use_fake_user = True
|
arm_object.pose_library.use_fake_user = True
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
# Operator to convert a pose library to dspl property
|
# Operator to convert an action to pose library
|
||||||
|
|
||||||
|
|
||||||
class DSPL_OT_ConvertPoseLibrary(bpy.types.Operator):
|
class YAPL_OT_ConvertPoseLibrary(bpy.types.Operator):
|
||||||
bl_idname = "dspl.convert_pose_library"
|
bl_idname = "yapl.convert_pose_library"
|
||||||
bl_label = "Convert Pose Library"
|
bl_label = "Convert Pose Library"
|
||||||
bl_description = "Convert Pose Library"
|
bl_description = "Convert Pose Library"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
arm_object = getArmatureObject(context)
|
arm_object, pose_library = get_armature_data(context)
|
||||||
arm_object.dspl.pose_library = arm_object.animation_data.action
|
if pose_library is None:
|
||||||
|
arm_object.pose_library = arm_object.animation_data.action
|
||||||
arm_object.animation_data.action = None
|
arm_object.animation_data.action = None
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
# Operator to to draw a menu for new poses
|
|
||||||
|
|
||||||
|
|
||||||
class DSPL_OT_DrawNewPoseMenu(bpy.types.Operator):
|
|
||||||
bl_idname = "dspl.draw_new_pose_menu"
|
|
||||||
bl_label = "New Pose Menu"
|
|
||||||
bl_description = "New Pose Menu"
|
|
||||||
bl_options = {'INTERNAL'}
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
return {'FINISHED'}
|
|
||||||
|
|
||||||
def invoke(self, context, event):
|
|
||||||
return context.window_manager.invoke_popup(self, width=200)
|
|
||||||
|
|
||||||
def draw(self, context):
|
|
||||||
dspl_create_popup_layout = self.layout
|
|
||||||
dspl_new_pose_menu = dspl_create_popup_layout.box()
|
|
||||||
|
|
||||||
arm_object = getArmatureObject(context)
|
|
||||||
pose_library = getPoseLib(context)
|
|
||||||
dspl_new_pose_menu.prop(
|
|
||||||
arm_object.dsplvars, "pose_new_name", text="Name")
|
|
||||||
dspl_new_pose_menu.prop(
|
|
||||||
arm_object.dsplvars,
|
|
||||||
"only_selected", icon='GROUP_BONE', text="Selected", toggle=True)
|
|
||||||
dspl_new_pose_menu.operator(
|
|
||||||
"dspl.add_pose", icon='ADD', text="Add New Pose").posename = arm_object.dsplvars.pose_new_name
|
|
||||||
|
|
||||||
|
|
||||||
# Operator to call up popup menus by ID
|
|
||||||
|
|
||||||
|
|
||||||
class DSPL_OT_CallPopupMenu(bpy.types.Operator):
|
|
||||||
bl_idname = "dspl.call_popup_menu"
|
|
||||||
bl_label = "Popup menu"
|
|
||||||
bl_description = "Popup menu"
|
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
|
||||||
|
|
||||||
menuID: bpy.props.StringProperty()
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
bpy.ops.wm.call_menu(name=self.menuID)
|
|
||||||
|
|
||||||
return {'FINISHED'}
|
|
||||||
|
|
||||||
|
|
||||||
# Operator to manage the big menu buttons
|
|
||||||
|
|
||||||
|
|
||||||
class DSPL_OT_MenuButtonHandler(bpy.types.Operator):
|
|
||||||
bl_idname = "dspl.menu_button_handler"
|
|
||||||
bl_label = "Button Handler"
|
|
||||||
bl_description = "Button Handler"
|
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
|
||||||
|
|
||||||
posename: bpy.props.StringProperty()
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
bpy.ops.wm.call_menu(name=self.menuID)
|
|
||||||
|
|
||||||
return {'FINISHED'}
|
|
||||||
|
|
||||||
def invoke(self, context, event):
|
|
||||||
if event.ctrl:
|
|
||||||
# Select
|
|
||||||
action_object = getPoseLib(context)
|
|
||||||
action_object.pose_markers.active_index = searchPoseMarker(context, posename=self.posename, type="index")
|
|
||||||
return {'FINISHED'}
|
|
||||||
elif event.alt:
|
|
||||||
# Remove
|
|
||||||
bpy.ops.dspl.remove_pose(posename = self.posename)
|
|
||||||
return {'FINISHED'}
|
|
||||||
elif event.shift:
|
|
||||||
# Rename
|
|
||||||
bpy.ops.dspl.rename_pose(posename = self.posename)
|
|
||||||
return {'FINISHED'}
|
|
||||||
else:
|
|
||||||
return self.execute(context)
|
|
||||||
|
|
||||||
# Operator to add keyframes and marker to pose library
|
# Operator to add keyframes and marker to pose library
|
||||||
|
|
||||||
|
|
||||||
class DSPL_OT_AddPose(bpy.types.Operator):
|
class YAPL_OT_AddPose(bpy.types.Operator):
|
||||||
bl_idname = "dspl.add_pose"
|
bl_idname = "yapl.add_pose"
|
||||||
bl_label = "Add Pose"
|
bl_label = "Add Pose"
|
||||||
bl_description = "Add Pose"
|
bl_description = "Add Pose"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
posename: bpy.props.StringProperty()
|
posename: bpy.props.StringProperty(default="Pose")
|
||||||
replace: bpy.props.BoolProperty(name="Replace", description="Replace existing pose", default=False, options={'SKIP_SAVE'})
|
replace: bpy.props.BoolProperty(name="Replace", description="Replace existing pose", default=False, options={'SKIP_SAVE', 'HIDDEN'})
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
arm_object, pose_library = get_armature_data(context)
|
||||||
if self.replace == False:
|
if self.replace == False:
|
||||||
arm_object = getArmatureObject(context)
|
pose_markers = pose_library.pose_markers
|
||||||
action_object = getPoseLib(context)
|
|
||||||
pose_markers = action_object.pose_markers
|
|
||||||
new_name = self.posename
|
new_name = self.posename
|
||||||
counter = 1
|
counter = 1
|
||||||
|
|
||||||
@ -154,7 +72,6 @@ class DSPL_OT_AddPose(bpy.types.Operator):
|
|||||||
|
|
||||||
# Check for duplicate names
|
# Check for duplicate names
|
||||||
while pose_markers.find(new_name) > -1:
|
while pose_markers.find(new_name) > -1:
|
||||||
print("Duplicate posename detected")
|
|
||||||
new_name = self.posename + ".{:03d}".format(counter)
|
new_name = self.posename + ".{:03d}".format(counter)
|
||||||
counter += 1
|
counter += 1
|
||||||
else:
|
else:
|
||||||
@ -163,19 +80,17 @@ class DSPL_OT_AddPose(bpy.types.Operator):
|
|||||||
pose_markers.new(name=pose_name)
|
pose_markers.new(name=pose_name)
|
||||||
pose_markers[pose_name].frame = new_marker
|
pose_markers[pose_name].frame = new_marker
|
||||||
|
|
||||||
setKeyframesFromBones(context, new_marker)
|
set_keyframes_from_bones(context, arm_object, new_marker)
|
||||||
|
|
||||||
action_object.pose_markers.active = pose_markers[pose_name]
|
pose_library.pose_markers.active = pose_markers[pose_name]
|
||||||
bpy.context.area.tag_redraw()
|
bpy.context.area.tag_redraw()
|
||||||
|
|
||||||
print("Added pose - " + pose_markers[new_name].name + " to frame " + str(pose_markers[new_name].frame))
|
self.report({'INFO'}, "YAPL: Added " + pose_markers[new_name].name + " to frame " + str(pose_markers[new_name].frame))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
arm_object = getArmatureObject(context)
|
pose_markers = pose_library.pose_markers
|
||||||
action_object = getPoseLib(context)
|
|
||||||
pose_markers = action_object.pose_markers
|
|
||||||
active_marker = pose_markers.active
|
active_marker = pose_markers.active
|
||||||
new_name = active_marker.name
|
new_name = self.posename
|
||||||
counter = 1
|
counter = 1
|
||||||
|
|
||||||
for pm in pose_markers:
|
for pm in pose_markers:
|
||||||
@ -190,9 +105,9 @@ class DSPL_OT_AddPose(bpy.types.Operator):
|
|||||||
|
|
||||||
new_marker = target_frame
|
new_marker = target_frame
|
||||||
|
|
||||||
setKeyframesFromBones(context, new_marker)
|
set_keyframes_from_bones(context, arm_object, new_marker)
|
||||||
|
|
||||||
|
|
||||||
|
self.report({'INFO'}, "YAPL: Replaced " + pose_markers[new_name].name + " on frame " + str(pose_markers[new_name].frame))
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@ -200,8 +115,8 @@ class DSPL_OT_AddPose(bpy.types.Operator):
|
|||||||
# Operator to remove keyframes and marker
|
# Operator to remove keyframes and marker
|
||||||
|
|
||||||
|
|
||||||
class DSPL_OT_RemovePose(bpy.types.Operator):
|
class YAPL_OT_RemovePose(bpy.types.Operator):
|
||||||
bl_idname = "dspl.remove_pose"
|
bl_idname = "yapl.remove_pose"
|
||||||
bl_label = "Remove Pose"
|
bl_label = "Remove Pose"
|
||||||
bl_description = "Remove Pose"
|
bl_description = "Remove Pose"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
@ -209,18 +124,17 @@ class DSPL_OT_RemovePose(bpy.types.Operator):
|
|||||||
posename: bpy.props.StringProperty()
|
posename: bpy.props.StringProperty()
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
arm_object = getArmatureObject(context)
|
arm_object, pose_library = get_armature_data(context)
|
||||||
action_object = getPoseLib(context)
|
pose_markers = pose_library.pose_markers
|
||||||
pose_markers = action_object.pose_markers
|
|
||||||
if self.posename:
|
if self.posename:
|
||||||
action_object.pose_markers.active_index = searchPoseMarker(context, posename=self.posename, type="index")
|
pose_library.pose_markers.active_index = search_pose_marker(context, posename=self.posename, type="index")
|
||||||
active_index = action_object.pose_markers.active_index
|
active_index = pose_library.pose_markers.active_index
|
||||||
else:
|
else:
|
||||||
active_index = pose_markers.active_index
|
active_index = pose_markers.active_index
|
||||||
active_marker = pose_markers.active
|
active_marker = pose_markers.active
|
||||||
active_frame = active_marker.frame
|
active_frame = active_marker.frame
|
||||||
|
|
||||||
fcurves = action_object.fcurves
|
fcurves = pose_library.fcurves
|
||||||
for fcu in fcurves:
|
for fcu in fcurves:
|
||||||
for kf in fcu.keyframe_points.values():
|
for kf in fcu.keyframe_points.values():
|
||||||
if kf.co.x == active_frame:
|
if kf.co.x == active_frame:
|
||||||
@ -238,9 +152,10 @@ class DSPL_OT_RemovePose(bpy.types.Operator):
|
|||||||
|
|
||||||
pose_markers.remove(marker=active_marker)
|
pose_markers.remove(marker=active_marker)
|
||||||
|
|
||||||
print(next_index)
|
pose_library.pose_markers.active = next_marker
|
||||||
action_object.pose_markers.active = next_marker
|
pose_library.pose_markers.active_index = next_index
|
||||||
action_object.pose_markers.active_index = next_index
|
|
||||||
|
self.report({'INFO'}, "YAPL: Removed " + self.posename)
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@ -248,8 +163,8 @@ class DSPL_OT_RemovePose(bpy.types.Operator):
|
|||||||
# Operator to rename the current pose
|
# Operator to rename the current pose
|
||||||
|
|
||||||
|
|
||||||
class DSPL_OT_RenamePose(bpy.types.Operator):
|
class YAPL_OT_RenamePose(bpy.types.Operator):
|
||||||
bl_idname = "dspl.rename_pose"
|
bl_idname = "yapl.rename_pose"
|
||||||
bl_label = "Rename Pose"
|
bl_label = "Rename Pose"
|
||||||
bl_description = "Rename Pose"
|
bl_description = "Rename Pose"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
@ -258,20 +173,21 @@ class DSPL_OT_RenamePose(bpy.types.Operator):
|
|||||||
pose_new_name: bpy.props.StringProperty()
|
pose_new_name: bpy.props.StringProperty()
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
arm_object, pose_library = get_armature_data(context)
|
||||||
arm_object = getArmatureObject(context)
|
pose_markers = pose_library.pose_markers
|
||||||
action_object = getPoseLib(context)
|
|
||||||
pose_markers = action_object.pose_markers
|
|
||||||
active_marker = pose_markers.active
|
active_marker = pose_markers.active
|
||||||
|
|
||||||
if self.posename:
|
if self.posename:
|
||||||
target_marker = searchPoseMarker(context, posename=self.posename, type="marker")
|
target_marker = search_pose_marker(context, posename=self.posename, type="marker")
|
||||||
else:
|
else:
|
||||||
target_marker = active_marker
|
target_marker = active_marker
|
||||||
|
|
||||||
if self.pose_new_name:
|
if self.pose_new_name:
|
||||||
target_marker.name = self.pose_new_name
|
target_marker.name = self.pose_new_name
|
||||||
context.area.tag_redraw()
|
context.area.tag_redraw()
|
||||||
|
|
||||||
|
self.report({'INFO'}, "YAPL: Renamed " + self.posename + " to " + self.pose_new_name + " on frame " + str(active_marker.frame))
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
else:
|
else:
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
@ -285,8 +201,8 @@ class DSPL_OT_RenamePose(bpy.types.Operator):
|
|||||||
# Operator to reorder pose markers
|
# Operator to reorder pose markers
|
||||||
|
|
||||||
|
|
||||||
class DSPL_OT_MovePose(bpy.types.Operator):
|
class YAPL_OT_MovePose(bpy.types.Operator):
|
||||||
bl_idname = "dspl.move_pose"
|
bl_idname = "yapl.move_pose"
|
||||||
bl_label = "Move Pose"
|
bl_label = "Move Pose"
|
||||||
bl_description = "Move pose"
|
bl_description = "Move pose"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
@ -295,18 +211,15 @@ class DSPL_OT_MovePose(bpy.types.Operator):
|
|||||||
posename: bpy.props.StringProperty(name="Pose Name", default="", options={'SKIP_SAVE'})
|
posename: bpy.props.StringProperty(name="Pose Name", default="", options={'SKIP_SAVE'})
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
arm_object = getArmatureObject(context)
|
arm_object, pose_library = get_armature_data(context)
|
||||||
action_object = getPoseLib(context)
|
pose_markers = pose_library.pose_markers
|
||||||
pose_lib = getPoseLib(context)
|
|
||||||
pose_markers = action_object.pose_markers
|
|
||||||
|
|
||||||
if self.posename:
|
if self.posename:
|
||||||
active_index = searchPoseMarker(context, posename=self.posename, type="index")
|
active_index = search_pose_marker(context, posename=self.posename, type="index")
|
||||||
active_marker = searchPoseMarker(context, posename=self.posename, type="marker")
|
active_marker = search_pose_marker(context, posename=self.posename, type="marker")
|
||||||
active_frame = active_marker.frame
|
active_frame = active_marker.frame
|
||||||
active_posename = active_marker.name
|
active_posename = active_marker.name
|
||||||
else:
|
else:
|
||||||
arm_object = getArmatureObject(context)
|
|
||||||
active_marker = pose_markers.active
|
active_marker = pose_markers.active
|
||||||
active_index = pose_markers.active_index
|
active_index = pose_markers.active_index
|
||||||
|
|
||||||
@ -318,21 +231,19 @@ class DSPL_OT_MovePose(bpy.types.Operator):
|
|||||||
swap_index = active_index + move_dir
|
swap_index = active_index + move_dir
|
||||||
|
|
||||||
if swap_index < 0:
|
if swap_index < 0:
|
||||||
# swap_index = len(pose_lib.pose_markers) - 1
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
elif swap_index >= len(pose_lib.pose_markers):
|
elif swap_index >= len(pose_library.pose_markers):
|
||||||
# swap_index = 0
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
swap_marker = pose_markers[swap_index]
|
swap_marker = pose_markers[swap_index]
|
||||||
|
|
||||||
tmp_marker_name = swap_marker.name
|
tmp_marker_name = swap_marker.name
|
||||||
tmp_marker_frame = swap_marker.frame
|
tmp_marker_frame = swap_marker.frame
|
||||||
action_object.pose_markers[swap_index].name = active_marker.name
|
pose_library.pose_markers[swap_index].name = active_marker.name
|
||||||
action_object.pose_markers[swap_index].frame = active_marker.frame
|
pose_library.pose_markers[swap_index].frame = active_marker.frame
|
||||||
action_object.pose_markers[active_index].name = tmp_marker_name
|
pose_library.pose_markers[active_index].name = tmp_marker_name
|
||||||
action_object.pose_markers[active_index].frame = tmp_marker_frame
|
pose_library.pose_markers[active_index].frame = tmp_marker_frame
|
||||||
action_object.pose_markers.active_index = swap_index
|
pose_library.pose_markers.active_index = swap_index
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@ -340,102 +251,49 @@ class DSPL_OT_MovePose(bpy.types.Operator):
|
|||||||
# Operator to apply a pose from active marker
|
# Operator to apply a pose from active marker
|
||||||
|
|
||||||
|
|
||||||
class DSPL_OT_ApplyPose(bpy.types.Operator):
|
class YAPL_OT_ApplyPose(bpy.types.Operator):
|
||||||
bl_idname = "dspl.apply_pose"
|
bl_idname = "yapl.apply_pose"
|
||||||
bl_label = "Apply Pose"
|
bl_label = "Apply Pose"
|
||||||
bl_description = "Apply Pose (Ctrl+Click to select, Alt+Click to remove)"
|
bl_description = "Apply Pose (Ctrl+Click to select, Shift+Click to rename, Alt+Click to remove)"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
posename: bpy.props.StringProperty()
|
posename: bpy.props.StringProperty()
|
||||||
|
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
arm_object = getArmatureObject(context)
|
arm_object, pose_library = get_armature_data(context)
|
||||||
action_object = getPoseLib(context)
|
pose_markers = pose_library.pose_markers
|
||||||
pose_markers = action_object.pose_markers
|
|
||||||
|
|
||||||
if self.posename:
|
if self.posename:
|
||||||
active_marker = searchPoseMarker(context, posename=self.posename, type="marker")
|
active_marker = search_pose_marker(context, posename=self.posename, type="marker")
|
||||||
active_frame = active_marker.frame
|
active_frame = active_marker.frame
|
||||||
active_posename = active_marker.name
|
active_posename = active_marker.name
|
||||||
action_object.pose_markers.active_index = searchPoseMarker(context, posename=self.posename, type="index")
|
pose_library.pose_markers.active_index = search_pose_marker(context, posename=self.posename, type="index")
|
||||||
else:
|
else:
|
||||||
active_index = pose_markers.active_index
|
active_index = pose_markers.active_index
|
||||||
active_marker = pose_markers.active
|
active_marker = pose_markers.active
|
||||||
active_frame = active_marker.frame
|
active_frame = active_marker.frame
|
||||||
active_posename = active_marker.name
|
active_posename = active_marker.name
|
||||||
|
|
||||||
for bone in arm_object.pose.bones:
|
set_bones_from_keyframes(context, arm_object, active_marker)
|
||||||
if bone.bone.select or arm_object.dsplvars.only_selected == False:
|
|
||||||
bone_name = bone.name
|
|
||||||
|
|
||||||
if bone.rotation_mode == "XYZ":
|
self.report({'INFO'}, "YAPL: Applied " + active_posename)
|
||||||
rot_mode = "rotation_euler"
|
|
||||||
elif bone.rotation_mode == "YZX":
|
|
||||||
rot_mode = "rotation_euler"
|
|
||||||
elif bone.rotation_mode == "ZXY":
|
|
||||||
rot_mode = "rotation_euler"
|
|
||||||
elif bone.rotation_mode == "QUATERNION":
|
|
||||||
rot_mode = "rotation_quaternion"
|
|
||||||
else:
|
|
||||||
print("Unsupported bone!")
|
|
||||||
rot_mode = None
|
|
||||||
|
|
||||||
loc_x = findFcurve(context, bone_name, "location", 0) or 0.0
|
|
||||||
loc_y = findFcurve(context, bone_name, "location", 1) or 0.0
|
|
||||||
loc_z = findFcurve(context, bone_name, "location", 2) or 0.0
|
|
||||||
if rot_mode == "rotation_quaternion":
|
|
||||||
rot_w = findFcurve(context, bone_name, rot_mode, 0) or 1.0
|
|
||||||
rot_x = findFcurve(context, bone_name, rot_mode, 1) or 0.0
|
|
||||||
rot_y = findFcurve(context, bone_name, rot_mode, 2) or 0.0
|
|
||||||
rot_z = findFcurve(context, bone_name, rot_mode, 3) or 0.0
|
|
||||||
elif rot_mode == "rotation_euler":
|
|
||||||
rot_x = findFcurve(context, bone_name, rot_mode, 0) or 0.0
|
|
||||||
rot_y = findFcurve(context, bone_name, rot_mode, 1) or 0.0
|
|
||||||
rot_z = findFcurve(context, bone_name, rot_mode, 2) or 0.0
|
|
||||||
scl_x = findFcurve(context, bone_name, "scale", 0) or 1.0
|
|
||||||
scl_y = findFcurve(context, bone_name, "scale", 1) or 1.0
|
|
||||||
scl_z = findFcurve(context, bone_name, "scale", 2) or 1.0
|
|
||||||
|
|
||||||
bone.location = mathutils.Vector((loc_x, loc_y, loc_z))
|
|
||||||
if bone.rotation_mode == "XYZ":
|
|
||||||
bone.rotation_euler = mathutils.Euler(
|
|
||||||
(rot_x, rot_y, rot_z))
|
|
||||||
elif bone.rotation_mode == "YZX":
|
|
||||||
bone.rotation_euler = mathutils.Euler(
|
|
||||||
(rot_x, rot_y, rot_z))
|
|
||||||
elif bone.rotation_mode == "ZXY":
|
|
||||||
bone.rotation_euler = mathutils.Euler(
|
|
||||||
(rot_z, rot_x, rot_y))
|
|
||||||
elif bone.rotation_mode == "YXZ":
|
|
||||||
bone.rotation_euler = mathutils.Euler(
|
|
||||||
(rot_y, rot_x, rot_z))
|
|
||||||
elif bone.rotation_mode == "XZY":
|
|
||||||
bone.rotation_euler = mathutils.Euler(
|
|
||||||
(rot_x, rot_z, rot_y))
|
|
||||||
elif rot_mode == "rotation_quaternion":
|
|
||||||
bone.rotation_quaternion = mathutils.Quaternion(
|
|
||||||
(rot_w, rot_x, rot_y, rot_z))
|
|
||||||
bone.scale = mathutils.Vector((scl_x, scl_y, scl_z))
|
|
||||||
|
|
||||||
|
|
||||||
print("Applied pose - " + active_posename)
|
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
if event.ctrl:
|
if event.ctrl:
|
||||||
# Select
|
# Select
|
||||||
action_object = getPoseLib(context)
|
arm_object, pose_library = get_armature_data(context)
|
||||||
action_object.pose_markers.active_index = searchPoseMarker(context, posename=self.posename, type="index")
|
pose_library.pose_markers.active_index = search_pose_marker(context, posename=self.posename, type="index")
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
elif event.alt:
|
elif event.alt:
|
||||||
# Remove
|
# Remove
|
||||||
bpy.ops.dspl.remove_pose(posename = self.posename)
|
bpy.ops.yapl.remove_pose(posename = self.posename)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
elif event.shift:
|
elif event.shift:
|
||||||
# Rename
|
# Rename
|
||||||
bpy.ops.dspl.rename_pose(posename = self.posename)
|
bpy.ops.yapl.rename_pose('INVOKE_DEFAULT', posename = self.posename)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
else:
|
else:
|
||||||
return self.execute(context)
|
return self.execute(context)
|
||||||
@ -444,8 +302,8 @@ class DSPL_OT_ApplyPose(bpy.types.Operator):
|
|||||||
# Operator to preview up and down pose list
|
# Operator to preview up and down pose list
|
||||||
|
|
||||||
|
|
||||||
class DSPL_OT_BrowsePoses(bpy.types.Operator):
|
class YAPL_OT_BrowsePoses(bpy.types.Operator):
|
||||||
bl_idname = "dspl.browse_poses"
|
bl_idname = "yapl.browse_poses"
|
||||||
bl_label = "Browse Poses"
|
bl_label = "Browse Poses"
|
||||||
bl_description = "Browse Poses"
|
bl_description = "Browse Poses"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
@ -457,7 +315,7 @@ class DSPL_OT_BrowsePoses(bpy.types.Operator):
|
|||||||
font_dpi = 72
|
font_dpi = 72
|
||||||
|
|
||||||
blf.position(font_id, 15, 30, 0)
|
blf.position(font_id, 15, 30, 0)
|
||||||
mod_var = self.pose_lib.pose_markers.active.name
|
mod_var = self.pose_library.pose_markers.active.name
|
||||||
blf.color(font_id, 1.0, 1.0, 1.0, 1.0)
|
blf.color(font_id, 1.0, 1.0, 1.0, 1.0)
|
||||||
blf.size(font_id, font_size)
|
blf.size(font_id, font_size)
|
||||||
blf.draw(font_id, "Previewing pose: " + mod_var)
|
blf.draw(font_id, "Previewing pose: " + mod_var)
|
||||||
@ -468,17 +326,17 @@ class DSPL_OT_BrowsePoses(bpy.types.Operator):
|
|||||||
|
|
||||||
if event.value == 'PRESS':
|
if event.value == 'PRESS':
|
||||||
if event.type in {'LEFT_ARROW', 'UP_ARROW'}:
|
if event.type in {'LEFT_ARROW', 'UP_ARROW'}:
|
||||||
if self.pose_lib.pose_markers.active_index <= 0:
|
if self.pose_library.pose_markers.active_index <= 0:
|
||||||
self.pose_lib.pose_markers.active_index = len(self.pose_lib.pose_markers) - 1
|
self.pose_library.pose_markers.active_index = len(self.pose_library.pose_markers) - 1
|
||||||
else:
|
else:
|
||||||
self.pose_lib.pose_markers.active_index = self.pose_lib.pose_markers.active_index - 1
|
self.pose_library.pose_markers.active_index = self.pose_library.pose_markers.active_index - 1
|
||||||
bpy.ops.dspl.apply_pose()
|
bpy.ops.yapl.apply_pose()
|
||||||
elif event.type in {'RIGHT_ARROW', 'DOWN_ARROW'}:
|
elif event.type in {'RIGHT_ARROW', 'DOWN_ARROW'}:
|
||||||
if self.pose_lib.pose_markers.active_index + 1 >= len(self.pose_lib.pose_markers):
|
if self.pose_library.pose_markers.active_index + 1 >= len(self.pose_library.pose_markers):
|
||||||
self.pose_lib.pose_markers.active_index = 0
|
self.pose_library.pose_markers.active_index = 0
|
||||||
else:
|
else:
|
||||||
self.pose_lib.pose_markers.active_index = self.pose_lib.pose_markers.active_index + 1
|
self.pose_library.pose_markers.active_index = self.pose_library.pose_markers.active_index + 1
|
||||||
bpy.ops.dspl.apply_pose()
|
bpy.ops.yapl.apply_pose()
|
||||||
|
|
||||||
if event.type in {'LEFTMOUSE', 'RET', 'NUMPAD_ENTER'}:
|
if event.type in {'LEFTMOUSE', 'RET', 'NUMPAD_ENTER'}:
|
||||||
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
|
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
|
||||||
@ -486,7 +344,7 @@ class DSPL_OT_BrowsePoses(bpy.types.Operator):
|
|||||||
|
|
||||||
elif event.type in {'RIGHTMOUSE', 'ESC'}:
|
elif event.type in {'RIGHTMOUSE', 'ESC'}:
|
||||||
self.arm_object.pose.backup_restore()
|
self.arm_object.pose.backup_restore()
|
||||||
self.pose_lib.pose_markers.active_index = self.backup_index
|
self.pose_library.pose_markers.active_index = self.backup_index
|
||||||
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
|
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
|
||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
|
||||||
@ -496,42 +354,44 @@ class DSPL_OT_BrowsePoses(bpy.types.Operator):
|
|||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
bpy.context.area.tag_redraw()
|
bpy.context.area.tag_redraw()
|
||||||
|
|
||||||
self.arm_object = getArmatureObject(context)
|
self.arm_object, self.pose_library = get_armature_data(context)
|
||||||
self.pose_lib = getPoseLib(context)
|
|
||||||
|
|
||||||
if self.pose_lib is None:
|
if self.pose_library is None:
|
||||||
self.report({'WARNING'}, "Pose Library not active")
|
self.report({'WARNING'}, "YAPL: Pose Library not active")
|
||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
|
||||||
self.arm_object.pose.backup_create(self.pose_lib)
|
self.arm_object.pose.backup_create(self.pose_library)
|
||||||
self.backup_index = self.pose_lib.pose_markers.active_index
|
self.backup_index = self.pose_library.pose_markers.active_index
|
||||||
bpy.ops.dspl.apply_pose()
|
bpy.ops.yapl.apply_pose()
|
||||||
|
|
||||||
if context.area.type == 'VIEW_3D':
|
if context.area.type == 'VIEW_3D':
|
||||||
print("Starting modal")
|
self.report({'INFO'}, "YAPL: Browsing Poses")
|
||||||
args = (self, context)
|
args = (self, context)
|
||||||
self._handle = bpy.types.SpaceView3D.draw_handler_add(self.draw_callback_px, args, 'WINDOW', 'POST_PIXEL')
|
self._handle = bpy.types.SpaceView3D.draw_handler_add(self.draw_callback_px, args, 'WINDOW', 'POST_PIXEL')
|
||||||
context.window_manager.modal_handler_add(self)
|
context.window_manager.modal_handler_add(self)
|
||||||
return {'RUNNING_MODAL'}
|
return {'RUNNING_MODAL'}
|
||||||
print("not in 3d")
|
|
||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
|
||||||
|
|
||||||
# Operator to unlink a pose library and mark for removal
|
# Operator to unlink a pose library and mark for removal
|
||||||
|
|
||||||
|
|
||||||
class DSPL_OT_UnlinkPoseLibrary(bpy.types.Operator):
|
class YAPL_OT_UnlinkPoseLibrary(bpy.types.Operator):
|
||||||
bl_idname = "dspl.unlink_pose_library"
|
bl_idname = "yapl.unlink_pose_library"
|
||||||
bl_label = "Unlink Pose Library"
|
bl_label = "Unlink Pose Library"
|
||||||
bl_description = "Unlink Pose Library"
|
bl_description = "Unlink Pose Library"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
arm_object = getArmatureObject(context)
|
arm_object, pose_library = get_armature_data(context)
|
||||||
pose_library = getPoseLib(context)
|
|
||||||
|
|
||||||
arm_object.dspl.pose_library.name = "del_" + arm_object.dspl.pose_library.name
|
try:
|
||||||
arm_object.dspl.pose_library = None
|
arm_object.pose_library = None
|
||||||
|
# arm_object.pose_library.use_fake_user = False
|
||||||
|
# if not arm_object.pose_library.name.startswith("del_"):
|
||||||
|
# arm_object.pose_library.name = "del_{}".format(arm_object.pose_library.name)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@ -539,8 +399,8 @@ class DSPL_OT_UnlinkPoseLibrary(bpy.types.Operator):
|
|||||||
# Operator to protect orphaned legacy pose libraries
|
# Operator to protect orphaned legacy pose libraries
|
||||||
|
|
||||||
|
|
||||||
class DSPL_OT_ProtectOrphanPoseLibrary(bpy.types.Operator):
|
class YAPL_OT_ProtectOrphanPoseLibrary(bpy.types.Operator):
|
||||||
bl_idname = "dspl.protect_orphan_pose_library"
|
bl_idname = "yapl.protect_orphan_pose_library"
|
||||||
bl_label = "Protect Orphaned Pose Libraries"
|
bl_label = "Protect Orphaned Pose Libraries"
|
||||||
bl_description = "Protect Orphaned Pose Libraries"
|
bl_description = "Protect Orphaned Pose Libraries"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
@ -576,26 +436,23 @@ class DSPL_OT_ProtectOrphanPoseLibrary(bpy.types.Operator):
|
|||||||
if orphaned_act:
|
if orphaned_act:
|
||||||
for act in orphaned_act:
|
for act in orphaned_act:
|
||||||
if "_loc" in act.name or "PoseLib" in act.name:
|
if "_loc" in act.name or "PoseLib" in act.name:
|
||||||
print("Protecting orphaned action: " + act.name)
|
self.report({'INFO'}, "YAPL: Protecting orphaned action: " + act.name)
|
||||||
act.use_fake_user = True
|
act.use_fake_user = True
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
DSPL_OT_CreatePoseLibrary,
|
YAPL_OT_CreatePoseLibrary,
|
||||||
DSPL_OT_ConvertPoseLibrary,
|
YAPL_OT_ConvertPoseLibrary,
|
||||||
DSPL_OT_CallPopupMenu,
|
YAPL_OT_AddPose,
|
||||||
DSPL_OT_DrawNewPoseMenu,
|
YAPL_OT_RemovePose,
|
||||||
DSPL_OT_MenuButtonHandler,
|
YAPL_OT_RenamePose,
|
||||||
DSPL_OT_AddPose,
|
YAPL_OT_MovePose,
|
||||||
DSPL_OT_RemovePose,
|
YAPL_OT_ApplyPose,
|
||||||
DSPL_OT_RenamePose,
|
YAPL_OT_BrowsePoses,
|
||||||
DSPL_OT_MovePose,
|
YAPL_OT_UnlinkPoseLibrary,
|
||||||
DSPL_OT_ApplyPose,
|
YAPL_OT_ProtectOrphanPoseLibrary
|
||||||
DSPL_OT_BrowsePoses,
|
|
||||||
DSPL_OT_UnlinkPoseLibrary,
|
|
||||||
DSPL_OT_ProtectOrphanPoseLibrary
|
|
||||||
)
|
)
|
||||||
|
|
||||||
register, unregister = bpy.utils.register_classes_factory(classes)
|
register, unregister = bpy.utils.register_classes_factory(classes)
|
||||||
|
Reference in New Issue
Block a user