Files
Avatar-Toolkit/ui/quick_access_panel.py
T
Yusarina 5dcaba381d Pose mode improvements, armature validation improvements.
Pose mode Improvements:

Batch processing for all mesh operations
Numpy-powered vertex array handling
Optimized modifier stack management
Smart shape key processing
Enhanced progress tracking

The armature validation system improvements:

Essential bones (hips, spine, chest, neck, head)
Proper bone hierarchy validation
Symmetry pair verification (e.g., arm.l/arm.r)
2024-12-04 00:54:21 +00:00

133 lines
5.2 KiB
Python

import bpy
from typing import Set, Optional, List, Tuple
from bpy.types import Operator, Panel, Menu, Context, UILayout
from .main_panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
from ..core.translations import t
from ..core.common import (
get_active_armature,
clear_default_objects,
validate_armature,
get_armature_list,
get_armature_stats
)
from ..core.importers.importer import import_types, imports
from ..functions.pose_mode import (
AvatarToolkit_OT_StartPoseMode,
AvatarToolkit_OT_StopPoseMode,
AvatarToolkit_OT_ApplyPoseAsShapekey,
AvatarToolkit_OT_ApplyPoseAsRest
)
class AvatarToolKit_OT_Import(Operator):
"""Import FBX files into Blender with Avatar Toolkit settings"""
bl_idname = "avatar_toolkit.import"
bl_label = t("QuickAccess.import")
def execute(self, context: Context) -> Set[str]:
clear_default_objects()
bpy.ops.import_scene.fbx('INVOKE_DEFAULT', filter_glob=imports)
return {'FINISHED'}
class AvatarToolKit_OT_ExportFBX(Operator):
"""Export selected objects as FBX"""
bl_idname = "avatar_toolkit.export_fbx"
bl_label = t("QuickAccess.export_fbx")
def execute(self, context: Context) -> Set[str]:
bpy.ops.export_scene.fbx('INVOKE_DEFAULT')
return {'FINISHED'}
class AvatarToolKit_MT_ExportMenu(Menu):
"""Export menu containing various export options"""
bl_idname = "AVATAR_TOOLKIT_MT_export_menu"
bl_label = t("QuickAccess.export")
def draw(self, context: Context) -> None:
layout: UILayout = self.layout
layout.operator("avatar_toolkit.export_fbx", text=t("QuickAccess.export_fbx"))
layout.operator("avatar_toolkit.export_resonite", text=t("QuickAccess.export_resonite"))
class AvatarToolKit_OT_ExportMenu(Operator):
"""Open the export menu"""
bl_idname = "avatar_toolkit.export"
bl_label = t("QuickAccess.export")
def execute(self, context: Context) -> Set[str]:
bpy.ops.wm.call_menu(name=AvatarToolKit_MT_ExportMenu.bl_idname)
return {'FINISHED'}
class AvatarToolKit_PT_QuickAccessPanel(Panel):
"""Quick access panel for common Avatar Toolkit operations"""
bl_label = t("QuickAccess.label")
bl_idname = "OBJECT_PT_avatar_toolkit_quick_access"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = CATEGORY_NAME
bl_parent_id = AvatarToolKit_PT_AvatarToolkitPanel.bl_idname
bl_order = 0
@classmethod
def poll(cls, context: Context) -> bool:
"""Only show panel in Object or Pose mode"""
return context.mode in {'OBJECT', 'POSE'}
def draw(self, context: Context) -> None:
"""Draw the panel layout"""
layout: UILayout = self.layout
# Armature Selection Box
armature_box: UILayout = layout.box()
col: UILayout = armature_box.column(align=True)
col.label(text=t("QuickAccess.select_armature"), icon='ARMATURE_DATA')
col.separator(factor=0.5)
# Armature Selection
col.prop(context.scene.avatar_toolkit, "active_armature", text="")
# Armature Validation
active_armature = get_active_armature(context)
if active_armature:
is_valid, messages = validate_armature(active_armature)
if is_valid:
info_box: UILayout = col.box()
row: UILayout = info_box.row()
split: UILayout = row.split(factor=0.6)
split.label(text=t("QuickAccess.valid_armature"), icon='CHECKMARK')
stats: dict = get_armature_stats(active_armature)
split.label(text=t("QuickAccess.bones_count", count=stats['bone_count']))
if stats['has_pose']:
info_box.label(text=t("QuickAccess.pose_bones_available"), icon='POSE_HLT')
else:
col.separator(factor=0.5)
# Display each validation message
for message in messages:
col.label(text=message, icon='ERROR')
# Pose Mode Controls
pose_box: UILayout = layout.box()
col = pose_box.column(align=True)
col.label(text=t("QuickAccess.pose_controls"), icon='ARMATURE_DATA')
col.separator(factor=0.5)
if context.mode == "POSE":
col.operator(AvatarToolkit_OT_StopPoseMode.bl_idname, icon='POSE_HLT')
col.separator(factor=0.5)
col.operator(AvatarToolkit_OT_ApplyPoseAsRest.bl_idname, icon='MOD_ARMATURE')
col.operator(AvatarToolkit_OT_ApplyPoseAsShapekey.bl_idname, icon='MOD_ARMATURE')
else:
col.operator(AvatarToolkit_OT_StartPoseMode.bl_idname, icon='POSE_HLT')
# Import/Export Box
import_box: UILayout = layout.box()
col = import_box.column(align=True)
col.label(text=t("QuickAccess.import_export"), icon='IMPORT')
col.separator(factor=0.5)
# Import/Export Buttons
button_row: UILayout = col.row(align=True)
button_row.scale_y = 1.5
button_row.operator("avatar_toolkit.import", text=t("QuickAccess.import"), icon='IMPORT')
button_row.operator("avatar_toolkit.export", text=t("QuickAccess.export"), icon='EXPORT')