Files
Avatar-Toolkit/functions/pose_mode.py
T
Yusarina ff23d23cfc Start of the Major Overhaul
I decided to go through each function and UI section one by one, improving and overhauling things. Each function and section is going to be fully tested and not rushed out.

This is the best way to catch things, but also include the code base as much as possible.
2024-12-03 22:58:17 +00:00

121 lines
4.2 KiB
Python

import bpy
import numpy as np
from bpy.types import Operator, Context, Object
from typing import List
from ..core.translations import t
from ..core.common import (
get_active_armature,
get_all_meshes,
apply_pose_as_rest,
apply_armature_to_mesh,
apply_armature_to_mesh_with_shapekeys,
validate_armature
)
class AvatarToolkit_OT_StartPoseMode(Operator):
bl_idname = 'avatar_toolkit.start_pose_mode'
bl_label = t("Quick_Access.start_pose_mode.label")
bl_description = t("Quick_Access.start_pose_mode.desc")
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
armature = get_active_armature(context)
if not armature or context.mode == "POSE":
return False
is_valid, _ = validate_armature(armature)
return is_valid
def execute(self, context: Context) -> set[str]:
armature = get_active_armature(context)
context.view_layer.objects.active = armature
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='DESELECT')
armature.select_set(True)
bpy.ops.object.mode_set(mode='POSE')
return {'FINISHED'}
class AvatarToolkit_OT_StopPoseMode(Operator):
bl_idname = 'avatar_toolkit.stop_pose_mode'
bl_label = t("Quick_Access.stop_pose_mode.label")
bl_description = t("Quick_Access.stop_pose_mode.desc")
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return get_active_armature(context) and context.mode == "POSE"
def execute(self, context: Context) -> set[str]:
bpy.ops.pose.transforms_clear()
bpy.ops.pose.select_all(action="INVERT")
bpy.ops.pose.transforms_clear()
bpy.ops.pose.select_all(action="INVERT")
bpy.ops.object.mode_set(mode='OBJECT')
return {'FINISHED'}
class AvatarToolkit_OT_ApplyPoseAsShapekey(Operator):
bl_idname = 'avatar_toolkit.apply_pose_as_shapekey'
bl_label = t("Quick_Access.apply_pose_as_shapekey.label")
bl_description = t("Quick_Access.apply_pose_as_shapekey.desc")
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
armature = get_active_armature(context)
if not armature or context.mode != 'POSE':
return False
is_valid, _ = validate_armature(armature)
return is_valid
def execute(self, context):
armature_obj = get_active_armature(context)
mesh_objects = get_all_meshes(context)
for mesh_obj in mesh_objects:
if not mesh_obj.data:
continue
if not mesh_obj.data.shape_keys:
mesh_obj.shape_key_add(name='Basis')
new_shape = mesh_obj.shape_key_add(name='Pose_Shapekey', from_mix=False)
depsgraph = context.evaluated_depsgraph_get()
eval_mesh = mesh_obj.evaluated_get(depsgraph)
for i, v in enumerate(eval_mesh.data.vertices):
new_shape.data[i].co = v.co.copy()
bpy.ops.pose.select_all(action='SELECT')
bpy.ops.pose.transforms_clear()
bpy.ops.object.mode_set(mode='OBJECT')
self.report({'INFO'}, t('Tools.apply_pose_as_rest.success'))
return {'FINISHED'}
class AvatarToolkit_OT_ApplyPoseAsRest(Operator):
bl_idname = 'avatar_toolkit.apply_pose_as_rest'
bl_label = t("Quick_Access.apply_pose_as_rest.label")
bl_description = t("Quick_Access.apply_pose_as_rest.desc")
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
armature = get_active_armature(context)
if not armature or context.mode != "POSE":
return False
is_valid, _ = validate_armature(armature)
return is_valid
def execute(self, context):
if not apply_pose_as_rest(
context=context,
armature_obj=get_active_armature(context),
meshes=get_all_meshes(context)
):
self.report({'ERROR'}, t("Quick_Access.apply_armature_failed"))
return {'CANCELLED'}
self.report({'INFO'}, t("Tools.apply_pose_as_rest.success"))
return {'FINISHED'}